|
1 | 1 | # swift-claude-code |
2 | 2 |
|
3 | | -Building a simplified Claude Code-like CLI agent from scratch in Swift. |
| 3 | +Exploring the architecture of coding agents by rebuilding a Claude Code-style CLI from scratch in Swift. |
4 | 4 |
|
5 | 5 | > **Current progress:** Stage 02 of 12 — tool dispatch with `read_file`, `write_file`, `edit_file` |
6 | 6 |
|
7 | 7 | ## Why This Exists |
8 | 8 |
|
9 | | -If you've used Claude Code, you know exactly what I'm talking about. Especially the first time you use it — it's just _different_ than any other coding agent out there. There's definitely some magic behind Claude Code, and I went down a huge rabbit hole trying to figure out what makes it special. |
| 9 | +Claude Code feels unusually effective compared to other coding agents, and I suspect most of it comes from architectural restraint rather than architectural complexity. I studied the tool surface, traced the interaction loop, and tried to isolate which design choices actually matter. |
10 | 10 |
|
11 | | -My hypothesis: **Claude Code is so good because of how simple it is.** |
| 11 | +My working theory: **coding agents benefit more from a small set of excellent tools and tight loop design than from large orchestration layers.** |
12 | 12 |
|
13 | | -Not the UI — the architecture. Down to the fact that it doesn't really have many tools. And the tools it does have are really simple: a search tool, a file editing tool. That's about it. But those tools are _really, really good_. |
| 13 | +Claude Code doesn't have many tools. The tools it does have are simple: a search tool, a file editing tool. But those tools are really good. And the system leans on the model far more than most agent implementations — less scaffolding, more trust in the LLM to do the heavy lifting. |
14 | 14 |
|
15 | | -The other big thing is that Claude Code relies on the model way more than other tools. Most people build a lot of scaffolding around the model, but Claude Code really lets the model do all of the heavy lifting. |
| 15 | +This project tests that idea by rebuilding the core mechanics from scratch in Swift, one stage at a time, to see how little architecture you actually need. |
16 | 16 |
|
17 | | -So I wanted to understand this deeply — not by reading about it, but by building it. This project rebuilds the core agent loop from scratch in Swift, one layer at a time, to see exactly how few moving parts you actually need. |
| 17 | +## Hypothesis |
18 | 18 |
|
19 | | -## Architecture |
| 19 | +This project tests a few specific ideas about coding agents: |
20 | 20 |
|
21 | | -Two-target Swift Package Manager project: |
| 21 | +- A small number of high-quality tools beats a large tool catalog |
| 22 | +- The model should do most of the heavy lifting — thin orchestration, not thick |
| 23 | +- Explicit task state improves reliability more than prompt-only planning |
| 24 | +- Controlled context injection matters more than persistent memory |
| 25 | +- Context compaction is a product feature, not just a token optimization |
22 | 26 |
|
23 | | -``` |
24 | | -swift-claude-code/ |
25 | | -├── Package.swift |
26 | | -├── Sources/ |
27 | | -│ ├── Core/ ← library (all logic) |
28 | | -│ │ ├── API/ |
29 | | -│ │ ├── Agent.swift agent loop + tool dispatch |
30 | | -│ │ └── ShellExecutor.swift |
31 | | -│ └── cli/ ← executable (@main entry point) |
32 | | -└── Tests/CoreTests/ |
33 | | -``` |
34 | | - |
35 | | -**Core** is the library — API client, shell executor, agent loop, tools, everything testable. **cli** is just the entry point. The executable is called `claude`. |
36 | | - |
37 | | -Raw HTTP to `POST https://api.anthropic.com/v1/messages` using [AsyncHTTPClient](https://github.com/swift-server/async-http-client). Works on both macOS and Linux. |
| 27 | +Each stage is designed to isolate one mechanism and see what it enables. |
38 | 28 |
|
39 | 29 | ## The Agent Loop |
40 | 30 |
|
@@ -67,27 +57,75 @@ func run(query: String) async throws -> String { |
67 | 57 | } |
68 | 58 | ``` |
69 | 59 |
|
70 | | -That's it. The loop is the invariant. Tools are the variable. Every stage adds entries to the tool handler dictionary and injection points before the API call, but the loop body itself never changes. |
| 60 | +The loop is the invariant. Tools are the variable. Every stage adds entries to the tool handler dictionary and injection points before the API call, but the loop body itself never changes. |
71 | 61 |
|
72 | 62 | ## Roadmap |
73 | 63 |
|
74 | | -Each stage adds one mechanism on top of the previous one. Progress is tracked via git tags. |
| 64 | +Progress is tracked via git tags. The roadmap is split into three phases — core mechanics first, then product-level features, then experimental multi-agent systems. |
| 65 | + |
| 66 | +### Phase 1 — Core Loop |
| 67 | + |
| 68 | +The minimum viable agent: a loop and a small set of good tools. |
75 | 69 |
|
76 | 70 | | Stage | What It Adds | Tag | |
77 | 71 | | ------ | ---------------------------------------------------------------------- | ------------------ | |
78 | | -| **00** | Bootstrap: SPM project | `00-bootstrap` | |
| 72 | +| **00** | Bootstrap: SPM project, two-target layout, CI | `00-bootstrap` | |
79 | 73 | | **01** | Agent loop + bash tool | `01-agent-loop` | |
80 | 74 | | **02** | Tool dispatch: `read_file`, `write_file`, `edit_file` with path safety | `02-tool-dispatch` | |
81 | | -| 03 | TodoWrite: Codable todo tracking with nag reminder injection | — | |
82 | | -| 04 | Subagents: recursive `agentLoop()` with fresh messages | — | |
83 | | -| 05 | Skill loading: read `.md` files from disk, inject as tool results | — | |
84 | | -| 06 | Context compaction: 3-layer strategy (micro, auto, manual) | — | |
85 | | -| 07 | Task system: file-based CRUD with dependency DAG | — | |
86 | | -| 08 | Background tasks: `Task {}` + actor-based notification queue | — | |
87 | | -| 09 | Agent teams: JSONL mailbox files + actor coordination | — | |
88 | | -| 10 | Team protocols: request-response with correlation IDs | — | |
89 | | -| 11 | Autonomous agents: idle-poll-claim cycle | — | |
90 | | -| 12 | Worktree isolation: `git worktree` via Process | — | |
| 75 | +| 03 | Todo tracking with nag reminder injection | — | |
| 76 | + |
| 77 | +### Phase 2 — Product Mechanics |
| 78 | + |
| 79 | +The features that make an agent feel like a usable product: context, memory management, and persistence. |
| 80 | + |
| 81 | +| Stage | What It Adds | Tag | |
| 82 | +| ----- | ------------------------------------------------------------ | --- | |
| 83 | +| 04 | Subagents: recursive loop with fresh context | — | |
| 84 | +| 05 | Skill loading: `.md` files injected as tool results | — | |
| 85 | +| 06 | Context compaction: 3-layer strategy (micro, auto, manual) | — | |
| 86 | +| 07 | Task system: file-based CRUD with dependency DAG | — | |
| 87 | +| 08 | Background tasks: `Task {}` + actor-based notification queue | — | |
| 88 | + |
| 89 | +### Phase 3 — Experimental |
| 90 | + |
| 91 | +Multi-agent coordination. These stages explore ideas beyond the core product loop. |
| 92 | + |
| 93 | +| Stage | What It Adds | Tag | |
| 94 | +| ----- | ----------------------------------------------------- | --- | |
| 95 | +| 09 | Agent teams: JSONL mailbox + actor coordination | — | |
| 96 | +| 10 | Team protocols: request-response with correlation IDs | — | |
| 97 | +| 11 | Autonomous agents: idle-poll-claim cycle | — | |
| 98 | +| 12 | Worktree isolation: `git worktree` via Process | — | |
| 99 | + |
| 100 | +## Architecture |
| 101 | + |
| 102 | +Two-target Swift Package Manager project: |
| 103 | + |
| 104 | +``` |
| 105 | +swift-claude-code/ |
| 106 | +├── Package.swift |
| 107 | +├── Sources/ |
| 108 | +│ ├── Core/ ← library (all logic) |
| 109 | +│ │ ├── API/ |
| 110 | +│ │ ├── Agent.swift agent loop + tool dispatch |
| 111 | +│ │ └── ShellExecutor.swift |
| 112 | +│ └── cli/ ← executable (@main entry point) |
| 113 | +└── Tests/CoreTests/ |
| 114 | +``` |
| 115 | + |
| 116 | +**Core** is the library — API client, shell executor, agent loop, tools, everything testable. **cli** is just the entry point. The executable is called `claude`. |
| 117 | + |
| 118 | +Raw HTTP to `POST https://api.anthropic.com/v1/messages` using [AsyncHTTPClient](https://github.com/swift-server/async-http-client). Works on both macOS and Linux. |
| 119 | + |
| 120 | +## Non-Goals |
| 121 | + |
| 122 | +This project is **not**: |
| 123 | + |
| 124 | +- A full Claude Code clone or drop-in replacement |
| 125 | +- A general-purpose multi-agent framework |
| 126 | +- Production-ready IDE tooling |
| 127 | + |
| 128 | +It's a staged exploration of coding-agent architecture — intentionally minimal, intentionally incomplete. |
91 | 129 |
|
92 | 130 | ## Tech Stack |
93 | 131 |
|
|
0 commit comments