A YAML-native AI coding agent harness, shipped as a single Go binary.
Define agents, skills, guardrails, and routing in YAML. Run them from the terminal, a headless CLI, or an HTTP API, backed by a multi-language code graph, persistent memory, and a security floor that project config can't weaken.
Documentation · Install · Quick start · Architecture · Releases
Chronos Code is an AI coding agent built on the Chronos agentic framework. You talk to one primary agent, chronos-code. It spawns specialists (coder, reviewer, debugger, and others) when needed, or when you @mention one.
Everything you'd normally tune in code lives in YAML: agents, skills, guardrails, security policy, model routing, and MCP servers. It works on first run with embedded defaults. chronos-code init exports those defaults into your project so you can edit them.
| 🧩 YAML-first | Agents, skills, guardrails, security policy, routing, and MCP servers are declared in YAML, not Go. |
| 🤝 Primary agent + specialists | chronos-code owns the conversation. Specialists run via spawn_subagent or @agent_id. |
| 🕸️ Code graph | Go via go/parser, plus 17 languages through a pure-Go tree-sitter runtime, with cross-repo federation. Included in every build. |
| 🪜 Tiered routing | Graph tools (T0) first, then cheap models (T1), then frontier models (T2). Complexity paths cap tool-call counts. |
| 🧠 Sessions & layered memory | Resumable SQLite sessions with compaction checkpoints. Episodic, procedural, semantic, and org-scoped memory. |
| 🛡️ Security floor | Injection detection, secret scanning, PII filtering, and cost caps. Project policy and --yolo can't weaken them. |
| 🔌 MCP, both ways | Consumes stdio and HTTPS SSE servers from .mcp.json, and serves its own code graph to other MCP hosts. |
| 📈 Review-gated learning | Turns session traces into YAML suggestions that you accept or reject. Nothing is applied automatically. |
| 🖥️ Three surfaces, one runtime | Interactive TUI, headless run, and an HTTP API (serve) all share one orchestrator. |
Prebuilt binaries for Linux, macOS, and Windows (amd64 and arm64) come with every tagged release.
macOS / Linux
curl -fsSL https://raw.githubusercontent.com/spawn08/chronos-code/main/scripts/install.sh | bashWindows (PowerShell)
irm https://raw.githubusercontent.com/spawn08/chronos-code/main/scripts/install.ps1 | iexThe installers detect your OS and architecture, download the matching archive, check it against the release's SHA256SUMS, and install chronos-code to ~/.local/bin.
| Variable | Purpose | Default |
|---|---|---|
VERSION |
Release tag to install, e.g. v0.7.0 |
latest |
INSTALL_DIR |
Install location | ~/.local/bin |
On Windows, use $env:VERSION / $env:INSTALL_DIR. If the script warns that the install directory isn't on PATH, add it.
Build from source
Requirements: Go 1.26+. No cgo needed; every build is pure Go. You also need a Chronos checkout next to this repo (or edit the replace directive in go.mod).
git clone https://github.com/spawn08/chronos.git
git clone https://github.com/spawn08/chronos-code.git
cd chronos-code
make build # → bin/chronos-code
make install # → $GOPATH/binEvery build, including release archives, ships the same parsers (Go plus 17 tree-sitter languages), SQLite sessions and FTS, memory, hooks, and the TUI. CI enforces a 56 MiB size limit on the binary.
Optional build tags:
| Tag | Adds |
|---|---|
lsp |
lsp_diagnostics, lsp_hover, lsp_references, lsp_rename_preview, backed by gopls, typescript-language-server, pyright-langserver, or rust-analyzer. Servers start lazily; a missing server doesn't stop anything else. |
postgres |
PostgreSQL storage backend (SQLite is the default). |
chronos-code login # configure a provider (Anthropic, OpenAI, Azure, …)
chronos-code # launch the interactive TUIA few more common starting points:
chronos-code run "add table-driven tests for internal/router" # one-shot, then exit
chronos-code run --json "summarize this repo" # machine-readable output
chronos-code init # export editable YAML to .chronos-code/
chronos-code serve # HTTP API on :8430In the TUI, mention a specialist to skip the router:
@reviewer check my last commit
@debugger why is TestAuth failing
@security-auditor threat-model the HTTP handlers
/ppd migrate the config loader to the new schema
/ppd <task> (or mentioning "PPD" in a request) runs the task as a rolling plan: planner proposes the next few steps with a verification command each, the primary agent tracks them with update_plan, completes each only after its check passes, and re-plans until the request is verified. The checklist is saved with the session, so /resume picks it back up.
cmd/chronos-code is a thin main, and internal/cli dispatches commands. The REPL, headless run, and serve each build a single Orchestrator. The orchestrator resolves configuration, indexes the workspace graph, wires up Chronos agents, and executes turns. The TUI and HTTP server are front ends to that runtime; they never call Chronos directly.
Chronos (github.com/spawn08/chronos) is used as a library: agent SDK, harness, tool runtime, streaming, and storage adapters. Chronos Code builds on its agent loop instead of reimplementing it.
- Surface. The CLI starts a REPL, a one-shot
run, orserve. - Orchestrator. Loads config, agents, skills, security policy, routing, graph, session, and memory stores.
- Router. Classifies the message with YAML regexes (T0), optionally checked by a cheap model (T1). It picks a model tier and an implementation path (
low/medium/high).chronos-codekeeps the conversation unless you@mentiona specialist. - Chronos agent loop. Order of escalation: graph tools (T0), then ranged file reads (T1), then shell and writes (T2). Guardrails and the security policy wrap every tool call. If an MCP server fails, healthy servers and chat keep working.
- Post-turn. The session is persisted, explicit memory intents are written, and learning may emit a pending suggestion for review.
Package layout
| Layer | Package | Role |
|---|---|---|
| Entry | cmd/chronos-code |
Binary main |
| Surfaces | internal/cli |
Command dispatch (no Cobra) |
internal/tui |
Bubble Tea REPL: streaming, approvals, slash commands | |
internal/server |
HTTP API (/v1/chat, sessions, memory, teams) |
|
| Core | internal/orchestrator |
Agent lifecycle, routing application, turn execution |
internal/config |
YAML discovery and merge | |
internal/defaults |
Embedded agents, skills, guardrails, routing (go:embed) |
|
internal/router |
Intent patterns, model routing, complexity paths, PPD policy | |
| Workspace | internal/workspace |
Project root, ignore rules, file indexing |
internal/graph |
Graph tools served by the chronos indexer (indexer) |
|
internal/projectdocs |
Watches project docs for context | |
internal/lsp |
Optional lsp tag: diagnostics, hover, references, rename preview |
|
| Context | internal/session |
Session persistence and resume |
internal/memory |
Local YAML memory (project / user / feedback) | |
internal/skills |
Skill discovery and selection | |
internal/activation, internal/attention, internal/incctx, internal/toolcompress |
Context window budgeting and compression | |
| Safety | internal/security |
Path/shell policy, permissions, hooks, sandbox |
internal/guardrail |
YAML guardrail engine | |
internal/verification |
Report/enforce verification policy | |
internal/budget |
Token and USD caps | |
internal/auth |
API keys, OAuth, keychain, SSO | |
| Integrations | internal/mcpdiscover |
.mcp.json load, test, redact, runtime |
internal/learning |
Trace → suggestion YAML; applied only after review | |
internal/teambuilder |
Multi-agent team definitions | |
internal/eval |
Offline token-efficiency and PPD eval harness |
| Agent | Role | Typical tier |
|---|---|---|
chronos-code |
Primary conversation agent: orients, routes, synthesizes | Frontier |
coder |
Implement, test, iterate | Frontier |
planner |
Next verifiable frontier of steps; re-plans from results | Frontier |
reviewer |
Bugs, style, simplification | Frontier |
debugger |
Reproduce first, test hypotheses, propose a verified fix | Frontier |
security-auditor |
Threat model, scan, validate findings, propose fixes | Frontier |
architect |
Design and structure | Frontier |
researcher |
Read-only search | Cheap |
explainer |
Explain code and concepts | Cheap |
Each agent is a YAML file. Run chronos-code init and edit .chronos-code/agents/*.yaml to change them or add your own.
.chronos-code/
├── config.yaml # model, storage, memory, learning, verification
├── routing.yaml # intents, models, complexity paths, PPD
├── security.yaml # path allowlists, shell restrictions, MCP trust
├── agents/ # chronos-code.yaml, coder.yaml, …
├── skills/
├── guardrails/
├── memory/ # project.yaml, user.yaml, feedback.yaml
└── learned/ # pending learning suggestions
.mcp.json # project MCP servers (repo root)
Runtime databases live under ~/.chronos-code/projects/<name>-<id>/ (override the root with CHRONOS_CODE_DATA_HOME). Existing project databases are imported from verified SQLite snapshots, and the originals are kept. A shared, partitioned ~/.chronos-code/memory.db provides user and organization recall across projects. See Harness reliability, layered memory, and hooks.
Highest to lowest:
- CLI flags
- Provider and server environment variables (
CHRONOS_CODE_PROVIDER,CHRONOS_CODE_MODEL, …) .chronos-code/config.yaml(project)~/.chronos-code/config.yaml(user)- Embedded defaults
verification:
mode: report # report | enforce: enforce refuses "done" without current evidence
defaults:
reasoning:
strategy: cot
native: true # Anthropic extended thinking / OpenAI reasoning effort (off by default)
effort: medium # low | medium | high
budget_tokens: 4096
summary: true # stream thinking summaries in the TUIModel and provider selection
--providerand--modeloverride the primary agent for the current process.CHRONOS_CODE_PROVIDER/CHRONOS_CODE_MODELdo the same when the flag is absent. Flags always win over YAML and request-time routing.- If you switch provider without a model, a model is reused only when that provider already has one configured on a resolved agent. Otherwise the command fails and asks for
--model, so a provider is never paired with a model it can't run. - At startup, if the configured provider has no credential and exactly one other provider is authorized, Chronos Code switches to that provider. With several authorized providers, the YAML choice is kept, unless Azure is one of them and
AZURE_OPENAI_ENDPOINT,AZURE_OPENAI_BASE_URL, orAZURE_OPENAI_DEPLOYMENTis set, in which case Azure is used. An Azure deployment with no credential anywhere also selects Azure, so a missing key is reported against Azure rather than as an Anthropic authentication failure. --model <id>without--providerpicks the provider that serves that model. When the model is unlisted (a custom Azure deployment name, for example) and the configured provider has no credential, the one authorized provider is used. Useazure/<deployment>or--provider azureto be explicit.chronos-code models [provider]lists live Anthropic, OpenAI, or Azure models when you're authorized, and labels static fallback results. In the TUI,/modellists models and Tab completes/model <provider> <id>.- Azure needs an endpoint and a real deployment name (
AZURE_OPENAI_DEPLOYMENTor--model). If you have only the key and endpoint, startup fails with a message saying so;chronos-code models azureandconfig showstill work to help you find it. In the TUI,/model azure-openai …(orazure openai) matches Azure entries, and live Azure models are added to the suggestions once fetched. chronos-code config showprints the effective primary agent, provider, and model, and where each value came from.
Rollback switches
Each switch works on its own. Sessions, memories, learned patterns, and .mcp.json stay on disk:
session:
recall_prior_summaries: false
context_report: false
learning:
pattern_injection: false
mcp:
discovery_enabled: falseRestart after changing these. memory.enabled: false stops both persistence and recall. The embedded security floor stays on regardless. If you need to reverse a .mcp.json change, restore it from the atomic-write backup in the same directory. See the rollback guide.
| Capability | Status |
|---|---|
| Code graph (Go + 17 tree-sitter languages), SQLite sessions, deterministic YAML memory | ✅ Default |
| Verification | ✅ report by default · enforce opt-in |
| Learning suggestions | ✅ On, human review required (auto_distill: false) |
| PostgreSQL storage | 🔧 Optional postgres build |
| LSP tools | 🔧 Optional lsp build |
| Delivery-strategy policy | 👀 ppd.mode: shadow (default) runs explicit /ppd requests as a rolling plan and only hints otherwise · enabled runs every qualifying request that way · disabled skips |
| Vector recall, branchable sessions | 🗺️ Roadmap |
| Command | Effect |
|---|---|
/login · Ctrl+L |
Claude Code / enterprise reuse, Codex/ChatGPT, API keys, OAuth |
/whoami |
Show the effective credential source |
/model |
Pick a model (Tab to autocomplete) |
/think |
Toggle native thinking |
/context |
Context sources, counts, budgets, and omission reasons (never memory bodies or secrets) |
/resume |
Continue the latest session (--resume <id> from the CLI) |
/session · /session list |
Show the full session ID and resume command, or browse saved sessions |
/compact |
Summarize history |
/rewind |
Undo the last file_write |
/plan on · /plan off |
Plan read-only; approve the plan (y, or a to auto-accept edits) and implementation starts automatically. --plan-mode starts in plan mode; headless runs auto-approve |
/learn |
Review pending learning suggestions |
/copy · Ctrl+Y · Ctrl+Shift+C |
Copy the last reply (/copy visible, /copy all, /copy code [n]) |
Ctrl+O |
Expand collapsed tool calls |
/mouse |
Toggle between wheel scrolling and unshifted drag-select |
Session resume: The TUI prints the full session ID and chronos-code --resume <id> at startup, after changing sessions, and after returning to your shell. The header shows the current ID, shortened when space is limited. /session shows the full details at any time.
Working status: The footer shows an animated indicator, the current activity or tool, and elapsed time throughout a run. Question and permission dialogs show a waiting state. Tool details reuse cached rendering, and long inline plans show a bounded preview with the full content available through /inspect. A scoped-instruction deferral appears as loading project instructions while the harness prepares the next model call and retry.
Scrolling and selection: The mouse wheel scrolls the transcript by default. Shift-drag selects text, which you copy with your terminal's shortcut. Streaming doesn't repaint the pane while you're scrolled away from the live tail, so your selection stays put until Ctrl+End.
Clarification dialogs: Agents are guided to resolve routine choices themselves and ask a small number of high-information questions for essential user decisions. When a decision needs your input, the agent can call ask_user_question to show up to four questions. Use arrow keys or Tab to move, Space to toggle multi-select choices, and Enter to answer and advance. Select Other to type a custom answer. Recommended options are marked. Escape cancels the questions; Ctrl+C interrupts the running task. Answers return to the agent in the same run. Headless run and HTTP serve return an input_required tool result so the agent can explain the missing decision and wait for a follow-up.
Memory intents: Only explicit forms persist: remember <category>: <fact>, forget: <mem_ID>, recall-past: <query>. Casual use of "remember", "always", or "never" does not.
- Security floor. The embedded floor can't be weakened by project policy or
--yolo.--yoloauto-approves tools that policy already allows; it never overrides deny rules or destructive-action confirmations. - Cost caps.
--budget <usd>sets a USD cap. If pricing for the model is unknown, a positive cap fails closed before any provider call. - Consuming MCP. Manage
.mcp.jsonwithchronos-code mcp add | list | test | remove. Only stdio and HTTPS SSE transports are accepted. Arguments or query values that look like credentials must be${ENV_VAR}references, and they are redacted in output. MCP tools are namespaced, require approval by default, and are closed on cleanup. Servers that are denied, untrusted, malformed, or unavailable don't block anything else. - Serving MCP.
chronos-code indexer mcpexposes the read-only code graph tools to other MCP hosts over stdio. Repositories listed inworkspace.indexer.federation(or passed via--repo [name=]dir) are indexed separately. Symbol lookup, search, and callers follow imports and API contracts across them. See docs/chronos-indexer.md.
chronos-code Start the interactive REPL
chronos-code run <message> Run one task, then exit
chronos-code init Export .chronos-code/ into the project
chronos-code login | logout | whoami Manage provider credentials
chronos-code providers List resolvable providers
chronos-code models [provider] Query live models (labeled static fallback)
chronos-code agents list List resolved agents
chronos-code config show | validate Inspect resolved config
chronos-code session list | delete | export
chronos-code memory list | search | forget
chronos-code mcp add | list | test | remove
chronos-code indexer mcp [--repo DIR] Serve code graph tools over MCP stdio
chronos-code learn suggest | list | show | accept | reject
chronos-code skills list | show
chronos-code team list | run
chronos-code eval run | ppd
chronos-code serve Start the HTTP API server
chronos-code version
Global flags: -c/--config, --provider <name>, --model <id>, --debug, --stream / --no-stream, --permission-mode, --yolo, --dangerously-skip-permissions (approve everything that would ask; policy blocks still apply — sandboxes/CI only), --plan-mode, --budget <usd>, --resume <session-id>, --json (headless).
make build # bin/chronos-code
make test # go test -race
make lint
make eval # token-efficiency eval against benchmark/eval/baseline.json
make size-check # release binary size gate (56 MiB)
make fmt vet tidyEvery push and pull request to main runs CI: build, lint, go test -race, the release-binary size gate, and the token-efficiency eval.
Benchmarks and evaluation
make evalreplays offline fixtures and compares paired totals withbenchmark/eval/baseline.json. It fails on contract errors, stale baseline totals, or a regression of more than 10% in optimized tokens.benchmark/eval/report.mdcomes from synthetic fixture replay. It is not a comparison with any external tool, so it can't support a performance claim on its own; that requires paired model runs on the same tasks, model, corpus revision, and success gate.benchmark/ppd/results.jsonis markedinvalidbecause no real model was invoked. It supports no PPD quality or efficiency claim, andchronos-code eval ppd --reportfails closed on it.--validate-onlychecks registration, not efficacy.- The
ppdconfig key remains for compatibility. Embedded routing setsppd.mode: shadow: explicit PPD requests get the interactive rolling-plan loop (planner,update_plan, per-step verification, re-plan), and other qualifying requests get an advisory hint.ppd.mode: enabledgives the rolling-plan loop to every qualifying request.
Chronos Code follows semantic versioning. Pushing a v* tag triggers the release workflow, which:
- Runs the test suite against the pinned Chronos revision (
release/chronos.version) - Builds
linux,darwin, andwindowsbinaries foramd64andarm64 - Generates an SPDX SBOM for each binary
- Writes a
SHA256SUMSmanifest, attests build provenance, and signs the manifest with Sigstore cosign (keyless) - Publishes everything to a GitHub Release
Local builds get their version from git describe; untagged commits report a dev version with a commit suffix. Check yours with chronos-code version.
Full user documentation, covering getting started, everyday use, plan mode, headless automation, configuration, agents and skills, permissions, and best practices, is at spawn08.github.io/chronos-code. The source is in docs/.
Released under the same license as Chronos.