# Koshi 0.2.0 — koshi.kdl (/docs/v0.2/configuration/koshi-kdl)



`koshi.kdl` holds the app settings. It sits directly in the
[config directory](/docs/v0.2/configuration#where-the-files-go). `version` is
required; everything else is optional. `theme`, `allow-beta-features`, and
`auto-close-session` are top-level; the rest are grouped into blocks.

<Callout>
  A bad field is skipped at startup, keeps its default, and is logged — the rest
  of the file still applies. The exception is `update`: a bad value there drops
  the whole file for that launch. `koshi config check` rejects bad fields
  outright.
</Callout>

Each section says who reads it: the **session**, which took its copy when it
started, or your **terminal**, which reads its own file every time it attaches.
See [Whose setting is it](/docs/v0.2/configuration#whose-setting-is-it).

## theme [#theme]

**Read by your terminal.** Two terminals showing one session can wear different
colours.

`theme "midnight"` loads `themes/midnight.kdl`. A missing, invalid, or omitted
theme — or `"default"` — uses the built-in colours. See
[Themes](/docs/v0.2/configuration/themes).

| Key     | Value                                                   | Default     | Since   |
| ------- | ------------------------------------------------------- | ----------- | ------- |
| `theme` | string — the `themes/<name>.kdl` to use, without `.kdl` | `"default"` | ≥ 0.1.0 |

## pane [#pane]

**Read by the session.** Panes are the session's, so every terminal sees the
same sizes.

| Key        | Value                                          | Default | Since   |
| ---------- | ---------------------------------------------- | ------- | ------- |
| `min-cols` | integer — smallest width a pane may shrink to  | `2`     | ≥ 0.1.0 |
| `min-rows` | integer — smallest height a pane may shrink to | `1`     | ≥ 0.1.0 |

## scrollback [#scrollback]

**Read by the session**, including `scroll-on-input`, so every attached
terminal gets the same answer.

| Key               | Value                                                                        | Default             | Since   |
| ----------------- | ---------------------------------------------------------------------------- | ------------------- | ------- |
| `max-lines`       | integer — lines of history kept per pane (negative means `0`: no scrollback) | `10000`             | ≥ 0.1.0 |
| `max-bytes`       | integer — byte ceiling on that history (negative means `0`)                  | `33554432` (32 MiB) | ≥ 0.1.0 |
| `scroll-on-input` | boolean — typing while scrolled up snaps the view back to the newest line    | `#true`             | ≥ 0.1.0 |

`scroll-on-input #false` keeps the view parked while the input still goes
through. Only the primary screen follows; the alternate screen is left to the
full-screen program on it.

## layout [#layout]

**Read by your terminal.** Two terminals viewing one session can differ.

| Key                  | Value                                                                                              | Default   | Since   |
| -------------------- | -------------------------------------------------------------------------------------------------- | --------- | ------- |
| `new-pane-direction` | `"left"` \| `"right"` \| `"up"` \| `"down"` — where a new pane opens when the command does not say | `"right"` | ≥ 0.1.0 |

The `new-pane-<side>` keybindings and an explicit `--direction` name their own
side and ignore this.

## mouse [#mouse]

**Read by your terminal** — the mouse is its own.

| Key             | Value                                     | Default               | Since   |
| --------------- | ----------------------------------------- | --------------------- | ------- |
| `border-resize` | boolean — drag a pane border to resize it | `#true`               | ≥ 0.1.0 |
| `scroll-lines`  | integer — lines per wheel notch           | `3`                   | ≥ 0.1.0 |
| `wheel`         | `"scroll-scrollback"` \| `"ignore"`       | `"scroll-scrollback"` | ≥ 0.1.0 |

## copy [#copy]

**Read by your terminal** — the copy is made where the selection was dragged.

| Key                        | Value                                            | Default | Since   |
| -------------------------- | ------------------------------------------------ | ------- | ------- |
| `trim-trailing-whitespace` | boolean — drop trailing blanks from copied lines | `#true` | ≥ 0.1.0 |

## terminal [#terminal]

**Read by the session** — it starts the programs in the panes, so it decides
what they are told.

| Key             | Value                                             | Default                                | Since   |
| --------------- | ------------------------------------------------- | -------------------------------------- | ------- |
| `term`          | string — the `TERM` value child programs see      | `"xterm-256color"`                     | ≥ 0.1.0 |
| `colorterm`     | string — the `COLORTERM` value child programs see | `"truecolor"`                          | ≥ 0.1.0 |
| `default-shell` | string — the shell to launch                      | your `$SHELL` (`%COMSPEC%` on Windows) | ≥ 0.1.0 |

## logging [#logging]

**Read by every koshi process** for its own log file. koshi writes
`logs/koshi-log-<session-id>.log` below the state directory. Disabled logging
creates no file at all.

| Key       | Value                                                          | Default     | Since   |
| --------- | -------------------------------------------------------------- | ----------- | ------- |
| `enabled` | boolean — write a log file at all                              | `#false`    | ≥ 0.1.0 |
| `level`   | `"info"` \| `"warning"` \| `"error"` — lowest severity written | `"warning"` | ≥ 0.1.0 |
| `format`  | `"pretty"` \| `"json"`                                         | `"pretty"`  | ≥ 0.1.0 |

`info` includes normal lifecycle events, `warning` recoverable problems, and
`error` failures that stop koshi. Each level includes the more severe ones.
Logs store ids and byte counts — never typed or copied text. Crash reports are
separate and always on; see
[Logging and crash reports](/docs/v0.2/using/logging).

## update [#update]

**Read by every installed koshi** for itself.

<Callout type="warn">
  A bad value in this block drops the whole `koshi.kdl` for that launch, not just
  the field.
</Callout>

| Key                   | Value                                               | Default  | Since   |
| --------------------- | --------------------------------------------------- | -------- | ------- |
| `auto-check`          | boolean — check GitHub for a newer koshi at startup | `#true`  | ≥ 0.1.0 |
| `check-interval-days` | integer — days between checks                       | `14`     | ≥ 0.1.0 |
| `allow-prerelease`    | boolean — offer pre-release builds too              | `#false` | ≥ 0.1.0 |

## allow-beta-features [#allow-beta-features]

**Read by every koshi process** when it starts, so the interactive session and
the `koshi` commands you type all get the same answer.

Some features are finished code that has not been used enough to be turned on
for everyone. They are off unless you say otherwise. Turning this on runs all
of them; there is no per-feature switch.

A beta feature you have not turned on refuses and says so, naming itself and
the line to add:

```text
koshi: `koshi <command>` is a beta feature and did nothing; add a top-level
`allow-beta-features #true` line to koshi.kdl to run it
```

Nothing crashes and nothing is lost; the command exits non-zero having done
nothing.

<Callout>
  No feature in 0.2.0 is marked beta. Every command runs whether the setting is
  on or off.
</Callout>

| Key                   | Value                                    | Default  | Since   |
| --------------------- | ---------------------------------------- | -------- | ------- |
| `allow-beta-features` | boolean — run features still marked beta | `#false` | ≥ 0.2.0 |

## auto-close-session [#auto-close-session]

**Read by the session**, from the `koshi.kdl` it saw when it started. A
terminal attaching later cannot change it.

A terminal leaving a session normally leaves the session running with nothing
attached, so `koshi attach` can rejoin it later. Turning this on ends the
session once the last terminal leaves.

koshi counts the terminals after the one that left is gone. If any are still
attached, the session keeps running; only an empty session ends.

Ending it asks every program in the session to stop, waits up to three seconds,
then kills whatever has not exited — long enough for a shell to write its
history and an editor its swap file. On Windows a program cannot be asked to
stop, so everything is killed at once. `koshi kill-session` skips the wait.

Every way of leaving counts: the quit keybinding (<kbd>\<C-q></kbd> by
default), `koshi detach`, closing the terminal, and moving the terminal to
another session with `koshi attach <session>` from inside a pane.

| Key                  | Value                                                   | Default  | Since   |
| -------------------- | ------------------------------------------------------- | -------- | ------- |
| `auto-close-session` | boolean — end the session when its last terminal leaves | `#false` | ≥ 0.2.0 |

## Every setting at its default [#every-setting-at-its-default]

`default-shell` is commented out because its default comes from `$SHELL` or
`%COMSPEC%`.

```kdl title="koshi.kdl"
// koshi.kdl — the complete default configuration.
version 1

theme "default"
allow-beta-features #false
auto-close-session #false

pane {
    min-cols 2
    min-rows 1
}

scrollback {
    max-lines 10000
    max-bytes 33554432       // 32 MiB
    scroll-on-input #true
}

layout {
    new-pane-direction "right"
}

mouse {
    border-resize #true
    scroll-lines 3
    wheel "scroll-scrollback"
}

copy {
    trim-trailing-whitespace #true
}

terminal {
    term "xterm-256color"
    colorterm "truecolor"
    // default-shell "/bin/zsh"  // optional override
}

logging {
    enabled #false
    level "warning"
    format "pretty"
}

update {
    auto-check #true
    check-interval-days 14
    allow-prerelease #false
}
```
