# Profiles (/docs/v0.1/configuration/profiles)



A profile is a saved session layout. Load one by name:

```bash
koshi --profile dev
```

That reads `profile/dev.kdl` instead of opening a single shell pane. The file
lives in a `profile/` subdirectory of the
[config directory](/docs/v0.1/configuration#where-the-files-go).

<Callout type="warn">
  If anything in the profile is wrong, the whole profile is dropped and koshi
  starts one shell instead. A missing named profile falls back the same way.
  `koshi config check` validates every saved profile.
</Callout>

## Structure [#structure]

A profile is one or more `tab` blocks, plus a required `version`.

| Node               | Meaning                                        | Since   |
| ------------------ | ---------------------------------------------- | ------- |
| `version <n>`      | Required schema version                        | ≥ 0.1.0 |
| `tab { … }`        | One tab; its children are the pane arrangement | ≥ 0.1.0 |
| `pane { … }`       | A terminal pane                                | ≥ 0.1.0 |
| `horizontal { … }` | Split its children left to right               | ≥ 0.1.0 |
| `vertical { … }`   | Split its children top to bottom               | ≥ 0.1.0 |
| `stack { … }`      | Children share one rectangle; one is expanded  | ≥ 0.1.0 |

## Inside a pane [#inside-a-pane]

| Key                     | Value                                                                      | Since   |
| ----------------------- | -------------------------------------------------------------------------- | ------- |
| `command "prog" "arg"…` | The program and its arguments. Omit for the default shell                  | ≥ 0.1.0 |
| `cwd "/path"`           | Working directory, used as written — absolute, and `~` is **not** expanded | ≥ 0.1.0 |
| `env "NAME" "VALUE"`    | One environment variable for this pane; repeatable                         | ≥ 0.1.0 |
| `focus`                 | Start with this pane focused; one per tab                                  | ≥ 0.1.0 |

Omitting `cwd` inherits the directory koshi was launched from. Launching from
`/home/me/proj` starts that pane there; an explicit `cwd "/srv/app"` still
wins.

## Sizing [#sizing]

Sizing keys are only valid on a direct child of `horizontal` or `vertical`.
Without any, children share the space equally.

| Key                      | Value                                            | Since   |
| ------------------------ | ------------------------------------------------ | ------- |
| `size 40` / `size "60%"` | A fixed size in cells, or a percent of the split | ≥ 0.1.0 |
| `weight 2`               | A relative share of the leftover space           | ≥ 0.1.0 |
| `min 10`                 | Never shrink below this many cells               | ≥ 0.1.0 |
| `preferred 30`           | The size to aim for when there is room           | ≥ 0.1.0 |

## Stacks and focus [#stacks-and-focus]

Inside a `stack`, `expanded` marks the one member shown open; the rest collapse
to a one-row header.

`focus` inside a `pane` marks the pane that starts focused — one per tab.
`focus` as a direct child of a `tab` marks the tab that starts active — one per
profile. Without either, the first pane of the first tab starts focused.

## A profile using every feature [#a-profile-using-every-feature]

```kdl title="profile/dev.kdl"
// profile/dev.kdl — a complete profile using every feature.
version 1

tab {
    // a horizontal split: editor on the left (60%), a tools column (40%) right
    horizontal {
        pane {
            command "nvim" "src/main.rs"    // program + its arguments
            cwd "/home/me/proj"             // absolute path (~ is not expanded)
            env "RUST_LOG" "debug"          // one env var...
            env "NO_COLOR" "1"              // ...repeat for more
            size "60%"                      // fixed share of the split
            focus                           // this pane starts focused
        }
        vertical {
            size "40%"
            pane {
                command "cargo" "watch" "-x" "test"
                cwd "/home/me/proj"
                weight 2                     // twice the leftover share of...
                min 5                        // ...but never below 5 rows,
                preferred 20                 // ...aiming for 20 when there's room
            }
            pane {
                cwd "/home/me/proj"          // no command → the default shell
                weight 1
            }
        }
    }
}

tab {
    focus                                    // this tab starts active

    // a stack: members share one rectangle; `expanded` is the open one
    stack {
        pane {
            command "journalctl" "-f"
        }
        pane {
            command "htop"
            expanded                         // this member starts open
        }
    }
}
```
