# Overview (/docs/v0.4/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.4/configuration/koshi-kdl)           | Theme, pane, scrollback, layout, mouse, copy, terminal, logging, image output, update, beta-feature, session-closing, other-user access, and remote access settings |
| [`themes/<name>.kdl`](/docs/v0.4/configuration/themes)      | Interface colours, selected by `theme "<name>"`                                                                                                                     |
| [`keybinding.kdl`](/docs/v0.4/configuration/keybinding-kdl) | Key bindings and the modes they live in                                                                                                                             |
| [`profile/<name>.kdl`](/docs/v0.4/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`, `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:

```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.4.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` 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.
