Imported from BogdanFloris/arc (
AGENTS.md). Install upstream withnpx skills add BogdanFloris/arc. Copyright stays with the author.
AGENTS.md — ARC (Autonomous Robotic Core)
ARC is a personal AI assistant harness: an always-on Rust daemon, thin clients, event-sourced memory, and multiple LLM providers. docs/DESIGN.md is the architectural authority. If work conflicts with it, stop and raise the conflict. Update the design first; do not silently diverge.
You
Write and speak in plain English. Say only what the reader needs. Lead with the claim, then the evidence. Use short sentences. Do not add filler, repeat known context, or narrate a correction's history. State each correction once. Follow ISO 24495-1: readers should find, understand, and use the information on first reading.
Current phase
See docs/TASKS.md
Workspace
arc-proto— protobuf schemas + prost-generated types. The ONLY place serialized formats are defined..protofiles inarc-proto/proto/, packagearc.v1.arc-core— all logic: event log, projections, providers, memory tools, tracing. Testable without a running daemon.arcd— daemon binary. Thin composition over arc-core. Owns the log, serves the WebSocket.arc— TUI client.arc-voice— voice client (Phase 4; placeholder until then).
New logic goes in arc-core unless it is genuinely binary-specific wiring.
Commands
just build/just test/just fmt/just lint— use these, not raw cargo, so flags stay consistent.just test -p arc-core <filter>narrows a test run. Summaries name failures and the full log undertarget/test-logs/; inspect that log instead of rerunning for output. For rendered frames, useARC_TEST_PASSTHROUGH=1 just test -p arc <filter> -- --nocapture. Seedocs/testing.md.- Run
just fmtandjust lintbefore declaring any task done. Warnings are not acceptable in new code. - Assign disjoint files when delegating. Workspace-wide formatting belongs to integration, after other writers stop. A child reports formatting needed unless its brief explicitly assigns integration and confirms exclusive workspace access. Keep the read-before-edit checks; reread after formatting.
Invariants — never violate
- Append-only. Durable state changes ONLY by appending an
Eventto the log. Never edit or rewrite log bytes. Hand-edits and migrations are events too. - Everything else is a projection. SQLite index, memory state, session trees must be deterministic replays of the log. Any code that writes projection state outside replay is a bug.
- Additive schemas. Never renumber, remove, or repurpose a proto field. Old events must always decode. Reserve numbers when deprecating.
- No vendor SDKs. Providers are plain HTTP + SSE via reqwest behind the
Providertrait. Auth is a swappable layer: API keys, plus the one OAuth exceptiondocs/providers.mdprinciple 2 records (Codex). No other OAuth without amending that principle first. - Secrets never touch the log, backups, traces, or test fixtures.
- Memory is tools, not injection. Identity and the distilled-record index enter automatically; project name/description and an available
AGENTS.mdare local context, not memory. - Identity file is human-owned. Code may propose edits in session output; it never writes
data/identity.md. - Tools run as the user. Project roots supply context and a Bash working directory, not access restrictions. File tools accept absolute paths anywhere the daemon user can reach. Tools run with a scrubbed environment: arcd keeps credentials and child tools never inherit them.
- Sessions are pinned to one provider. Role is chosen at session or job creation and does not change for its lifetime. A mid-session model swap discards the prompt cache, which is ~96% of the workload.
Conventions
-
Rust 2021+, workspace-level deps in root
Cargo.toml; crates opt in to what they use. -
Errors:
thiserrorfor library errors in arc-core,anyhowat binary edges. -
Async: tokio throughout; no other runtimes.
-
Instrumentation: every LLM call, tool call, memory operation, and consolidation pass gets
tracingspans (these become Perfetto traces). If you add a subsystem, instrument it in the same change, not later. -
Comments are rare. Default to none; the code should explain itself. Add one only when code cannot explain:
- an external rule you can't see from here (an SSE framing quirk, what SQLite's
content=tables do, fsync ordering); - a constant whose consequence lives in another file (bumping this rebuilds the index; 20 digits is what makes names sort);
- a line that looks wrong and isn't (dropping this sender is the kill signal; this empty loop reaps tasks).
One line above the code, under ten words, plain English. Never restate a name, never head a section, never argue for the change — that belongs in the commit message. Tests,
thiserrormessages, and generated code document themselves. - an external rule you can't see from here (an SSE framing quirk, what SQLite's
-
Tests live with the code; projection logic must have replay tests (log in → state out, deterministic).
-
In event tests, find events by kind, session, and call id rather than fixed positions. Assert exact sequence numbers only when their values or ordering are the contract under test.
-
To see a TUI screen, render an
Appin a test withrenderedand read it withplain_text(the helpers inarc/src/ui.rstests); never splice a throwaway test in with a script. A change that touches drawing shows the frame in its report. -
ARC's own runtime state lives under the configured data directory —
data/in a checkout,~/.local/state/arc/once installed. User-requested tools can operate elsewhere.
Version control
The repo is jj, colocated with git. Use jj; never run git write commands — a git commit on the detached HEAD makes history jj only half-adopts. The working copy is shared with other work: commit only the paths your task touched (jj commit <paths> -m "..."). Commit when the task says to commit; otherwise leave changes in the working copy for review.
Commit style
Small, single-purpose commits: <crate>: <imperative summary> (e.g. arc-core: add event log segment writer). Schema changes are their own commit, separate from code that uses them.
When unsure
Prefer a smaller diff, a narrow interface over a premature feature, DESIGN.md over cleverness, and asking over assuming. The open questions in docs/DESIGN.md are deliberate. Do not settle them in code.
