chutes-build 0.4.2 → 1.0.0
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.
- package/CHANGELOG.md +529 -1
- package/PRIVACY.md +14 -4
- package/README.md +130 -169
- package/SECURITY.md +24 -62
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,534 @@ project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.0.0] - 2026-08-07
|
|
10
|
+
|
|
11
|
+
Chutes Build is re-based onto `xai-org/grok-build` 1.0.0 (`afbc0fb`) and adopts
|
|
12
|
+
its version, so the number now says which upstream this build actually is.
|
|
13
|
+
|
|
14
|
+
### Why the re-base
|
|
15
|
+
|
|
16
|
+
`.github/upstream.json` recorded `lastReviewedVersion: 0.2.117`, but those
|
|
17
|
+
commits had been *reviewed and not taken* — the records said "nothing safe to
|
|
18
|
+
port in isolation". For the retained crates the tree was still at the 2026-07-17
|
|
19
|
+
fork point, 2075 files and roughly 440k lines behind upstream. Cherry-picking
|
|
20
|
+
could not close that: upstream added 94k lines in five days. Measuring the fork
|
|
21
|
+
showed why re-basing was the cheaper path — only 102 files existed here and not
|
|
22
|
+
upstream, and only 26 actually consume `chutes-build-core`.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
Everything upstream shipped between the fork point and 1.0.0 arrives at once:
|
|
27
|
+
1348 files of work from the never-taken window, plus the roughly 110 changes
|
|
28
|
+
between 0.2.117 and 1.0.0. Highlights users will notice: session recaps that
|
|
29
|
+
follow the language of the conversation, narrow markdown tables that reflow
|
|
30
|
+
inside their cells with hard splits on grapheme boundaries, a plan-viewer
|
|
31
|
+
scrollbar that is easier to grab, `--output-format streaming-messages-json`,
|
|
32
|
+
tabbed usage and session-info, and a large batch of terminal, tmux and session
|
|
33
|
+
fixes.
|
|
34
|
+
|
|
35
|
+
### Security
|
|
36
|
+
|
|
37
|
+
Carried forward and, where upstream had since fixed them differently, taken from
|
|
38
|
+
upstream instead:
|
|
39
|
+
|
|
40
|
+
- Permission rules for Read, Edit and Grep lexically normalize the tool's path
|
|
41
|
+
before the glob match, so `Read(src/**)` can no longer be escaped with
|
|
42
|
+
`src/../../etc/passwd`.
|
|
43
|
+
- `NotebookEdit` / `NotebookRead` no longer alias onto `Edit` / `Read`.
|
|
44
|
+
- A client-forwarded MCP server matching an on-disk Claude or Cursor config is
|
|
45
|
+
rejected while that vendor's `mcps` switch is off.
|
|
46
|
+
- Diagnostic logging of a credential fragment no longer panics on a non-ASCII
|
|
47
|
+
token.
|
|
48
|
+
- Chutes API keys (`cpk_`) are recognised by the secret redactor.
|
|
49
|
+
- Memory passes through the secret filter at every write path, and every write
|
|
50
|
+
path now creates its file owner-only. Three of the four created files with the
|
|
51
|
+
process umask, so a fresh install's `MEMORY.md` and both bootstrap templates
|
|
52
|
+
were world-readable — and memory holds whatever you asked the agent to
|
|
53
|
+
remember.
|
|
54
|
+
- `model-router` dispatch validates `CHUTES_ROUTER_BASE_URL` through the
|
|
55
|
+
endpoint policy before a session credential is sent to it.
|
|
56
|
+
- The default inference endpoint is `llm.chutes.ai` again. The re-base had left
|
|
57
|
+
upstream's `api.x.ai/v1`, so any model entry without an explicit base URL
|
|
58
|
+
would have sent a Chutes API key to xAI.
|
|
59
|
+
- The relay and gateway WebSocket endpoints are loopback sentinels again, not
|
|
60
|
+
`code.grok.com` and `grok.com`. Chutes Build has no vendor relay; those paths
|
|
61
|
+
must fail closed.
|
|
62
|
+
- The changelog fetch, the update check and the remote-session/workspace clients
|
|
63
|
+
point at a closed loopback port, so none of them can phone home.
|
|
64
|
+
- The npm scaffold that would install `@xai-official/grok-<platform>` binaries on
|
|
65
|
+
postinstall is gone, along with the version check that compared this build
|
|
66
|
+
against upstream's package.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- Cloudflare edge failures (520–524, 529, 530) are retried instead of ending the
|
|
71
|
+
turn, while origin-TLS 525/526 stay fatal.
|
|
72
|
+
- A server `Retry-After` is clamped to 30s and jittered.
|
|
73
|
+
- Failed requests no longer dump a Cloudflare HTML error page into the terminal.
|
|
74
|
+
- The sandbox starts on large workspaces (deny-glob entry budget 200k → 2M).
|
|
75
|
+
- `bin/protoc` is a DotSlash wrapper Windows cannot execute from a build script;
|
|
76
|
+
a vendored platform binary is now the fallback.
|
|
77
|
+
|
|
78
|
+
### Fixed (the Chutes tool layer was unreachable)
|
|
79
|
+
|
|
80
|
+
- **`generate_media`, `list_media_models`, `describe_media_model`, `browser`,
|
|
81
|
+
`ocr_page` and `get_chutes_usage` were in no toolset.** The re-base kept every
|
|
82
|
+
implementation and dropped every registration, so six thousand lines of working
|
|
83
|
+
code compiled, passed their own tests, and could not be called. Upstream's
|
|
84
|
+
toolsets carried its Imagine tools instead, which talk to an endpoint Chutes has
|
|
85
|
+
no equivalent for.
|
|
86
|
+
- **`/imagine` and `/imagine-video` had disappeared**, for the same reason: the
|
|
87
|
+
pager hides a command whose required tools are not advertised, and they required
|
|
88
|
+
the xAI Imagine tools. Both now use `generate_media`, and their instructions
|
|
89
|
+
teach the Chutes workflow — list the catalog, describe the model, compose the
|
|
90
|
+
payload from the cord's own example — because no two Chutes media models share a
|
|
91
|
+
schema. `/imagine-video` is rewritten rather than renamed: upstream's guidance
|
|
92
|
+
opens with "there is no text-to-video tool", which is true of that API and false
|
|
93
|
+
here.
|
|
94
|
+
- **Plugin sources in the system temp directory were auto-trusted on Windows.**
|
|
95
|
+
Auto-trust covers anything under the user's home, and on Windows temp *is* under
|
|
96
|
+
the home — so a plugin unpacked there skipped the explicit trust step entirely.
|
|
97
|
+
Found by a test that had been failing on Windows since before the re-base.
|
|
98
|
+
- Five upstream test failures on Windows are gone; `xai-grok-agent` now passes all
|
|
99
|
+
578. Two were real defects rather than test bugs: the trust hole above, and a
|
|
100
|
+
home-directory guard no test on Windows could reach.
|
|
101
|
+
|
|
102
|
+
### Authentication
|
|
103
|
+
|
|
104
|
+
Upstream ships an OAuth application everyone signs in through, so its
|
|
105
|
+
documentation and defaults put browser login first and treat the API key as a
|
|
106
|
+
fallback. Chutes does not work that way: OAuth needs an application you register in
|
|
107
|
+
your own account area at [chutes.ai/app/api](https://chutes.ai/app/api), so there is
|
|
108
|
+
no client ID that could serve anyone but its owner.
|
|
109
|
+
|
|
110
|
+
- **The compiled-in OAuth client ID is gone.** It offered a sign-in that would fail
|
|
111
|
+
for every user but one. `OAuth2ProviderConfig::from_env` now returns `None` unless
|
|
112
|
+
`CHUTES_BUILD_OAUTH2_CLIENT_ID` names an app, which is also upstream's shape and
|
|
113
|
+
so one seam fewer at the next merge. With no app configured, `login` already said
|
|
114
|
+
the right thing — "Sign-in is not available for this deployment. Set
|
|
115
|
+
CHUTES_API_KEY instead." — and now that message is reachable.
|
|
116
|
+
- **A cached session survives a shell with no OAuth app configured.** The
|
|
117
|
+
compatibility check compares a credential's issuer against the configured one;
|
|
118
|
+
with no provider configured there is nothing to compare against, and the question
|
|
119
|
+
becomes which credentials are self-sufficient. A session is: `oidc::refresh`
|
|
120
|
+
renews it from the issuer and client id stored in the credential itself, not from
|
|
121
|
+
the config. So exporting `CHUTES_BUILD_OAUTH2_CLIENT_ID`, signing in, and then
|
|
122
|
+
launching from a desktop shortcut or a cron entry that lacks the variable keeps
|
|
123
|
+
working — discarding the session there would strand the user in the one state
|
|
124
|
+
where interactive login is unavailable. The legacy issuer-less `WebLogin`
|
|
125
|
+
credential is still rejected, now for either config shape, because it has neither
|
|
126
|
+
issuer nor client id to renew with.
|
|
127
|
+
- **The documentation was rewritten around the API key**, which is the primary and
|
|
128
|
+
always-valid credential rather than a fallback: the authentication chapter, the
|
|
129
|
+
first-launch section of the getting-started guide, `docs/getting-started.md` and
|
|
130
|
+
the README. `docs/getting-started.md` had also described a "bundled client ID"
|
|
131
|
+
that no longer exists.
|
|
132
|
+
- **`jsonwebtoken` had no provider to sign or verify with.** It picks one from cargo
|
|
133
|
+
features, and this graph enables both: the shell declares `rust_crypto`, while
|
|
134
|
+
`xai-file-utils` -> `gcloud-storage` -> `gcloud-auth` enables `jwt-aws-lc-rs`. Cargo
|
|
135
|
+
unifies features across the graph, so neither can be turned off from here, and with
|
|
136
|
+
both on the crate refuses to choose — every signature operation panics. Production
|
|
137
|
+
survived on placement alone: `run_login_flow_with_config` installed a provider and
|
|
138
|
+
is the only entry to the one function that verifies an id_token, which holds exactly
|
|
139
|
+
until a second verification path appears. The install now sits at each point of use,
|
|
140
|
+
behind a `OnceLock`, so the library is correct by construction; 23 auth tests that
|
|
141
|
+
had been failing on Linux CI depend on it too.
|
|
142
|
+
- **Six example keys read `CHUTES_API_KEY="xai-..."`** — upstream's prefix, left
|
|
143
|
+
behind when the rebrand renamed the variable but not its value. A Chutes key is
|
|
144
|
+
`cpk_`-prefixed, which the redactor already knew and the docs did not.
|
|
145
|
+
|
|
146
|
+
The API key also has to be *enterable*, and on this branch it was not:
|
|
147
|
+
|
|
148
|
+
- **`/apikey` did not exist.** `slash/commands/apikey.rs` came across in the
|
|
149
|
+
re-base and was never declared in `slash/commands/mod.rs`, so it was not
|
|
150
|
+
compiled — the same registration gap as the Chutes tool layer, in a third
|
|
151
|
+
registry, and invisible for the same reason: an unreferenced module is not
|
|
152
|
+
built, so nothing warns. Everything it needs went with it —
|
|
153
|
+
`Action::EnterApiKey`/`SubmitApiKey`, `Effect::SubmitApiKey`,
|
|
154
|
+
`AuthMode::ApiKeyEntry`, the dispatchers, the welcome-screen arm, the `k` key.
|
|
155
|
+
The shell half was intact the whole time: `chutes.build/setApiKey` is handled in
|
|
156
|
+
`extensions/auth.rs` and allow-listed in `acp_agent.rs`. Nothing could reach it.
|
|
157
|
+
- **`/login` jumped straight into OAuth** instead of asking, because
|
|
158
|
+
`Action::ShowLoginMenu` went the same way. It now opens the choice menu
|
|
159
|
+
("Login with …" / "Enter API key" / "Quit") that the fork's `/login` always did.
|
|
160
|
+
- Together these meant a fresh install advertised exactly one login method —
|
|
161
|
+
browser sign-in — which without a registered app cannot run. The only way in was
|
|
162
|
+
to set the environment variable before starting the program.
|
|
163
|
+
- Four registries now, and the fourth caught itself: the pager's
|
|
164
|
+
`pager_builtin_triggers_are_reserved_in_shell` failed the moment `/apikey`
|
|
165
|
+
became real, because `apikey` was not in the shell's `PAGER_COMMAND_KEYS` and a
|
|
166
|
+
skill of that name could have shadowed it. Reserved. The new
|
|
167
|
+
`apikey_registered_in_builtin_commands` is the test that would have caught the
|
|
168
|
+
original gap.
|
|
169
|
+
|
|
170
|
+
The documentation had described `/apikey` and the in-app entry all along, in
|
|
171
|
+
`docs/slash-commands.md` and `docs/getting-started.md`. Third time in this release
|
|
172
|
+
that auditing the docs against the code found the code wrong.
|
|
173
|
+
|
|
174
|
+
### Fixed (voice had no working transport)
|
|
175
|
+
|
|
176
|
+
- **Speech-to-text could not work at all.** The re-base took upstream's 1.0.0 voice
|
|
177
|
+
crate, which is streaming-only — it opens a WebSocket to `{api_base}/v1/stt` — and
|
|
178
|
+
the rebrand pointed that at `api.chutes.ai`, where the route does not exist. Chutes
|
|
179
|
+
serves Whisper-family models as ordinary chutes over request/response HTTP, which
|
|
180
|
+
is exactly why the fork wrote a batch transport and made it the default. The two
|
|
181
|
+
files implementing it, `pcm.rs` and `stt/batch.rs`, came across in Fase 1 and were
|
|
182
|
+
never declared in any module, so neither was compiled; `SttMode`, `batch_api_base`
|
|
183
|
+
and the pipeline's batch branch were not copied at all. What shipped was a feature
|
|
184
|
+
whose only transport was a route the backend does not serve.
|
|
185
|
+
- Restored as a graft onto upstream's newer pipeline rather than a copy over it:
|
|
186
|
+
the subprocess capture that replaced the in-process one no longer exposes
|
|
187
|
+
`peak_meter()`, so the silence guard takes its running peak from the chunks with
|
|
188
|
+
`pcm::peak_abs_i16_le` — which is what that module is for, and the batch path holds
|
|
189
|
+
every sample anyway.
|
|
190
|
+
- `[voice].api_base` goes back to a closed loopback address. Streaming has no Chutes
|
|
191
|
+
backend, so the default must fail immediately rather than resolve to a real host
|
|
192
|
+
that cannot answer.
|
|
193
|
+
- Batch STT now posts through `xai_grok_http::shared_client()` instead of building a
|
|
194
|
+
bare `reqwest::Client`. The fork's version skipped `CHUTES_EXTRA_CA_BUNDLE` — a
|
|
195
|
+
proxy-terminated corporate network is precisely where that request would otherwise
|
|
196
|
+
fail — and the connection health-checks.
|
|
197
|
+
- The STT transport is documented in `docs/configuration.md`, which had listed the
|
|
198
|
+
media variables and said nothing about how speech is transcribed. The 0.4.x
|
|
199
|
+
changelog had mentioned `stt_mode = "streaming"` all along.
|
|
200
|
+
- `xai-grok-http/src/extra_ca.rs` deleted: upstream 1.0.0 ships `xai-grok-extra-ca`,
|
|
201
|
+
reading the same `CHUTES_EXTRA_CA_BUNDLE` with a size cap and rustls validation the
|
|
202
|
+
fork's copy lacked, and `xai-grok-http` already calls it. The old module was dead
|
|
203
|
+
code that a reader would have taken for the live one.
|
|
204
|
+
|
|
205
|
+
A sweep for the same failure mode — a source file that no `mod` declaration
|
|
206
|
+
reaches, and so is never compiled — found four in total across the tree, honouring
|
|
207
|
+
`#[path]` and `include!` to avoid false positives. All four are addressed in this
|
|
208
|
+
release; the sweep now returns nothing.
|
|
209
|
+
|
|
210
|
+
### Added (the Advisor is back)
|
|
211
|
+
|
|
212
|
+
The fourth undeclared file was `/advisor`, and unlike the others its backend had
|
|
213
|
+
not come across either — so this is a feature port rather than a registration,
|
|
214
|
+
though a small one, because the `[subagents.roles]` model-pin mechanism it hangs
|
|
215
|
+
off is upstream's and was already here.
|
|
216
|
+
|
|
217
|
+
- **The `advisor` built-in subagent**, invoked like any other through `task` with
|
|
218
|
+
`subagent_type: "advisor"`: an on-demand senior reviewer for architecture,
|
|
219
|
+
correctness, security and trade-offs. Read-only by construction — repository
|
|
220
|
+
inspection, Context7, memory and web fetch, with no shell, no edit and no nested
|
|
221
|
+
agents — so it can review a claim without being able to act on it. Defaults to
|
|
222
|
+
maximum reasoning effort, because it is called sparingly for plans, blockers and
|
|
223
|
+
completion claims, where review quality matters more than latency.
|
|
224
|
+
- **`/advisor`** turns it on or off and pins the model it uses, writing
|
|
225
|
+
`[subagents.toggle].advisor` and `[subagents.roles.advisor].model`. An empty pin
|
|
226
|
+
clears it and the advisor inherits the session's model. `true` is removed rather
|
|
227
|
+
than written, so an untouched config file stays untouched.
|
|
228
|
+
- `advisor` is reserved in the shell's `PAGER_COMMAND_KEYS` — the check that caught
|
|
229
|
+
the same omission for `/apikey`.
|
|
230
|
+
|
|
231
|
+
### Security (`agent serve` authentication)
|
|
232
|
+
|
|
233
|
+
Two CodeQL alerts pointed at `print_serve_startup_info` writing a secret to stderr.
|
|
234
|
+
Following them found the token itself was the problem, and the printing was the
|
|
235
|
+
least of it:
|
|
236
|
+
|
|
237
|
+
```rust
|
|
238
|
+
let raw = uuid::Uuid::new_v4().to_string().replace('-', "");
|
|
239
|
+
raw.chars().cycle().take(len).collect() // len = 12
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
- **The token was 48 bits.** Twelve characters of a v4 UUID's hex, for a credential
|
|
243
|
+
that authorises a server which runs shell commands and edits files, on a `/ws`
|
|
244
|
+
endpoint with no rate limit. Now 32 bytes from the OS CSPRNG, base64url without
|
|
245
|
+
padding. The `cycle()` also meant any length above 32 repeated the same UUID while
|
|
246
|
+
looking like it added entropy.
|
|
247
|
+
- **The comparison was not constant-time.** `token == expected_secret` on `&str`
|
|
248
|
+
returns at the first differing byte, so an unauthenticated caller could recover the
|
|
249
|
+
token one byte at a time — roughly 12 x 16 attempts instead of 2^48. Now
|
|
250
|
+
`ring::constant_time::verify_slices_are_equal`, with the length compared separately
|
|
251
|
+
because it is not secret. `ring` moves from dev-dependency to dependency, which
|
|
252
|
+
costs nothing: it was already in this crate's normal build graph via aws-config.
|
|
253
|
+
- **The token is printed only when stderr is a terminal.** An operator reading their
|
|
254
|
+
own console still gets it; a redirected stderr — a systemd journal, a CI log,
|
|
255
|
+
`2>serve.log` — no longer persists a live credential to disk. That was CodeQL's
|
|
256
|
+
actual finding.
|
|
257
|
+
- **A non-loopback `--bind` now warns.** The transport is `ws://` and the token
|
|
258
|
+
travels as a query parameter, so binding to a routable address puts both on the
|
|
259
|
+
wire in cleartext. Previously silent.
|
|
260
|
+
|
|
261
|
+
Eight tests, including that a correct prefix does not authenticate and that an empty
|
|
262
|
+
presented token is rejected.
|
|
263
|
+
|
|
264
|
+
The other 308 open alerts were triaged by reading each flagged line on `main`: 263
|
|
265
|
+
are test fixtures, and the rest are `session_id` values (a UUID naming a local file,
|
|
266
|
+
not a credential), closed-loopback sentinels for the features policy disables, or
|
|
267
|
+
URLs whose `https` scheme `endpoint_policy::validate_endpoint_url` enforces where
|
|
268
|
+
CodeQL cannot see it through a `format!`. One more real finding needs no fix here:
|
|
269
|
+
`bin/trace_classify.rs` logged an API key, and this release deletes that binary.
|
|
270
|
+
|
|
271
|
+
Those 308 are now dismissed on GitHub, each with the reasoning for its group rather
|
|
272
|
+
than a blanket note; the 3 real ones stay open so the next scan closes them as fixed,
|
|
273
|
+
which is a truer record. The two Dependabot `lru` alerts are dismissed as `not_used`:
|
|
274
|
+
the advisory is an `IterMut` Stacked Borrows violation, and neither crate holding an
|
|
275
|
+
`LruCache` ever iterates it — `ratatui 0.29` memoizes layouts through `get`/`put`,
|
|
276
|
+
`aws-sdk-s3` has no `iter_mut()` at all. Bumping `aws-sdk-s3` to the release that
|
|
277
|
+
does require the patched `lru` was tried and reverted: it drags the aws-smithy stack
|
|
278
|
+
forward, wants rustc 1.94.1 against this repo's 1.94.0 pin, and still leaves
|
|
279
|
+
`ratatui 0.29` as a source. `docs/code-review-2026-08-01.md` CR-003 records the
|
|
280
|
+
evidence and what closing it would actually cost.
|
|
281
|
+
|
|
282
|
+
### Repository and CI
|
|
283
|
+
|
|
284
|
+
Landing the re-base exposed two checks that had never run against this tree, both
|
|
285
|
+
broken by the re-base itself rather than by anything in it:
|
|
286
|
+
|
|
287
|
+
- **The secrets scan pinned its allowlist to commit SHAs.** `.gitleaksignore` listed
|
|
288
|
+
twelve reviewed fixtures as `<sha>:<path>:<rule>:<line>`; the re-base moved every
|
|
289
|
+
one into a new commit and all twelve went stale together. Since this project tracks
|
|
290
|
+
upstream by re-basing, that mechanism was guaranteed to break at every sync. Six
|
|
291
|
+
fixtures are now allowlisted **by value** in `.gitleaks.toml`, which survives a
|
|
292
|
+
rewrite, and six that exist only in old commits — from before upstream annotated
|
|
293
|
+
the lines — keep SHA pins, in published history that will not move. Verified three
|
|
294
|
+
ways: clean tree, clean 159-commit history, and a probe proving a realistic `ghp_`
|
|
295
|
+
token and a real ES256 JWT sharing the fixtures' own header are still reported.
|
|
296
|
+
- **`cargo deny` had been skipped every run**, because gitleaks failed before it in
|
|
297
|
+
the same job. It reported an undeclared git source — `our-forks/async-openai`,
|
|
298
|
+
upstream's fork and the client the sampler uses for Chutes' OpenAI-compatible API —
|
|
299
|
+
and five advisories, none with a patched release. Each is now ignored with a
|
|
300
|
+
reachability check that was run rather than assumed: no `{:p}` anywhere for the
|
|
301
|
+
crossbeam-epoch formatting bug, zero `git2::Remote::list` call sites, and a logging
|
|
302
|
+
stack that does not depend on `rand` for the re-entrancy advisory.
|
|
303
|
+
|
|
304
|
+
- `git2` 0.20.4 for the `Buf` dereference advisory, carrying libgit2 1.9.1 -> 1.9.6.
|
|
305
|
+
Its two other advisories have no fixed release yet.
|
|
306
|
+
- Releases now carry the six platform executables. All three existing releases have
|
|
307
|
+
notes and **zero assets**, while the README said "take a binary from Releases" —
|
|
308
|
+
so anyone not using npm had nowhere to download this program from. The workflow
|
|
309
|
+
attaches them from the run that built them, and refuses to publish if one is
|
|
310
|
+
missing.
|
|
311
|
+
- A social-preview card, three README badges, and the release notes taken from this
|
|
312
|
+
file rather than written twice.
|
|
313
|
+
|
|
314
|
+
### Documentation
|
|
315
|
+
|
|
316
|
+
The documentation was audited against the code rather than proofread, which is a
|
|
317
|
+
different exercise and found things a read-through would not:
|
|
318
|
+
|
|
319
|
+
- **The README presented the project as SpaceXAI's, under SpaceXAI's logo.** This
|
|
320
|
+
is a fork; upstream wrote most of the code and is credited for it, but not with
|
|
321
|
+
authorship of this tree, and their mark is theirs. `CONTRIBUTING.md` likewise
|
|
322
|
+
described upstream's "no external patches" policy as if it were ours.
|
|
323
|
+
- **`SECURITY.md` sent vulnerability reports to xAI's HackerOne programme** — to
|
|
324
|
+
people who do not maintain this code and cannot fix it, disclosing our issue to
|
|
325
|
+
a third party on the way.
|
|
326
|
+
- **Every install instruction was a 404.** `chutes.ai/cli/install.sh`,
|
|
327
|
+
`install.ps1`, `chutes.ai/cli`, `chutes.ai/build/changelog`,
|
|
328
|
+
`console.chutes.ai`, and the `docs.chutes.ai/build/overview` that `/docs` itself
|
|
329
|
+
opened. Each replacement was checked with a request.
|
|
330
|
+
- **Config examples named `grok-4.5`**, which this build cannot serve, and
|
|
331
|
+
`chutes-build update` was documented as the way to upgrade when it installs
|
|
332
|
+
nothing.
|
|
333
|
+
- **The ACP extension methods were documented under `x.ai/`** while the handlers
|
|
334
|
+
answer on `chutes.build/` — the page integrators read to know what to call.
|
|
335
|
+
- **Version pinning, the telemetry knobs and the coding-data row were documented
|
|
336
|
+
as working controls.** All four version keys parse and nothing acts on them; the
|
|
337
|
+
telemetry switches are compiled out; the privacy row is locked. Each now says so.
|
|
338
|
+
- **Two guide chapters existed on disk and shipped nowhere.** `USER_GUIDE` lists
|
|
339
|
+
what `/docs` shows and what is extracted to `$CHUTES_BUILD_HOME/docs`, and the
|
|
340
|
+
fork's Chutes-ecosystem and browser chapters were not in it — the same
|
|
341
|
+
registration gap as the tool layer, in a different registry. Renumbered to 25 and
|
|
342
|
+
26 and registered.
|
|
343
|
+
- Memory's owner-only file permissions and the absence of any coding-data
|
|
344
|
+
retention control are now stated in `PRIVACY.md`, where a reader looks for them.
|
|
345
|
+
|
|
346
|
+
One code defect came out of the audit, in the direction that matters — the docs
|
|
347
|
+
were right and the code was not:
|
|
348
|
+
|
|
349
|
+
- **A custom model-catalog endpoint received the ambient `CHUTES_API_KEY`.**
|
|
350
|
+
`PRIVACY.md` promises it never does and documents `CHUTES_MODELS_API_KEY` for
|
|
351
|
+
that case; the re-base dropped the separate auth arm, so pointing
|
|
352
|
+
`CHUTES_BUILD_MODELS_LIST_URL` at any host sent it your Chutes credential during
|
|
353
|
+
startup. Restored, with the test asserting the separation.
|
|
354
|
+
|
|
355
|
+
### Changed
|
|
356
|
+
|
|
357
|
+
- The upstream sync procedure changes from "port selectively, never merge" to a
|
|
358
|
+
merge of `upstream/main` with conflicts expected in the Chutes seams. See
|
|
359
|
+
`docs/upstream-sync.md`.
|
|
360
|
+
- `project_picker` and the bundled `SKILL.md` files follow upstream and are
|
|
361
|
+
removed.
|
|
362
|
+
- The coding-data retention row in settings is locked with a reason instead of
|
|
363
|
+
offered: this build has no such control, and the extension behind the row
|
|
364
|
+
already refused the call. The data-sharing banner never renders for the same
|
|
365
|
+
reason.
|
|
366
|
+
- Rate-limit and tier-restriction messages no longer pitch an upstream
|
|
367
|
+
subscription. The 429 message named SuperGrok and linked to it; the media
|
|
368
|
+
tools told the model to sell it.
|
|
369
|
+
- `scripts/seam_sweep.py` (new) compares the values the previous release shipped
|
|
370
|
+
against a re-based tree. It exists because a constant whose value came from
|
|
371
|
+
upstream compiles fine and its tests assert against the constant, which is how
|
|
372
|
+
the endpoint and credential defaults above survived a green gate.
|
|
373
|
+
|
|
374
|
+
### Fixed (identity)
|
|
375
|
+
|
|
376
|
+
Behavioural verification of the built binary, which the gate cannot do, found
|
|
377
|
+
the product still calling itself Chutes Build in the places users actually look:
|
|
378
|
+
|
|
379
|
+
- `--version` printed `grok 1.0.0`; `Usage:` printed `grok`, because `parse_cli`
|
|
380
|
+
filters `argv[0]` against a launcher allowlist that did not include our own
|
|
381
|
+
binary name.
|
|
382
|
+
- 983 occurrences of the bare product word in CLI help and error text had no
|
|
383
|
+
rebrand rule at all, and 14 stderr diagnostics were prefixed `grok:` — the
|
|
384
|
+
name of a program that does not exist.
|
|
385
|
+
- `models` offered `grok-4.5`: the model catalog had come across from upstream.
|
|
386
|
+
- The built-in agent profiles parsed as `grok-build-plan` while every caller
|
|
387
|
+
asked for `chutes-build-plan`, so `--agent chutes-build-plan` resolved to
|
|
388
|
+
nothing and plan mode fell back to the default profile.
|
|
389
|
+
- The session update and close notifications kept upstream's `_x.ai` extension
|
|
390
|
+
namespace in the replay filter, the session store and the pager's method table,
|
|
391
|
+
while the handlers answered on ours. (Written without the trailing slash on
|
|
392
|
+
purpose: the rebrand rule that fixes those names would otherwise rewrite this
|
|
393
|
+
sentence describing them, as it did once already.)
|
|
394
|
+
|
|
395
|
+
Then a real Chutes API key went in, and found what no static check had:
|
|
396
|
+
|
|
397
|
+
- **The ambient API key was read from `XAI_API_KEY`**, while every error message,
|
|
398
|
+
every doc page and the fork itself said `CHUTES_API_KEY`. Anyone following the
|
|
399
|
+
instructions was never authenticated. The auth-method id users write as
|
|
400
|
+
`preferred_method` in `config.toml` was upstream's too. 304 occurrences across
|
|
401
|
+
69 files.
|
|
402
|
+
- **570 places told the user to run `grok login`, `grok doctor`, `grok wrap …`**
|
|
403
|
+
in help text, error messages and the bundled user guide. An instruction naming
|
|
404
|
+
a binary that does not exist is worse than no instruction.
|
|
405
|
+
- **`update --check` reached `storage.googleapis.com`** for a channel pointer in a
|
|
406
|
+
bucket that does not exist — a third update endpoint, hidden from the seam
|
|
407
|
+
sweep because rustfmt had wrapped its value onto the next line. Deadened at
|
|
408
|
+
loopback like the other two.
|
|
409
|
+
|
|
410
|
+
- **The notification-hook tests were writing the whole process environment,
|
|
411
|
+
API key included, into files in the crate root.** They interpolated an
|
|
412
|
+
unquoted Windows path into `sh -c`, so the redirect missed the temp directory.
|
|
413
|
+
Thirty such files had accumulated and been committed to the re-base branch;
|
|
414
|
+
history was purged, `.gitignore` now blocks the pattern, and the keys were
|
|
415
|
+
rotated. The branch had never been pushed.
|
|
416
|
+
- **A blank `CHUTES_API_KEY` counted as set**, so a CI job exporting a secret
|
|
417
|
+
that does not exist was told it was using an API key and then failed to
|
|
418
|
+
authenticate. Blank is unset now, as it already was for per-model `env_key`.
|
|
419
|
+
|
|
420
|
+
With those fixed, a live run authenticates, lists the 15 Chutes models from
|
|
421
|
+
`llm.chutes.ai`, and completes a turn through the Auto router in about 13
|
|
422
|
+
seconds, talking only to `api.chutes.ai`, `llm.chutes.ai` and the configured
|
|
423
|
+
router — never to `x.ai` or `grok.com`, and writing nothing outside
|
|
424
|
+
`$CHUTES_BUILD_HOME`.
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
## [0.4.3] - 2026-08-03
|
|
428
|
+
|
|
429
|
+
### Added
|
|
430
|
+
|
|
431
|
+
- The `browser` tool gained the actions its workflow was missing: `wait`
|
|
432
|
+
(until a selector is visible or page text appears), `key` (`Enter`, `Tab`,
|
|
433
|
+
`Escape`, arrows, `Home`/`End`, `PageUp`/`PageDown`), `scroll`, `select`,
|
|
434
|
+
`back`, `reload`, `text` (full visible page text), and `console` / `network`,
|
|
435
|
+
which report the session's browser logs, uncaught errors, and requests.
|
|
436
|
+
- Documented desktop control as an opt-in MCP integration, including what
|
|
437
|
+
enabling it gives away, since no built-in tool captures the screen or
|
|
438
|
+
synthesizes input.
|
|
439
|
+
- `--output-format streaming-messages-json` emits headless output in the
|
|
440
|
+
Anthropic Messages API wire shape: a `system`/`init` line, `assistant` lines
|
|
441
|
+
whose `content[]` carries thinking, text and `tool_use` blocks, `user` lines
|
|
442
|
+
carrying each `tool_result`, and a final `result`. Ported from upstream.
|
|
443
|
+
- `streaming-json` now reports tool activity as `tool_call` and
|
|
444
|
+
`tool_call_update` lines. The headless runner ignored ACP tool-call updates
|
|
445
|
+
entirely, so a consumer could see the agent's prose but never what it did.
|
|
446
|
+
- `CHUTES_EXTRA_CA_BUNDLE` adds extra TLS roots from a PEM bundle, for networks
|
|
447
|
+
where a proxy terminates TLS with its own root. Opt-in and additive: unset by
|
|
448
|
+
default, never replaces the built-in roots, and never disables verification.
|
|
449
|
+
A bundle that is oversized, unreadable, or unparseable is reported and
|
|
450
|
+
ignored instead of breaking every request. Ported from upstream, reworked to
|
|
451
|
+
use reqwest's own PEM bundle parsing rather than adding a crate to the
|
|
452
|
+
generated workspace root.
|
|
453
|
+
|
|
454
|
+
### Fixed
|
|
455
|
+
|
|
456
|
+
- `browser click` now focuses the element before clicking, matching a real
|
|
457
|
+
pointer click. Without it a click on a field left focus on the body, so a
|
|
458
|
+
following `key` went nowhere.
|
|
459
|
+
- Cancelling now stops an in-flight `/compact`. Compaction runs as a command
|
|
460
|
+
rather than a turn, so the cancel path returned early and left a long
|
|
461
|
+
compaction running with no way to stop it. Other commands are unaffected.
|
|
462
|
+
Ported from upstream.
|
|
463
|
+
- Saving MCP settings no longer discards the rest of `config.toml`. Every MCP
|
|
464
|
+
writer parsed the file with a fallback to an empty table, so one syntax error
|
|
465
|
+
turned the next save into a full rewrite containing only what that call was
|
|
466
|
+
persisting. Unparseable configs are now refused, the user-config write lock
|
|
467
|
+
covers the whole read-modify-write so concurrent saves cannot erase each
|
|
468
|
+
other, and writes go through the shared atomic helper instead of a fixed
|
|
469
|
+
temporary filename two writers could collide on. Ported from upstream.
|
|
470
|
+
- The encrypted prompt templates no longer depend on how the repository was
|
|
471
|
+
checked out. Generator and staleness test compared raw `include_str!` bytes,
|
|
472
|
+
so arrays built on a CRLF working tree matched only on Windows; both sides
|
|
473
|
+
now fold line endings first, which also makes the decrypted prompt
|
|
474
|
+
byte-identical on every platform.
|
|
475
|
+
- Two pager tests no longer depend on the machine they run on: one budgeted its
|
|
476
|
+
wait in poll counts rather than elapsed time, and two built past instants by
|
|
477
|
+
subtracting more than the machine's uptime, which panics on a recently booted
|
|
478
|
+
box or a fresh CI runner.
|
|
479
|
+
- `/advisor` now spawns. Its curated toolset already declares `memory_search`,
|
|
480
|
+
`memory_get` and `web_fetch`, and session-level injection appended a second
|
|
481
|
+
copy of each; both entries resolved to one client-facing name, so toolset
|
|
482
|
+
validation rejected the agent with `duplicate client_name` on every attempt.
|
|
483
|
+
Injection now skips tools the agent already declares.
|
|
484
|
+
- Bundled skills cited tool names the model is never shown (`task` is exposed
|
|
485
|
+
as `spawn_subagent`, `run_in_background` as `background`), sending it after
|
|
486
|
+
tools absent from its schema. Names corrected in `/best-of-n` and
|
|
487
|
+
`/check-work`, with a test tying skill text to the advertised names.
|
|
488
|
+
- Repaired the nine stale `xai-grok-agent` tests: two asserted behavior the
|
|
489
|
+
code no longer has (retired `grok_*` toolset presets, `web_search` before it
|
|
490
|
+
became a default-on native provider), three compared prompt budgets against
|
|
491
|
+
raw `include_str!` output that a CRLF checkout inflates, two compared paths
|
|
492
|
+
with hardcoded forward slashes, and two staged a fake home through `$HOME`,
|
|
493
|
+
which `dirs::home_dir` honours only on Unix. The two home-dependent rules are
|
|
494
|
+
now split into injectable helpers covered on every platform, and their
|
|
495
|
+
environment-driven integration tests are marked Unix-only.
|
|
496
|
+
- The CI Rust job now runs the `xai-grok-agent` library tests and the bundled
|
|
497
|
+
skill checks, which were previously never executed by any workflow.
|
|
498
|
+
|
|
499
|
+
### Changed
|
|
500
|
+
|
|
501
|
+
- `generate_media` is self-contained: it resolves a plain model name against
|
|
502
|
+
the catalog and places the new top-level `prompt` into whatever text field
|
|
503
|
+
the selected cord declares, so `{model, kind, prompt}` is a complete call.
|
|
504
|
+
`params` is now optional and only needed for non-default settings or input
|
|
505
|
+
assets, and schema-mismatch errors list the accepted fields instead of
|
|
506
|
+
directing the caller back to `describe_media_model`. The `/imagine`,
|
|
507
|
+
`/imagine-video` and `imagine` skill instructions no longer mandate the
|
|
508
|
+
three-call list → describe → generate sequence.
|
|
509
|
+
- Updated the pinned `actions/checkout` workflow dependency to `v7.0.1`,
|
|
510
|
+
including its Git argument escaping and pull-request safety fixes.
|
|
511
|
+
|
|
512
|
+
### Security
|
|
513
|
+
|
|
514
|
+
- Marked the three synthetic secret-detection fixtures explicitly so both
|
|
515
|
+
worktree and full-history Gitleaks scans pass without weakening real-secret
|
|
516
|
+
detection.
|
|
517
|
+
|
|
518
|
+
### Documentation
|
|
519
|
+
|
|
520
|
+
- Recorded the CodeQL static-analysis triage in the security review: current
|
|
521
|
+
alert counts, the disposition of each query, and the reachability argument
|
|
522
|
+
showing the retained upstream backend client cannot run while
|
|
523
|
+
`REMOTE_SESSION_REGISTRY` is `false`.
|
|
524
|
+
- Documented the pinned Rust/Node toolchain, the single supported package
|
|
525
|
+
manager, the artifacts the project actually produces, the protected assets
|
|
526
|
+
and generated files, and the repository-visibility rules in `AGENTS.md`.
|
|
527
|
+
- Described the advisor's actual read-only toolset and the `/advisor` controls
|
|
528
|
+
in the subagents guide, and recorded the self-contained `generate_media`
|
|
529
|
+
workflow in the Chutes ecosystem and MCP guides.
|
|
530
|
+
- Listed the browser tool's full action set — what each reading action reports
|
|
531
|
+
and how elements are addressed — in the web and browser guide, and documented
|
|
532
|
+
`CHUTES_EXTRA_CA_BUNDLE` alongside the endpoint settings.
|
|
533
|
+
- Documented both headless streaming formats and what each line carries in the
|
|
534
|
+
CLI reference, and noted in the slash-command list that `/compact` can now be
|
|
535
|
+
stopped while it runs.
|
|
536
|
+
|
|
9
537
|
## [0.4.2] - 2026-08-01
|
|
10
538
|
|
|
11
539
|
### Added
|
|
@@ -16,7 +544,7 @@ project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
16
544
|
|
|
17
545
|
### Changed
|
|
18
546
|
|
|
19
|
-
- Reviewed
|
|
547
|
+
- Reviewed Chutes Build upstream through `0.2.117` and recorded the selective
|
|
20
548
|
port and deferral decisions.
|
|
21
549
|
- Removed the orphaned Dependabot auto-merge workflow after automated version
|
|
22
550
|
update PRs were disabled.
|
package/PRIVACY.md
CHANGED
|
@@ -11,13 +11,23 @@ where supported, sessions, logs, local exports, and user memory under
|
|
|
11
11
|
`~/.chutes-build` (or `CHUTES_BUILD_HOME`). Plugins, user roles/personas, and
|
|
12
12
|
managed bundled-agent definitions use that same root; setting
|
|
13
13
|
`CHUTES_BUILD_HOME` does not fall back to those resources in the default home.
|
|
14
|
-
Project memory
|
|
15
|
-
|
|
16
|
-
prompts.
|
|
14
|
+
Project and global memory are maintained in `MEMORY.md` under that root, with
|
|
15
|
+
per-session logs beside them. Known secret formats are filtered before every
|
|
16
|
+
memory write, but users should still avoid entering secrets into prompts. Memory
|
|
17
|
+
files are created owner-only (mode 0600 where the platform has POSIX
|
|
18
|
+
permissions), including the bootstrap templates written on first run.
|
|
17
19
|
|
|
18
20
|
`chutes-build trace` always creates a local archive. Remote session sharing and
|
|
19
21
|
search, remote workspace exposure, upstream managed configuration commands, and
|
|
20
|
-
automatic update checks are disabled
|
|
22
|
+
automatic update checks are disabled — compiled out through
|
|
23
|
+
`chutes-build-core::product`, with their endpoints pointed at a closed loopback
|
|
24
|
+
port rather than left resolvable.
|
|
25
|
+
|
|
26
|
+
There is no coding-data retention opt-in. Upstream offers one, both as a settings
|
|
27
|
+
row and as a startup banner; here the setting is locked with the reason shown
|
|
28
|
+
inline and the banner never appears, because the control would have nothing to
|
|
29
|
+
enable. Nothing in this build sends your prompts, code, or traces to us or to
|
|
30
|
+
anyone else for retention or training. Session storage is forced to local mode
|
|
21
31
|
even if inherited write-back settings are present. Updates are installed
|
|
22
32
|
manually.
|
|
23
33
|
|
package/README.md
CHANGED
|
@@ -1,206 +1,167 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[Chutes](https://chutes.ai) ecosystem.**
|
|
3
|
+
<h1>Chutes Build (<code>chutes-build</code>)</h1>
|
|
5
4
|
|
|
6
|
-
[](https://github.com/TheStreamCode/chutes-build/actions/workflows/ci.yml)
|
|
7
|
-
[](https://github.com/TheStreamCode/chutes-build/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/chutes-build)
|
|
7
|
+
[](LICENSE)
|
|
9
8
|
|
|
10
|
-
Chutes Build
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
**Chutes Build** is a terminal-based AI coding agent for the
|
|
10
|
+
[Chutes](https://chutes.ai) ecosystem. It runs as a full-screen TUI that
|
|
11
|
+
understands your codebase, edits files, executes shell commands, searches the web,
|
|
12
|
+
and manages long-running tasks — interactively, headlessly for scripting/CI, or
|
|
13
|
+
embedded in editors via the Agent Client Protocol (ACP).
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
[Installing](#installing) ·
|
|
16
|
+
[Building from source](#building-from-source) ·
|
|
17
|
+
[Documentation](#documentation) ·
|
|
18
|
+
[Repository layout](#repository-layout) ·
|
|
19
|
+
[Development](#development) ·
|
|
20
|
+
[Contributing](#contributing) ·
|
|
21
|
+
[License](#license)
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
> commands and file changes before approving them, especially in unfamiliar
|
|
19
|
-
> repositories.
|
|
23
|
+

|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
</div>
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
| --- | --- |
|
|
25
|
-
| **Chutes-native** | Live model discovery, `Auto (Chutes Router)`, model-aware reasoning controls, account usage, OCR, voice, and media generation are integrated directly into the Rust runtime. |
|
|
26
|
-
| **Private by default** | Sessions, memory, traces, logs, configuration, and exports stay local. Cloud features run only when their documented provider call is needed. |
|
|
27
|
-
| **Built for real repositories** | Planning, permission controls, worktrees, MCP, skills, background tasks, advisor review, and parallel subagents share one coherent session model. |
|
|
28
|
-
| **Transparent fork** | Chutes-specific product code is separated from retained `grok-build` infrastructure, with documented upstream review and Apache-2.0 attribution. |
|
|
27
|
+
## What this is, and what it is built on
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
Chutes Build is a fork of [`xai-org/grok-build`](https://github.com/xai-org/grok-build)
|
|
30
|
+
— SpaceXAI's Grok Build — re-based onto upstream 1.0.0 and adapted to run on
|
|
31
|
+
Chutes. Upstream wrote most of the code in this tree and it is used here under
|
|
32
|
+
Apache-2.0; the project is not affiliated with or endorsed by SpaceXAI.
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
What the fork changes:
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
- **Chutes, not xAI.** Inference goes to `llm.chutes.ai`, the model catalog is
|
|
37
|
+
Chutes', `model-router` ("Chutes Auto") is the default route, and media
|
|
38
|
+
generation, OCR, usage and quota all go through Chutes APIs.
|
|
39
|
+
- **Nothing phones home.** Telemetry, remote error reporting, upload, session
|
|
40
|
+
sharing, remote workspace exposure and self-update are off at compile time and
|
|
41
|
+
their endpoints are deadened, not merely unused. See
|
|
42
|
+
[`PRIVACY.md`](PRIVACY.md).
|
|
43
|
+
- **A few exclusive features**: Chutes media generation and editing, OCR, voice
|
|
44
|
+
input through a Chutes STT endpoint, Context7 documentation lookup, and an
|
|
45
|
+
isolated browser tool.
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```powershell
|
|
45
|
-
npx chutes-build
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The launcher does not download executables from a lifecycle script.
|
|
49
|
-
|
|
50
|
-
### Authenticate
|
|
51
|
-
|
|
52
|
-
An API key is the most reliable way to start. Create one in the Chutes
|
|
53
|
-
dashboard, then press `k` on the welcome screen, run `/apikey`, or store it
|
|
54
|
-
through the hidden-input CLI flow:
|
|
55
|
-
|
|
56
|
-
```powershell
|
|
57
|
-
chutes-build login
|
|
58
|
-
chutes-build
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
For a process-local credential:
|
|
62
|
-
|
|
63
|
-
```powershell
|
|
64
|
-
$env:CHUTES_API_KEY = "your-api-key"
|
|
65
|
-
chutes-build
|
|
66
|
-
```
|
|
47
|
+
Everything else is meant to track upstream closely, so their fixes arrive by
|
|
48
|
+
merge rather than by hand. [`docs/upstream-sync.md`](docs/upstream-sync.md)
|
|
49
|
+
documents that procedure and records each sync;
|
|
50
|
+
[`.github/upstream.json`](.github/upstream.json) records the commit this tree is
|
|
51
|
+
level with. `SOURCE_REV` is inherited from upstream's published tree and refers to
|
|
52
|
+
their monorepo, not to anything in this repository.
|
|
67
53
|
|
|
68
|
-
|
|
69
|
-
OAuth applications may require registered client credentials; see
|
|
70
|
-
[Authentication](docs/getting-started.md#authentication) for the supported
|
|
71
|
-
fallbacks and environment variables.
|
|
54
|
+
---
|
|
72
55
|
|
|
73
|
-
|
|
56
|
+
## Installing
|
|
74
57
|
|
|
75
|
-
|
|
76
|
-
Use `/model` interactively or inspect the live catalog from the CLI:
|
|
58
|
+
Via npm, which fetches the binary for your platform:
|
|
77
59
|
|
|
78
|
-
```
|
|
79
|
-
chutes-build
|
|
80
|
-
chutes-build
|
|
81
|
-
chutes-build --model model-router
|
|
60
|
+
```sh
|
|
61
|
+
npm i -g chutes-build
|
|
62
|
+
chutes-build --version
|
|
82
63
|
```
|
|
83
64
|
|
|
84
|
-
|
|
65
|
+
Or build from source below.
|
|
85
66
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
| **Orchestration** | Read-only advisor, foreground/background subagents, concurrent fan-out, bounded nesting, grouped waits, and isolated worktrees. |
|
|
91
|
-
| **Knowledge** | Context7 library documentation, official Chutes source checks, web search, local full-text memory, and Chutes-hosted semantic recall. |
|
|
92
|
-
| **Multimodal** | Image and PDF OCR, image/video understanding, voice dictation, and typed image, video, music, and speech generation artifacts. |
|
|
93
|
-
| **Automation** | MCP servers, plugins, skills, background tasks, and isolated Chrome/Edge control through local DevTools. |
|
|
67
|
+
From 1.0.0 on, each
|
|
68
|
+
[release](https://github.com/TheStreamCode/chutes-build/releases) also carries the
|
|
69
|
+
six platform executables as downloadable assets. Earlier releases (0.4.x) carry
|
|
70
|
+
release notes only — npm is the way to install those.
|
|
94
71
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
72
|
+
There is no self-update: `chutes-build` never contacts an update server, and the
|
|
73
|
+
`update` subcommand reports where to get a newer version rather than fetching one.
|
|
74
|
+
[`CHANGELOG.md`](CHANGELOG.md) records what changed in each release.
|
|
98
75
|
|
|
99
|
-
##
|
|
76
|
+
## Building from source
|
|
100
77
|
|
|
101
|
-
|
|
102
|
-
| --- | --- |
|
|
103
|
-
| **Local state** | Configuration, credentials, sessions, memory, logs, traces, exports, plugins, and agent definitions live under `~/.chutes-build` or `CHUTES_BUILD_HOME`. |
|
|
104
|
-
| **Hosted inference** | Prompts and selected context leave the machine only for the Chutes model request that needs them. Semantic memory sends selected memory chunks to the configured Chutes embedding route. |
|
|
105
|
-
| **Explicit tools** | OCR, voice, media, web, browser, MCP, and plugin actions send only the inputs required by the selected operation and provider. |
|
|
106
|
-
| **Disabled surfaces** | Product telemetry, remote error reporting, automatic trace upload, upstream session sharing/search, remote workspace exposure, and automatic updates cannot be enabled through normal configuration. |
|
|
107
|
-
| **Credentials** | Ambient Chutes credentials are restricted to allowlisted official HTTPS hosts. Custom endpoints require dedicated credentials and explicit trust configuration. |
|
|
78
|
+
Requirements:
|
|
108
79
|
|
|
109
|
-
|
|
110
|
-
|
|
80
|
+
- **Rust** — the toolchain is pinned by [`rust-toolchain.toml`](rust-toolchain.toml);
|
|
81
|
+
`rustup` installs it automatically on first build.
|
|
82
|
+
- **[DotSlash](https://dotslash-cli.com)** — required so hermetic tools under
|
|
83
|
+
[`bin/`](bin/) (notably [`bin/protoc`](bin/protoc)) can download and run.
|
|
84
|
+
Install it and ensure `dotslash` is on your `PATH` **before** building:
|
|
111
85
|
|
|
112
|
-
|
|
86
|
+
```sh
|
|
87
|
+
cargo install dotslash
|
|
88
|
+
# or: prebuilt packages — https://dotslash-cli.com/docs/installation/
|
|
89
|
+
/usr/bin/env dotslash --help # sanity check
|
|
90
|
+
```
|
|
113
91
|
|
|
114
|
-
|
|
92
|
+
- **protoc** — proto codegen resolves [`bin/protoc`](bin/protoc) via DotSlash,
|
|
93
|
+
or falls back to a `protoc` on `PATH` / `$PROTOC`.
|
|
94
|
+
- Windows, macOS and Linux all build. Windows is where this tree is developed and
|
|
95
|
+
gated, and it needs the vendored `protoc` fallback carried here — upstream 1.0.0
|
|
96
|
+
does not build on Windows at all, because `bin/protoc` is a DotSlash wrapper the
|
|
97
|
+
platform cannot execute from a build script.
|
|
115
98
|
|
|
116
|
-
```
|
|
117
|
-
chutes-build
|
|
99
|
+
```sh
|
|
100
|
+
cargo run -p chutes-build # build + launch the TUI
|
|
101
|
+
cargo build -p chutes-build --release # release binary: target/release/chutes-build
|
|
102
|
+
cargo check -p chutes-build # fast validation
|
|
118
103
|
```
|
|
119
104
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
Create an isolated worktree session:
|
|
127
|
-
|
|
128
|
-
```powershell
|
|
129
|
-
chutes-build --worktree feature-auth
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Resume the latest session for the current directory:
|
|
133
|
-
|
|
134
|
-
```powershell
|
|
135
|
-
chutes-build --continue
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Use `chutes-build --help` for the installed version's authoritative option
|
|
139
|
-
set. See the [CLI reference](docs/cli-reference.md) and
|
|
140
|
-
[slash-command reference](docs/slash-commands.md) for the maintained overview.
|
|
105
|
+
The binary artifact is named `xai-grok-pager`; official installs ship it as
|
|
106
|
+
`chutes-build`. On first launch it asks for a Chutes API key — the primary
|
|
107
|
+
credential, created at [chutes.ai/app/api](https://chutes.ai/app/api) and also
|
|
108
|
+
readable from `CHUTES_API_KEY`. Browser login is opt-in and needs an OAuth app you
|
|
109
|
+
register yourself; see the
|
|
110
|
+
[authentication guide](crates/codegen/xai-grok-pager/docs/user-guide/02-authentication.md).
|
|
141
111
|
|
|
142
112
|
## Documentation
|
|
143
113
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
`crates/codegen/xai-grok-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
114
|
+
The documentation lives in this repository. There is no separate site: an earlier
|
|
115
|
+
link to `docs.chutes.ai/build/overview` was a 404 dressed as a promise.
|
|
116
|
+
|
|
117
|
+
The user guide ships with the pager crate:
|
|
118
|
+
[`crates/codegen/xai-grok-pager/docs/user-guide/`](crates/codegen/xai-grok-pager/docs/user-guide/)
|
|
119
|
+
— getting started, keyboard shortcuts, slash commands, configuration, theming,
|
|
120
|
+
MCP servers, skills, plugins, hooks, headless mode, sandboxing, and more.
|
|
121
|
+
|
|
122
|
+
## Repository layout
|
|
123
|
+
|
|
124
|
+
| Path | Contents |
|
|
125
|
+
|------|----------|
|
|
126
|
+
| `crates/codegen/xai-grok-pager-bin` | Composition-root package `chutes-build`; builds the `chutes-build` binary |
|
|
127
|
+
| `crates/codegen/xai-grok-pager` | The TUI: scrollback, prompt, modals, rendering |
|
|
128
|
+
| `crates/codegen/xai-grok-shell` | Agent runtime + leader/stdio/headless entry points |
|
|
129
|
+
| `crates/codegen/xai-grok-tools` | Tool implementations (terminal, file edit, search, ...) |
|
|
130
|
+
| `crates/codegen/xai-grok-workspace` | Host filesystem, VCS, execution, checkpoints |
|
|
131
|
+
| `crates/codegen/...` | The rest of the CLI crate closure (config, MCP, markdown, sandbox, ...) |
|
|
132
|
+
| `crates/common/`, `crates/build/`, `prod/mc/` | Small shared leaf crates pulled in by the closure |
|
|
133
|
+
| `third_party/` | Vendored upstream source (Mermaid diagram stack) — see below |
|
|
134
|
+
|
|
135
|
+
> [!IMPORTANT]
|
|
136
|
+
> The root `Cargo.toml` (workspace members, dependency versions, lints,
|
|
137
|
+
> profiles) is **generated** — treat it as read-only. Prefer editing per-crate
|
|
138
|
+
> `Cargo.toml` files.
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
cargo check -p <crate> # always target specific crates; full-workspace builds are slow
|
|
144
|
+
cargo test -p xai-grok-config # per-crate tests
|
|
145
|
+
cargo clippy -p <crate> # lint config: clippy.toml at the repo root
|
|
146
|
+
cargo fmt --all # rustfmt.toml at the repo root
|
|
170
147
|
```
|
|
171
148
|
|
|
172
|
-
|
|
173
|
-
`target/release/chutes-build` on macOS/Linux.
|
|
174
|
-
|
|
175
|
-
### Repository map
|
|
176
|
-
|
|
177
|
-
| Path | Ownership |
|
|
178
|
-
| --- | --- |
|
|
179
|
-
| `AGENTS.md` | Repository-wide guidance and verification contract for coding agents. |
|
|
180
|
-
| `crates/chutes-build-core/` | Chutes routing, endpoint policy, catalog, reasoning, account, media, privacy, and product policy. |
|
|
181
|
-
| `crates/codegen/` | Retained and adapted upstream runtime crates. Keep crate names stable to make upstream review practical. |
|
|
182
|
-
| `npm/` | Native launcher, platform-package assembly, and npm verification. |
|
|
183
|
-
| `docs/` | Public technical references, maintainer procedures, and design records. |
|
|
184
|
-
| `.github/workflows/` | CI, security policy checks, upstream monitoring, and release packaging. |
|
|
185
|
-
| `prod/` and `third_party/` | Shared protocol sources and retained attribution/material from upstream. |
|
|
186
|
-
|
|
187
|
-
The root `Cargo.toml` is generated and treated as read-only. Make dependency
|
|
188
|
-
changes in the owning crate manifest or generator source instead of manually
|
|
189
|
-
reorganizing the generated workspace.
|
|
149
|
+
## Contributing
|
|
190
150
|
|
|
191
|
-
|
|
151
|
+
> [!NOTE]
|
|
152
|
+
> External contributions are not accepted. See [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
192
153
|
|
|
193
|
-
|
|
194
|
-
[`xai-org/grok-build`](https://github.com/xai-org/grok-build). Upstream changes
|
|
195
|
-
are reviewed and ported selectively; they are never merged or released
|
|
196
|
-
automatically. See [Upstream synchronization](docs/upstream-sync.md).
|
|
154
|
+
## License
|
|
197
155
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), and [SECURITY.md](SECURITY.md) before
|
|
201
|
-
contributing.
|
|
156
|
+
First-party code in this repository is licensed under the **Apache License,
|
|
157
|
+
Version 2.0** — see [`LICENSE`](LICENSE).
|
|
202
158
|
|
|
203
|
-
|
|
204
|
-
[NOTICE](NOTICE), and [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES).
|
|
159
|
+
Third-party and vendored code remains under its original licenses. See:
|
|
205
160
|
|
|
206
|
-
|
|
161
|
+
- [`THIRD-PARTY-NOTICES`](THIRD-PARTY-NOTICES) — crates.io / git dependencies,
|
|
162
|
+
bundled UI themes, and **in-tree source ports** (including openai/codex and
|
|
163
|
+
sst/opencode tool implementations)
|
|
164
|
+
- [`crates/codegen/xai-grok-tools/THIRD_PARTY_NOTICES.md`](crates/codegen/xai-grok-tools/THIRD_PARTY_NOTICES.md)
|
|
165
|
+
— crate-local notice for the codex and opencode ports (license texts +
|
|
166
|
+
Apache §4(b) change notice)
|
|
167
|
+
- [`third_party/NOTICE`](third_party/NOTICE) — vendored Mermaid-stack index
|
package/SECURITY.md
CHANGED
|
@@ -1,73 +1,35 @@
|
|
|
1
1
|
# Security Policy
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Chutes Build is a fork of
|
|
4
|
+
[`xai-org/grok-build`](https://github.com/xai-org/grok-build). Where to report
|
|
5
|
+
depends on which part is affected, and if you are not sure, report it here first.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
the latest revision of the default branch; older source snapshots are not
|
|
7
|
-
supported.
|
|
7
|
+
## Report it here
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Use GitHub's private vulnerability reporting on this repository:
|
|
10
|
+
<https://github.com/TheStreamCode/chutes-build/security/advisories/new>.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
open a public issue and do not include live credentials, private source code,
|
|
13
|
-
session archives, or personal data in a report.
|
|
12
|
+
Please do not open a public issue for a vulnerability.
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
Anything in the fork's own surface belongs here:
|
|
16
15
|
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
-
|
|
16
|
+
- credential resolution and storage (`CHUTES_API_KEY`, `auth.json`, the OAuth
|
|
17
|
+
flow against the Chutes IdP);
|
|
18
|
+
- which endpoints may receive a credential (`chutes-build-core::endpoint_policy`);
|
|
19
|
+
- the plugin trust boundary, permission rules, and the sandbox;
|
|
20
|
+
- the Chutes tools — media generation, OCR, the isolated browser, Context7;
|
|
21
|
+
- memory storage and the secret filter.
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
and remediation timing will be coordinated according to severity and the
|
|
26
|
-
availability of a safe fix.
|
|
23
|
+
## Report it upstream too
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
If the flaw is in code inherited from upstream and reproduces on Grok Build, it
|
|
26
|
+
affects their users as well: please also report it through their process. A fix
|
|
27
|
+
landing upstream reaches more people, and it comes back here by merge.
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
and control an isolated browser. Model output, repository contents, web pages,
|
|
32
|
-
MCP servers, tool responses, and downloaded documents are untrusted input. Keep
|
|
33
|
-
permission prompts enabled, use trusted repositories, and never expose secrets
|
|
34
|
-
in prompts or committed files.
|
|
29
|
+
## What this build does not do
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Ambient Chutes credentials are restricted to allowlisted official HTTPS hosts.
|
|
43
|
-
Custom inference and model-catalog endpoints require dedicated credentials.
|
|
44
|
-
OAuth client secrets are read from the environment, used for token exchange
|
|
45
|
-
and refresh when configured, and are never persisted by Chutes Build.
|
|
46
|
-
|
|
47
|
-
Credential-bearing and download clients reject URL credentials, unexpected
|
|
48
|
-
ports, insecure schemes, redirects, and private, loopback, link-local, or
|
|
49
|
-
special-use DNS results. Development endpoint overrides require the explicit
|
|
50
|
-
`CHUTES_ALLOW_INSECURE_ENDPOINTS=1` opt-in; the opt-in does not make ambient
|
|
51
|
-
Chutes credentials transferable to arbitrary model endpoints. Custom Context7
|
|
52
|
-
endpoints require their own opt-in and never receive `CONTEXT7_API_KEY`.
|
|
53
|
-
|
|
54
|
-
Machine-readable MCP listings redact environment/header values and URL
|
|
55
|
-
credentials. Destructive session, memory, plugin, marketplace, and worktree
|
|
56
|
-
operations require an interactive confirmation unless an explicit `--yes`
|
|
57
|
-
flag is provided. Media responses stream to bounded temporary storage, default
|
|
58
|
-
to 128 MiB with a 512 MiB hard ceiling, and use transactional create-new
|
|
59
|
-
artifact writes. Automatic permission mode only fast-paths deterministic
|
|
60
|
-
read-only shell commands; classifier failure returns to the normal user prompt.
|
|
61
|
-
|
|
62
|
-
## Automated release checks
|
|
63
|
-
|
|
64
|
-
CI scans the complete Git history for known secret patterns and evaluates the
|
|
65
|
-
resolved Rust dependency graph for advisories, licenses, duplicate versions,
|
|
66
|
-
and unapproved sources. Release packaging additionally executes every native
|
|
67
|
-
binary, creates SHA-256 sidecars for native npm archives, verifies those
|
|
68
|
-
sidecars after artifact download, and runs the assembled launcher with its
|
|
69
|
-
native Linux package before publication can begin.
|
|
70
|
-
|
|
71
|
-
Documented advisory exceptions must include a bounded rationale in `deny.toml`.
|
|
72
|
-
New advisories or source-policy violations fail CI by default. The current
|
|
73
|
-
review record is maintained in [docs/security-review.md](docs/security-review.md).
|
|
31
|
+
Some classes of report do not apply, because the behaviour is compiled out rather
|
|
32
|
+
than merely disabled: telemetry, remote error reporting, session sharing, remote
|
|
33
|
+
workspace exposure, trace upload, and self-update. See
|
|
34
|
+
[`PRIVACY.md`](PRIVACY.md) and `chutes-build-core::product`. If you find one of
|
|
35
|
+
them active, that *is* a vulnerability and we want to hear about it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chutes-build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Privacy-first, open-source coding agent for the Chutes ecosystem",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Michael Gasperini (Mikesoft)",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"check": "npm test && npm run verify:release && npm pack --dry-run"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"chutes-build-darwin-arm64": "0.
|
|
41
|
-
"chutes-build-darwin-x64": "0.
|
|
42
|
-
"chutes-build-linux-arm64-gnu": "0.
|
|
43
|
-
"chutes-build-linux-x64-gnu": "0.
|
|
44
|
-
"chutes-build-win32-arm64": "0.
|
|
45
|
-
"chutes-build-win32-x64": "0.
|
|
40
|
+
"chutes-build-darwin-arm64": "1.0.0",
|
|
41
|
+
"chutes-build-darwin-x64": "1.0.0",
|
|
42
|
+
"chutes-build-linux-arm64-gnu": "1.0.0",
|
|
43
|
+
"chutes-build-linux-x64-gnu": "1.0.0",
|
|
44
|
+
"chutes-build-win32-arm64": "1.0.0",
|
|
45
|
+
"chutes-build-win32-x64": "1.0.0"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"ai",
|