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.
"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. 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. The Claude skills question is
described under 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):
{
"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.
Two directories: one global, one per repository. Conversations are kept in the
global one, so they are not scattered across every checkout you have opened
and do not vanish with a git clean. The per-repository one sits in your
working tree and is git-ignored, because an event log is yours rather than the
project's.
| Path | What |
|---|---|
~/.config/codey/config.json | the answers, written by the wizard and /settings; hooks go here by hand |
~/.config/codey/trust.json | which checkouts' Claude Code settings you trusted, and which version of them |
~/.config/chats/<repo>/ | saved conversations for that checkout, which is what -resume and /resume read; <repo> is its path with / turned into - |
~/.config/chats/<repo>/history | what has been typed at the prompt there, which ↑ walks back through |
<repo>/.codey/events.jsonl | the event log METRICS.md is built from |
Older builds kept the conversations in <repo>/.codey/sessions/ and the prompt
history in <repo>/.codey/history. The first run in such a checkout moves them
to ~/.config/chats/ and says so; a file already at the new path is never
overwritten, and the old copy is left where it was.
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 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 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.