# Koshi 0.5.0 — Overview (/docs/v0.5/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.5/configuration/koshi-kdl)           | Theme, pane, scrollback, layout, mouse, copy, terminal input, motion, logging, image output, update, beta-feature, session-closing, other-user access, and remote access settings |
| [`themes/<name>.kdl`](/docs/v0.5/configuration/themes)      | Interface colours, selected by `theme "<name>"`                                                                                                                                   |
| [`keybinding.kdl`](/docs/v0.5/configuration/keybinding-kdl) | Key bindings and the modes they live in                                                                                                                                           |
| [`profile/<name>.kdl`](/docs/v0.5/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`, `image-support`, `reduced-motion`, `stay-in-pane-placement-mode-after-placement`, `remote-reconnect` | Every time it attaches        |
| Every process | `logging`, `update`, `allow-beta-features`, `allow-other-users`, `shared-sessions-dir`, `remote-listen`                                                                                            | For itself                    |

`allow-other-users` is the exception to "once, at startup": the session reads it
again for every connection and every request another user makes, so turning it
off shuts those users out without a restart.

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. The current schema is version 2:

```kdl
version 2
```

```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. Version 1 files migrate to version 2.
An unreadable file, malformed KDL, unsupported version, or missing step stops
this command before any file is written. Unknown keys and bad values are kept
by the migration, though `koshi config check` still reports them.
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.

Session servers and the router also migrate config before reading it at
startup. If that migration fails, they report the error and continue with the
files as they are. Startup migration does not repair bad fields: unknown keys
and bad values remain in the migrated file and `koshi config check` still
rejects them.

## 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` inside `pane`
  produces ``unknown key `pane.min-col`; did you mean `pane.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.
