Releases: TheStreamCode/chutes-build
Release list
Chutes Build 1.0.3
Measured against the live Chutes endpoint with a real key, not reasoned about from
the source. Two of the findings below contradicted what the code looked like it
did, and one contradicted an earlier fix in this same release.
Fixed
- Every model claimed a 256,000-token context. The catalogue at
llm.chutes.ai/v1/modelspublishescontext_lengthper model;
parse_remote_model_valuelooked forcontextWindow,context_windowand two
_metaspellings, none of which Chutes sends, so all thirteen fell through to
one default. It was wrong in both directions at once:Qwen3-32Bholds 40,960,
so the product promised six times what exists and its requests were refused;
DeepSeek-V4-Flash,Kimi-K3andGLM-5.2hold 1,048,576, so three quarters
of the window went unused. Compaction and truncation were sizing themselves
against a figure no model agreed with. Eleven of thirteen now carry their
published value; the two that publish nothing keep a default. - Each model now carries its own output limit, from
max_output_length—
but only where that is smaller than the window. Several models publish the
two as the same number, which means "output may use the whole context" rather
than "always ask for this much": sending it asmax_tokensleaves no room for
the prompt, andQwen3-32Banswers400 Requested token count exceeds. Nine
models gain a real cap, two are skipped. This was caught by testing the fix
against the endpoint before shipping it — the first version of the change would
have broken a model that previously worked. - An endpoint override reached inference but not the catalogue.
docs/configuration.mddocumentsCHUTES_ROUTER_BASE_URL,
CHUTES_INFERENCE_BASE_URLandCHUTES_MODELS_BASE_URL, and
chutes-build-corehonours them, but the re-base left the agent's
EndpointsConfigreading only theCHUTES_BUILD_*spellings. The documented
names come first now, with the others kept as fallbacks. - The system prompt introduced the agent as xAI's. The re-base overwrote
templates/prompt.mdwith upstream's, so every model was told at every turn
that it was "released by xAI" instead of "a privacy-first coding agent
optimized for the Chutes ecosystem" — the branding fix in 1.0.1 covered what
the user could see, not what the model was told. The same overwrite deleted
the<official_chutes_sources>block, which is the larger loss: it is what
directed the model to treatchutes.ai/docsandchutes.ai/newsas the
primary authority on Chutes products, APIs, models, pricing and quotas, to
say when a claim is unverified rather than blending fact with inference, and
— a security instruction, not a stylistic one — never to put API keys,
credentials, private code or repository contents into a search query or
outbound request. Both restored from 0.4.3 and the encrypted templates
regenerated. Present in the 1.0.3 binaries; this entry was written after the
build was dispatched, so the 1.0.3 tag does not carry it.
Notes on tool compatibility
The catalogue's supported_features is accurate: every model advertising tools
emits a real tool_calls finish, and the two advertising nothing do not. A first
probe suggested three Qwen models were broken — they were not. The probe gave them
96 output tokens, which a reasoning model spends thinking before it can emit the
call. That is the finding worth keeping: a thinking model needs output budget
before tool use works at all, and without it the failure is silent and looks like
missing support.
Chutes Build 1.0.2
Three faults a user meets in the first minute. All reproduced against the live
service with a real API key, not inferred from the source.
Fixed
/modeloffered a single model.ModelFetchAuth::resolvetreated any stored
credential as a session, and logging in with an API key stores one — so
auth.jsonholding achutes::api_keyentry sent the catalogue fetch down the
session path, which asks the router proxy. That proxy advertises exactly one
model: itself.llm.chutes.ai/v1/modelsreturns thirteen. The request URL was
already right for API keys; only the classification was wrong.modelsnow
lists all fourteen, with the configured default marked — a default the product
previously could not resolve even when the user had named it.- "Sign in with Chutes" could not complete. The re-base replaced the fork's
OAuth scopes with upstream's —grok-cli:access,api:access,
conversations:*,workspaces:*— none of which exist atapi.chutes.ai. Its
discovery document offersaccount:read,chutes:read,chutes:invoke; an
authorization server rejects scopes it does not know. Restored to the minimum the
client uses. OAuth still requires an application you register yourself at
chutes.ai — there is no
shared client id, by design — and the API key remains the primary method. - The welcome screen disagreed with its own input bar. The wordmark blended
from a fixed gray because the re-base replacedtheme.accent_assistantwith
upstream'stheme.gray. It takes the accent again, so the centre of the screen
and the prompt border move together. - The feedback prompt's default still read "You've been using Grok Code
productively!". It lives inprod/mc/cli-chat-proxy-types, outside the crates
the 1.0.1 sweep looked at — found by searching the shipped binary rather than
the tree.
Changed
- Silver is the brand accent. Not a rename of the green: in this palette one
constant carried both the brand and the meaning of success and of a diff's
insertion side. Those are now two families.SILVERtakes the chrome — wordmark,
assistant, model and command labels, active prompt border, H1 rule — and green
stays exactly where it says something, because a silver diff against a red one is
unreadable. The silver is cool on purpose: these neutral grays are warm, so a
warm silver would sink into the furniture.
Chutes Build 1.0.1
Fixed (the TUI wore upstream's identity)
- The splash showed Grok's wordmark.
assets/logo/logo07.txtand
logo05.txtwere byte-identical to upstream's: the re-base overwrote the Chutes
wordmark and 1.0.0 shipped it, so every start drew the wrong brand. Restored. A
sweep of every asset in the tree says these two were the only ones taken. - A Chutes user was offered a subscription to another company's product.
Hitting a usage limit produced "Upgrade to SuperGrok" and "Upgrade to SuperGrok
Heavy"; a restricted command said it "requires SuperGrok". The buttons already
pointed at chutes.ai/pricing — the fork had rebranded where they go and left
what they say. This one predates the re-base; v0.4.3 carries the same strings. - The screen-mode settings described opening "plain grok", the welcome gate read
"SuperGrok subscription required", and the feedback prompt opened with "You've
been using Grok Code productively!".
Rust identifiers, crate names, telemetry event types and model ids such as
grok-4.5 are deliberately untouched: AGENTS.md keeps them so upstream diffs
stay readable, and a model name is data rather than branding.
The wordmark's hash is now pinned by a test, so a merge that takes upstream's
side there fails instead of shipping. The loss was silent by nature: nothing
compiles differently, no test read the bytes, and the only symptom was on screen.
Security
- The
agent servetoken comparison no longer rests on a function that
disclaims the property it was chosen for. It used
ring::constant_time::verify_slices_are_equal, which ring now deprecates as an
"internal function not intended for external use with no promises regarding side
channels" — while the reason for calling it at all is that==on&strreturns
at the first differing byte, and over a socket with no rate limit that leaks the
token one byte at a time. It now usessubtle::ConstantTimeEq, which is
maintained for this and also resists the compiler folding the comparison back
into an early return. No new code enters the build:subtlewas already in the
graph through rustls, so the lock file moves by one line.
Fixed
--helphad upstream's branding back in it. The re-base took upstream's
wording over the fork's in five places a user reads, three of them flag names:
--grok-ws-originand--grok-ws-url, which 0.4.3 spelled--chutes-ws-*and
kept hidden, so the re-base both renamed them and put internal plumbing into the
top-level help;--xai-api-base-url, described as "the public xAI API base URL"
when it overrides the Chutes inference base URL; the positional-prompt example,
which readgrok "fix the bug"beside achutes-buildexample on the same
line; and thescreen_modehelp, which said "To default plaingrokto
minimal". Found by installing the published 1.0.0 the way a user gets it and
reading every help surface — the step the release procedure asks for and which
had not been done.leader/mod.rspasses those flags to the child process, so
the rename covers it too.
Repository and CI
xai-grok-shell --lib auth::runs on Windows. It failed 24 there, and the
CI step had never executed at all, because the pager step above it always failed
first. A provider command goes throughcmd /Coff Unix — deliberately, for
exit-code propagation — while the fixtures were POSIX one-liners. They now drive
auth-provider-fixture, a real helper invoked withargs, so no shell
interprets them. Two lock tests read the lock file through a second handle while
holding it, which Windows refuses; they read through the holding handle now, as
the product does.- The Linux job reaches its end. It had not passed in the last twenty runs, so
four steps below the failure — auth and session integration, agent construction
and bundled skills, Chutes-native tools, and clippy — had not run either. Behind
them were a bannedtokio::process::Command::spawnin a test the ban does not
describe, and a doc comment separated from the function it documents. - That job's 60-minute limit was sized for the broken state. The first run to
reach the end spent 59.7 minutes on work that passed and was killed during the
cache save — which left the next run cold, slower, and killed in the same
place. Raised to 90, matching Windows. Measured twice since at 65 and 67 minutes:
the cost is roughly 45 minutes of tests plus 11 of clippy, not compilation, so a
warm cache moves it very little and the headroom is about a quarter. - All five CI jobs pass. Windows had been red since 1.0.0 landed and Linux had
not finished in over twenty runs; this is the first complete green run. RUSTSEC-2026-0249is recorded indeny.toml:smartstringis unmaintained —
archived, not vulnerable — and reaches this tree only as a non-optional
dependency ofrhai, whose latest stable we already use, so no bump closes it.
It turned the dependency job red on a documentation-only commit, an hour after
the same check passed, because that job reads the live advisory database.- A flaky history-delivery test asked for a repaint and a result in one condition;
it fails when the daemon is fast enough to answer before the eager snapshot,
which is why widening its deadline had not helped.
Chutes Build 1.0.0
Chutes Build is re-based onto xai-org/grok-build 1.0.0 (afbc0fb) and adopts
its version, so the number now says which upstream this build actually is.
Why the re-base
.github/upstream.json recorded lastReviewedVersion: 0.2.117, but those
commits had been reviewed and not taken — the records said "nothing safe to
port in isolation". For the retained crates the tree was still at the 2026-07-17
fork point, 2075 files and roughly 440k lines behind upstream. Cherry-picking
could not close that: upstream added 94k lines in five days. Measuring the fork
showed why re-basing was the cheaper path — only 102 files existed here and not
upstream, and only 26 actually consume chutes-build-core.
Added
Everything upstream shipped between the fork point and 1.0.0 arrives at once:
1348 files of work from the never-taken window, plus the roughly 110 changes
between 0.2.117 and 1.0.0. Highlights users will notice: session recaps that
follow the language of the conversation, narrow markdown tables that reflow
inside their cells with hard splits on grapheme boundaries, a plan-viewer
scrollbar that is easier to grab, --output-format streaming-messages-json,
tabbed usage and session-info, and a large batch of terminal, tmux and session
fixes.
Security
Carried forward and, where upstream had since fixed them differently, taken from
upstream instead:
- Permission rules for Read, Edit and Grep lexically normalize the tool's path
before the glob match, soRead(src/**)can no longer be escaped with
src/../../etc/passwd. NotebookEdit/NotebookReadno longer alias ontoEdit/Read.- A client-forwarded MCP server matching an on-disk Claude or Cursor config is
rejected while that vendor'smcpsswitch is off. - Diagnostic logging of a credential fragment no longer panics on a non-ASCII
token. - Chutes API keys (
cpk_) are recognised by the secret redactor. - Memory passes through the secret filter at every write path, and every write
path now creates its file owner-only. Three of the four created files with the
process umask, so a fresh install'sMEMORY.mdand both bootstrap templates
were world-readable — and memory holds whatever you asked the agent to
remember. model-routerdispatch validatesCHUTES_ROUTER_BASE_URLthrough the
endpoint policy before a session credential is sent to it.- The default inference endpoint is
llm.chutes.aiagain. The re-base had left
upstream'sapi.x.ai/v1, so any model entry without an explicit base URL
would have sent a Chutes API key to xAI. - The relay and gateway WebSocket endpoints are loopback sentinels again, not
code.grok.comandgrok.com. Chutes Build has no vendor relay; those paths
must fail closed. - The changelog fetch, the update check and the remote-session/workspace clients
point at a closed loopback port, so none of them can phone home. - The npm scaffold that would install
@xai-official/grok-<platform>binaries on
postinstall is gone, along with the version check that compared this build
against upstream's package.
Fixed
- Cloudflare edge failures (520–524, 529, 530) are retried instead of ending the
turn, while origin-TLS 525/526 stay fatal. - A server
Retry-Afteris clamped to 30s and jittered. - Failed requests no longer dump a Cloudflare HTML error page into the terminal.
- The sandbox starts on large workspaces (deny-glob entry budget 200k → 2M).
bin/protocis a DotSlash wrapper Windows cannot execute from a build script;
a vendored platform binary is now the fallback.
Fixed (the Chutes tool layer was unreachable)
generate_media,list_media_models,describe_media_model,browser,
ocr_pageandget_chutes_usagewere in no toolset. The re-base kept every
implementation and dropped every registration, so six thousand lines of working
code compiled, passed their own tests, and could not be called. Upstream's
toolsets carried its Imagine tools instead, which talk to an endpoint Chutes has
no equivalent for./imagineand/imagine-videohad disappeared, for the same reason: the
pager hides a command whose required tools are not advertised, and they required
the xAI Imagine tools. Both now usegenerate_media, and their instructions
teach the Chutes workflow — list the catalog, describe the model, compose the
payload from the cord's own example — because no two Chutes media models share a
schema./imagine-videois rewritten rather than renamed: upstream's guidance
opens with "there is no text-to-video tool", which is true of that API and false
here.- Plugin sources in the system temp directory were auto-trusted on Windows.
Auto-trust covers anything under the user's home, and on Windows temp is under
the home — so a plugin unpacked there skipped the explicit trust step entirely.
Found by a test that had been failing on Windows since before the re-base. - Five upstream test failures on Windows are gone;
xai-grok-agentnow passes all
578. Two were real defects rather than test bugs: the trust hole above, and a
home-directory guard no test on Windows could reach.
Authentication
Upstream ships an OAuth application everyone signs in through, so its
documentation and defaults put browser login first and treat the API key as a
fallback. Chutes does not work that way: OAuth needs an application you register in
your own account area at chutes.ai/app/api, so there is
no client ID that could serve anyone but its owner.
- The compiled-in OAuth client ID is gone. It offered a sign-in that would fail
for every user but one.OAuth2ProviderConfig::from_envnow returnsNoneunless
CHUTES_BUILD_OAUTH2_CLIENT_IDnames an app, which is also upstream's shape and
so one seam fewer at the next merge. With no app configured,loginalready said
the right thing — "Sign-in is not available for this deployment. Set
CHUTES_API_KEY instead." — and now that message is reachable. - A cached session survives a shell with no OAuth app configured. The
compatibility check compares a credential's issuer against the configured one;
with no provider configured there is nothing to compare against, and the question
becomes which credentials are self-sufficient. A session is:oidc::refresh
renews it from the issuer and client id stored in the credential itself, not from
the config. So exportingCHUTES_BUILD_OAUTH2_CLIENT_ID, signing in, and then
launching from a desktop shortcut or a cron entry that lacks the variable keeps
working — discarding the session there would strand the user in the one state
where interactive login is unavailable. The legacy issuer-lessWebLogin
credential is still rejected, now for either config shape, because it has neither
issuer nor client id to renew with. - The documentation was rewritten around the API key, which is the primary and
always-valid credential rather than a fallback: the authentication chapter, the
first-launch section of the getting-started guide,docs/getting-started.mdand
the README.docs/getting-started.mdhad also described a "bundled client ID"
that no longer exists. jsonwebtokenhad no provider to sign or verify with. It picks one from cargo
features, and this graph enables both: the shell declaresrust_crypto, while
xai-file-utils->gcloud-storage->gcloud-authenablesjwt-aws-lc-rs. Cargo
unifies features across the graph, so neither can be turned off from here, and with
both on the crate refuses to choose — every signature operation panics. Production
survived on placement alone:run_login_flow_with_configinstalled a provider and
is the only entry to the one function that verifies an id_token, which holds exactly
until a second verification path appears. The install now sits at each point of use,
behind aOnceLock, so the library is correct by construction; 23 auth tests that
had been failing on Linux CI depend on it too.- Six example keys read
CHUTES_API_KEY="xai-..."— upstream's prefix, left
behind when the rebrand renamed the variable but not its value. A Chutes key is
cpk_-prefixed, which the redactor already knew and the docs did not.
The API key also has to be enterable, and on this branch it was not:
/apikeydid not exist.slash/commands/apikey.rscame across in the
re-base and was never declared inslash/commands/mod.rs, so it was not
compiled — the same registration gap as the Chutes tool layer, in a third
registry, and invisible for the same reason: an unreferenced module is not
built, so nothing warns. Everything it needs went with it —
Action::EnterApiKey/SubmitApiKey,Effect::SubmitApiKey,
AuthMode::ApiKeyEntry, the dispatchers, the welcome-screen arm, thekkey.
The shell half was intact the whole time:chutes.build/setApiKeyis handled in
extensions/auth.rsand allow-listed inacp_agent.rs. Nothing could reach it./loginjumped straight into OAuth instead of asking, because
Action::ShowLoginMenuwent the same way. It now opens the choice menu
("Login with …" / "Enter API key" / "Quit") that the fork's/loginalways did.- Together these meant a fresh install advertised exactly one login method —
browser sign-in — which without a registered app cannot run. The only way in was
to set the environment variable before starting the program. - Four registries now, and the fourth caught itself: the pager's
pager_builtin_triggers_are_reserved_in_shellfailed the moment/apikey
became real, becauseapikeywas not in the shell'sPAGER_COMMAND_KEYSand a
skill of that name could have shadowed it. Reserved. The new
apikey_registered_in_builtin_commandsis the test that would have caught the
original gap.
The documentation had described /apikey and the in-app entry all along, in
docs/slash-commands.md and docs/getting-started.md. Thir...
Chutes Build 0.4.3
Added
- The
browsertool gained the actions its workflow was missing:wait
(until a selector is visible or page text appears),key(Enter,Tab,
Escape, arrows,Home/End,PageUp/PageDown),scroll,select,
back,reload,text(full visible page text), andconsole/network,
which report the session's browser logs, uncaught errors, and requests. - Documented desktop control as an opt-in MCP integration, including what
enabling it gives away, since no built-in tool captures the screen or
synthesizes input. --output-format streaming-messages-jsonemits headless output in the
Anthropic Messages API wire shape: asystem/initline,assistantlines
whosecontent[]carries thinking, text andtool_useblocks,userlines
carrying eachtool_result, and a finalresult. Ported from upstream.streaming-jsonnow reports tool activity astool_calland
tool_call_updatelines. The headless runner ignored ACP tool-call updates
entirely, so a consumer could see the agent's prose but never what it did.CHUTES_EXTRA_CA_BUNDLEadds extra TLS roots from a PEM bundle, for networks
where a proxy terminates TLS with its own root. Opt-in and additive: unset by
default, never replaces the built-in roots, and never disables verification.
A bundle that is oversized, unreadable, or unparseable is reported and
ignored instead of breaking every request. Ported from upstream, reworked to
use reqwest's own PEM bundle parsing rather than adding a crate to the
generated workspace root.
Fixed
browser clicknow focuses the element before clicking, matching a real
pointer click. Without it a click on a field left focus on the body, so a
followingkeywent nowhere.- Cancelling now stops an in-flight
/compact. Compaction runs as a command
rather than a turn, so the cancel path returned early and left a long
compaction running with no way to stop it. Other commands are unaffected.
Ported from upstream. - Saving MCP settings no longer discards the rest of
config.toml. Every MCP
writer parsed the file with a fallback to an empty table, so one syntax error
turned the next save into a full rewrite containing only what that call was
persisting. Unparseable configs are now refused, the user-config write lock
covers the whole read-modify-write so concurrent saves cannot erase each
other, and writes go through the shared atomic helper instead of a fixed
temporary filename two writers could collide on. Ported from upstream. - The encrypted prompt templates no longer depend on how the repository was
checked out. Generator and staleness test compared rawinclude_str!bytes,
so arrays built on a CRLF working tree matched only on Windows; both sides
now fold line endings first, which also makes the decrypted prompt
byte-identical on every platform. - Two pager tests no longer depend on the machine they run on: one budgeted its
wait in poll counts rather than elapsed time, and two built past instants by
subtracting more than the machine's uptime, which panics on a recently booted
box or a fresh CI runner. /advisornow spawns. Its curated toolset already declaresmemory_search,
memory_getandweb_fetch, and session-level injection appended a second
copy of each; both entries resolved to one client-facing name, so toolset
validation rejected the agent withduplicate client_nameon every attempt.
Injection now skips tools the agent already declares.- Bundled skills cited tool names the model is never shown (
taskis exposed
asspawn_subagent,run_in_backgroundasbackground), sending it after
tools absent from its schema. Names corrected in/best-of-nand
/check-work, with a test tying skill text to the advertised names. - Repaired the nine stale
xai-grok-agenttests: two asserted behavior the
code no longer has (retiredgrok_*toolset presets,web_searchbefore it
became a default-on native provider), three compared prompt budgets against
rawinclude_str!output that a CRLF checkout inflates, two compared paths
with hardcoded forward slashes, and two staged a fake home through$HOME,
whichdirs::home_dirhonours only on Unix. The two home-dependent rules are
now split into injectable helpers covered on every platform, and their
environment-driven integration tests are marked Unix-only. - The CI Rust job now runs the
xai-grok-agentlibrary tests and the bundled
skill checks, which were previously never executed by any workflow.
Changed
generate_mediais self-contained: it resolves a plain model name against
the catalog and places the new top-levelpromptinto whatever text field
the selected cord declares, so{model, kind, prompt}is a complete call.
paramsis now optional and only needed for non-default settings or input
assets, and schema-mismatch errors list the accepted fields instead of
directing the caller back todescribe_media_model. The/imagine,
/imagine-videoandimagineskill instructions no longer mandate the
three-call list → describe → generate sequence.- Updated the pinned
actions/checkoutworkflow dependency tov7.0.1,
including its Git argument escaping and pull-request safety fixes.
Security
- Marked the three synthetic secret-detection fixtures explicitly so both
worktree and full-history Gitleaks scans pass without weakening real-secret
detection.
Documentation
- Recorded the CodeQL static-analysis triage in the security review: current
alert counts, the disposition of each query, and the reachability argument
showing the retained upstream backend client cannot run while
REMOTE_SESSION_REGISTRYisfalse. - Documented the pinned Rust/Node toolchain, the single supported package
manager, the artifacts the project actually produces, the protected assets
and generated files, and the repository-visibility rules inAGENTS.md. - Described the advisor's actual read-only toolset and the
/advisorcontrols
in the subagents guide, and recorded the self-containedgenerate_media
workflow in the Chutes ecosystem and MCP guides. - Listed the browser tool's full action set — what each reading action reports
and how elements are addressed — in the web and browser guide, and documented
CHUTES_EXTRA_CA_BUNDLEalongside the endpoint settings. - Documented both headless streaming formats and what each line carries in the
CLI reference, and noted in the slash-command list that/compactcan now be
stopped while it runs.
Chutes Build 0.4.2
Highlights
- Added
/undoas an alias for/rewindand tightened plan revision approval behavior. - Fixed repeated-tool-call history ordering and notification-hook environment isolation and test races.
- Reviewed Grok Build upstream through
0.2.117, selectively retaining only compatible changes. - Updated vulnerable transitive Rust dependencies and strengthened repository, CI, and security guidance.
- Published the launcher plus six native npm packages for Linux, macOS, and Windows on x64 and arm64.
Install
npm install -g chutes-build@0.4.2
Validated by CI, CodeQL, six-platform packaging, an assembled Linux launcher smoke test, and a live Windows registry install.
See CHANGELOG.md for the complete release notes.
Chutes Build 0.4.1
Highlights
- Hardened endpoint validation, folder-trust enforcement, permission classification, and generated-media persistence.
- Improved session recovery, remote ACP task output, Esc cancellation, fork/rewind safety, and repeated-tool-call protection.
- Refreshed the full documentation set and README presentation; removed the obsolete promotional video.
- Published the launcher plus six native npm packages for Linux, macOS, and Windows on x64 and arm64.
Install
npm install -g chutes-build@0.4.1
Validated by CI, CodeQL, a six-platform packaging preflight, an assembled launcher smoke test, and a live Windows registry install.