chad-code 1.0.4__tar.gz → 1.0.6__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-1.0.4/src/chad_code.egg-info → chad_code-1.0.6}/PKG-INFO +42 -14
- {chad_code-1.0.4 → chad_code-1.0.6}/README.md +38 -12
- {chad_code-1.0.4 → chad_code-1.0.6}/pyproject.toml +31 -2
- chad_code-1.0.6/src/chad/__init__.py +14 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/agent.py +175 -62
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/base_engine.py +67 -7
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/bench.py +2 -2
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/cli.py +267 -130
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/completion_engine.py +168 -15
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/engine.py +61 -52
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/guardrails.py +160 -72
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/levers.py +132 -49
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/mlx_fastpath.py +26 -7
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/mlx_qsdpa.py +333 -32
- chad_code-1.0.6/src/chad/parakeet/LICENSE +201 -0
- chad_code-1.0.6/src/chad/parakeet/__init__.py +27 -0
- chad_code-1.0.6/src/chad/parakeet/alignment.py +287 -0
- chad_code-1.0.6/src/chad/parakeet/attention.py +640 -0
- chad_code-1.0.6/src/chad/parakeet/audio.py +183 -0
- chad_code-1.0.6/src/chad/parakeet/cache.py +156 -0
- chad_code-1.0.6/src/chad/parakeet/conformer.py +423 -0
- chad_code-1.0.6/src/chad/parakeet/ctc.py +34 -0
- chad_code-1.0.6/src/chad/parakeet/parakeet.py +1055 -0
- chad_code-1.0.6/src/chad/parakeet/rnnt.py +155 -0
- chad_code-1.0.6/src/chad/parakeet/tokenizer.py +3 -0
- chad_code-1.0.6/src/chad/parakeet/utils.py +112 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/prompt.py +40 -8
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/prove.py +5 -5
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/repomap.py +4 -4
- chad_code-1.0.6/src/chad/serve.py +814 -0
- chad_code-1.0.6/src/chad/speech.py +565 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/syntaxgate.py +18 -19
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/toolcall_parse.py +4 -4
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/tools.py +263 -17
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/tui.py +298 -15
- {chad_code-1.0.4 → chad_code-1.0.6/src/chad_code.egg-info}/PKG-INFO +42 -14
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad_code.egg-info/SOURCES.txt +18 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad_code.egg-info/requires.txt +4 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_agent.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_agent_e2e.py +88 -32
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_agent_guards.py +79 -13
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_cli.py +248 -3
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_completion_engine.py +84 -2
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_config.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_confirm_preview.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_done_audit.py +237 -104
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_edit.py +6 -6
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_edit_corruption.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_engine.py +5 -9
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_engine_kvquant.py +0 -8
- chad_code-1.0.6/tests/test_engine_pld_hybrid.py +227 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_garble_invariant.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_gate.py +85 -9
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_intent.py +4 -4
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_lever_bite.py +104 -18
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_mlx_fastpath.py +2 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_mlx_qsdpa.py +75 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_render.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_repomap.py +1 -1
- chad_code-1.0.6/tests/test_serve.py +815 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_session.py +1 -1
- chad_code-1.0.6/tests/test_speech.py +284 -0
- chad_code-1.0.6/tests/test_speech_tui.py +508 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_subagent.py +7 -5
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_symbols.py +1 -1
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_syntaxgate.py +4 -4
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_toolcall_parse.py +2 -2
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_tools.py +204 -17
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_tui.py +51 -2
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_validate.py +1 -1
- chad_code-1.0.4/src/chad/__init__.py +0 -7
- {chad_code-1.0.4 → chad_code-1.0.6}/LICENSE +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/setup.cfg +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/atif.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/compaction.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/config.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/diag.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/ignore.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/lsp.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/mcp.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/mcp_oauth.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/profiles.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/render.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/session.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/skills.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/symbols.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad/validate.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad_code.egg-info/dependency_links.txt +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad_code.egg-info/entry_points.txt +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/src/chad_code.egg-info/top_level.txt +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_atif.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_bench.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_compact_notice.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_compaction.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_drift_warn.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_feel_pack.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_ignore.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_levers.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_log_redaction.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_lsp.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_mcp.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_mcp_oauth.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_plan_review.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_prove.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_replace_lines.py +0 -0
- {chad_code-1.0.4 → chad_code-1.0.6}/tests/test_skills.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chad-code
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
4
4
|
Summary: Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/nathansutton/chad
|
|
@@ -21,7 +21,7 @@ Requires-Dist: mlx<0.33,>=0.32.0; sys_platform == "darwin"
|
|
|
21
21
|
Requires-Dist: mlx-lm<0.32,>=0.31.3; sys_platform == "darwin"
|
|
22
22
|
Requires-Dist: transformers<5.13,>=5.0
|
|
23
23
|
Requires-Dist: jinja2>=3.1
|
|
24
|
-
Requires-Dist: numpy<
|
|
24
|
+
Requires-Dist: numpy<3,>=1.26
|
|
25
25
|
Requires-Dist: huggingface-hub>=1.22.0
|
|
26
26
|
Requires-Dist: jedi>=0.19.2
|
|
27
27
|
Requires-Dist: prompt_toolkit>=3.0.43
|
|
@@ -33,6 +33,8 @@ Provides-Extra: highlight
|
|
|
33
33
|
Requires-Dist: pygments>=2.17; extra == "highlight"
|
|
34
34
|
Provides-Extra: lsp
|
|
35
35
|
Requires-Dist: serena-agent>=1.5; extra == "lsp"
|
|
36
|
+
Provides-Extra: speech
|
|
37
|
+
Requires-Dist: sounddevice>=0.5; extra == "speech"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
38
40
|
# chad — a local, MLX-backed coding agent
|
|
@@ -58,7 +60,7 @@ uvx chad-code # runs chad anywhere — the command is still `chad`
|
|
|
58
60
|
uvx chad-code prove # 2-min offline smoke test: 4 tiny fix-it tasks, verified, timed 🗿
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
First run picks the right Ornith model for your RAM (9B under
|
|
63
|
+
First run picks the right Ornith model for your RAM (9B under 24 GB, 35B at 24 GB+), asks,
|
|
62
64
|
and downloads it once (~5 GB / ~13 GB, resumable) into the shared Hugging Face cache. While
|
|
63
65
|
it downloads, `cd` into a project and think of a scoped first ask — *"fix the failing test
|
|
64
66
|
in `tests/test_x.py`"* lands; *"improve my codebase"* flails.
|
|
@@ -81,10 +83,12 @@ instrument:
|
|
|
81
83
|
| **Harness** | open-ended, anything you can imagine | plan. execute. nothing else. |
|
|
82
84
|
| **When wrong** | reasons a way out | already shipped |
|
|
83
85
|
|
|
84
|
-

|
|
85
87
|
|
|
86
|
-
> Real session, unedited (
|
|
87
|
-
>
|
|
88
|
+
> Real session, unedited (the silent prefill is cut): a local 35B finds the cent that
|
|
89
|
+
> floor division loses, fixes it, and verifies itself — then your own `pytest`, in your
|
|
90
|
+
> own shell. Recorded with `--yolo` so nothing pauses for a keypress; the default mode
|
|
91
|
+
> stops and asks before every edit and every command.
|
|
88
92
|
|
|
89
93
|
## Frontier scores, laptop cost
|
|
90
94
|
|
|
@@ -139,16 +143,20 @@ uv run chad -c # resume this directory's last conversation
|
|
|
139
143
|
```
|
|
140
144
|
|
|
141
145
|
**The model.** chad picks one for you by RAM and downloads it once into the shared Hugging
|
|
142
|
-
Face cache (`~/.cache/huggingface`, reused across every project).
|
|
143
|
-
|
|
146
|
+
Face cache (`~/.cache/huggingface`, reused across every project). Override with
|
|
147
|
+
`--model 9b` / `--model 35b`, or `--model <repo or local dir>` for anything else.
|
|
144
148
|
|
|
145
149
|
| Your Mac | Model | Footprint |
|
|
146
150
|
|---|---|---|
|
|
147
|
-
| **≥
|
|
148
|
-
| **16 / 18
|
|
149
|
-
|
|
150
|
-
The 35B's working set
|
|
151
|
-
|
|
151
|
+
| **≥ 24 GB** | [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 | ~13 GB resident (~16 GB with KV) |
|
|
152
|
+
| **16 / 18 GB** | [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 |
|
|
153
|
+
|
|
154
|
+
The 35B's floor used to be 32 GB — its working set SIGKILLed a 24 GB Mac mid-turn. The
|
|
155
|
+
fused attention kernel and the 8-bit-from-the-start KV cache it enables cut the per-token
|
|
156
|
+
cache cost enough to give that headroom back, and the compaction trigger now sizes itself
|
|
157
|
+
from the live Metal budget, so a tight box narrows its context window instead of dying.
|
|
158
|
+
24 GB runs the 35B; 16/18 GB still get the 9B. If a 24 GB machine feels tight next to your
|
|
159
|
+
other apps, `--model 9b` puts it back. Quant names follow
|
|
152
160
|
[Unsloth's dynamic-quant convention](https://docs.unsloth.ai/) (`UD-…`).
|
|
153
161
|
|
|
154
162
|
**Upgrading** — depends on how you installed: `uv tool upgrade chad-code`; `uvx --refresh
|
|
@@ -167,7 +175,10 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
167
175
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
168
176
|
|
|
169
177
|
- **shift-tab cycles permission modes** — `normal` (confirm each bash/write/edit) →
|
|
170
|
-
`auto-accept edits`
|
|
178
|
+
`auto-accept edits` (edits land silently; **terminal commands still ask**) → `yolo`
|
|
179
|
+
(nothing asks) → `plan mode` (read-only: investigate + propose a numbered plan) → back.
|
|
180
|
+
- **the approval prompt shows what you're approving** — the full command on its own lines
|
|
181
|
+
above the input, not a clipped single line. Approving blind isn't approving.
|
|
171
182
|
- **type-ahead message queue** — keep typing while the agent works; messages run in order.
|
|
172
183
|
- **ctrl-c interrupts the running turn** without killing the session.
|
|
173
184
|
- **live status line** — model, mode, context %, a state glyph + verb, elapsed seconds, and
|
|
@@ -177,6 +188,14 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
177
188
|
`/model`, `/mode`, `/help`, `/exit`. Same set in the `--repl` line interface.
|
|
178
189
|
- **`@file` / `@dir` mentions** and **`!command` shell passthrough** — pull a file into
|
|
179
190
|
context inline, or run a shell command without invoking the model.
|
|
191
|
+
- **voice mode, all local** — `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes
|
|
192
|
+
into the input box for you to review before Enter sends it (esc discards a take);
|
|
193
|
+
replies are read aloud via macOS `say`. A pre-roll buffer means your first syllable
|
|
194
|
+
isn't clipped, and a personal word table (`~/.chad/speech_words.json`) teaches it your
|
|
195
|
+
identifiers — `{"pie test": "pytest"}`. Dictation cost is linear in take length, so a
|
|
196
|
+
long thought is fine; `/speech` off releases both the mic and the weights. Nothing
|
|
197
|
+
leaves the machine. Needs the `speech` extra (`uv sync --extra speech` — just a mic
|
|
198
|
+
library; no torch, no numba).
|
|
180
199
|
|
|
181
200
|
**Usage.** `uv run chad --help` is the source of truth:
|
|
182
201
|
|
|
@@ -187,8 +206,17 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
187
206
|
| `--plan` | start in read-only plan mode (investigate + propose, edits blocked) |
|
|
188
207
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
189
208
|
| `--no-think` | skip Ornith's `<think>` blocks — faster on well-scoped work |
|
|
209
|
+
| `--model` | `35b`, `9b`, `auto`, or any HF repo id / local model dir |
|
|
190
210
|
| `--repl` | plain line REPL instead of the TUI |
|
|
191
211
|
|
|
212
|
+
Plus three subcommands, each with its own `--help`:
|
|
213
|
+
|
|
214
|
+
| Command | What it does |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `chad serve` | serve this Mac's model to a container or the LAN ([Configuration](docs/configuration.md#serving-the-local-model-to-a-container-chad-serve)) |
|
|
217
|
+
| `chad prove` | 2-minute offline smoke test: 4 tiny fix-it tasks, verified, timed |
|
|
218
|
+
| `chad levers` | print the harness lever registry as JSON (ablation driver) |
|
|
219
|
+
|
|
192
220
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools; the model
|
|
193
221
|
runs greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every
|
|
194
222
|
resume forks a new branch rather than overwriting — details in
|
|
@@ -21,7 +21,7 @@ uvx chad-code # runs chad anywhere — the command is still `chad`
|
|
|
21
21
|
uvx chad-code prove # 2-min offline smoke test: 4 tiny fix-it tasks, verified, timed 🗿
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
First run picks the right Ornith model for your RAM (9B under
|
|
24
|
+
First run picks the right Ornith model for your RAM (9B under 24 GB, 35B at 24 GB+), asks,
|
|
25
25
|
and downloads it once (~5 GB / ~13 GB, resumable) into the shared Hugging Face cache. While
|
|
26
26
|
it downloads, `cd` into a project and think of a scoped first ask — *"fix the failing test
|
|
27
27
|
in `tests/test_x.py`"* lands; *"improve my codebase"* flails.
|
|
@@ -44,10 +44,12 @@ instrument:
|
|
|
44
44
|
| **Harness** | open-ended, anything you can imagine | plan. execute. nothing else. |
|
|
45
45
|
| **When wrong** | reasons a way out | already shipped |
|
|
46
46
|
|
|
47
|
-

|
|
48
48
|
|
|
49
|
-
> Real session, unedited (
|
|
50
|
-
>
|
|
49
|
+
> Real session, unedited (the silent prefill is cut): a local 35B finds the cent that
|
|
50
|
+
> floor division loses, fixes it, and verifies itself — then your own `pytest`, in your
|
|
51
|
+
> own shell. Recorded with `--yolo` so nothing pauses for a keypress; the default mode
|
|
52
|
+
> stops and asks before every edit and every command.
|
|
51
53
|
|
|
52
54
|
## Frontier scores, laptop cost
|
|
53
55
|
|
|
@@ -102,16 +104,20 @@ uv run chad -c # resume this directory's last conversation
|
|
|
102
104
|
```
|
|
103
105
|
|
|
104
106
|
**The model.** chad picks one for you by RAM and downloads it once into the shared Hugging
|
|
105
|
-
Face cache (`~/.cache/huggingface`, reused across every project).
|
|
106
|
-
|
|
107
|
+
Face cache (`~/.cache/huggingface`, reused across every project). Override with
|
|
108
|
+
`--model 9b` / `--model 35b`, or `--model <repo or local dir>` for anything else.
|
|
107
109
|
|
|
108
110
|
| Your Mac | Model | Footprint |
|
|
109
111
|
|---|---|---|
|
|
110
|
-
| **≥
|
|
111
|
-
| **16 / 18
|
|
112
|
-
|
|
113
|
-
The 35B's working set
|
|
114
|
-
|
|
112
|
+
| **≥ 24 GB** | [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 | ~13 GB resident (~16 GB with KV) |
|
|
113
|
+
| **16 / 18 GB** | [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 |
|
|
114
|
+
|
|
115
|
+
The 35B's floor used to be 32 GB — its working set SIGKILLed a 24 GB Mac mid-turn. The
|
|
116
|
+
fused attention kernel and the 8-bit-from-the-start KV cache it enables cut the per-token
|
|
117
|
+
cache cost enough to give that headroom back, and the compaction trigger now sizes itself
|
|
118
|
+
from the live Metal budget, so a tight box narrows its context window instead of dying.
|
|
119
|
+
24 GB runs the 35B; 16/18 GB still get the 9B. If a 24 GB machine feels tight next to your
|
|
120
|
+
other apps, `--model 9b` puts it back. Quant names follow
|
|
115
121
|
[Unsloth's dynamic-quant convention](https://docs.unsloth.ai/) (`UD-…`).
|
|
116
122
|
|
|
117
123
|
**Upgrading** — depends on how you installed: `uv tool upgrade chad-code`; `uvx --refresh
|
|
@@ -130,7 +136,10 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
130
136
|
`uv run chad` launches a full-screen terminal UI (built on prompt_toolkit):
|
|
131
137
|
|
|
132
138
|
- **shift-tab cycles permission modes** — `normal` (confirm each bash/write/edit) →
|
|
133
|
-
`auto-accept edits`
|
|
139
|
+
`auto-accept edits` (edits land silently; **terminal commands still ask**) → `yolo`
|
|
140
|
+
(nothing asks) → `plan mode` (read-only: investigate + propose a numbered plan) → back.
|
|
141
|
+
- **the approval prompt shows what you're approving** — the full command on its own lines
|
|
142
|
+
above the input, not a clipped single line. Approving blind isn't approving.
|
|
134
143
|
- **type-ahead message queue** — keep typing while the agent works; messages run in order.
|
|
135
144
|
- **ctrl-c interrupts the running turn** without killing the session.
|
|
136
145
|
- **live status line** — model, mode, context %, a state glyph + verb, elapsed seconds, and
|
|
@@ -140,6 +149,14 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
140
149
|
`/model`, `/mode`, `/help`, `/exit`. Same set in the `--repl` line interface.
|
|
141
150
|
- **`@file` / `@dir` mentions** and **`!command` shell passthrough** — pull a file into
|
|
142
151
|
context inline, or run a shell command without invoking the model.
|
|
152
|
+
- **voice mode, all local** — `/speech`, then ctrl-t to talk: Parakeet-on-MLX transcribes
|
|
153
|
+
into the input box for you to review before Enter sends it (esc discards a take);
|
|
154
|
+
replies are read aloud via macOS `say`. A pre-roll buffer means your first syllable
|
|
155
|
+
isn't clipped, and a personal word table (`~/.chad/speech_words.json`) teaches it your
|
|
156
|
+
identifiers — `{"pie test": "pytest"}`. Dictation cost is linear in take length, so a
|
|
157
|
+
long thought is fine; `/speech` off releases both the mic and the weights. Nothing
|
|
158
|
+
leaves the machine. Needs the `speech` extra (`uv sync --extra speech` — just a mic
|
|
159
|
+
library; no torch, no numba).
|
|
143
160
|
|
|
144
161
|
**Usage.** `uv run chad --help` is the source of truth:
|
|
145
162
|
|
|
@@ -150,8 +167,17 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
150
167
|
| `--plan` | start in read-only plan mode (investigate + propose, edits blocked) |
|
|
151
168
|
| `--yolo` | auto-approve bash/write/edit (skip confirm prompts) |
|
|
152
169
|
| `--no-think` | skip Ornith's `<think>` blocks — faster on well-scoped work |
|
|
170
|
+
| `--model` | `35b`, `9b`, `auto`, or any HF repo id / local model dir |
|
|
153
171
|
| `--repl` | plain line REPL instead of the TUI |
|
|
154
172
|
|
|
173
|
+
Plus three subcommands, each with its own `--help`:
|
|
174
|
+
|
|
175
|
+
| Command | What it does |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `chad serve` | serve this Mac's model to a container or the LAN ([Configuration](docs/configuration.md#serving-the-local-model-to-a-container-chad-serve)) |
|
|
178
|
+
| `chad prove` | 2-minute offline smoke test: 4 tiny fix-it tasks, verified, timed |
|
|
179
|
+
| `chad levers` | print the harness lever registry as JSON (ablation driver) |
|
|
180
|
+
|
|
155
181
|
A headless task (positional, or piped with no TTY) auto-approves mutating tools; the model
|
|
156
182
|
runs greedy (temp 0). Every conversation is persisted under `~/.chad/sessions/`, and every
|
|
157
183
|
resume forks a new branch rather than overwriting — details in
|
|
@@ -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 = "1.0.
|
|
7
|
+
version = "1.0.6"
|
|
8
8
|
description = "Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -49,7 +49,10 @@ dependencies = [
|
|
|
49
49
|
# absent in a clean install (e.g. chad inside a Linux benchmark container), where its
|
|
50
50
|
# absence crashes the first turn. Declare it directly.
|
|
51
51
|
"jinja2>=3.1",
|
|
52
|
-
|
|
52
|
+
# <3: the old <2 cap was 1.0.0-era caution, not a known break. numpy 2.4.6
|
|
53
|
+
# verified end-to-end (full gate + live Parakeet-on-MLX transcription +
|
|
54
|
+
# `chad prove` 4/4); staying open keeps 2.x-floored ASR deps adoptable.
|
|
55
|
+
"numpy>=1.26,<3",
|
|
53
56
|
"huggingface-hub>=1.22.0", # first-run model download (cli.py/engine.py); imported directly, not just transitively
|
|
54
57
|
"jedi>=0.19.2", # in-process symbolic code intelligence (read/search/edit)
|
|
55
58
|
"prompt_toolkit>=3.0.43",
|
|
@@ -78,6 +81,16 @@ highlight = ["pygments>=2.17"]
|
|
|
78
81
|
# heavyweight tree; absent, every caller falls back to the tree-sitter backend.
|
|
79
82
|
# Install with `uv sync --extra lsp`.
|
|
80
83
|
lsp = ["serena-agent>=1.5"]
|
|
84
|
+
# Voice mode (/speech in the TUI): push-to-talk dictation via chad's vendored
|
|
85
|
+
# Parakeet-on-MLX (src/chad/parakeet — the PyPI parakeet-mlx drags librosa's
|
|
86
|
+
# numba/scipy tree for one mel-filterbank call) + spoken replies via macOS
|
|
87
|
+
# `say`. All on-device, nothing leaves the machine. mlx/numpy/huggingface-hub
|
|
88
|
+
# are already core deps, so the extra adds only the mic (sounddevice/PortAudio).
|
|
89
|
+
# Optional and import-guarded in speech.py: absent, /speech prints the install
|
|
90
|
+
# hint and everything else is untouched. Install with `uv sync --extra speech`.
|
|
91
|
+
speech = [
|
|
92
|
+
"sounddevice>=0.5",
|
|
93
|
+
]
|
|
81
94
|
|
|
82
95
|
# The one entrypoint: `uv run chad`. (`chad-bench` reproduces docs/benchmarks.md.)
|
|
83
96
|
# `chad-code` is an alias so `uvx chad-code` (which runs the console script matching
|
|
@@ -107,6 +120,10 @@ build-backend = "setuptools.build_meta"
|
|
|
107
120
|
[tool.setuptools.packages.find]
|
|
108
121
|
where = ["src"]
|
|
109
122
|
|
|
123
|
+
# The vendored Parakeet code is Apache-2.0; its license text must travel with
|
|
124
|
+
# the code, wheel included.
|
|
125
|
+
[tool.setuptools.package-data]
|
|
126
|
+
"chad.parakeet" = ["LICENSE"]
|
|
110
127
|
[tool.pytest.ini_options]
|
|
111
128
|
testpaths = ["tests"]
|
|
112
129
|
# No "-q" here: CI/docs/agents all invoke `pytest -q` explicitly, and stacking the two
|
|
@@ -127,6 +144,12 @@ src = ["src", "tests"]
|
|
|
127
144
|
select = ["F", "E9", "I"]
|
|
128
145
|
ignore = ["E741"] # ambiguous var names (l/I) appear in existing math code
|
|
129
146
|
|
|
147
|
+
[tool.ruff.lint.per-file-ignores]
|
|
148
|
+
# Vendored upstream (see chad/parakeet/__init__.py), kept byte-close for
|
|
149
|
+
# future re-syncs — not held to chad's own lint standard. (F401: imports left
|
|
150
|
+
# in place for upstream fidelity after the transcribe(path) cut.)
|
|
151
|
+
"src/chad/parakeet/*" = ["F401", "F821", "F841", "E741"]
|
|
152
|
+
|
|
130
153
|
[tool.mypy]
|
|
131
154
|
python_version = "3.11"
|
|
132
155
|
files = ["src/chad"]
|
|
@@ -142,6 +165,12 @@ disable_error_code = ["var-annotated"]
|
|
|
142
165
|
# Tighten (disallow_untyped_defs, re-enable var-annotated, add B/UP/SIM in ruff) in a
|
|
143
166
|
# follow-up once this baseline holds.
|
|
144
167
|
|
|
168
|
+
[[tool.mypy.overrides]]
|
|
169
|
+
# Vendored upstream inference code (see chad/parakeet/__init__.py) is not held
|
|
170
|
+
# to chad's gate so re-syncs stay a plain re-copy.
|
|
171
|
+
module = "chad.parakeet.*"
|
|
172
|
+
ignore_errors = true
|
|
173
|
+
|
|
145
174
|
[[tool.mypy.overrides]]
|
|
146
175
|
# mlx_fastpath patches mlx_lm classes that only exist on macOS: with mlx installed
|
|
147
176
|
# (dev Macs, the macos CI jobs) its `type: ignore[method-assign]` comments are load-
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""chad — a local MLX-backed, Claude-Code-style coding agent.
|
|
2
|
+
|
|
3
|
+
A flat collection of cooperating modules behind one console script (``chad``):
|
|
4
|
+
the inference engine, the tool layer, the agent loop, and the terminal UI.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "1.0.6"
|
|
8
|
+
|
|
9
|
+
# chad sets no MLX_* runtime vars. MLX_METAL_FAST_SYNCH, MLX_MAX_OPS_PER_BUFFER
|
|
10
|
+
# and MLX_MAX_MB_PER_BUFFER were each measured end-to-end on the 35B and every
|
|
11
|
+
# setting was slower than mlx's own defaults (1-4% at both 8k and 32k), so the
|
|
12
|
+
# mechanism that used to apply them at package import is gone. Any future entry
|
|
13
|
+
# has to be set before mlx's backend initializes — package import is the last
|
|
14
|
+
# hook early enough, since chad imports mlx lazily inside functions.
|