@@ -4,19 +4,7 @@ These are decisions, not aspirations — the code already reflects them.
44When in doubt, the tenet wins over momentum. When two tenets conflict,
55they're listed roughly in priority order.
66
7- ## 1. Better than Claude Code, not a clone
8-
9- We study Claude Code's source as a benchmark for feature coverage and learn
10- from their architectural mistakes. Every feature we add should be a * better*
11- implementation, not a copy-paste. We have CC's source for reference; what we
12- copy is the * idea* (collapsed read groups, tool-status spinners, ` !cmd ` shell
13- escape), never the wording or the data structures.
14-
15- ** Why this matters** : this is open source. Verbatim copies of CC's prompt
16- strings or code create IP risk. The technique is fine; the specific words
17- must be original.
18-
19- ## 2. Any LLM provider, never lock-in
7+ ## 1. Any LLM provider, never lock-in
208
219OAuth login for our hosted offering, BYOK for everything else. Anthropic,
2210OpenAI, Groq, OpenRouter, Ollama, anything OpenAI-compatible. Provider
@@ -25,33 +13,30 @@ abstracts the protocol differences.
2513
2614** Implication** : don't write code that assumes a specific provider's quirks
2715unless you also write the fallback path. Don't depend on provider-specific
28- features (e.g. Anthropic's tool_use blocks) outside of the protocol adapter
29- layer in ` @earendil-works/pi-ai ` .
16+ features outside of the protocol adapter layer in ` @earendil-works/pi-ai ` .
3017
31- ## 3 . Simplicity beats features
18+ ## 2 . Simplicity beats features
3219
33- CC is 512K LOC. We're ~ 22K. That's not an accident — it's a position. Before
34- adding a feature, ask: "is this * the* feature, or * a* feature?" Most of CC's
35- features are accretion. Most ours should not be.
20+ The codebase is small on purpose. Before adding a feature, ask: "is this
21+ * the* feature, or * a* feature?" Most accretion is regret-shaped.
3622
3723** Practical rules** :
3824- No premature abstraction. Three similar lines is better than a wrong helper.
3925- No backwards-compat shims for code you're rewriting in the same PR.
4026- No "let's make this configurable" before there's a second use case.
4127- Comments explain * why* , not * what* . Default to none.
4228
43- ## 4 . Effect-based permissions
29+ ## 3 . Effect-based permissions
4430
4531Tools declare their ** effects** (` reads_fs ` , ` writes_fs ` , ` runs_shell ` ,
4632` network ` ). Permission policies match on effects, not tool names. Adding a
4733new tool = declaring its effects; the permission system already knows what
48- to do. CC has 300K+ lines of permission AST parsing for tool-name patterns;
49- we have ~ 600 lines because we made the foundational call differently.
34+ to do.
5035
5136Don't add tool-name special-cases to the permission engine. If a real
5237restriction needs to exist, it's a new effect.
5338
54- ## 5 . Streaming is a UX commitment
39+ ## 4 . Streaming is a UX commitment
5540
5641Models emit tokens at 60-100 Hz. Tools emit stdout in bursts. The TUI has
5742to keep up * without* repainting at that rate or it'll thrash the user's
@@ -60,10 +45,10 @@ terminal. We coalesce to 16ms (60fps) in `use-coalesced-agent-events.ts`.
6045If you're adding a state path the streaming pipeline goes through, ask:
6146"does this allocate on every event?" Often the answer is "we make a new Map
6247per update" — and that's * fine* because the reducer microbenchmark
63- (` npm run bench:micro ` ) says we have 10M+ events/sec of headroom. But
48+ (` npm run bench:micro ` ) shows we have 10M+ events/sec of headroom. But
6449don't add work without checking.
6550
66- ## 6 . The agent loop belongs to pi-mono
51+ ## 5 . The agent loop belongs to pi-mono
6752
6853` @earendil-works/pi-agent-core ` owns: the model.run() loop, message
6954shape, tool-call protocol, session persistence. We do not reimplement
@@ -74,7 +59,7 @@ Things we own: the TUI, tools, slash commands, permissions, the glue
7459sidecar, OAuth, the wizard, the headless ` run ` subcommand, the JSON-RPC
7560` app-server ` .
7661
77- ## 7 . Test the load-bearing parts
62+ ## 6 . Test the load-bearing parts
7863
7964Tools, the reducer, the router, parsers, and credential handling have
8065unit tests. The interactive TUI does not — yet. We accept the trade-off:
@@ -87,22 +72,22 @@ The faux provider from pi-ai (`registerFauxProvider`) is the right tool
8772for E2E tests — see ` src/agent/__test__/agent-e2e.test.ts ` . No mocks, real
8873agent loop, deterministic.
8974
90- ## 8 . Don't fight the user's terminal
75+ ## 7 . Don't fight the user's terminal
9176
9277Setting raw mode? Restore it on every exit path, including uncaught
9378exceptions. Setting the terminal title? Use OSC 0 and accept that
9479non-TTYs won't see it. Hiding the cursor? Show it back on unmount.
9580See ` src/ui/terminal-restore.ts ` . The user's ` stty sane ` recovery
9681moments are user-trust-destroying — we don't get to have those.
9782
98- ## 9 . Don't commit aspirations
83+ ## 8 . Don't commit aspirations
9984
100- Per ` CLAUDE.md ` §2.4: never commit specs, governance docs, or policy
101- files for systems that do not yet exist. This ` .settings/ ` folder
102- describes what's * in the code today* , not what we'd like to build.
103- If we add a feature, the docs follow the code — not the other way.
85+ Never commit specs, governance docs, or policy files for systems that do
86+ not yet exist. This ` .settings/ ` folder describes what's * in the code
87+ today* , not what we'd like to build. If we add a feature, the docs follow
88+ the code — not the other way.
10489
105- ## 10 . Ship something you'd use
90+ ## 9 . Ship something you'd use
10691
10792The author runs this in production for daily development. Bugs that
10893annoy us get fixed first. Features no one uses get deleted. This is a
0 commit comments