# Setup
The first run on a terminal opens a full-screen wizard instead of the chat: the
mark assembles, the name lights up, and it asks five questions one at a time,
plus the three that are only sometimes there — the Claude Code login question
where there is no API key and Claude Code is logged in, the Claude skills
question on a machine that has some, and the herdr one on a machine that has
[herdr](hooks.md#herdr).
"First run" means the config file does not say `"setup": "done"` — the marker
the wizard stamps when the last question is answered — rather than that no file
exists, so a config written by hand, or by a build with fewer questions in it,
still gets asked the ones it is missing.
```
codey setup step 1 of 5
◆━━━━━━━━━━━━◇────────────◇────────────◇────────────◇
Which model should the agent use?
▌ ◆ Claude Opus 5 $5 / $25 per Mtok
◇ Claude Sonnet 5 $2 / $10 per Mtok
◇ Claude Haiku 4.5 $1 / $5 per Mtok
◇ custom…
claude-opus-5 · 1.0M token context
↑↓ move enter next esc back ctrl+c cancel
```
| Question | Answers |
| --- | --- |
| Model | whatever `GET /v1/models` returns, plus `custom…` for any id |
| Effort | the API's own `llm.EffortLevels`: `low` `medium` `high` `xhigh` `max` |
| Approvals | ask before every mutating call, or accept them all |
| Web search | `none`, Claude's hosted search, or a command on this machine |
| Theme | `ember` `mint` `iris` `mono` |
| Claude Code login | no, or borrow it when no key is set — asked only where no key or token was given, the endpoint is Anthropic's, and Claude Code is logged in |
| Claude skills | leave them alone, use them in place, or copy them once — asked only where there are some |
| herdr skill | install it, or not — asked only where herdr is |
The last three are the steps that are sometimes not there. The rail knows how
many questions this run is actually asking rather than how many the build has,
so a machine with none of them gets a five-node rail with no gaps in it, and
`step 7 of 8` on a machine with all three counts the questions you are being
asked. The Claude Code login question opens on no, and both answers carry the
same sentence about the terms: the login is issued to Claude Code, and using it
from another client is outside Anthropic's terms for it — so it is a choice
for your own machine, described [under Quick start](install.md#quick-start). Someone with
an API key set is not asked at all, because there is nothing for them to
decide. The answer is `claude_code_auth`; changing it mid-session says it takes
effect on the next start, because the client was built, credential and all,
before the wizard opened.
The herdr answer is also the one that is not a preference: it is an act,
carried out once, so nothing about it is written to the config. It appears when
`HERDR_ENV=1` or `herdr` is on `PATH`. What it installs, and what happens when
the download fails, is [on the hooks page](hooks.md#the-herdr-skill). The Claude skills question is
described under [skills](skills.md#claude-codes-skills); "copy them once" is an act in
the same way, carried out as the wizard closes, and it is the mode rather than
the act that is saved.
It is the same catalogue and the same pricing table `/model` uses, through the
same `GET /v1/models` call, so the two cannot disagree about what a model is
called or what it costs. Where they differ is failure: `/model` reports the
error and closes, because there is a session to go back to. The wizard cannot
do that on a first run, so it falls back to the models this build can price and
says so. `custom…` is there because a gateway may serve something no build has
heard of.
The theme step previews by applying the palette for real — reading a swatch
tells you nothing about what a transcript looks like in it — and it recolours
the whole TUI, pickers and slider included. Cancelling puts the old one back.
Answers land in `~/.config/codey/config.json` (`XDG_CONFIG_HOME` is
honoured):
```json
{
"version": 1,
"model": "claude-opus-5",
"effort": "high",
"approvals": "ask",
"web_search": "custom",
"search_command": "ddgs text -q {{query}} -m {{count}} -nc",
"claude_skills": "use",
"diagnostics": "on",
"claude_code_auth": "off",
"theme": "ember",
"auto_compact": "on",
"setup": "done"
}
```
`claude_code_auth` is `"on"` or `"off"`, and a missing key — or any other word
— means off: the Claude Code login is borrowed only on an explicit `"on"`, or
for one run with `-claude-code-auth`, and `-no-claude-code-auth` beats both.
A missing key is also how Codey knows it has never asked, which is what the
one-time question for someone upgrading reads.
`auto_compact` is the one key neither the wizard nor `/settings` offers a row
for — set it by hand, or pass `-no-auto-compact` for a single run.
`diagnostics` is the one `/settings` has a row for and the wizard does not
ask about: it defaults to on, it runs a tool already installed on this machine,
and nothing it reads leaves the machine, which is the test every question in
that interview is really asking. Both screens
write the whole file but only touch what they asked about, so it survives them.
Set to `"off"`, the conversation is never folded on its own: the window becomes
a wall rather than a trigger, and at `-compact-floor` the turn stops before
sending a request that would not fit,
naming `/compact` and `/clear` as the ways on. The prompt is refused *before* it
joins the history, so compacting and asking again sends it once rather than
twice. `/compact` keeps working throughout — the setting governs the automatic
fold, not the manual one. Anything other than `"on"` or `"off"` is dropped, and
a missing key means on, so a config written before this existed does not
suddenly start stopping the agent.
Nothing in that file is required, and none of it wins an argument with a flag:
precedence is **flag, then config, then the built-in default**, so
`-model claude-sonnet-5` is still a one-run override. `accept-all` saved as a
default is honoured, but `-yolo` can only turn approvals off, never on — a file
should not be able to quietly grant the agent more than the command line did.
`-no-auto-compact` runs the same way round: the flag can only turn the automatic
fold off, and a config that never mentions it leaves it on.
A value this build does not recognise is dropped rather than forwarded to the
API, and effort is checked against `llm.EffortLevels` rather than a second copy
of the same five strings.
`/setup` reopens the wizard at any time. Finishing applies the answers through
the same setters `/model` and `/effort` use, so a setting chosen in the wizard
and the same setting chosen from the prompt cannot come out different — the
wizard just reports them in one line instead of three. It is refused mid-turn:
changing the model while a turn is in flight would finish it on a different
model than it started. A config file that cannot be parsed is reported and then
ignored, and is never overwritten until you finish the wizard.
`/model` and `/effort` change the running session and say "from the next turn
on"; they do not write to the file. The two screens that do are the wizard and
`/settings`.
## Where Codey keeps things
Two directories: one global, one per repository. The second sits in your
working tree and is git-ignored, because sessions and an event log are yours
rather than the project's.
| Path | What |
| --- | --- |
| `~/.config/codey/config.json` | the answers, written by the wizard and `/settings`; [hooks](hooks.md) go here by hand |
| `~/.config/codey/trust.json` | which checkouts' [Claude Code files](mcp.md#trusting-a-project) you trusted, and which version of them |
| `<repo>/.codey/sessions/` | saved conversations, which is what `-resume` and `/resume` read |
| `<repo>/.codey/events.jsonl` | the event log METRICS.md is built from |
| `<repo>/.codey/history` | what has been typed at the prompt here, which `↑` walks back through |
Codey was called `harness` until recently, and both of those used to live under
that name. Neither rename costs you anything. The config is read from
`~/.config/harness/config.json` when there is nothing at the new path, so a
setup you have already done still counts and the wizard stays shut; that is a
read, and the old file is left where it is for an older build to keep using.
The per-repository directory is instead moved once, on the first run in a clone
that still has a `.harness/`, and Codey says so when it does — the event log is
append-only, so leaving half a repository's history under the old name would
quietly corrupt the numbers rather than preserve them. A clone that somehow has
both keeps the newer one and leaves `.harness/` alone.
## /settings
`/settings` is the same settings without the interview: one row each, changed
in place, applied as you move.
```
Settings ↑↓ row · ←→ change · esc done
❯ Model Opus 5 $5 / $25 per Mtok
Effort high default
Approvals Ask me first recommended
Web search No web access default
Diagnostics On default
Claude Code login No, I'll use an API key default
Claude skills Leave them alone default
Theme ember
claude-opus-5 · enter to pick from anthropic
saved to ~/.config/codey/config.json
```
`←→` cycles a row and applies it there and then — the theme repaints under the
panel, the way it previews in the wizard — and `esc` closes and writes the
file. There is no cancel, because there is nothing left to confirm: the session
already has every change. A panel that was only read leaves the file alone, and
so does a value cycled back to where it started.
The rows come from the same option lists the wizard's steps are built from, so
neither screen can invent a name for a theme or a sentence about an effort
level the other does not use. The model row is the exception: its choices come
from the endpoint rather than from this build, so `enter` hands over to the
`/model` picker and lands back here once you have chosen.
The Claude Code login row is there whether or not the wizard asked, so the
opt-in [described under Quick start](install.md#quick-start) can be turned on or back off
without rerunning setup. Like web search, diagnostics and Claude's skills, it
is decided when the session starts, so a change says it takes effect on the
next start rather than pretending to swap the credential under a conversation
already in progress.
What the panel shows is the *session*, not the file — `/effort`, `shift+tab`
and `-yolo` all change a setting without the file hearing about it, and a panel
that disagreed with the status bar two lines below it would be worse than
useless. Only the rows actually touched are written back, which is what keeps a
`-yolo` run from quietly saving "accept everything" as the default for every
run after it. And the setup marker is *not* stamped here: changing a theme is
not answering the setup questions, so someone who has only ever used this panel
is still offered the wizard.
The whole thing is `↑↓` and `enter`, `esc` to go back. Animations collapse to
their final frame under `NO_COLOR`, a `dumb` terminal, or a window under 60×20,
and any key skips the one playing.