chad-code 2.0.3__tar.gz → 2.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.
- {chad_code-2.0.3/src/chad_code.egg-info → chad_code-2.1.0}/PKG-INFO +62 -45
- {chad_code-2.0.3 → chad_code-2.1.0}/README.md +59 -43
- {chad_code-2.0.3 → chad_code-2.1.0}/pyproject.toml +56 -3
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/__init__.py +1 -1
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/agent.py +181 -151
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/ambient.py +69 -30
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/atif.py +53 -26
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/base_engine.py +5 -24
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/bench.py +35 -8
- chad_code-2.1.0/src/chad/checkpoint.py +231 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/cli.py +243 -171
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/completion_engine.py +28 -162
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/diag.py +16 -9
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/engine.py +1086 -1147
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/guardrails.py +50 -69
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/ignore.py +0 -5
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mcp.py +169 -131
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mcp_oauth.py +61 -44
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mlx_dflash.py +78 -33
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mlx_fastpath.py +49 -25
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mlx_qmm_mma.py +35 -9
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/mlx_qsdpa.py +133 -106
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/prompt.py +6 -7
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/prove.py +67 -23
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/render.py +24 -17
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/repomap.py +91 -21
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/seatbelt.py +132 -102
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/session.py +60 -19
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/skills.py +9 -11
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/speech.py +44 -27
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/spill.py +8 -6
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/toolcall_parse.py +6 -6
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/tools.py +113 -25
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/tui.py +100 -12
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/validate.py +58 -21
- {chad_code-2.0.3 → chad_code-2.1.0/src/chad_code.egg-info}/PKG-INFO +62 -45
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad_code.egg-info/SOURCES.txt +1 -2
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad_code.egg-info/requires.txt +1 -1
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_agent_e2e.py +256 -12
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_agent_guards.py +42 -23
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_ambient.py +66 -45
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_atif.py +33 -12
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_bench.py +22 -14
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_checkpoint.py +73 -4
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_cli.py +163 -158
- chad_code-2.1.0/tests/test_cli_modes.py +235 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_completion_engine.py +30 -15
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_config.py +23 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_confirm_preview.py +23 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_edit.py +42 -30
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_engine.py +240 -98
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_engine_dflash.py +148 -15
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_engine_kvquant.py +1 -3
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_engine_pld_hybrid.py +0 -1
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_engine_pld_wide.py +32 -9
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_feel_pack.py +6 -8
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_gate.py +45 -43
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_intent.py +80 -91
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_log_redaction.py +18 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_matrix_bench.py +104 -1
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_mcp.py +70 -64
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_mcp_oauth.py +9 -10
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_mlx_qsdpa.py +22 -30
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_prove.py +68 -1
- chad_code-2.1.0/tests/test_repomap.py +295 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_seatbelt.py +101 -82
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_session.py +106 -22
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_skills.py +2 -3
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_speech_tui.py +165 -149
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_spill.py +3 -4
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_toolcall_parse.py +17 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_tools.py +138 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_tui.py +41 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_validate.py +36 -3
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_warm_prefix_tiers.py +64 -72
- chad_code-2.0.3/src/chad/checkpoint.py +0 -149
- 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.1.0}/LICENSE +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/setup.cfg +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/compaction.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/config.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/levers.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/LICENSE +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/__init__.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/alignment.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/attention.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/audio.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/cache.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/conformer.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/ctc.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/parakeet.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/rnnt.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/tokenizer.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/parakeet/utils.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad/syntaxgate.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad_code.egg-info/dependency_links.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad_code.egg-info/entry_points.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/src/chad_code.egg-info/top_level.txt +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_agent.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_compaction.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_ignore.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_levers.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_mlx_fastpath.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_mlx_qmm_mma.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_render.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_repomap_polyglot.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_speech.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.0}/tests/test_syntaxgate.py +0 -0
- {chad_code-2.0.3 → chad_code-2.1.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.1.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
|
|
|
@@ -73,32 +78,36 @@ 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
|
-
|
|
81
|
+
What do you gain over pointing a generic local-model tool at the same weights?
|
|
82
|
+
Qwen3.8-27B at the same `UD-Q3_K_XL` recipe (Unsloth's GGUF for
|
|
78
83
|
llama.cpp, chad's MLX conversion of the same bit map), the same M4 Pro (24 GB), one engine
|
|
79
84
|
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
|
-
|
|
|
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**, default | 101 tok/s | **62.9 tok/s**¹ | DFlash2 block drafter |
|
|
87
94
|
|
|
88
|
-
A 200-token function body takes roughly 18 seconds at 10.9 tok/s and 3 at
|
|
89
|
-
|
|
90
|
-
for.
|
|
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.
|
|
91
97
|
|
|
92
|
-
Ollama does not get its own row: it is llama.cpp underneath
|
|
93
|
-
|
|
98
|
+
Ollama does not get its own row: it is llama.cpp underneath, measured without speculative
|
|
99
|
+
decoding, and on the same GGUF (0.32.15, Modelfile `FROM` only) it measures 96 tok/s
|
|
94
100
|
prefill and the same **10.9** decode.
|
|
95
101
|
|
|
96
|
-
¹
|
|
97
|
-
against ten real mid-session contexts from `~/.chad/sessions` (12
|
|
102
|
+
¹ 63 is a ceiling: `chad-bench`'s prompt is tiled code the drafter reads easily. Replayed
|
|
103
|
+
against ten real mid-session contexts from `~/.chad/sessions` (12-19k tokens, tool results in
|
|
98
104
|
place, 384-token decodes) the same engine measures **31.7 tok/s median / 21.4 floor** greedy
|
|
99
105
|
against 14.8 serial, and **27.6 / 17.7** thinking against 13.9. That ~2× is what a session
|
|
100
|
-
lives at.
|
|
101
|
-
|
|
106
|
+
lives at.
|
|
107
|
+
|
|
108
|
+
² llama.cpp has run DFlash2 since build 10658. Here it accepts 96.5% of drafted tokens and still
|
|
109
|
+
gains nothing: verifying 8 tokens costs ~6.4 serial steps on this GGUF and Mac
|
|
110
|
+
([details](docs/benchmarks.md#same-model-same-mac-stock-engine)).
|
|
102
111
|
|
|
103
112
|
Method, the longer runs and the caveats are in
|
|
104
113
|
[Throughput & performance](docs/benchmarks.md#same-model-same-mac-stock-engine); the rows are
|
|
@@ -110,17 +119,17 @@ committed under [`benchmarks/stock/_runs/`](benchmarks/stock/); reproduce them w
|
|
|
110
119
|
chad owns its inference loop instead of talking to a server, and the engine is fitted to the
|
|
111
120
|
one checkpoint it ships:
|
|
112
121
|
|
|
113
|
-
-
|
|
122
|
+
- DFlash2 block speculation. A bundled 1.9B drafter ([z-lab's DFlash2](https://huggingface.co/z-lab/Qwen3.8-27B-DFlash2),
|
|
114
123
|
ported to MLX and quantized) proposes a whole block of tokens from the main model's own
|
|
115
124
|
hidden states. The main model verifies the block in one batched forward, and exact
|
|
116
125
|
rejection sampling keeps every emitted token the model's own.
|
|
117
|
-
-
|
|
126
|
+
- A persistent prefix KV cache. The transcript is kept a strict token-prefix of the live
|
|
118
127
|
cache, so a follow-up step prefills the ~16 tokens it appended instead of the 5,000 it
|
|
119
|
-
already read: **~0.
|
|
128
|
+
already read: **~0.55 s per step instead of ~48 s**. Any server with prompt caching gets
|
|
120
129
|
the easy case; the work is holding it true across compaction, truncated turns and restarts.
|
|
121
130
|
The system prefix is checkpointed to disk, so the second session anywhere starts warm
|
|
122
131
|
(75.6 s → 5.5 s to the first tool call).
|
|
123
|
-
-
|
|
132
|
+
- Fused Metal kernels. Quantized-KV attention, a small-M matmul for speculative verify,
|
|
124
133
|
and a compiled single-token layer step, chosen per machine at load time, no knobs.
|
|
125
134
|
|
|
126
135
|
## What chad gives up
|
|
@@ -146,16 +155,21 @@ budget; everything else is deliberately plain.
|
|
|
146
155
|
|
|
147
156
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
148
157
|
|
|
149
|
-
-
|
|
158
|
+
- shift-tab cycles permission modes: `normal` (confirm each bash/write/edit) →
|
|
150
159
|
`auto-accept edits` (edits land silently, **terminal commands still ask**) → `yolo`
|
|
151
160
|
(nothing asks) → `plan mode` (read-only: investigate and propose a numbered plan) → back.
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
A finished plan lands in `./plans/`; ctrl-g (or `/accept`) clears the context and starts
|
|
162
|
+
implementing it ([details](docs/configuration.md#plan-mode)).
|
|
163
|
+
- Type-ahead message queue. Keep typing while the agent works; messages run in order.
|
|
164
|
+
- ctrl-c interrupts the running turn without killing the session. **↑prefilled /
|
|
154
165
|
↓generated** token counts show an advancing **%** on an unavoidable full re-prefill, so it
|
|
155
166
|
is never silent.
|
|
156
|
-
-
|
|
167
|
+
- `@file` / `@dir` mentions and `!command` shell passthrough. Pull a file into
|
|
157
168
|
context inline, or run a shell command without invoking the model.
|
|
158
|
-
-
|
|
169
|
+
- Standing project instructions. A `CLAUDE.md` (or `AGENTS.md`) in the working directory is
|
|
170
|
+
appended to the system prompt, and `/init` reads the project and writes one for you
|
|
171
|
+
([details](docs/configuration.md#project-instructions-claudemd--agentsmd)).
|
|
172
|
+
- Voice mode, all local. `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes into
|
|
159
173
|
the input box for you to review before Enter sends it, and replies are read aloud via macOS
|
|
160
174
|
`say`. A word table teaches it your identifiers. Needs the `speech` extra
|
|
161
175
|
([details](docs/configuration.md#voice-mode-speech)).
|
|
@@ -169,12 +183,13 @@ budget; everything else is deliberately plain.
|
|
|
169
183
|
| `--plan` | start in read-only plan mode (investigate and propose, edits blocked) |
|
|
170
184
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
171
185
|
| `--no-think` | skip the model's `<think>` blocks, faster on well-scoped work |
|
|
186
|
+
| `--think-budget N` | soft-cap each step's `<think>` at N tokens, force-close it and carry on (off by default) |
|
|
187
|
+
| `--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
188
|
| `--model` | `auto` (the shipped default), or any HF repo id / local model dir |
|
|
173
189
|
| `--repl` | plain line REPL instead of the TUI |
|
|
174
190
|
|
|
175
|
-
|
|
176
|
-
`chad
|
|
177
|
-
and `chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
191
|
+
Two subcommands, each with its own `--help`: `chad prove` (the offline smoke test) and
|
|
192
|
+
`chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
178
193
|
|
|
179
194
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools and runs
|
|
180
195
|
greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every resume
|
|
@@ -220,7 +235,7 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
220
235
|
uv run chad -c # resume this directory's last conversation
|
|
221
236
|
```
|
|
222
237
|
|
|
223
|
-
|
|
238
|
+
Two features are opt-in because they pull deps not every install wants:
|
|
224
239
|
`speech` (voice mode: a mic library, no torch) and `highlight` (syntax colour in diffs and
|
|
225
240
|
previews). An extra rides on the install spec, not on a separate command, so how you add it
|
|
226
241
|
depends on how you installed chad:
|
|
@@ -234,12 +249,12 @@ uv sync --extra speech # from a clone
|
|
|
234
249
|
`/speech` in the TUI prints whichever of those matches your install, so you never have to
|
|
235
250
|
work it out from here.
|
|
236
251
|
|
|
237
|
-
|
|
252
|
+
Upgrading depends on how you installed: `uv tool upgrade chad-code`, `uvx --refresh
|
|
238
253
|
chad-code`, or `git pull && uv sync` for a clone. What changed lands in
|
|
239
254
|
[`CHANGELOG.md`](CHANGELOG.md). Model weights are versioned separately, so a code upgrade
|
|
240
255
|
never re-downloads the model.
|
|
241
256
|
|
|
242
|
-
|
|
257
|
+
For development, `uv sync` once, then `uv run pytest -q`. The fast unit gate loads **no model
|
|
243
258
|
weights**, runs in seconds, and is what CI runs. For throughput on your own machine, use
|
|
244
259
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)).
|
|
245
260
|
|
|
@@ -247,11 +262,12 @@ weights**, runs in seconds, and is what CI runs. For throughput on your own mach
|
|
|
247
262
|
|
|
248
263
|
chad speaks the same two extension formats as Claude Code:
|
|
249
264
|
|
|
250
|
-
-
|
|
251
|
-
`./.claude/skills/` and it becomes a slash command:
|
|
252
|
-
Skills cost nothing until you run one, because
|
|
253
|
-
prompt.
|
|
254
|
-
|
|
265
|
+
- [Agent Skills](https://agentskills.io). Drop a `SKILL.md` folder in `./.agents/skills/`
|
|
266
|
+
or `./.claude/skills/` (or under `~/` for every project) and it becomes a slash command:
|
|
267
|
+
`/ship`, `/investigate the flaky test`. Skills cost nothing until you run one, because
|
|
268
|
+
chad puts no skill catalog in the system prompt. Precedence and the full list of roots
|
|
269
|
+
are in the [Configuration reference](docs/configuration.md#agent-skills-agentskillsio).
|
|
270
|
+
- [MCP servers](https://modelcontextprotocol.io). Configure stdio or HTTP servers in
|
|
255
271
|
`./.mcp.json` to expose external tools (GitHub, Postgres, Linear, Slack, …) alongside
|
|
256
272
|
chad's builtins, with static-token and OAuth auth.
|
|
257
273
|
|
|
@@ -259,16 +275,17 @@ Both are covered in full in the [Configuration reference](docs/configuration.md)
|
|
|
259
275
|
|
|
260
276
|
## Documentation
|
|
261
277
|
|
|
262
|
-
-
|
|
278
|
+
- [Design & internals](docs/design.md) covers why prefill is the bill, the persistent
|
|
263
279
|
prefix cache, the trimmable/append-only trade, why the tool surface is five tools, and the
|
|
264
280
|
ideas borrowed from other agents.
|
|
265
|
-
-
|
|
281
|
+
- [Throughput & performance](docs/benchmarks.md) has the prefill, decode and warm-step
|
|
266
282
|
numbers you can reproduce with `chad-bench`, the stock-engine comparison, and what the
|
|
267
283
|
cross-session warm start is worth.
|
|
268
|
-
-
|
|
269
|
-
|
|
270
|
-
|
|
284
|
+
- [Configuration reference](docs/configuration.md) documents project instructions, Agent
|
|
285
|
+
Skills, MCP servers, plan mode, the slash commands, the context window, every environment
|
|
286
|
+
variable, and the safety opt-outs.
|
|
287
|
+
- [Troubleshooting](docs/troubleshooting.md) maps symptoms to knobs for when a session
|
|
271
288
|
rambles, loops, or slows.
|
|
272
|
-
-
|
|
289
|
+
- [Contributing](CONTRIBUTING.md) says what lands easily and what needs a conversation
|
|
273
290
|
first.
|
|
274
291
|
|
|
@@ -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
|
|
|
@@ -38,32 +42,36 @@ 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
|
-
|
|
45
|
+
What do you gain over pointing a generic local-model tool at the same weights?
|
|
46
|
+
Qwen3.8-27B at the same `UD-Q3_K_XL` recipe (Unsloth's GGUF for
|
|
43
47
|
llama.cpp, chad's MLX conversion of the same bit map), the same M4 Pro (24 GB), one engine
|
|
44
48
|
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
|
-
|
|
|
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**, default | 101 tok/s | **62.9 tok/s**¹ | DFlash2 block drafter |
|
|
52
58
|
|
|
53
|
-
A 200-token function body takes roughly 18 seconds at 10.9 tok/s and 3 at
|
|
54
|
-
|
|
55
|
-
for.
|
|
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.
|
|
56
61
|
|
|
57
|
-
Ollama does not get its own row: it is llama.cpp underneath
|
|
58
|
-
|
|
62
|
+
Ollama does not get its own row: it is llama.cpp underneath, measured without speculative
|
|
63
|
+
decoding, and on the same GGUF (0.32.15, Modelfile `FROM` only) it measures 96 tok/s
|
|
59
64
|
prefill and the same **10.9** decode.
|
|
60
65
|
|
|
61
|
-
¹
|
|
62
|
-
against ten real mid-session contexts from `~/.chad/sessions` (12
|
|
66
|
+
¹ 63 is a ceiling: `chad-bench`'s prompt is tiled code the drafter reads easily. Replayed
|
|
67
|
+
against ten real mid-session contexts from `~/.chad/sessions` (12-19k tokens, tool results in
|
|
63
68
|
place, 384-token decodes) the same engine measures **31.7 tok/s median / 21.4 floor** greedy
|
|
64
69
|
against 14.8 serial, and **27.6 / 17.7** thinking against 13.9. That ~2× is what a session
|
|
65
|
-
lives at.
|
|
66
|
-
|
|
70
|
+
lives at.
|
|
71
|
+
|
|
72
|
+
² llama.cpp has run DFlash2 since build 10658. Here it accepts 96.5% of drafted tokens and still
|
|
73
|
+
gains nothing: verifying 8 tokens costs ~6.4 serial steps on this GGUF and Mac
|
|
74
|
+
([details](docs/benchmarks.md#same-model-same-mac-stock-engine)).
|
|
67
75
|
|
|
68
76
|
Method, the longer runs and the caveats are in
|
|
69
77
|
[Throughput & performance](docs/benchmarks.md#same-model-same-mac-stock-engine); the rows are
|
|
@@ -75,17 +83,17 @@ committed under [`benchmarks/stock/_runs/`](benchmarks/stock/); reproduce them w
|
|
|
75
83
|
chad owns its inference loop instead of talking to a server, and the engine is fitted to the
|
|
76
84
|
one checkpoint it ships:
|
|
77
85
|
|
|
78
|
-
-
|
|
86
|
+
- DFlash2 block speculation. A bundled 1.9B drafter ([z-lab's DFlash2](https://huggingface.co/z-lab/Qwen3.8-27B-DFlash2),
|
|
79
87
|
ported to MLX and quantized) proposes a whole block of tokens from the main model's own
|
|
80
88
|
hidden states. The main model verifies the block in one batched forward, and exact
|
|
81
89
|
rejection sampling keeps every emitted token the model's own.
|
|
82
|
-
-
|
|
90
|
+
- A persistent prefix KV cache. The transcript is kept a strict token-prefix of the live
|
|
83
91
|
cache, so a follow-up step prefills the ~16 tokens it appended instead of the 5,000 it
|
|
84
|
-
already read: **~0.
|
|
92
|
+
already read: **~0.55 s per step instead of ~48 s**. Any server with prompt caching gets
|
|
85
93
|
the easy case; the work is holding it true across compaction, truncated turns and restarts.
|
|
86
94
|
The system prefix is checkpointed to disk, so the second session anywhere starts warm
|
|
87
95
|
(75.6 s → 5.5 s to the first tool call).
|
|
88
|
-
-
|
|
96
|
+
- Fused Metal kernels. Quantized-KV attention, a small-M matmul for speculative verify,
|
|
89
97
|
and a compiled single-token layer step, chosen per machine at load time, no knobs.
|
|
90
98
|
|
|
91
99
|
## What chad gives up
|
|
@@ -111,16 +119,21 @@ budget; everything else is deliberately plain.
|
|
|
111
119
|
|
|
112
120
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
113
121
|
|
|
114
|
-
-
|
|
122
|
+
- shift-tab cycles permission modes: `normal` (confirm each bash/write/edit) →
|
|
115
123
|
`auto-accept edits` (edits land silently, **terminal commands still ask**) → `yolo`
|
|
116
124
|
(nothing asks) → `plan mode` (read-only: investigate and propose a numbered plan) → back.
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
A finished plan lands in `./plans/`; ctrl-g (or `/accept`) clears the context and starts
|
|
126
|
+
implementing it ([details](docs/configuration.md#plan-mode)).
|
|
127
|
+
- Type-ahead message queue. Keep typing while the agent works; messages run in order.
|
|
128
|
+
- ctrl-c interrupts the running turn without killing the session. **↑prefilled /
|
|
119
129
|
↓generated** token counts show an advancing **%** on an unavoidable full re-prefill, so it
|
|
120
130
|
is never silent.
|
|
121
|
-
-
|
|
131
|
+
- `@file` / `@dir` mentions and `!command` shell passthrough. Pull a file into
|
|
122
132
|
context inline, or run a shell command without invoking the model.
|
|
123
|
-
-
|
|
133
|
+
- Standing project instructions. A `CLAUDE.md` (or `AGENTS.md`) in the working directory is
|
|
134
|
+
appended to the system prompt, and `/init` reads the project and writes one for you
|
|
135
|
+
([details](docs/configuration.md#project-instructions-claudemd--agentsmd)).
|
|
136
|
+
- Voice mode, all local. `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes into
|
|
124
137
|
the input box for you to review before Enter sends it, and replies are read aloud via macOS
|
|
125
138
|
`say`. A word table teaches it your identifiers. Needs the `speech` extra
|
|
126
139
|
([details](docs/configuration.md#voice-mode-speech)).
|
|
@@ -134,12 +147,13 @@ budget; everything else is deliberately plain.
|
|
|
134
147
|
| `--plan` | start in read-only plan mode (investigate and propose, edits blocked) |
|
|
135
148
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
136
149
|
| `--no-think` | skip the model's `<think>` blocks, faster on well-scoped work |
|
|
150
|
+
| `--think-budget N` | soft-cap each step's `<think>` at N tokens, force-close it and carry on (off by default) |
|
|
151
|
+
| `--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
152
|
| `--model` | `auto` (the shipped default), or any HF repo id / local model dir |
|
|
138
153
|
| `--repl` | plain line REPL instead of the TUI |
|
|
139
154
|
|
|
140
|
-
|
|
141
|
-
`chad
|
|
142
|
-
and `chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
155
|
+
Two subcommands, each with its own `--help`: `chad prove` (the offline smoke test) and
|
|
156
|
+
`chad levers` (print the result-channel lever registry as JSON, for A/B ablation).
|
|
143
157
|
|
|
144
158
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools and runs
|
|
145
159
|
greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every resume
|
|
@@ -185,7 +199,7 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
185
199
|
uv run chad -c # resume this directory's last conversation
|
|
186
200
|
```
|
|
187
201
|
|
|
188
|
-
|
|
202
|
+
Two features are opt-in because they pull deps not every install wants:
|
|
189
203
|
`speech` (voice mode: a mic library, no torch) and `highlight` (syntax colour in diffs and
|
|
190
204
|
previews). An extra rides on the install spec, not on a separate command, so how you add it
|
|
191
205
|
depends on how you installed chad:
|
|
@@ -199,12 +213,12 @@ uv sync --extra speech # from a clone
|
|
|
199
213
|
`/speech` in the TUI prints whichever of those matches your install, so you never have to
|
|
200
214
|
work it out from here.
|
|
201
215
|
|
|
202
|
-
|
|
216
|
+
Upgrading depends on how you installed: `uv tool upgrade chad-code`, `uvx --refresh
|
|
203
217
|
chad-code`, or `git pull && uv sync` for a clone. What changed lands in
|
|
204
218
|
[`CHANGELOG.md`](CHANGELOG.md). Model weights are versioned separately, so a code upgrade
|
|
205
219
|
never re-downloads the model.
|
|
206
220
|
|
|
207
|
-
|
|
221
|
+
For development, `uv sync` once, then `uv run pytest -q`. The fast unit gate loads **no model
|
|
208
222
|
weights**, runs in seconds, and is what CI runs. For throughput on your own machine, use
|
|
209
223
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)).
|
|
210
224
|
|
|
@@ -212,11 +226,12 @@ weights**, runs in seconds, and is what CI runs. For throughput on your own mach
|
|
|
212
226
|
|
|
213
227
|
chad speaks the same two extension formats as Claude Code:
|
|
214
228
|
|
|
215
|
-
-
|
|
216
|
-
`./.claude/skills/` and it becomes a slash command:
|
|
217
|
-
Skills cost nothing until you run one, because
|
|
218
|
-
prompt.
|
|
219
|
-
|
|
229
|
+
- [Agent Skills](https://agentskills.io). Drop a `SKILL.md` folder in `./.agents/skills/`
|
|
230
|
+
or `./.claude/skills/` (or under `~/` for every project) and it becomes a slash command:
|
|
231
|
+
`/ship`, `/investigate the flaky test`. Skills cost nothing until you run one, because
|
|
232
|
+
chad puts no skill catalog in the system prompt. Precedence and the full list of roots
|
|
233
|
+
are in the [Configuration reference](docs/configuration.md#agent-skills-agentskillsio).
|
|
234
|
+
- [MCP servers](https://modelcontextprotocol.io). Configure stdio or HTTP servers in
|
|
220
235
|
`./.mcp.json` to expose external tools (GitHub, Postgres, Linear, Slack, …) alongside
|
|
221
236
|
chad's builtins, with static-token and OAuth auth.
|
|
222
237
|
|
|
@@ -224,16 +239,17 @@ Both are covered in full in the [Configuration reference](docs/configuration.md)
|
|
|
224
239
|
|
|
225
240
|
## Documentation
|
|
226
241
|
|
|
227
|
-
-
|
|
242
|
+
- [Design & internals](docs/design.md) covers why prefill is the bill, the persistent
|
|
228
243
|
prefix cache, the trimmable/append-only trade, why the tool surface is five tools, and the
|
|
229
244
|
ideas borrowed from other agents.
|
|
230
|
-
-
|
|
245
|
+
- [Throughput & performance](docs/benchmarks.md) has the prefill, decode and warm-step
|
|
231
246
|
numbers you can reproduce with `chad-bench`, the stock-engine comparison, and what the
|
|
232
247
|
cross-session warm start is worth.
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
248
|
+
- [Configuration reference](docs/configuration.md) documents project instructions, Agent
|
|
249
|
+
Skills, MCP servers, plan mode, the slash commands, the context window, every environment
|
|
250
|
+
variable, and the safety opt-outs.
|
|
251
|
+
- [Troubleshooting](docs/troubleshooting.md) maps symptoms to knobs for when a session
|
|
236
252
|
rambles, loops, or slows.
|
|
237
|
-
-
|
|
253
|
+
- [Contributing](CONTRIBUTING.md) says what lands easily and what needs a conversation
|
|
238
254
|
first.
|
|
239
255
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# import name, and command name are independent. `uvx chad-code` runs the alias
|
|
5
5
|
# script added under [project.scripts].
|
|
6
6
|
name = "chad-code"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
description = "Claude-Code-style coding agent that runs entirely on a 24 GB Apple Silicon Mac (MLX, Qwen3.8-27B)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -23,6 +23,7 @@ classifiers = [
|
|
|
23
23
|
"Programming Language :: Python :: 3.11",
|
|
24
24
|
"Programming Language :: Python :: 3.12",
|
|
25
25
|
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
26
27
|
"Topic :: Software Development :: Code Generators",
|
|
27
28
|
]
|
|
28
29
|
dependencies = [
|
|
@@ -42,7 +43,11 @@ dependencies = [
|
|
|
42
43
|
# A/B-confirmed 2026-08-23: same wheel, same prompt, sane on ==0.32.0, garbled on
|
|
43
44
|
# ==0.32.1). Point releases must be re-gated against the custom QSDPA/DFlash2/MMA
|
|
44
45
|
# kernels before widening this pin.
|
|
45
|
-
|
|
46
|
+
# mlx 0.32.2: re-gated and admitted — greedy output byte-identical to 0.32.0 on the
|
|
47
|
+
# shipped model, `chad prove` 4/4, full suite green, decode within noise (M4 Pro;
|
|
48
|
+
# independently on M5 Pro, #50). The range admits only gated releases; the upper
|
|
49
|
+
# bound moves when the next point release is gated, not before.
|
|
50
|
+
"mlx>=0.32.0,!=0.32.1,<=0.32.2; sys_platform == 'darwin'",
|
|
46
51
|
"mlx-lm>=0.31.3,<0.32; sys_platform == 'darwin'",
|
|
47
52
|
# mlx-lm requires transformers>=5.0, but 5.13.0 regressed AutoTokenizer.register:
|
|
48
53
|
# it now does `key.__module__.startswith("transformers.")` with no hasattr guard, and
|
|
@@ -139,7 +144,7 @@ testpaths = ["tests"]
|
|
|
139
144
|
[tool.ruff]
|
|
140
145
|
line-length = 100
|
|
141
146
|
# Vendored Exercism exercises (benchmarks/matrix/tasks/) are upstream files, kept byte-identical.
|
|
142
|
-
extend-exclude = ["benchmarks/matrix/tasks"]
|
|
147
|
+
extend-exclude = ["benchmarks/matrix/tasks", "tools/anti_slop"] # vendored linter: not chad's style
|
|
143
148
|
src = ["src", "tests"]
|
|
144
149
|
|
|
145
150
|
[tool.ruff.lint]
|
|
@@ -194,3 +199,51 @@ ignore_errors = true
|
|
|
194
199
|
# that is likewise Any on Linux.
|
|
195
200
|
module = ["chad.mlx_fastpath", "chad.mlx_qmm_mma", "chad.engine"]
|
|
196
201
|
warn_unused_ignores = false
|
|
202
|
+
|
|
203
|
+
# anti-slop: the third lane of the gate, next to ruff (style/correctness) and mypy
|
|
204
|
+
# (types). It rejects the evidence-discarding patterns a coding agent reaches for when a
|
|
205
|
+
# checker complains — `Any`/`object` contracts, unexplained `cast`/`# type: ignore`,
|
|
206
|
+
# string-target mocking, `getattr` dispatch — which ruff and mypy both permit by
|
|
207
|
+
# construction. Vendored (tools/anti_slop, MIT, TinyFrontier/anti-slop-py) so it needs
|
|
208
|
+
# no dependency and runs on the stdlib alone; it does need Python 3.12+, so `make slop`
|
|
209
|
+
# runs it under `uv run --python 3.12` regardless of the 3.11 project pin.
|
|
210
|
+
# Run `uv run --python 3.12 --no-project python tools/anti_slop --explain <rule>` for
|
|
211
|
+
# the reasoning behind any finding.
|
|
212
|
+
[tool.anti-slop]
|
|
213
|
+
include = ["src", "tests", "benchmarks"]
|
|
214
|
+
exclude = [
|
|
215
|
+
".agents/**",
|
|
216
|
+
".claude/**",
|
|
217
|
+
"src/chad/parakeet/**", # vendored upstream, not held to chad's gate (see ruff/mypy)
|
|
218
|
+
"benchmarks/matrix/tasks/**", # vendored Exercism exercises, kept byte-identical
|
|
219
|
+
"tools/anti_slop/**",
|
|
220
|
+
]
|
|
221
|
+
# Pre-existing findings live in the baseline (regenerate: `make slop-baseline`). A run
|
|
222
|
+
# fails only on what is NEW; edit a baselined line and its finding comes back, so the
|
|
223
|
+
# debt retires as the code it sits on is touched. Never regenerate to hide a new finding.
|
|
224
|
+
baseline = ".anti-slop-baseline.json"
|
|
225
|
+
|
|
226
|
+
[tool.anti-slop.rules]
|
|
227
|
+
# Escape-hatch tier: every one at error. These discard evidence the checker already had.
|
|
228
|
+
no-any-parameters = "error"
|
|
229
|
+
no-any-returns = "error"
|
|
230
|
+
no-any-type-aliases = "error"
|
|
231
|
+
no-chained-casts = "error"
|
|
232
|
+
no-conditional-empty-dict-spread = "error"
|
|
233
|
+
no-dynamic-dispatch = "error"
|
|
234
|
+
no-known-value-widening = "error"
|
|
235
|
+
no-unsafe-dict-values = "error"
|
|
236
|
+
no-widen-then-cast = "error"
|
|
237
|
+
require-safety-comment = "error"
|
|
238
|
+
# Architectural tier: policy, also at error, with the two exceptions below.
|
|
239
|
+
no-object-parameters = "error"
|
|
240
|
+
no-string-attribute-access = "error"
|
|
241
|
+
no-module-mocking = "error"
|
|
242
|
+
# chad's domain objects ARE untyped model output: tool args arrive as JSON the model
|
|
243
|
+
# wrote, and validate.py/mcp.py decode them at that boundary with isinstance — which is
|
|
244
|
+
# the recipe this rule prescribes, not the pattern it bans (the linter's own repository
|
|
245
|
+
# turns it off for the same reason over ast nodes). Kept at warn so a new inline
|
|
246
|
+
# isinstance deep in agent code still reports, without failing the run.
|
|
247
|
+
no-adhoc-isinstance = "warn"
|
|
248
|
+
# Tensor shapes are domain vocabulary in the MLX kernel modules; `shape` names the thing.
|
|
249
|
+
no-shape-in-symbol-names = { level = "error", terms = [] }
|
|
@@ -4,7 +4,7 @@ A flat collection of cooperating modules behind one console script (``chad``):
|
|
|
4
4
|
the inference engine, the tool layer, the agent loop, and the terminal UI.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "2.0
|
|
7
|
+
__version__ = "2.1.0"
|
|
8
8
|
|
|
9
9
|
# chad sets no MLX_* runtime vars. MLX_METAL_FAST_SYNCH, MLX_MAX_OPS_PER_BUFFER
|
|
10
10
|
# and MLX_MAX_MB_PER_BUFFER were each measured end-to-end on the 35B and every
|