chad-code 2.0.3__tar.gz → 2.2.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.
- {chad_code-2.0.3/src/chad_code.egg-info → chad_code-2.2.0}/PKG-INFO +88 -61
- {chad_code-2.0.3 → chad_code-2.2.0}/README.md +85 -59
- {chad_code-2.0.3 → chad_code-2.2.0}/pyproject.toml +56 -3
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/__init__.py +1 -1
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/agent.py +197 -158
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/ambient.py +69 -30
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/atif.py +53 -26
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/base_engine.py +8 -24
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/bench.py +35 -8
- chad_code-2.2.0/src/chad/checkpoint.py +231 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/cli.py +261 -193
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/completion_engine.py +29 -162
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/diag.py +16 -9
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/engine.py +1118 -1149
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/guardrails.py +50 -69
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/ignore.py +0 -5
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/mcp.py +169 -131
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/mcp_oauth.py +61 -44
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/mlx_dflash.py +175 -34
- chad_code-2.2.0/src/chad/mlx_fastpath.py +793 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/mlx_qmm_mma.py +184 -62
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/mlx_qsdpa.py +133 -106
- chad_code-2.2.0/src/chad/prism_pack.py +253 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/prompt.py +6 -7
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/prove.py +67 -23
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/render.py +24 -17
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/repomap.py +91 -21
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/seatbelt.py +132 -102
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/session.py +60 -19
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/skills.py +9 -11
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/speech.py +44 -27
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/spill.py +8 -6
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/toolcall_parse.py +6 -6
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/tools.py +113 -25
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/tui.py +100 -12
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/validate.py +58 -21
- {chad_code-2.0.3 → chad_code-2.2.0/src/chad_code.egg-info}/PKG-INFO +88 -61
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad_code.egg-info/SOURCES.txt +3 -2
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad_code.egg-info/requires.txt +1 -1
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_agent_e2e.py +289 -12
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_agent_guards.py +42 -23
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_ambient.py +66 -45
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_atif.py +33 -12
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_bench.py +22 -14
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_checkpoint.py +73 -4
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_cli.py +165 -160
- chad_code-2.2.0/tests/test_cli_modes.py +235 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_completion_engine.py +30 -15
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_config.py +23 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_confirm_preview.py +23 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_edit.py +42 -30
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_engine.py +240 -98
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_engine_dflash.py +288 -15
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_engine_kvquant.py +1 -3
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_engine_pld_hybrid.py +0 -1
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_engine_pld_wide.py +32 -9
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_feel_pack.py +6 -8
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_gate.py +45 -43
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_intent.py +80 -91
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_log_redaction.py +18 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_matrix_bench.py +104 -1
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_mcp.py +70 -64
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_mcp_oauth.py +9 -10
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_mlx_qmm_mma.py +75 -14
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_mlx_qsdpa.py +22 -30
- chad_code-2.2.0/tests/test_prism_pack.py +374 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_prove.py +68 -1
- chad_code-2.2.0/tests/test_repomap.py +295 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_seatbelt.py +101 -82
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_session.py +106 -22
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_skills.py +2 -3
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_speech_tui.py +165 -149
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_spill.py +3 -4
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_toolcall_parse.py +17 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_tools.py +138 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_tui.py +41 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_validate.py +36 -3
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_warm_prefix_tiers.py +87 -72
- chad_code-2.0.3/src/chad/checkpoint.py +0 -149
- chad_code-2.0.3/src/chad/mlx_fastpath.py +0 -409
- chad_code-2.0.3/src/chad/serve.py +0 -823
- chad_code-2.0.3/tests/test_repomap.py +0 -198
- chad_code-2.0.3/tests/test_serve.py +0 -815
- {chad_code-2.0.3 → chad_code-2.2.0}/LICENSE +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/setup.cfg +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/compaction.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/config.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/levers.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/LICENSE +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/__init__.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/alignment.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/attention.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/audio.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/cache.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/conformer.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/ctc.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/parakeet.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/rnnt.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/tokenizer.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/parakeet/utils.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad/syntaxgate.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad_code.egg-info/dependency_links.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad_code.egg-info/entry_points.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/src/chad_code.egg-info/top_level.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_agent.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_compaction.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_ignore.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_levers.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_mlx_fastpath.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_render.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_repomap_polyglot.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_speech.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_syntaxgate.py +0 -0
- {chad_code-2.0.3 → chad_code-2.2.0}/tests/test_toolcall_dialect.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chad-code
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Claude-Code-style coding agent that runs entirely on a 24 GB Apple Silicon Mac (MLX, Qwen3.8-27B)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/nathansutton/chad
|
|
@@ -13,11 +13,12 @@ Classifier: Operating System :: MacOS
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
17
|
Classifier: Topic :: Software Development :: Code Generators
|
|
17
18
|
Requires-Python: >=3.11
|
|
18
19
|
Description-Content-Type: text/markdown
|
|
19
20
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: mlx
|
|
21
|
+
Requires-Dist: mlx!=0.32.1,<=0.32.2,>=0.32.0; sys_platform == "darwin"
|
|
21
22
|
Requires-Dist: mlx-lm<0.32,>=0.31.3; sys_platform == "darwin"
|
|
22
23
|
Requires-Dist: transformers<5.13,>=5.0
|
|
23
24
|
Requires-Dist: jinja2>=3.1
|
|
@@ -43,9 +44,13 @@ Dynamic: license-file
|
|
|
43
44
|
> *Coding under supervision.*
|
|
44
45
|
|
|
45
46
|
chad is a single-user coding agent that runs entirely on an Apple Silicon Mac via
|
|
46
|
-
[MLX](https://github.com/ml-explore/mlx). One 27B model and no API key.
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
[MLX](https://github.com/ml-explore/mlx). One 27B model and no API key. (Not affiliated
|
|
48
|
+
with Anthropic.)
|
|
49
|
+
|
|
50
|
+
Plenty of harnesses run local models now, and [pi](https://pi.dev) is a fantastic default
|
|
51
|
+
for the same reason llama.cpp is: it works with everything. I was steering chad in the
|
|
52
|
+
opposite direction. One model and one set of silicon, taken to the max. Swap out your
|
|
53
|
+
`CHAD_MODEL` and it still runs, you just leave the drafter and the kernels behind.
|
|
49
54
|
|
|
50
55
|
## Try it
|
|
51
56
|
|
|
@@ -54,13 +59,13 @@ uvx chad-code # runs anywhere; the command is still `chad`
|
|
|
54
59
|
uvx chad-code prove # offline smoke test: 4 tiny fix-it tasks, verified, timed 🗿
|
|
55
60
|
```
|
|
56
61
|
|
|
57
|
-
The first run asks, then downloads the model once (~
|
|
62
|
+
The first run asks, then downloads the model once (~8 GB) into the shared Hugging
|
|
58
63
|
Face cache. While it downloads, `cd` into a project and think of a scoped first ask:
|
|
59
64
|
*"fix the failing test in `tests/test_x.py`"* lands, *"improve my codebase"* flails.
|
|
60
65
|
|
|
61
66
|
chad targets 24 GB and nothing smaller. It runs below that and tells you it is doing so,
|
|
62
|
-
but
|
|
63
|
-
window too small to work in.
|
|
67
|
+
but 8 GB of weights and drafter plus a ~4 GB prefill transient sit resident before a single
|
|
68
|
+
token of context, so a 16 GB Mac gets a window too small to work in.
|
|
64
69
|
|
|
65
70
|
The PyPI package is `chad-code`. Bare `chad` is an unrelated squatted package.
|
|
66
71
|
|
|
@@ -73,32 +78,42 @@ The PyPI package is `chad-code`. Bare `chad` is an unrelated squatted package.
|
|
|
73
78
|
|
|
74
79
|
## Same model, same Mac, stock engine
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
resident at a time, each measured with its own benchmark on a 512-token prompt and a
|
|
81
|
+
What do you gain over pointing a generic local-model tool at the same weights?
|
|
82
|
+
Qwen3.8-27B at the `UD-Q3_K_XL` recipe (Unsloth's GGUF for llama.cpp, chad's MLX
|
|
83
|
+
conversion of the same bit map; chad runs it with `--model`), the same M4 Pro (24 GB), one
|
|
84
|
+
engine resident at a time, each measured with its own benchmark on a 512-token prompt and a
|
|
80
85
|
128-token generation.
|
|
81
86
|
|
|
82
87
|
| Engine | Prefill (512-tok prompt) | Decode (128 tok) | Speculative decoding |
|
|
83
88
|
|---|---|---|---|
|
|
84
|
-
| llama.cpp `llama-bench` (stock, build 10470) | 102 tok/s | 10.9 tok/s |
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
for
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
| llama.cpp `llama-bench` (stock, build 10470) | 102 tok/s | 10.9 tok/s | off in this benchmark |
|
|
90
|
+
| llama.cpp `llama-server` (build 10917), serial | 97 tok/s | 11.3 tok/s | off |
|
|
91
|
+
| llama.cpp `llama-server` (build 10917) | 95 tok/s | 11.1 tok/s² | DFlash2 drafter (Q4_K_M GGUF) |
|
|
92
|
+
| **chad**, serial (`CHAD_NO_DFLASH=1`) | 100 tok/s | 17.9 tok/s | off |
|
|
93
|
+
| **chad** | 101 tok/s | **62.9 tok/s**¹ | DFlash2 block drafter |
|
|
94
|
+
|
|
95
|
+
A 200-token function body takes roughly 18 seconds at 10.9 tok/s and 3 at 63. You wait for
|
|
96
|
+
the first one and you talk to the second.
|
|
97
|
+
|
|
98
|
+
The weights chad ships by default are the same model in Prism ML's **ternary** build
|
|
99
|
+
(every projection Hadamard-rotated and stored at 2 bits): 7.2 GB resident instead of 12.3,
|
|
100
|
+
the same 64 tok/s drafted and 21 serial on this Mac, and the 5 GB it gives back is
|
|
101
|
+
context, roughly a **150k-token window** where the 3-bit landed near 56k. The like-for-like
|
|
102
|
+
table above stays on the 3-bit recipe because that is the quant llama.cpp has a GGUF of.
|
|
103
|
+
|
|
104
|
+
Ollama does not get its own row: it is llama.cpp underneath, measured without speculative
|
|
105
|
+
decoding, and on the same GGUF (0.32.15, Modelfile `FROM` only) it measures 96 tok/s
|
|
94
106
|
prefill and the same **10.9** decode.
|
|
95
107
|
|
|
96
|
-
¹
|
|
97
|
-
against ten real mid-session contexts from `~/.chad/sessions` (12
|
|
108
|
+
¹ 63 is a ceiling: `chad-bench`'s prompt is tiled code the drafter reads easily. Replayed
|
|
109
|
+
against ten real mid-session contexts from `~/.chad/sessions` (12-19k tokens, tool results in
|
|
98
110
|
place, 384-token decodes) the same engine measures **31.7 tok/s median / 21.4 floor** greedy
|
|
99
111
|
against 14.8 serial, and **27.6 / 17.7** thinking against 13.9. That ~2× is what a session
|
|
100
|
-
lives at.
|
|
101
|
-
|
|
112
|
+
lives at.
|
|
113
|
+
|
|
114
|
+
² llama.cpp has run DFlash2 since build 10658. Here it accepts 96.5% of drafted tokens and still
|
|
115
|
+
gains nothing: verifying 8 tokens costs ~6.4 serial steps on this GGUF and Mac
|
|
116
|
+
([details](docs/benchmarks.md#same-model-same-mac-stock-engine)).
|
|
102
117
|
|
|
103
118
|
Method, the longer runs and the caveats are in
|
|
104
119
|
[Throughput & performance](docs/benchmarks.md#same-model-same-mac-stock-engine); the rows are
|
|
@@ -110,17 +125,17 @@ committed under [`benchmarks/stock/_runs/`](benchmarks/stock/); reproduce them w
|
|
|
110
125
|
chad owns its inference loop instead of talking to a server, and the engine is fitted to the
|
|
111
126
|
one checkpoint it ships:
|
|
112
127
|
|
|
113
|
-
-
|
|
128
|
+
- DFlash2 block speculation. A bundled 1.9B drafter ([z-lab's DFlash2](https://huggingface.co/z-lab/Qwen3.8-27B-DFlash2),
|
|
114
129
|
ported to MLX and quantized) proposes a whole block of tokens from the main model's own
|
|
115
130
|
hidden states. The main model verifies the block in one batched forward, and exact
|
|
116
131
|
rejection sampling keeps every emitted token the model's own.
|
|
117
|
-
-
|
|
132
|
+
- A persistent prefix KV cache. The transcript is kept a strict token-prefix of the live
|
|
118
133
|
cache, so a follow-up step prefills the ~16 tokens it appended instead of the 5,000 it
|
|
119
|
-
already read: **~0.
|
|
134
|
+
already read: **~0.55 s per step instead of ~48 s**. Any server with prompt caching gets
|
|
120
135
|
the easy case; the work is holding it true across compaction, truncated turns and restarts.
|
|
121
136
|
The system prefix is checkpointed to disk, so the second session anywhere starts warm
|
|
122
137
|
(75.6 s → 5.5 s to the first tool call).
|
|
123
|
-
-
|
|
138
|
+
- Fused Metal kernels. Quantized-KV attention, a small-M matmul for speculative verify,
|
|
124
139
|
and a compiled single-token layer step, chosen per machine at load time, no knobs.
|
|
125
140
|
|
|
126
141
|
## What chad gives up
|
|
@@ -146,16 +161,21 @@ budget; everything else is deliberately plain.
|
|
|
146
161
|
|
|
147
162
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
148
163
|
|
|
149
|
-
-
|
|
164
|
+
- shift-tab cycles permission modes: `normal` (confirm each bash/write/edit) →
|
|
150
165
|
`auto-accept edits` (edits land silently, **terminal commands still ask**) → `yolo`
|
|
151
166
|
(nothing asks) → `plan mode` (read-only: investigate and propose a numbered plan) → back.
|
|
152
|
-
|
|
153
|
-
|
|
167
|
+
A finished plan lands in `./plans/`; ctrl-g (or `/accept`) clears the context and starts
|
|
168
|
+
implementing it ([details](docs/configuration.md#plan-mode)).
|
|
169
|
+
- Type-ahead message queue. Keep typing while the agent works; messages run in order.
|
|
170
|
+
- ctrl-c interrupts the running turn without killing the session. **↑prefilled /
|
|
154
171
|
↓generated** token counts show an advancing **%** on an unavoidable full re-prefill, so it
|
|
155
172
|
is never silent.
|
|
156
|
-
-
|
|
173
|
+
- `@file` / `@dir` mentions and `!command` shell passthrough. Pull a file into
|
|
157
174
|
context inline, or run a shell command without invoking the model.
|
|
158
|
-
-
|
|
175
|
+
- Standing project instructions. A `CLAUDE.md` (or `AGENTS.md`) in the working directory is
|
|
176
|
+
appended to the system prompt, and `/init` reads the project and writes one for you
|
|
177
|
+
([details](docs/configuration.md#project-instructions-claudemd--agentsmd)).
|
|
178
|
+
- Voice mode, all local. `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes into
|
|
159
179
|
the input box for you to review before Enter sends it, and replies are read aloud via macOS
|
|
160
180
|
`say`. A word table teaches it your identifiers. Needs the `speech` extra
|
|
161
181
|
([details](docs/configuration.md#voice-mode-speech)).
|
|
@@ -169,12 +189,13 @@ budget; everything else is deliberately plain.
|
|
|
169
189
|
| `--plan` | start in read-only plan mode (investigate and propose, edits blocked) |
|
|
170
190
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
171
191
|
| `--no-think` | skip the model's `<think>` blocks, faster on well-scoped work |
|
|
192
|
+
| `--think-budget N` | soft-cap each step's `<think>` at N tokens, force-close it and carry on (off by default) |
|
|
193
|
+
| `--backend llama` | run the same harness against a remote llama.cpp server, with `--base-url`, `--tokenizer` and `--api-key-env` ([details](docs/configuration.md#alternate-backend-remote)) |
|
|
172
194
|
| `--model` | `auto` (the shipped default), or any HF repo id / local model dir |
|
|
173
195
|
| `--repl` | plain line REPL instead of the TUI |
|
|
174
196
|
|
|
175
|
-
|
|
176
|
-
`chad
|
|
177
|
-
and `chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
197
|
+
Two subcommands, each with its own `--help`: `chad prove` (the offline smoke test) and
|
|
198
|
+
`chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
178
199
|
|
|
179
200
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools and runs
|
|
180
201
|
greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every resume
|
|
@@ -187,20 +208,24 @@ chad ships exactly one, downloaded once into the shared Hugging Face cache
|
|
|
187
208
|
|
|
188
209
|
| Model | Quant | Footprint |
|
|
189
210
|
|---|---|---|
|
|
190
|
-
| [Qwen3.8-27B `
|
|
211
|
+
| [Qwen3.8-27B `Ternary-Bonsai-2-DFlash2`](https://huggingface.co/nathansutton/Qwen3.8-27B-Ternary-Bonsai-2-DFlash2-MLX) (default) | Prism ML's ternary build: Hadamard-rotated, 2-bit group-128, levels {−s, 0, +s}; bundled 4-bit DFlash2 drafter | ~8 GB resident, 262k native context, ~150k usable on 24 GB |
|
|
212
|
+
| [Qwen3.8-27B `UD-Q3_K_XL-DFlash2`](https://huggingface.co/nathansutton/Qwen3.8-27B-UD-Q3_K_XL-DFlash2-MLX) via `--model` | 3-bit group-64 body, 5-bit `lm_head`, the same bundled drafter | ~13 GB resident, ~56k usable on 24 GB |
|
|
191
213
|
|
|
192
214
|
Qwen3.8-27B is **dense** (64 layers: 48 GatedDeltaNet + 16 full attention), so every
|
|
193
|
-
parameter is on the critical path for every token and the quant is where decode speed
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
215
|
+
parameter is on the critical path for every token and the quant is where both decode speed
|
|
216
|
+
and context come from: the governor prices a gigabyte of weights at about 29k tokens of
|
|
217
|
+
window. The ternary build is Prism ML's [Bonsai](https://huggingface.co/prism-ml/Ternary-Bonsai-2-27B-mlx-2bit)
|
|
218
|
+
pack of this checkpoint, repacked text-only with the base tokenizer and the drafter
|
|
219
|
+
bundled (Apache-2.0; created using Bonsai by Prism ML). Its projections are stored in a
|
|
220
|
+
rotated basis that an ordinary MLX loader would silently get wrong, so chad carries its own
|
|
221
|
+
loader for it and fits the decode fast-path, the verify kernel and the drafter to it. What it
|
|
222
|
+
costs: on code, teacher-forced perplexity is 4.49 against the 3-bit's 3.99 (+12%), while
|
|
223
|
+
the private eval tiers tie at 56/56. The 3-bit stays one flag away.
|
|
199
224
|
|
|
200
225
|
`--model <repo or local dir>` runs different weights through the same engine and stays a
|
|
201
226
|
first-class escape hatch. The drafter, the fused-attention coverage, the decode fastpath and
|
|
202
|
-
the context governor are all fitted to the
|
|
203
|
-
they do not break.
|
|
227
|
+
the context governor are all fitted to the two checkpoints above, so other weights run
|
|
228
|
+
slower; they do not break.
|
|
204
229
|
|
|
205
230
|
## Installing & upgrading
|
|
206
231
|
|
|
@@ -220,7 +245,7 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
220
245
|
uv run chad -c # resume this directory's last conversation
|
|
221
246
|
```
|
|
222
247
|
|
|
223
|
-
|
|
248
|
+
Two features are opt-in because they pull deps not every install wants:
|
|
224
249
|
`speech` (voice mode: a mic library, no torch) and `highlight` (syntax colour in diffs and
|
|
225
250
|
previews). An extra rides on the install spec, not on a separate command, so how you add it
|
|
226
251
|
depends on how you installed chad:
|
|
@@ -234,12 +259,12 @@ uv sync --extra speech # from a clone
|
|
|
234
259
|
`/speech` in the TUI prints whichever of those matches your install, so you never have to
|
|
235
260
|
work it out from here.
|
|
236
261
|
|
|
237
|
-
|
|
262
|
+
Upgrading depends on how you installed: `uv tool upgrade chad-code`, `uvx --refresh
|
|
238
263
|
chad-code`, or `git pull && uv sync` for a clone. What changed lands in
|
|
239
264
|
[`CHANGELOG.md`](CHANGELOG.md). Model weights are versioned separately, so a code upgrade
|
|
240
265
|
never re-downloads the model.
|
|
241
266
|
|
|
242
|
-
|
|
267
|
+
For development, `uv sync` once, then `uv run pytest -q`. The fast unit gate loads **no model
|
|
243
268
|
weights**, runs in seconds, and is what CI runs. For throughput on your own machine, use
|
|
244
269
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)).
|
|
245
270
|
|
|
@@ -247,11 +272,12 @@ weights**, runs in seconds, and is what CI runs. For throughput on your own mach
|
|
|
247
272
|
|
|
248
273
|
chad speaks the same two extension formats as Claude Code:
|
|
249
274
|
|
|
250
|
-
-
|
|
251
|
-
`./.claude/skills/` and it becomes a slash command:
|
|
252
|
-
Skills cost nothing until you run one, because
|
|
253
|
-
prompt.
|
|
254
|
-
|
|
275
|
+
- [Agent Skills](https://agentskills.io). Drop a `SKILL.md` folder in `./.agents/skills/`
|
|
276
|
+
or `./.claude/skills/` (or under `~/` for every project) and it becomes a slash command:
|
|
277
|
+
`/ship`, `/investigate the flaky test`. Skills cost nothing until you run one, because
|
|
278
|
+
chad puts no skill catalog in the system prompt. Precedence and the full list of roots
|
|
279
|
+
are in the [Configuration reference](docs/configuration.md#agent-skills-agentskillsio).
|
|
280
|
+
- [MCP servers](https://modelcontextprotocol.io). Configure stdio or HTTP servers in
|
|
255
281
|
`./.mcp.json` to expose external tools (GitHub, Postgres, Linear, Slack, …) alongside
|
|
256
282
|
chad's builtins, with static-token and OAuth auth.
|
|
257
283
|
|
|
@@ -259,16 +285,17 @@ Both are covered in full in the [Configuration reference](docs/configuration.md)
|
|
|
259
285
|
|
|
260
286
|
## Documentation
|
|
261
287
|
|
|
262
|
-
-
|
|
288
|
+
- [Design & internals](docs/design.md) covers why prefill is the bill, the persistent
|
|
263
289
|
prefix cache, the trimmable/append-only trade, why the tool surface is five tools, and the
|
|
264
290
|
ideas borrowed from other agents.
|
|
265
|
-
-
|
|
291
|
+
- [Throughput & performance](docs/benchmarks.md) has the prefill, decode and warm-step
|
|
266
292
|
numbers you can reproduce with `chad-bench`, the stock-engine comparison, and what the
|
|
267
293
|
cross-session warm start is worth.
|
|
268
|
-
-
|
|
269
|
-
|
|
270
|
-
|
|
294
|
+
- [Configuration reference](docs/configuration.md) documents project instructions, Agent
|
|
295
|
+
Skills, MCP servers, plan mode, the slash commands, the context window, every environment
|
|
296
|
+
variable, and the safety opt-outs.
|
|
297
|
+
- [Troubleshooting](docs/troubleshooting.md) maps symptoms to knobs for when a session
|
|
271
298
|
rambles, loops, or slows.
|
|
272
|
-
-
|
|
299
|
+
- [Contributing](CONTRIBUTING.md) says what lands easily and what needs a conversation
|
|
273
300
|
first.
|
|
274
301
|
|
|
@@ -8,9 +8,13 @@
|
|
|
8
8
|
> *Coding under supervision.*
|
|
9
9
|
|
|
10
10
|
chad is a single-user coding agent that runs entirely on an Apple Silicon Mac via
|
|
11
|
-
[MLX](https://github.com/ml-explore/mlx). One 27B model and no API key.
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
[MLX](https://github.com/ml-explore/mlx). One 27B model and no API key. (Not affiliated
|
|
12
|
+
with Anthropic.)
|
|
13
|
+
|
|
14
|
+
Plenty of harnesses run local models now, and [pi](https://pi.dev) is a fantastic default
|
|
15
|
+
for the same reason llama.cpp is: it works with everything. I was steering chad in the
|
|
16
|
+
opposite direction. One model and one set of silicon, taken to the max. Swap out your
|
|
17
|
+
`CHAD_MODEL` and it still runs, you just leave the drafter and the kernels behind.
|
|
14
18
|
|
|
15
19
|
## Try it
|
|
16
20
|
|
|
@@ -19,13 +23,13 @@ uvx chad-code # runs anywhere; the command is still `chad`
|
|
|
19
23
|
uvx chad-code prove # offline smoke test: 4 tiny fix-it tasks, verified, timed 🗿
|
|
20
24
|
```
|
|
21
25
|
|
|
22
|
-
The first run asks, then downloads the model once (~
|
|
26
|
+
The first run asks, then downloads the model once (~8 GB) into the shared Hugging
|
|
23
27
|
Face cache. While it downloads, `cd` into a project and think of a scoped first ask:
|
|
24
28
|
*"fix the failing test in `tests/test_x.py`"* lands, *"improve my codebase"* flails.
|
|
25
29
|
|
|
26
30
|
chad targets 24 GB and nothing smaller. It runs below that and tells you it is doing so,
|
|
27
|
-
but
|
|
28
|
-
window too small to work in.
|
|
31
|
+
but 8 GB of weights and drafter plus a ~4 GB prefill transient sit resident before a single
|
|
32
|
+
token of context, so a 16 GB Mac gets a window too small to work in.
|
|
29
33
|
|
|
30
34
|
The PyPI package is `chad-code`. Bare `chad` is an unrelated squatted package.
|
|
31
35
|
|
|
@@ -38,32 +42,42 @@ The PyPI package is `chad-code`. Bare `chad` is an unrelated squatted package.
|
|
|
38
42
|
|
|
39
43
|
## Same model, same Mac, stock engine
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
resident at a time, each measured with its own benchmark on a 512-token prompt and a
|
|
45
|
+
What do you gain over pointing a generic local-model tool at the same weights?
|
|
46
|
+
Qwen3.8-27B at the `UD-Q3_K_XL` recipe (Unsloth's GGUF for llama.cpp, chad's MLX
|
|
47
|
+
conversion of the same bit map; chad runs it with `--model`), the same M4 Pro (24 GB), one
|
|
48
|
+
engine resident at a time, each measured with its own benchmark on a 512-token prompt and a
|
|
45
49
|
128-token generation.
|
|
46
50
|
|
|
47
51
|
| Engine | Prefill (512-tok prompt) | Decode (128 tok) | Speculative decoding |
|
|
48
52
|
|---|---|---|---|
|
|
49
|
-
| llama.cpp `llama-bench` (stock, build 10470) | 102 tok/s | 10.9 tok/s |
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
for
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
| llama.cpp `llama-bench` (stock, build 10470) | 102 tok/s | 10.9 tok/s | off in this benchmark |
|
|
54
|
+
| llama.cpp `llama-server` (build 10917), serial | 97 tok/s | 11.3 tok/s | off |
|
|
55
|
+
| llama.cpp `llama-server` (build 10917) | 95 tok/s | 11.1 tok/s² | DFlash2 drafter (Q4_K_M GGUF) |
|
|
56
|
+
| **chad**, serial (`CHAD_NO_DFLASH=1`) | 100 tok/s | 17.9 tok/s | off |
|
|
57
|
+
| **chad** | 101 tok/s | **62.9 tok/s**¹ | DFlash2 block drafter |
|
|
58
|
+
|
|
59
|
+
A 200-token function body takes roughly 18 seconds at 10.9 tok/s and 3 at 63. You wait for
|
|
60
|
+
the first one and you talk to the second.
|
|
61
|
+
|
|
62
|
+
The weights chad ships by default are the same model in Prism ML's **ternary** build
|
|
63
|
+
(every projection Hadamard-rotated and stored at 2 bits): 7.2 GB resident instead of 12.3,
|
|
64
|
+
the same 64 tok/s drafted and 21 serial on this Mac, and the 5 GB it gives back is
|
|
65
|
+
context, roughly a **150k-token window** where the 3-bit landed near 56k. The like-for-like
|
|
66
|
+
table above stays on the 3-bit recipe because that is the quant llama.cpp has a GGUF of.
|
|
67
|
+
|
|
68
|
+
Ollama does not get its own row: it is llama.cpp underneath, measured without speculative
|
|
69
|
+
decoding, and on the same GGUF (0.32.15, Modelfile `FROM` only) it measures 96 tok/s
|
|
59
70
|
prefill and the same **10.9** decode.
|
|
60
71
|
|
|
61
|
-
¹
|
|
62
|
-
against ten real mid-session contexts from `~/.chad/sessions` (12
|
|
72
|
+
¹ 63 is a ceiling: `chad-bench`'s prompt is tiled code the drafter reads easily. Replayed
|
|
73
|
+
against ten real mid-session contexts from `~/.chad/sessions` (12-19k tokens, tool results in
|
|
63
74
|
place, 384-token decodes) the same engine measures **31.7 tok/s median / 21.4 floor** greedy
|
|
64
75
|
against 14.8 serial, and **27.6 / 17.7** thinking against 13.9. That ~2× is what a session
|
|
65
|
-
lives at.
|
|
66
|
-
|
|
76
|
+
lives at.
|
|
77
|
+
|
|
78
|
+
² llama.cpp has run DFlash2 since build 10658. Here it accepts 96.5% of drafted tokens and still
|
|
79
|
+
gains nothing: verifying 8 tokens costs ~6.4 serial steps on this GGUF and Mac
|
|
80
|
+
([details](docs/benchmarks.md#same-model-same-mac-stock-engine)).
|
|
67
81
|
|
|
68
82
|
Method, the longer runs and the caveats are in
|
|
69
83
|
[Throughput & performance](docs/benchmarks.md#same-model-same-mac-stock-engine); the rows are
|
|
@@ -75,17 +89,17 @@ committed under [`benchmarks/stock/_runs/`](benchmarks/stock/); reproduce them w
|
|
|
75
89
|
chad owns its inference loop instead of talking to a server, and the engine is fitted to the
|
|
76
90
|
one checkpoint it ships:
|
|
77
91
|
|
|
78
|
-
-
|
|
92
|
+
- DFlash2 block speculation. A bundled 1.9B drafter ([z-lab's DFlash2](https://huggingface.co/z-lab/Qwen3.8-27B-DFlash2),
|
|
79
93
|
ported to MLX and quantized) proposes a whole block of tokens from the main model's own
|
|
80
94
|
hidden states. The main model verifies the block in one batched forward, and exact
|
|
81
95
|
rejection sampling keeps every emitted token the model's own.
|
|
82
|
-
-
|
|
96
|
+
- A persistent prefix KV cache. The transcript is kept a strict token-prefix of the live
|
|
83
97
|
cache, so a follow-up step prefills the ~16 tokens it appended instead of the 5,000 it
|
|
84
|
-
already read: **~0.
|
|
98
|
+
already read: **~0.55 s per step instead of ~48 s**. Any server with prompt caching gets
|
|
85
99
|
the easy case; the work is holding it true across compaction, truncated turns and restarts.
|
|
86
100
|
The system prefix is checkpointed to disk, so the second session anywhere starts warm
|
|
87
101
|
(75.6 s → 5.5 s to the first tool call).
|
|
88
|
-
-
|
|
102
|
+
- Fused Metal kernels. Quantized-KV attention, a small-M matmul for speculative verify,
|
|
89
103
|
and a compiled single-token layer step, chosen per machine at load time, no knobs.
|
|
90
104
|
|
|
91
105
|
## What chad gives up
|
|
@@ -111,16 +125,21 @@ budget; everything else is deliberately plain.
|
|
|
111
125
|
|
|
112
126
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
113
127
|
|
|
114
|
-
-
|
|
128
|
+
- shift-tab cycles permission modes: `normal` (confirm each bash/write/edit) →
|
|
115
129
|
`auto-accept edits` (edits land silently, **terminal commands still ask**) → `yolo`
|
|
116
130
|
(nothing asks) → `plan mode` (read-only: investigate and propose a numbered plan) → back.
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
A finished plan lands in `./plans/`; ctrl-g (or `/accept`) clears the context and starts
|
|
132
|
+
implementing it ([details](docs/configuration.md#plan-mode)).
|
|
133
|
+
- Type-ahead message queue. Keep typing while the agent works; messages run in order.
|
|
134
|
+
- ctrl-c interrupts the running turn without killing the session. **↑prefilled /
|
|
119
135
|
↓generated** token counts show an advancing **%** on an unavoidable full re-prefill, so it
|
|
120
136
|
is never silent.
|
|
121
|
-
-
|
|
137
|
+
- `@file` / `@dir` mentions and `!command` shell passthrough. Pull a file into
|
|
122
138
|
context inline, or run a shell command without invoking the model.
|
|
123
|
-
-
|
|
139
|
+
- Standing project instructions. A `CLAUDE.md` (or `AGENTS.md`) in the working directory is
|
|
140
|
+
appended to the system prompt, and `/init` reads the project and writes one for you
|
|
141
|
+
([details](docs/configuration.md#project-instructions-claudemd--agentsmd)).
|
|
142
|
+
- Voice mode, all local. `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes into
|
|
124
143
|
the input box for you to review before Enter sends it, and replies are read aloud via macOS
|
|
125
144
|
`say`. A word table teaches it your identifiers. Needs the `speech` extra
|
|
126
145
|
([details](docs/configuration.md#voice-mode-speech)).
|
|
@@ -134,12 +153,13 @@ budget; everything else is deliberately plain.
|
|
|
134
153
|
| `--plan` | start in read-only plan mode (investigate and propose, edits blocked) |
|
|
135
154
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
136
155
|
| `--no-think` | skip the model's `<think>` blocks, faster on well-scoped work |
|
|
156
|
+
| `--think-budget N` | soft-cap each step's `<think>` at N tokens, force-close it and carry on (off by default) |
|
|
157
|
+
| `--backend llama` | run the same harness against a remote llama.cpp server, with `--base-url`, `--tokenizer` and `--api-key-env` ([details](docs/configuration.md#alternate-backend-remote)) |
|
|
137
158
|
| `--model` | `auto` (the shipped default), or any HF repo id / local model dir |
|
|
138
159
|
| `--repl` | plain line REPL instead of the TUI |
|
|
139
160
|
|
|
140
|
-
|
|
141
|
-
`chad
|
|
142
|
-
and `chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
161
|
+
Two subcommands, each with its own `--help`: `chad prove` (the offline smoke test) and
|
|
162
|
+
`chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
143
163
|
|
|
144
164
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools and runs
|
|
145
165
|
greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every resume
|
|
@@ -152,20 +172,24 @@ chad ships exactly one, downloaded once into the shared Hugging Face cache
|
|
|
152
172
|
|
|
153
173
|
| Model | Quant | Footprint |
|
|
154
174
|
|---|---|---|
|
|
155
|
-
| [Qwen3.8-27B `
|
|
175
|
+
| [Qwen3.8-27B `Ternary-Bonsai-2-DFlash2`](https://huggingface.co/nathansutton/Qwen3.8-27B-Ternary-Bonsai-2-DFlash2-MLX) (default) | Prism ML's ternary build: Hadamard-rotated, 2-bit group-128, levels {−s, 0, +s}; bundled 4-bit DFlash2 drafter | ~8 GB resident, 262k native context, ~150k usable on 24 GB |
|
|
176
|
+
| [Qwen3.8-27B `UD-Q3_K_XL-DFlash2`](https://huggingface.co/nathansutton/Qwen3.8-27B-UD-Q3_K_XL-DFlash2-MLX) via `--model` | 3-bit group-64 body, 5-bit `lm_head`, the same bundled drafter | ~13 GB resident, ~56k usable on 24 GB |
|
|
156
177
|
|
|
157
178
|
Qwen3.8-27B is **dense** (64 layers: 48 GatedDeltaNet + 16 full attention), so every
|
|
158
|
-
parameter is on the critical path for every token and the quant is where decode speed
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
179
|
+
parameter is on the critical path for every token and the quant is where both decode speed
|
|
180
|
+
and context come from: the governor prices a gigabyte of weights at about 29k tokens of
|
|
181
|
+
window. The ternary build is Prism ML's [Bonsai](https://huggingface.co/prism-ml/Ternary-Bonsai-2-27B-mlx-2bit)
|
|
182
|
+
pack of this checkpoint, repacked text-only with the base tokenizer and the drafter
|
|
183
|
+
bundled (Apache-2.0; created using Bonsai by Prism ML). Its projections are stored in a
|
|
184
|
+
rotated basis that an ordinary MLX loader would silently get wrong, so chad carries its own
|
|
185
|
+
loader for it and fits the decode fast-path, the verify kernel and the drafter to it. What it
|
|
186
|
+
costs: on code, teacher-forced perplexity is 4.49 against the 3-bit's 3.99 (+12%), while
|
|
187
|
+
the private eval tiers tie at 56/56. The 3-bit stays one flag away.
|
|
164
188
|
|
|
165
189
|
`--model <repo or local dir>` runs different weights through the same engine and stays a
|
|
166
190
|
first-class escape hatch. The drafter, the fused-attention coverage, the decode fastpath and
|
|
167
|
-
the context governor are all fitted to the
|
|
168
|
-
they do not break.
|
|
191
|
+
the context governor are all fitted to the two checkpoints above, so other weights run
|
|
192
|
+
slower; they do not break.
|
|
169
193
|
|
|
170
194
|
## Installing & upgrading
|
|
171
195
|
|
|
@@ -185,7 +209,7 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
185
209
|
uv run chad -c # resume this directory's last conversation
|
|
186
210
|
```
|
|
187
211
|
|
|
188
|
-
|
|
212
|
+
Two features are opt-in because they pull deps not every install wants:
|
|
189
213
|
`speech` (voice mode: a mic library, no torch) and `highlight` (syntax colour in diffs and
|
|
190
214
|
previews). An extra rides on the install spec, not on a separate command, so how you add it
|
|
191
215
|
depends on how you installed chad:
|
|
@@ -199,12 +223,12 @@ uv sync --extra speech # from a clone
|
|
|
199
223
|
`/speech` in the TUI prints whichever of those matches your install, so you never have to
|
|
200
224
|
work it out from here.
|
|
201
225
|
|
|
202
|
-
|
|
226
|
+
Upgrading depends on how you installed: `uv tool upgrade chad-code`, `uvx --refresh
|
|
203
227
|
chad-code`, or `git pull && uv sync` for a clone. What changed lands in
|
|
204
228
|
[`CHANGELOG.md`](CHANGELOG.md). Model weights are versioned separately, so a code upgrade
|
|
205
229
|
never re-downloads the model.
|
|
206
230
|
|
|
207
|
-
|
|
231
|
+
For development, `uv sync` once, then `uv run pytest -q`. The fast unit gate loads **no model
|
|
208
232
|
weights**, runs in seconds, and is what CI runs. For throughput on your own machine, use
|
|
209
233
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)).
|
|
210
234
|
|
|
@@ -212,11 +236,12 @@ weights**, runs in seconds, and is what CI runs. For throughput on your own mach
|
|
|
212
236
|
|
|
213
237
|
chad speaks the same two extension formats as Claude Code:
|
|
214
238
|
|
|
215
|
-
-
|
|
216
|
-
`./.claude/skills/` and it becomes a slash command:
|
|
217
|
-
Skills cost nothing until you run one, because
|
|
218
|
-
prompt.
|
|
219
|
-
|
|
239
|
+
- [Agent Skills](https://agentskills.io). Drop a `SKILL.md` folder in `./.agents/skills/`
|
|
240
|
+
or `./.claude/skills/` (or under `~/` for every project) and it becomes a slash command:
|
|
241
|
+
`/ship`, `/investigate the flaky test`. Skills cost nothing until you run one, because
|
|
242
|
+
chad puts no skill catalog in the system prompt. Precedence and the full list of roots
|
|
243
|
+
are in the [Configuration reference](docs/configuration.md#agent-skills-agentskillsio).
|
|
244
|
+
- [MCP servers](https://modelcontextprotocol.io). Configure stdio or HTTP servers in
|
|
220
245
|
`./.mcp.json` to expose external tools (GitHub, Postgres, Linear, Slack, …) alongside
|
|
221
246
|
chad's builtins, with static-token and OAuth auth.
|
|
222
247
|
|
|
@@ -224,16 +249,17 @@ Both are covered in full in the [Configuration reference](docs/configuration.md)
|
|
|
224
249
|
|
|
225
250
|
## Documentation
|
|
226
251
|
|
|
227
|
-
-
|
|
252
|
+
- [Design & internals](docs/design.md) covers why prefill is the bill, the persistent
|
|
228
253
|
prefix cache, the trimmable/append-only trade, why the tool surface is five tools, and the
|
|
229
254
|
ideas borrowed from other agents.
|
|
230
|
-
-
|
|
255
|
+
- [Throughput & performance](docs/benchmarks.md) has the prefill, decode and warm-step
|
|
231
256
|
numbers you can reproduce with `chad-bench`, the stock-engine comparison, and what the
|
|
232
257
|
cross-session warm start is worth.
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
258
|
+
- [Configuration reference](docs/configuration.md) documents project instructions, Agent
|
|
259
|
+
Skills, MCP servers, plan mode, the slash commands, the context window, every environment
|
|
260
|
+
variable, and the safety opt-outs.
|
|
261
|
+
- [Troubleshooting](docs/troubleshooting.md) maps symptoms to knobs for when a session
|
|
236
262
|
rambles, loops, or slows.
|
|
237
|
-
-
|
|
263
|
+
- [Contributing](CONTRIBUTING.md) says what lands easily and what needs a conversation
|
|
238
264
|
first.
|
|
239
265
|
|