Vectrum
Sign In
49 lines · 2.5 KB
# Internals

## Layout

```
cmd/codey        flag parsing, wiring, REPL
internal/llm     Messages API: types, HTTP, SSE, pricing
internal/agent   turn loop, conversation state, compaction, sessions
internal/tools   the tool registry and the tools
internal/diag    language servers and linters, and what they say about an edit
internal/skills   discovery and parsing of SKILL.md, Codey's own and Claude Code's
internal/websearch  the search command, the URL jail, HTML to text
internal/mcp     MCP client: starts the configured servers, offers their tools
internal/config  saved defaults: model, effort, approvals, web search, theme, diagnostics
internal/approval  allow / deny / ask, with shell analysis and Claude Code's permission rules
internal/ccsettings  Claude Code's MCP servers, permission rules and CLAUDE.md, and who may grant what
internal/ask     questions the agent puts to you mid-task, and the tool for it
internal/hooks   the lifecycle, published: fan-out, and the config's commands
internal/herdr   reporting agent state to the herdr pane Codey is running in
internal/attach  pictures pasted into a prompt: clipboard, files, markers
internal/metrics JSONL event log
internal/ui      line-based terminal rendering
internal/acp     Agent Client Protocol: the wire, and its vocabulary
internal/serve   Codey as an agent another program drives, over ACP
internal/tui     full-screen Bubble Tea front end, and the setup wizard
evals            task suite and runner
```

Two rules hold the shape: `agent` never imports `ui` or `tui`, so the eval
runner and the ACP front end can drive the loop headless; and every tool returns `(string, error)`
where the error is text the model reads, not an exception Codey swallows.
A failed edit is a normal event in the transcript.

The TUI obeys the first rule through two one-way hatches. Events reach it via
`agent.Observe`, forwarded into the Bubble Tea loop with `Program.Send`, which
is safe from the agent's goroutine. Approvals go out the same way and then
block the agent on a reply channel until a key arrives, and questions take the
same hatch with an answer on the way back. Those channels are buffered and the
wait honours the turn's context, so neither side can strand the other.

## Evals

```bash
./evals/selftest.sh    # no API calls: checks the tasks measure something
go run ./evals -n 3    # the real thing
```

Ten tasks, a fresh temp directory per run, full transcripts under
`evals/runs/<timestamp>/`. See [METRICS.md](../../METRICS.md).