chad-code 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. chad_code-0.1.0/LICENSE +21 -0
  2. chad_code-0.1.0/PKG-INFO +370 -0
  3. chad_code-0.1.0/README.md +334 -0
  4. chad_code-0.1.0/pyproject.toml +130 -0
  5. chad_code-0.1.0/setup.cfg +4 -0
  6. chad_code-0.1.0/src/chad/__init__.py +7 -0
  7. chad_code-0.1.0/src/chad/agent.py +1093 -0
  8. chad_code-0.1.0/src/chad/base_engine.py +109 -0
  9. chad_code-0.1.0/src/chad/bench.py +243 -0
  10. chad_code-0.1.0/src/chad/cli.py +469 -0
  11. chad_code-0.1.0/src/chad/compaction.py +108 -0
  12. chad_code-0.1.0/src/chad/config.py +63 -0
  13. chad_code-0.1.0/src/chad/diag.py +100 -0
  14. chad_code-0.1.0/src/chad/engine.py +883 -0
  15. chad_code-0.1.0/src/chad/guardrails.py +373 -0
  16. chad_code-0.1.0/src/chad/ignore.py +18 -0
  17. chad_code-0.1.0/src/chad/lsp.py +323 -0
  18. chad_code-0.1.0/src/chad/mcp.py +719 -0
  19. chad_code-0.1.0/src/chad/mcp_oauth.py +329 -0
  20. chad_code-0.1.0/src/chad/openai_engine.py +252 -0
  21. chad_code-0.1.0/src/chad/prompt.py +305 -0
  22. chad_code-0.1.0/src/chad/render.py +462 -0
  23. chad_code-0.1.0/src/chad/repomap.py +767 -0
  24. chad_code-0.1.0/src/chad/session.py +281 -0
  25. chad_code-0.1.0/src/chad/skills.py +407 -0
  26. chad_code-0.1.0/src/chad/symbols.py +360 -0
  27. chad_code-0.1.0/src/chad/syntaxgate.py +105 -0
  28. chad_code-0.1.0/src/chad/toolcall_parse.py +115 -0
  29. chad_code-0.1.0/src/chad/tools.py +962 -0
  30. chad_code-0.1.0/src/chad/tui.py +921 -0
  31. chad_code-0.1.0/src/chad/validate.py +361 -0
  32. chad_code-0.1.0/src/chad_code.egg-info/PKG-INFO +370 -0
  33. chad_code-0.1.0/src/chad_code.egg-info/SOURCES.txt +64 -0
  34. chad_code-0.1.0/src/chad_code.egg-info/dependency_links.txt +1 -0
  35. chad_code-0.1.0/src/chad_code.egg-info/entry_points.txt +4 -0
  36. chad_code-0.1.0/src/chad_code.egg-info/requires.txt +17 -0
  37. chad_code-0.1.0/src/chad_code.egg-info/top_level.txt +1 -0
  38. chad_code-0.1.0/tests/test_agent.py +119 -0
  39. chad_code-0.1.0/tests/test_agent_e2e.py +184 -0
  40. chad_code-0.1.0/tests/test_agent_guards.py +478 -0
  41. chad_code-0.1.0/tests/test_cli.py +204 -0
  42. chad_code-0.1.0/tests/test_compaction.py +189 -0
  43. chad_code-0.1.0/tests/test_config.py +102 -0
  44. chad_code-0.1.0/tests/test_confirm_preview.py +51 -0
  45. chad_code-0.1.0/tests/test_edit.py +107 -0
  46. chad_code-0.1.0/tests/test_engine.py +654 -0
  47. chad_code-0.1.0/tests/test_feel_pack.py +122 -0
  48. chad_code-0.1.0/tests/test_gate.py +198 -0
  49. chad_code-0.1.0/tests/test_ignore.py +27 -0
  50. chad_code-0.1.0/tests/test_intent.py +192 -0
  51. chad_code-0.1.0/tests/test_log_redaction.py +110 -0
  52. chad_code-0.1.0/tests/test_lsp.py +115 -0
  53. chad_code-0.1.0/tests/test_mcp.py +655 -0
  54. chad_code-0.1.0/tests/test_mcp_oauth.py +340 -0
  55. chad_code-0.1.0/tests/test_openai_engine.py +183 -0
  56. chad_code-0.1.0/tests/test_render.py +169 -0
  57. chad_code-0.1.0/tests/test_repomap.py +362 -0
  58. chad_code-0.1.0/tests/test_session.py +164 -0
  59. chad_code-0.1.0/tests/test_skills.py +303 -0
  60. chad_code-0.1.0/tests/test_subagent.py +403 -0
  61. chad_code-0.1.0/tests/test_symbols.py +246 -0
  62. chad_code-0.1.0/tests/test_syntaxgate.py +98 -0
  63. chad_code-0.1.0/tests/test_toolcall_parse.py +127 -0
  64. chad_code-0.1.0/tests/test_tools.py +336 -0
  65. chad_code-0.1.0/tests/test_tui.py +375 -0
  66. chad_code-0.1.0/tests/test_validate.py +195 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nate Sutton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,370 @@
1
+ Metadata-Version: 2.4
2
+ Name: chad-code
3
+ Version: 0.1.0
4
+ Summary: Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)
5
+ License-Expression: MIT
6
+ Project-URL: Repository, https://github.com/nathansutton/chad
7
+ Project-URL: Issues, https://github.com/nathansutton/chad/issues
8
+ Keywords: mlx,coding-agent,apple-silicon,local-llm,tui
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Code Generators
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: mlx<0.32,>=0.31.2
21
+ Requires-Dist: mlx-lm<0.32,>=0.31.3
22
+ Requires-Dist: transformers<5.13,>=5.0
23
+ Requires-Dist: numpy<2,>=1.26
24
+ Requires-Dist: huggingface-hub>=0.34
25
+ Requires-Dist: jedi>=0.19.2
26
+ Requires-Dist: prompt_toolkit>=3.0.43
27
+ Requires-Dist: tree-sitter>=0.25.2
28
+ Requires-Dist: tree-sitter-language-pack>=1.11.0
29
+ Requires-Dist: rustworkx>=0.15
30
+ Requires-Dist: mcp>=1.27
31
+ Provides-Extra: highlight
32
+ Requires-Dist: pygments>=2.17; extra == "highlight"
33
+ Provides-Extra: lsp
34
+ Requires-Dist: serena-agent>=1.5; extra == "lsp"
35
+ Dynamic: license-file
36
+
37
+ # chad — a local, MLX-backed coding agent
38
+
39
+ [![tests](https://github.com/nathansutton/chad/actions/workflows/tests.yml/badge.svg)](https://github.com/nathansutton/chad/actions/workflows/tests.yml)
40
+
41
+ <img src="docs/chad-vs-claude.png" width="480" alt="Claude: Master of the Universe (an ornate, impossibly intricate carved-horse banister) vs chad: Master of Your Laptop (a plastic toy horse gaffer-taped to a stair post)">
42
+
43
+
44
+ > Claude can do anything, for anyone, anywhere. chad does one thing. 🗿
45
+ > *Coding under supervision.*
46
+
47
+ chad has some of the same moves as Claude — tool use, plan mode, a real TUI — but driven
48
+ by a local model on your laptop instead of a frontier model in a datacenter. He isn't a
49
+ smaller Claude; he's a blunter instrument.
50
+
51
+ | | **Claude** | **chad** 🗿 |
52
+ |---------------------|--------------------------------------------------|--------------------------------------------|
53
+ | **Range** | every workflow, every person, incredible nuance | one job: code, on your machine |
54
+ | **Runs** | anywhere — cloud, IDE, terminal, phone | your laptop. that's it. |
55
+ | **Brain** | a frontier model in a datacenter | Ornith model on Apple Silicon |
56
+ | **Disposition** | understands what you *really* meant | does what you *said* |
57
+ | **Harness** | open-ended, anything you can imagine | plan. execute. nothing else. |
58
+ | **When wrong** | reasons a way out | already shipped 🗿 |
59
+
60
+ Think of it as report cards. On [terminal-bench 2.1](https://www.tbench.ai/leaderboard) —
61
+ the standard exam for CLI coding agents — Claude (Opus 4.8) is the **A student** at
62
+ **82.7%**, near the top of the class. Ornith, the model behind chad, is a **C+ student**
63
+ at **64.2%**. The bet was never that chad out-scores Claude — it's that a C+ student
64
+ running free on your own machine is still worth having around. 🗿
65
+
66
+ > chad doesn't run on a H100 server, and you don't have one. He will never will be in the
67
+ > big leagues. Those are for Claude. chad does **one** thing, MLX inference on a MacBook Pro,
68
+ > and this whole repo is about making that one thing as fast as the laptop allows: a persistent
69
+ > prefix KV cache so prefill never re-reads the transcript, and a model that decodes near the
70
+ > memory-bandwidth ceiling. chad is not here to win SOTA benchmarks. He's just here to help. 🗿
71
+
72
+ ![chad fixing a failing test end to end — reason, read, edit, rerun pytest, all on a local 35B](docs/demo.gif)
73
+
74
+ > Real session, unedited: the default local 35B reasons through the failure, edits the
75
+ > file, reruns the tests, and confirms green. The cold model load is cut; everything after
76
+ > is real time.
77
+
78
+ A single-user agentic coding backend that runs **entirely locally on Apple Silicon**
79
+ via [MLX](https://github.com/ml-explore/mlx). It gives you Claude-Code-style tool use
80
+ (bash, read, write, edit, glob, grep) driven by a local model — and, increasingly, a
81
+ Claude-Code-style **feel**: a full-screen TUI with shift-tab plan mode, a type-ahead
82
+ message queue, mid-turn interrupt, and live throughput/context status.
83
+
84
+ It targets the machine most developers actually have — a **24 GB Apple Silicon
85
+ MacBook** — and the whole design follows from one constraint that machine imposes:
86
+ **prefill is the dominant cost** in an agentic loop, so a persistent prefix KV cache that
87
+ never re-reads the transcript is the core engineering. The full story is in
88
+ [Design & internals](docs/design.md).
89
+
90
+ ## The bet: at this end of the report card, the harness beats the model
91
+
92
+ Every serious coding harness was designed for a frontier model behind a datacenter
93
+ API. That design bakes in two assumptions: the model is an A student, and prefill is
94
+ somebody else's electricity. Both are false on a laptop. A C+ student emits tool calls
95
+ with typos, quotes edits it never applies, and rambles — and every token of transcript
96
+ it drags around must be re-read by *your* GPU at a few hundred tokens a second.
97
+
98
+ So chad's real thesis isn't "run a model locally" — plenty of tools do that. It's that
99
+ **for a small model, harness quality is worth more than a model upgrade**, and that the
100
+ harness and the inference engine have to be designed *together*. You can measure it: a
101
+ private rig runs the **same Ornith-9B weights** on the **same 34 Exercism-style tasks**
102
+ on the **same MacBook**, varying only the harness (external harnesses reach the model
103
+ through an OpenAI-style local server — the standard way to attach them to a local
104
+ backend):
105
+
106
+ | harness | tasks passed | median time-to-first-token | median prefix-cache reuse |
107
+ |---|---|---|---|
108
+ | **chad** | **17/34** | **0.71 s** | **99%** |
109
+ | pi | 10/34 | 3.2 s | 77% |
110
+ | opencode | 2/34 | 2.9 s | 0% |
111
+ | aider / cline / goose / Claude Code (via router) | 0/34 | 3.3–6.1 s | 0–85% |
112
+
113
+ (One model, one machine, n=34 — read it as a measurement of *fit to a local backend*,
114
+ not of those harnesses in general; they're excellent at what they were built for, which
115
+ is a frontier model on the other end of a fast API.)
116
+
117
+ The gap is entirely nameable failure modes. The model pours its edit into the
118
+ reasoning channel and the harness drops it. The model asks for a `read` tool the
119
+ harness doesn't ship. The harness rejects nested tool arguments a weak model loves to
120
+ emit. The context balloons, cache reuse hits 0%, decode falls to 2 tok/s. chad handles
121
+ each of these *inside* the harness: tool calls are parsed in four dialects and
122
+ repaired, arguments are schema-coerced with an annotated self-repair loop, edits go
123
+ through a forgiveness cascade before failing, loop/thrash/verify guards keep the turn
124
+ honest — and, above all, the transcript is engineered to remain a **strict token-prefix
125
+ of the live KV cache** across every step, because on a local model prefix stability is
126
+ a *harness* property, not a server feature. That co-design is the whole moat: it's why
127
+ the same C+ student passes 17 tasks under chad and 0 under harnesses built for the A
128
+ student. A C+ student with a good tutor, running free on your own machine. 🗿
129
+
130
+ ### Why the engine is in-process (and not behind an OpenAI layer)
131
+
132
+ A fair question is whether chad should talk to its model through an OpenAI-style
133
+ `/v1/chat/completions` boundary — the way every external harness above does — so the
134
+ frontend and backend decouple cleanly. It shouldn't, and the table already shows why:
135
+ that boundary is stateless text-in/text-out, and chad's core engineering (diffing
136
+ rendered *token ids* against a live KV cache, warm-prefix disk checkpoints,
137
+ `close_unclosed_think` prefix repair, interruptible chunked prefill, RAM-aware context
138
+ sizing, cache push/pop) all require *owning* the tokenizer and the cache object. None of
139
+ it survives the API. The coupling isn't debt; it's the measured moat.
140
+
141
+ To keep that answer honest rather than asserted, chad ships a thin, flag-gated adapter
142
+ (`--backend openai`, `src/chad/openai_engine.py`) that runs the *same harness* against
143
+ any OpenAI-compatible endpoint — so "harness value" and "engine value" can be measured
144
+ separately as an ablation arm. The adapter's honest degradations (it can't report cache
145
+ reuse, can't show prefill progress, and interrupts by dropping the stream) are documented
146
+ in-code. A measured in-process vs. served comparison (the same harness through
147
+ `mlx_lm.server`) is queued on the maintainer's eval rig; the expected result is a
148
+ pass-rate near-equal (the harness carries it), with wall-clock/TTFT materially worse.
149
+
150
+ ## Quickstart
151
+
152
+ Apple Silicon + [uv](https://docs.astral.sh/uv/). No clone, no model build — install and
153
+ run in one line; the model downloads itself on first use. The PyPI distribution is
154
+ **`chad-code`** (bare `chad` is a squatted, unrelated package); the command is still `chad`:
155
+
156
+ ```bash
157
+ uvx chad-code # run chad anywhere, no clone — the command is still `chad`
158
+ ```
159
+
160
+ Or install it for good — then it's just `chad`:
161
+
162
+ ```bash
163
+ uv tool install chad-code # install to ~/.local/bin
164
+ chad # then it's just `chad`
165
+ ```
166
+
167
+ To run the very latest **unreleased `main`** instead of the last release, use the git URL:
168
+
169
+ ```bash
170
+ uvx --from git+https://github.com/nathansutton/chad chad # bleeding edge, no clone
171
+ ```
172
+
173
+ Or, working from a clone (the dev path):
174
+
175
+ ```bash
176
+ uv sync # install deps + the `chad` entrypoint (one time)
177
+ uv run chad # launch the full-screen TUI
178
+ uv run chad "add a --json flag to main.py and update the tests" # one-shot, headless
179
+ uv run chad -c # resume this directory's last conversation
180
+ ```
181
+
182
+ **Development / testing.** `uv sync` is the one-time setup. The fast unit gate is
183
+ `uv run pytest -q` — it loads **no model weights**, runs in seconds, and is what CI runs.
184
+ To measure throughput on your own machine, `uv run chad-bench` (see
185
+ [Throughput & performance](docs/benchmarks.md)).
186
+
187
+ **Optional: precise refs/rename.** LSP-precise cross-file find-references and
188
+ scope-correct rename need the `lsp` extra — `uv tool install 'chad-code[lsp]'` (installed)
189
+ or `uv sync --extra lsp` (from a clone); without it chad uses the tree-sitter fallback
190
+ automatically (see [the symbolic stack](docs/design.md)).
191
+
192
+ **The model.** chad picks one model for you and downloads it once into the shared Hugging
193
+ Face cache (`~/.cache/huggingface`, reused across every project):
194
+
195
+ | Your Mac | Model | Footprint |
196
+ |---|---|---|
197
+ | **≥ 24 GB** (default) | [Ornith-1.0-35B `UD-Q2_K_XL`](https://huggingface.co/nathansutton/Ornith-1.0-35B-UD-Q2_K_XL-MLX) — 35B MoE, 2-bit experts | ~12 GB |
198
+ | **16 / 18 GB** (auto-fallback) | [Ornith-1.0-9B `UD-Q4_K_XL`](https://huggingface.co/nathansutton/Ornith-1.0-9B-UD-Q4_K_XL-MLX) — 4-bit AWQ | ~5 GB |
199
+
200
+ chad detects your RAM and chooses; the first run asks before downloading (~12 GB / ~5 GB —
201
+ 2-4 minutes on gigabit fiber, 15-25 on a 100 Mbit line; the download is resumable, so a
202
+ killed first run picks up where it left off), or auto-downloads when headless. No model
203
+ picker, no flags. Override with `CHAD_MODEL=<repo
204
+ or local dir>` to force a specific one. Quant names follow
205
+ [Unsloth's dynamic-quant convention](https://docs.unsloth.ai/) (`UD-…`) so the scheme is
206
+ recognizable. chad downloads the pre-quantized model from Hugging Face on first run.
207
+
208
+ That's the whole on-ramp. The model and the throughput numbers you can reproduce live in
209
+ [Throughput & performance](docs/benchmarks.md).
210
+
211
+ Run `chad` from inside the project you want it to work on — it snapshots the working
212
+ directory into context at startup.
213
+
214
+ ### Upgrading
215
+
216
+ How you refresh depends on how you installed it:
217
+
218
+ - **`uv tool install` users**: `uv tool upgrade chad-code` re-resolves and installs the
219
+ latest release. (If chad isn't a uv tool, uv tells you so — install it with the `uv tool
220
+ install` line above.)
221
+ - **`uvx` users**: `uvx` caches the resolved environment, so a plain re-run can stay
222
+ pinned to an older resolve. Force the latest release with `uvx --refresh chad-code`.
223
+ - **Bleeding-edge (`main`)**: to jump ahead of the last release, re-run the git-URL form
224
+ with `--refresh`: `uvx --refresh --from git+https://github.com/nathansutton/chad chad`.
225
+ - **Dev clones**: `git pull && uv sync`.
226
+
227
+ What changed lands in [`CHANGELOG.md`](CHANGELOG.md). Model weights are versioned
228
+ separately from the code: a code upgrade never re-downloads the model, and a *model* bump
229
+ announces itself in the changelog (superseded snapshots can then be freed — see
230
+ [Troubleshooting](docs/troubleshooting.md)).
231
+
232
+ ## Interactive UX (Claude Code parity)
233
+
234
+ `uv run chad` launches a full-screen terminal UI (`tui.py`, built on prompt_toolkit):
235
+
236
+ - **shift-tab cycles permission modes** — `normal` (confirm each bash/write/edit) →
237
+ `auto-accept edits` → `plan mode` (read-only: the agent investigates and proposes a
238
+ numbered plan, all mutations blocked) → back. The current mode shows in the status bar.
239
+ - **type-ahead message queue** — keep typing while the agent works; messages run in
240
+ order. The status bar shows the queued count.
241
+ - **ctrl-c interrupts the running turn** (stops generation) without killing the session.
242
+ - **inline y/n approval** for mutating tools in normal mode.
243
+ - **live status line** — model, mode, context %, and a live activity readout: a state
244
+ glyph + verb (Reading / Editing / Running…), elapsed seconds, and **↑prefilled /
245
+ ↓generated** token counts. When the prefix cache can't be reused and a full prefill is
246
+ unavoidable (after a `/compact` or a truncation invalidates the cached prefix), it shows
247
+ an advancing **%** so that otherwise-silent re-prefill is legible. (Raw tok/s and
248
+ PLD-acceptance diagnostics still go to `~/.chad/session.log`.)
249
+ - **slash commands** — `/init` (scaffold a `CLAUDE.md` from the actual project files),
250
+ `/skills` (list discovered Agent Skills), `/mcp` (list configured MCP servers + their
251
+ tools; `/mcp trust` trusts this project's `./.mcp.json` servers so they start, `/mcp
252
+ login <server>` does an OAuth login), `/accept` (accept a pending plan and implement it),
253
+ `/resume` (list this directory's recent sessions; `/resume <n>` forks one — see
254
+ [Sessions](#sessions-resume--fork)), `/reset` (`/clear`), `/compact` (reclaim context
255
+ now — strips old reasoning + truncates old tool outputs, never drops a message),
256
+ `/model` (model + context status), `/mode`, `/help`, `/exit`. Same set in the `--repl`
257
+ line interface.
258
+ - **`@file` / `@dir` mentions** — write `@path` in a message and a file is pulled into
259
+ context inline (bounded by the read tool's skeleton/cap policy, no `read` round-trip) or
260
+ a directory becomes a short listing. Works in the TUI, `--repl`, and `-p`. Emails/
261
+ decorators don't trigger it (the `@` must follow whitespace); only real paths attach.
262
+ - **`!command` shell passthrough** — a line starting with `!` runs that shell command
263
+ directly (interruptible) and shows the output, without invoking the model — for quick
264
+ `!git status` / `!ls` checks without leaving the prompt. (TUI and `--repl`.)
265
+
266
+ The agent loop runs on a worker thread; the UI owns the asyncio loop. Agent I/O
267
+ (`emit`/`confirm`/`should_stop`) is injected, so the *same* `Agent` code drives both the
268
+ TUI and the plain line REPL (`--repl`). The loop stays fast on a **persistent prefix KV
269
+ cache**: each step re-renders the whole transcript but only prefills the handful of new
270
+ tokens. The few moments it *can't* — Ornith's hybrid SSM/attention cache is non-trimmable,
271
+ so `/compact` or a mid-turn truncation invalidates the prefix and forces a one-time full
272
+ re-prefill — are exactly when the status line's advancing **%** earns its place: the long
273
+ prefill is the price of the cache design, now shown rather than silent (see
274
+ [Design & internals](docs/design.md)).
275
+
276
+ ## Usage
277
+
278
+ One entrypoint, a handful of flags. `uv run chad --help` is the source of truth:
279
+
280
+ ```bash
281
+ uv run chad # full-screen TUI (shift-tab for modes, type to queue, ctrl-c to interrupt)
282
+ uv run chad "do the thing" # one-shot headless task, then exit
283
+ uv run chad -c # resume this directory's most recent conversation
284
+ uv run chad -c "now also add the --verbose flag" # resume and continue headless
285
+ uv run chad --resume # list this directory's recent sessions, pick one by number
286
+ echo "fix the typo in greet.py" | uv run chad "$(cat)" # pipe a task in
287
+ ```
288
+
289
+ | Flag | What it does |
290
+ |---|---|
291
+ | `-c, --continue` | resume this directory's **most recent** session (non-destructive — see [Sessions](#sessions-resume--fork)) |
292
+ | `--resume` | list the directory's recent sessions and pick one by number (interactive TTY only) |
293
+ | `--plan` | start in read-only plan mode (investigate + propose, all edits blocked) |
294
+ | `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
295
+ | `--no-think` | skip Ornith's `<think>` blocks — faster on well-scoped work (thinking is on by default) |
296
+ | `--repl` | plain line REPL instead of the TUI |
297
+
298
+ Curated on purpose — `uv run chad --help` is the full set. Notable extras it lists:
299
+ `--think-budget` / `--turn-budget-tokens` / `--turn-budget-s` / `--auto-continue` (the
300
+ think-cap and runaway-turn governor — see the [Configuration reference](docs/configuration.md#turn-budgets--think-cap));
301
+ `--backend openai` / `--base-url` / `--api-key-env` (a research spike that runs the
302
+ harness against an OpenAI-compatible endpoint); and `--version` (prints `chad 0.1.0`
303
+ plus the checkout's commit — quote it in bug reports).
304
+
305
+ No model flag: chad runs Ornith (the RAM-appropriate size — see [Quickstart](#quickstart)).
306
+ A headless task (positional, or piped with no TTY) auto-approves mutating tools — otherwise
307
+ the confirm prompt would EOF and no file could ever change. Use `--plan` for a read-only
308
+ investigation.
309
+
310
+ The model runs greedy (temp 0). On first run chad downloads it from Hugging Face into
311
+ `~/.cache/huggingface` (~12 GB for the 35B, ~5 GB for the 9B); thereafter it loads from
312
+ that cache.
313
+
314
+ The rarely-touched tuning knobs (`CHAD_MAX_CONTEXT`, `CHAD_KV_BITS`, `CHAD_MODEL`, the
315
+ turn-budget/think-cap and alternate-backend knobs, the safety/A-B opt-outs, and the
316
+ session-log controls) live in environment variables, fully documented in the
317
+ [Configuration reference](docs/configuration.md).
318
+
319
+ ### Sessions (resume + fork)
320
+
321
+ Every conversation is persisted as JSON under `~/.chad/sessions/<cwdhash>/<session_id>.json`
322
+ (one file per session, `0600`, atomic write — the store holds full tool args/results, so
323
+ it is never world-readable). chad keeps **multiple sessions per directory**, so a project
324
+ can carry more than one thread of work:
325
+
326
+ - **`chad -c`** resumes the **most recent** session for this directory — the simple case,
327
+ unchanged. Now non-destructive: older sessions are kept, not overwritten.
328
+ - **`chad --resume`** (and **`/resume`** in the TUI) lists the last ~10 sessions —
329
+ `2h ago · 14 turns · "fix the flaky retry test…"` — and you pick one by number. In the
330
+ TUI, `/resume` prints the numbered list and `/resume <n>` selects. `--resume` needs an
331
+ interactive terminal; headless, use `-c`.
332
+ - **Implicit fork.** Resuming *any* session mints a **new** session id seeded with the old
333
+ messages (copy-on-resume) and writes to a new file — the original is never rewritten. So
334
+ every resume is a branch: go back to a session from before a bad turn and continue it
335
+ without destroying either thread. There is no separate fork command; that's the whole
336
+ feature.
337
+ - **Retention.** The newest 20 sessions per directory are kept; older ones are pruned on
338
+ save. A tiny per-directory `index.json` (title / timestamp / turn count) makes listing
339
+ cheap, and a pre-existing single-slot session file is migrated into the new layout
340
+ automatically the first time you list. Resume still pays a cold re-prefill of the
341
+ restored transcript (only the message list is stored, not the KV cache).
342
+
343
+ ## Extending chad
344
+
345
+ chad speaks the same two extension formats as Claude Code:
346
+
347
+ - **[Agent Skills](https://agentskills.io)** — drop a `SKILL.md` folder in
348
+ `./.claude/skills/` (or `~/.claude/skills/`) and chad discovers it, loading the full
349
+ instructions only when a task matches (progressive disclosure keeps context small).
350
+ - **[MCP servers](https://modelcontextprotocol.io)** — configure stdio or HTTP servers in
351
+ `./.mcp.json` (or `~/.chad/mcp.json`) to expose external tools (GitHub, Postgres, Linear,
352
+ Slack, …) alongside chad's builtins, with static-token and OAuth auth.
353
+
354
+ Both are covered in full — discovery rules, config schema, OAuth flow, the harness
355
+ behavior — in the [Configuration reference](docs/configuration.md).
356
+
357
+ ## Documentation
358
+
359
+ - **[Design & internals](docs/design.md)** — why prefill is the bill, the persistent
360
+ prefix cache, the trimmable/append-only cache trade, why a language server matters on a
361
+ small model, architecture, and the ideas borrowed from other agents.
362
+ - **[Throughput & performance](docs/benchmarks.md)** — prefill / decode / warm-step numbers
363
+ you can reproduce with `chad-bench`, the bandwidth ceiling, and the thinking-budget / PLD
364
+ levers.
365
+ - **[Configuration reference](docs/configuration.md)** — Agent Skills, MCP servers, the
366
+ context window, every environment variable, and the safety opt-outs.
367
+ - **[Troubleshooting](docs/troubleshooting.md)** — when a session rambles, loops, or slows:
368
+ the symptom→knob map for a small local model.
369
+ - **[Contributing](CONTRIBUTING.md)** — what lands easily, and what needs a conversation
370
+ first (behavior changes are eval-gated on a private rig).