The crate binds the claw to its client tools, not tools at large,
so it carries the claw's name: package, lib and dep names, the
mock's binary, and the conformance suite's use paths. Specs and
README follow. The tools/contract directory keeps its name, and
no reference to the old name remains.
The spec's §10 consumer steps land. The rhema binary routes `mcp`
and everything unrecognized (the external subcommand, which is the
road the init file's stubs take: `rhema __server <name> ...`) to
rhema_mcp::cli::run, whose exit code owns the process; outside a
wired shell it exits 4 silently, exactly the spec's contract. The
claw gains its first subcommand the same way (`claw mcp ...`).
The frontends wire: session_agent_config (the TUI's three call
sites) and the headless one-shot merge the wiring's shell_env into
the agent config and the lines into the prompt's mcp section --
always behind the sandbox gate, so a session whose bash runs
elsewhere advertises nothing it cannot run. The registry keys by
profile name: a profile switch rewires, staying put reuses the
bridge and its already-spawned servers. The bridge itself moved to
a dedicated thread with its own runtime in this pass, which is what
makes wire() synchronous -- a dedicated runtime dropped at return
took the accept loop with it the first time, and a blocking CLI read
starving a current-thread runtime taught the same lesson from the
other side.
Muting persists: disabled_mcp_servers lands beside skills_disabled
in the config file, the settings toggle writes both the live set and
the config through save_config, and the running agent rebuilds so
the very next turn sees the change -- the MCP twin of the skill
toggle, with the round-trip test extended to assert the config.
The process-level pin the spec's §9 asked for: a bash child sources
the provisioned init file from BASH_ENV, calls the generated
function, the stub execs the CLI bin (the same dispatch the rhema
binary routes to), and the envelope prints -- plus the unknown-tool
path exiting 2 through clap's own text. provision and wire grow
provision_with_bin/wire_with_bin test seams so the exec chain can
run without building the frontend; the standalone rhema-mcp-cli
bin target is the seam's exec side.
A chat message may carry inline images: the messages route checks the
budget (5 MiB decoded per image, eight a message) and the dispatch
copies the bytes into the attachment store, so the replay streams ids
and media types over SSE, never megabytes. The turn's input carries
the inline image blocks the providers take, base64 verbatim — the
session checkpoint holds what the model saw.
BackendError and WatchShapeError replace the String registry and
watch seams, the tool operations report ToolError, the accessors
drop the get_ prefix, the too-many-arguments allows become
expects, and the llama catalog passes through unchanged.
The claw is the server half of the client tools. The middleware now
knows two bearer classes: the human token answers every /v1 route as
before; the agent token answers only the routes the contract
allowlists, and only with the contract header at the matching version
— consents, sessions, ingest, and the phones answer it 403, so a
model holding the token cannot prompt-inject its way past the scoping
to answer its own secret asks. Boot refuses the configuration where
agent_token is the human token: the scoping is the safety, and one
value playing both roles silently unscopes everything the shell
holds.
Three new routes write the tables the resident already reads: push to
the notification queue, schedule and cancel tasks the resident's tick
fires — the tools get native-shaped writes without the daemon growing
a second brain. A JSON fallback gives the one error shape everywhere,
unknown routes included. The daemon composes the tools' environment
(RHEMA_URL, RHEMA_TOKEN, the tools' bin dir on PATH) and hands it to
the resident's shell through the agent-tools env layer; with no
agent_token it provisions nothing, exactly as before.
The proof is the contract's conformance suite run against this router
over real HTTP — same answers as the mock, checked at test time.
The claw's sessions never end by design — one interactive chat, forge
threads alive as long as their pull requests, coding jobs stashed
across runs — so off-by-default would mean the view is never on where
it matters most. On: chat turns wrap the provider seam with the view
and join zoom to the resolver chain, the mirror living on the handler
so it survives the per-dispatch agent rebuild; forge threads and
coding jobs set the coding agent's transcript field. The config turns
it off with transcript: false.
The stored `colors` key names a palette — rhema (the default,
Jadeite), aquamarine, black-and-white, or dracula — and the
Appearance page of /settings cycles it live, like the theme and
icon toggles beside it. Each palette carries a dark and a light
appearance under the existing `theme` key; dracula's light side is
derived, the official palette ships only dark.
The appearance decision moves off token comparison: Theme now
answers is_dark() from the ground/text luminance, so palettes
beyond the original two get the right per-profile fallback tones.