# Koshi 0.2.0 — Overview (/docs/v0.2/configuration)



koshi reads four optional KDL file types. With none present, built-in defaults
apply. Every file that does exist must declare a supported `version`.

| File                                                        | What it sets                                                                                                        |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| [`koshi.kdl`](/docs/v0.2/configuration/koshi-kdl)           | Theme, pane, scrollback, layout, mouse, copy, terminal, logging, update, beta-feature, and session-closing settings |
| [`themes/<name>.kdl`](/docs/v0.2/configuration/themes)      | Interface colours, selected by `theme "<name>"`                                                                     |
| [`keybinding.kdl`](/docs/v0.2/configuration/keybinding-kdl) | Key bindings and the modes they live in                                                                             |
| [`profile/<name>.kdl`](/docs/v0.2/configuration/profiles)   | A saved layout, opened with `koshi --profile <name>`                                                                |

## Where the files go [#where-the-files-go]

The two top-level files sit in the config directory. Themes and profiles use
their own subdirectories.

| Platform | Config directory                      |
| -------- | ------------------------------------- |
| Linux    | `~/.config/koshi`                     |
| macOS    | `~/Library/Application Support/koshi` |
| Windows  | `%APPDATA%\koshi\config`              |

```
<config dir>/
    koshi.kdl
    keybinding.kdl
    themes/
        midnight.kdl
        solarized.kdl
    profile/
        dev.kdl
        writing.kdl
```

koshi has no config-path override. Linux still follows `XDG_CONFIG_HOME`.

```bash
koshi config path
```

## Whose setting is it [#whose-setting-is-it]

A session runs in its own process, and your terminal is a client attached to
it. Each side reads the config files it needs.

| Read by       | Settings                                                                                     | When                          |
| ------------- | -------------------------------------------------------------------------------------------- | ----------------------------- |
| The session   | `pane`, `scrollback`, `terminal`, `auto-close-session`                                       | Once, when the session starts |
| Your terminal | `theme`, `themes/<name>.kdl`, `keybinding.kdl`, `mouse`, `copy`, `layout.new-pane-direction` | Every time it attaches        |
| Every process | `logging`, `update`, `allow-beta-features`                                                   | For itself                    |

Two terminals watching one session can therefore wear different colours and use
different keys, but never disagree about pane sizes or scrollback.

<Callout>
  The session keeps the settings it read at startup. A terminal that attaches
  later cannot change them from its own `koshi.kdl` — restart the session to
  change a session-owned setting.
</Callout>

## Versions and migration [#versions-and-migration]

Every file declares one top-level `version` with one integer argument, starting
at 1, and no child block:

```kdl
version 1
```

```bash
koshi config check     # validate every present file, change nothing
koshi config migrate   # validate, then apply registered schema steps
```

`check` fails on missing versions, bad KDL, bad values, unknown keys, and
unsupported versions, and reports errors from all files together.

`migrate` validates every file before writing, applies each version step in
order, and validates after each step. Invalid input or a missing step stops
migration before any file is written. Changed files are replaced atomically,
one at a time; symlinks stay and their targets change. A write error lists the
files already completed and marks the failed one as possibly changed.

The current schema version is `1`, so valid version `1` files are reported as
current and left alone. koshi 0.2.0 adds no schema step: a file written for
0.1.0 is still current. Migration never runs during startup and never repairs
invalid config.

## When a file has a mistake [#when-a-file-has-a-mistake]

* **`koshi.kdl` and themes are field-partial.** A bad field keeps its default
  and the other valid fields still apply. koshi logs each skipped field.
* **Keybindings and profiles are all-or-nothing.** Any error drops the whole
  file.
* **Unknown keys name the nearest valid key.** `min-col 2` produces
  ``did you mean `min-cols`?``. `koshi config check` treats that typo as an
  error even though startup would keep the other fields.
* **A missing or invalid theme** falls back to the built-in `default` colours
  and logs why.

## Explain one setting [#explain-one-setting]

```bash
koshi config explain koshi.scrollback.max-lines
```

Keys are file-qualified: `koshi.pane.min-cols`, `keybinding.chord-timeout-ms`,
`theme.colors.accent`, `profile.version`. The command prints which file the
setting belongs to, its default, and what it does.
