You've built Claude Code
You started with a while loop and an echo tool. You're ending with a terminal coding agent that reads, writes, and edits files, runs bash, asks permission, confines itself to a sandbox, spawns subagents, speaks MCP as both client and server, fires hooks, loads skills, compacts its own context, plans before it acts, and fixes real repositories — graded with zero LLM judgment, the same way every single run. That's not a toy. That's the architecture behind Claude Code, Cursor's agent mode, Aider, and OpenHands, in code you wrote.
The tower you built
Read it bottom-up — each floor stands on the one below it:
- The loop —
tool_use→ execute →tool_result→ repeat untilend_turn. The heartbeat; everything else hangs off it. - Tools —
Read/view,Write/create,Edit/str_replace,Glob,Grep,Bash: hands that touch a real filesystem, with the read-before-edit and stale-write contracts that make edits safe. - Permissions —
deny → ask → allow → mode default: the brakes that decide whether a call runs at all, before the side effect. - The sandbox — path canonicalization + containment, so even an allowed action can't escape the working tree.
- Subagents — the
Tasktool: an isolated context that returns only a final message, keeping a research detour out of the main window. - MCP — JSON-RPC over stdio, as both a client (discover and call external tools) and a server (expose your own).
- Hooks —
PreToolUse/PostToolUse/Stopsubprocesses that block, modify, or inject context on the agent's lifecycle. - Skills —
SKILL.mdbundles invoked by name, with$ARGUMENTSand dynamic injection: extensibility without touching the agent's code. - Context — window-pressure tracking, structured compaction, and a JSONL transcript that survives a long session.
- Plan & tasks — a read-only planning mode gated by
ExitPlanMode, plus a task store with dependency edges. - The CLI —
claude-code run <task-dir>: the entry point that wires every floor together and proves it on a frozen suite.
The headline guarantee held the whole way down: tools have real side effects, the model is frozen by a cassette, and "done" is a test's exit code plus a byte diff — never a model judging itself.
Where to go next
You built the contract of each subsystem — faithfully, but minimally. The production versions go further, and now you have the foundation to read them:
- Real OS sandboxing. You modeled containment as a path guard pinned to
$TASK_DIR. Production Claude Code drops to the kernel — macOS Seatbelt, Linux bubblewrap — so a confusedbashcan't reach the host even if your guard has a bug. The contract you built is the same; the mechanism is the OS. - HTTP/SSE MCP transports. You hand-rolled JSON-RPC over stdio. The same message shapes ride over HTTP and SSE to reach remote servers — the framing changes, the protocol doesn't.
- Output styles. Swap the agent's system prompt and formatting to retarget it (explanatory, concise, a teammate's voice) without changing a line of the loop.
- Multi-agent teammates. Your parallel-dispatch subagents are the seed of full multi-agent teams — a lead that delegates to specialists, each in its own context, coordinating through shared task state.
None of this is graded. It's the map of what's past the edge of what you built — and you're now equipped to build any of it.
Your ~2,000-line agent fixed a real repo, respected a deny rule, called an MCP server, and fired a hook — and it does it identically every run. That terminal trajectory ending in green tests is the most screenshot-worthy artifact on the platform, and it's earned: my Claude Code — loop, tools, permissions, subagents, MCP, hooks — fixed the repo, and it does it the same way every time.