Skip to content

How anchor works

anchor is a minimal coding harness: one model working in one directory through a few tools, plus sub-agents, skills and MCP. It’s written in C# on .NET 10 and Microsoft.Extensions.AI, and it stays under 15,000 lines of source. A new feature has to justify every line it adds.

The full design notes are in DESIGN.md. This page is the short version.

anchor drives the model directly instead of handing tool calls to a library’s automatic loop. A turn ends when the model answers in text. There’s no cap on rounds; instead, a loop guard stops a turn that repeats the same call 5 times or fails 3 calls in a row.

Tools reach the disk, processes and MCP servers only through one class, the Gate. Every action takes the same path:

policy (allow / ask / deny) → approval (if ask) → effect

A test fails if any tool touches files or starts a process directly. Paths are checked where they really point, with symlinks resolved. A write shows its diff first, and a file that changes while you look at the diff is never overwritten.

Writes and commands that aren’t provably read-only ask first. The sandbox is the directory anchor was started in. --yolo turns the questions off.

4. Hard denials that –yolo doesn’t lift

Section titled “4. Hard denials that –yolo doesn’t lift”

Secret and credential files, privilege escalation, raw disk writes, deleting system directories, and piping downloads into a shell are always denied. Secret values are masked in all output the model sees. See Safety and approvals.

The core emits typed events, and a renderer draws them. The terminal UI, -p and --json are three renderers over the same events, which is why the JSON protocol exposes everything the terminal shows.

Every message carries its kind (user, assistant, tool, summary, note), so anchor never parses text prefixes to tell them apart. That’s what makes compaction and session replay reliable.

src/Anchor/
Core/Agent.cs the turn loop
Core/Gate.cs the only path to disk, processes and MCP tools
Core/Policy.cs pure allow / ask / deny rules
Core/ShellCommand.cs a conservative bash reader: hard denials, read-only commands
Core/Compactor.cs summarize, trim, drop rounds
Core/Until.cs work until a check command passes
Core/SessionLog.cs append-only JSONL sessions
Core/SubAgentRunner.cs fresh agents per task in the background, same gate
Tools/ read, list, glob, grep, write, edit, shell, agent tools, skill, ask_user
Mcp/ config and trust, background connections, OAuth, keychain
Providers/ Anthropic (official SDK, cached) and OpenAI-compatible, with retries
Cli/ REPL, rendering, approvals, -p and --json

Multi-agent orchestration (graphs, routing, validators), plans, memory, telemetry and a plugin registry. Any of these could be added later as a tool behind the gate.

Deciding when work is done is left to a command you choose, not to a model. That’s why /until takes a check command rather than a goal for a judge model to evaluate.

  • Tests use a scripted fake model and never call a live LLM.
  • Security tests use an approver that always says yes, so they prove the policy holds on its own.
  • Each milestone is also checked by hand against a real model.