Release notes land here, newest first. Two things ship on their own cadence, so each release entry says which one it covers.
Platform releases
What changed in the product itself: new surfaces, behavior changes, and anything that alters a documented flow.
Runner releases
What changed in the self-hosted runner: installer, containment, adapters, and the commands you run day to day.
The platform updates itself, so there is nothing to do on your side. Upgrading a runner means re-running its installer, which keeps your pairing and rolls back by itself if a release cannot stay up. See upgrades and uninstall.
Platform and runner entries interleave in one list, newest first, and each entry says which of the two it covers.
2026-09-21 · Platform: knowledge search knows which project it is in
An agent searching what your workspace knows now starts with the project it is working in, and anything it brings back from somewhere else says where it came from.
A search covers the project the agent is working in. The huddle’s project, the task’s project, or the project a conversation with Eva is about. Until now every search read the whole workspace, so a question about one product could be answered from another one with nothing in the answer to say so. Asking the same question in a huddle about a single product and in a huddle about the company used to give the same answer; now it gives the right one for each. See how far a search reaches.
An agent can still look wider, and it has to mean it. It can search projects you name, or every project in the workspace when the question is genuinely about more than one product. In a huddle it judges that from the huddle’s title and objective, which is one more reason to write both properly. See start a huddle.
A passage from another project is labelled with that project’s name. Passages from the project you are in stay unlabelled, so the ones that came from elsewhere stand out, and agents are told to attribute them to the project they name. Inside a coding run the label carries the project’s identifier instead, because a run holds no list of your projects. See knowledge in runs.
A search with no project to narrow to says so. A conversation with Eva that belongs to no project searches everything, and the result says that is what happened rather than leaving it to be assumed.
Agents in a huddle can look up your projects. So an agent asked about another product can find it by name instead of guessing at it.
Marketing recall follows the same rule. A draft still receives its project’s active learnings and every tenant-wide one. What changed is the asking: an agent searching for a learning searches this project, and reaches another project’s learnings only when it is asked to. See learnings.
Coding runs get this through the runner, so a self-hosted machine needs the runner release that ships beside this change. Until it is upgraded, searches from that machine keep covering the whole workspace with nothing labelled. See upgrades and uninstall.
A search from a coding run now covers the project the run belongs to, and says when a passage came from somewhere else.
A run searches its own project. What the run’s task belongs to, rather than everything your workspace knows. A run that needs more can search projects by name, or all of them, when the work genuinely spans products.
A passage from another project is labelled. The label carries the project’s identifier, because a run holds no list of your projects. Passages from the run’s own project stay unlabelled.
Upgrade before your next run. This release and the platform change beside it share one contract. A runner left on an older version will report that its search was rejected rather than quietly searching everything, so nothing goes unnoticed, but that machine cannot search your knowledge until it is upgraded.
Upgrade by re-running the installer on that machine:
The sign-in a runner does for itself can now be used for managed runs, if you choose to send it, and runs on CommandChain’s servers use current coding agents again.
The runner’s own sign-in can be pushed for managed runs. Signing a runner in with commandchain-runner signin and then turning on managed runs used to report that no credential was found, because a push only ever read your personal login. Ask for that sign-in by name and it goes up: commandchain-runner creds push --agent claude-code --from-runner-signin, or the same row on the runner screen. See managed runner credentials.
Nothing is sent unless you ask for it, and four pages now say so. A runner’s sign-in stays on the machine it was made on. A bare creds push still reads only your personal login, and the runner sign-in goes up only when you name it and give the same acknowledgment every upload takes. See sign-in only or full setup.
Runs on CommandChain’s servers use current coding agents. The managed servers had been reusing a months-old build of Claude Code because the step that installs it never changed. Both coding agents are now pinned to a stated version, each server records what it carries, and a build that does not match what it claims is rejected instead of rolling out.
A chat agent keeps the tools it is supposed to keep. The list of what a chat agent may not reach named three tools the coding agent no longer has and missed two it does, so two built-ins stayed reachable that the rule says should not be. The list is now measured against the coding agent that actually ships.
A healthy run stops reporting a dropped connection. Every attempt logged a dropped connection and a dial error twice before settling, which read like a fault and was not one.
Upgrade by re-running the installer on that machine:
Agents on a runner you host yourself have their tools back, runs on CommandChain’s servers work again, and a program the sandbox stops now says so on the task.
An agent on a self-hosted runner can use its tools again. Every agent on a runner you host yourself was starting with nothing it could call. A task without a repository behind it had no way to hand its work back, so it ended with a written answer instead of a deliverable. Tools are there from the first turn again, and a task with no repository hands back real work through them.
A task that needs code asks for a repository instead of guessing. When the work plainly needs a codebase and none is attached, the agent asks for one: the task waits with the repository picker on it, and no throwaway code is written in the meantime. See connect repositories.
Runs on CommandChain’s servers work again. This was checked by running a whole task end to end on those servers, on the same setup a run of yours gets, rather than taken on trust from the fix. The 0.9.2 note announced this before it was true; this is the release it became true in.
A program the sandbox stops now says so on the task. Some programs read their own details the moment they start, which the sandbox does not allow, and one that treats the refusal as fatal used to stop with nothing to show for it. The task now says in plain words what happened and what to do about it. See runner troubleshooting.
Upgrade by re-running the installer on that machine:
A coding agent that cannot start now says what stopped it, and the sandbox on Linux lets an agent list the names of what is on the machine it runs on.
Agents on a self-hosted runner and runs on CommandChain’s servers are still affected. An earlier version of this note said this release fixed both of those. It did not. A check against the running system afterwards found both problems still there on this exact release: an agent on your own machine still came up with nothing it could call, and a run on the managed servers still stopped before the coding agent was reached. Both are fixed in 0.9.3 above, which is the version to upgrade to.
A coding agent that cannot start says what happened. A failed start used to be reported as a missing program, which sent people hunting for an install that was already there. The message now carries what the agent itself reported.
On Linux, the sandbox now lets an agent list the names of the folders and files on the machine it runs on. It still cannot open, run or change anything outside the task it was given. See the runner security model.
Upgrade by re-running the installer on that machine:
The languages a project needs are already installed on CommandChain’s servers, and a task that stopped for something missing starts again on its own.
Runs on CommandChain’s servers are still affected by a startup problem. A run on the managed servers stops before the coding agent is reached, and reports it as a missing program. An earlier version of this note said this release fixed that. It did not. A later check found the same failure still there, and it stayed there through 0.9.2. It is fixed in 0.9.3.
The managed servers come with the languages projects need. Node.js, Python, Go, Rust and Java are installed and pinned there, along with the package managers those languages use, so managed work is no longer turned away for a language it could not find. See execution backends.
A task waiting on a sign-in or a missing language starts by itself. As soon as a runner reports that it has been signed in, or that the language is now installed, every task parked on it is released. Nobody has to reopen anything.
A missing language raises a task for whoever can install it. One task per language, sent to the person best placed to act on it, carrying the install commands for macOS, Debian or Ubuntu, and Fedora or RHEL. Install it, then open the runner with commandchain-runner and press r to check again: the runner reports the language, the waiting tasks start, and the install task completes itself. See answer a setup task.
The runner keeps everything it stores in one folder. The pairing credential, the workspaces, its own coding-agent sign-ins and its lock files now all live under the same directory, and COMMANDCHAIN_RUNNER_STATE_DIR moves all of them together. It used to move the sign-ins alone. See runner environment variables.
Upgrade by re-running the installer on that machine:
A self-hosted runner now holds its own sign-in for each coding CLI, and the runner screen is the place you set one up.
A self-hosted runner keeps its own sign-in and never uploads it. The runner signs in to Claude Code, Codex or Gemini on its own machine, in its own store, and renews that sign-in by itself before it expires. Nothing is sent to CommandChain, and your personal sign-in on that machine is left alone. If you would rather a run used your real CLI setup, hooks, plugins and all, there is a per-machine setting for that, and turning it on shows you exactly what it exposes first.
The runner screen guides you through setup, one key at a time. Running commandchain-runner with nothing after it opens the screen: it checks the machine can contain an agent, helps you install a coding CLI, pairs the runner, signs it in, and says when it is ready. Signing in, signing out, uploading a login for managed runs and re-checking installed languages are all rows on its menu. The signin, signout and creds status commands still work for anyone who prefers them.
A second commandchain-runner attaches to the one already running. Opening the runner on a machine where the service is up now shows you that runner instead of starting a competing one.
Managed runs are unchanged. A run on CommandChain’s managed servers still uses the workspace’s own AI account, released to one attempt at a time.
Upgrade by re-running the installer on that machine:
A Claude Code sign-in problem now reads as one, instead of looking like a run that finished.
A failed Claude Code sign-in is reported with its own message. Current Claude Code reports some account and API failures as a finished result marked as an error. The runner now treats that mark as a failure, and it shows the message Claude Code gave rather than a bare status, so the run and the runner screen say what went wrong.
Upgrade by re-running the installer on that machine:
Gemini CLI runs that sign in with a Google account no longer stop partway through.
Gemini CLI uses the sign-in CommandChain gives it, and leaves renewing it to CommandChain. A run now hands Gemini CLI only a current access token. Before this, Gemini CLI tried to renew the sign-in by itself shortly before it expired, with nothing on the runner to renew it with, and a long run could stop on an authentication error.
Upgrade by re-running the installer on that machine:
Codex works in huddles and on managed runners, and the runner screen keeps the errors it sees so you can read them.
Codex signs in reliably in huddles. A huddle turn on Codex now uses the sign-in CommandChain renews for it, so a Codex account no longer fails a huddle once its first sign-in has aged.
Managed runners can run Codex. The managed runner image now carries the Codex CLI beside Claude Code, so a workspace whose AI account for managed runs is a Codex one has somewhere to run.
The runner screen keeps errors for you to review. When a coding agent reports an error, the runner screen says how many there are. Press e to read them, the arrow keys to scroll, and enter to dismiss the one you have read. Anything that looks like a secret is removed from the text first.
A run that waits for an approval holds for ten minutes, then parks. A run no longer sits on the runner indefinitely waiting for someone to approve it. After ten minutes it parks and frees the runner, and approving it afterwards picks the work up again.
Upgrade by re-running the installer on that machine:
Work bound to a repository is now checked on the way through, and one verification is the only thing that merges it.
A task is done when its branch has merged, not when its run was accepted. An accepted run leaves the task in progress with the merge still ahead of it, and work waiting on that task stays blocked until the branch has actually landed. Nothing reads as finished on a branch that never reached your default branch. See task states.
A huddle that touches a repository now gets a final check of its own. It appears in the task list with the others but belongs to no branch: it waits until every task in the huddle that touches the repository has merged into the working copy, then runs against that collected work and checks what the huddle set out to do rather than what any one task did. It cannot be started by hand, and accepting it is what opens the pull request. See ship code from a huddle.
The pull request carries one check per acceptance criterion. When it opens, CommandChain commits a workflow file to the working branch and GitHub runs it, with one check for every acceptance criterion and one for every negative case across all the tasks on the branch, each named after the criterion it proves. The commands are the ones you approved at draft review, and nothing an agent wrote during the run reaches that file.
One ship verification merges the branch, and a person gives its verdict. It is created once the checks and the review have both finished, filled in from what actually happened on the branch, and assigned to the delivery owner: whoever started the huddle, else whoever created the task, else the project owner. A Pass merges the working copy into the branch it was cut from and moves every task on it to done. There is no other control anywhere in the product that merges a delivery branch. See score a verification task.
An agent that cannot go on now asks you, instead of stalling. An assist is for a blocker only a person can clear, and a setup task is for a value or a decision an agent needs. Both push the work first and park the run, so answering resumes it from where it stopped, and an answer that looks like a secret is stored as a secret rather than as text on the task. A run that stopped at a limit with work worth keeping arrives the same way, as a decision offering its best branch, more budget, or cancellation. See answer an assist task and answer a setup task.
Merged work keeps being checked after it lands. A merge registers the command behind each acceptance criterion as a standing check, and every one of them runs again each night against a fresh copy of the branch the work landed on. A failure raises one fix task, notes the repeat on it the next night, and escalates to the regression owner on the third. See keep merged work checked nightly and regression scenarios.
Merging is a graduated permission of its own.code.merge ships at approve-each, and it is proposed for promotion only after ten deliveries in the last thirty days whose ship verification passed with a full score, no override, and no earlier request for changes. One attributable nightly failure takes it back down. See autonomy action classes.
A run shows what it checked rather than what it claimed. The run page carries the repository gates, the command paired with each acceptance criterion, the evidence behind each one, the mutation floor, what the reviewer reported and which model reported it, the red team, and which of the four endings the run reached. See reading a run.
A run now proves itself on the way through: your repository’s own checks run before any review, the review has to show its working, an attack tries to break what survived, and the tests that attack leaves behind are kept.
Your repository’s own checks now run before any review, and a red one stops the run. Once per attempt, after the agent has committed and before the review reads it, the platform runs the setup your repository needs, its own test, lint and build commands, and the command paired with each acceptance criterion, then three checks on the work itself: that every criterion has pasted output behind it, that the change touched a test file at all, and that nothing hollow passed, meaning a test command that ran zero tests while reporting success, or a gate the change edited with no negative case to prove it still rejects bad input. No model takes part, and the reviewer is shown the results and cannot change them. A run cannot be accepted while any row is red, whatever the review scored. See the checks and why a red check stops a run.
Those commands run inside the same containment as the agent. When a task names a toolchain, the prepare commands that install its dependencies run in the working tree the agent will use, inside the same sandbox, with the same run environment. The runner’s own credential, its git token and any coding agent key stay outside it. Every command takes its time limit from what is left of the run’s clock: one that does not finish is stopped and recorded as timed out, as is one the clock ran out on before it could start, so nothing is left running after the run has moved on. A prepare command that fails ends the run as inconclusive with the reason toolchain_unavailable, which is a statement about the environment rather than a verdict on the work. See workspaces and git.
The review works in a throwaway copy and cannot commit on the task branch. The runner adds a second working tree of the same commit beside the first, points the review at it, and deletes it when the review ends, so nothing a reviewer writes can reach your branch, and the reviewer holds no credential that could push. The runner records where the branch pointed before the review and reads it again afterwards: a branch that moved is put back, the attempt carries a branch_tampered result you can see on the run, and an iteration whose branch moved cannot finish as passed. The branch is pushed before the run is finalized, so the commit reported on the run is the commit that was reviewed, and the commit a later merge is pinned to. See the review works in a throwaway copy.
Which model and which coding agent reviewed is recorded on the run. The review does not run on the model that wrote the code: with every check green it runs on the stronger of the two models your agent is configured with, and with a check red it runs on the implementation model and is advisory, telling the next attempt what to fix without being able to finish the run. A review can be pointed at a different coding agent, which defaults to the one doing the work. A review model the reviewing agent’s own family does not accept is refused before the review starts, with no credential released to it, rather than failing partway through. Whichever model graded the work is written on the review itself. See which model reviews.
A review has to show its evidence. Every acceptance criterion comes back met, unverified or missing, and unverified scores zero exactly as missing does, so a plausible implementation with nothing pasted to show it working does not pass. The platform counts the commands a review actually ran: a review that filed a full report having run none is thrown away and retried, up to three attempts in all, and a run where none of them ran a command ends inconclusive. A review that disagrees with the run’s own checks about the same command also ends the run inconclusive rather than passing or failing it, because the check is then the unreliable part and the repair belongs there. See what the reviewer reports.
Every run bound to a repository carries a verification profile. Lite, Standard or Full, chosen from the task’s own spec when the task is merged: Lite when every changed file is documentation, Full for anything sensitive such as a migration, a workflow file, or code named for authentication or payment, and Standard for everything else. Each profile carries more proof than the one below it. You can raise a profile until the first run starts and never lower one, and your plan sets the highest profile a managed run may use, so a task above that ceiling is blocked before it spends anything rather than quietly running cheaper. See verification profiles and what your plan caps.
The mutation floor runs last, and a language it cannot cover says so. Once the other checks are green, the platform changes one small thing at a time in each file the task changed, a comparison, an argument, the body of a function, and runs the tests again: a suite that still passes was not checking that behaviour. It runs on the changed files only, and on the Full profile only. A repository in a language with no mutation tool records the row as skipped with that reason, as does one that has not yet committed a mutation configuration with a score threshold, and skipped is not a pass: it means nobody checked. See the mutation floor.
A red team runs after a review that would otherwise finish the work. A separate agent gets the same model as the reviewer and its own copy of the code, with one objective, which is to make the implementation fail against the spec it was given. It writes small tests under tests/redteam/ in your repository’s own test framework and runs them. A serious finding sends the work back for another round instead of finishing it, with the failing test and its output attached, and the report it wrote is kept beside the check logs. See reading a run.
The probes that passed are committed to your branch. They arrive as one commit named test(redteam): probes for <task key>, made by the platform rather than by the agent. Only test files under tests/redteam/ that also match your repository’s own test patterns are taken, and a probe never overwrites a file you already have. An attack that failed to break the code today keeps running against it tomorrow. See the attack is kept.
A run on the Lite profile skips the red team, which is one reason the verification profile is shown on the run.
A capped run no longer reports itself as passed. A run that ran out of time, iterations or money after once scoring well used to finish as though the review had accepted it, and the task moved on as done. It now ends as partial: the best score it reached and the commit that earned it are recorded, the branch is pushed, and the decision goes to the delivery owner as a task offering three choices, which are to accept the branch as it stands, extend the budget and carry on from the pushed branch, or cancel. See budgets.
Repository-bound runs now need runner 0.8.0 or later. A runner below that version is no longer given work that is bound to a repository, because an older binary finishes such a run having run none of these checks, attacked nothing, and reported a capped run as passed. Runs that touch no repository are unaffected. Re-run the installer on the machine and it picks that work up again.
Upgrade by re-running the installer on that machine:
A runner now says what version it is and which languages it can run, and the platform stops handing a machine work it cannot do.
A runner reports its version, and a run that checks out one of your repositories needs 0.6.0 or later. Every runner sends its version when it pairs and on every heartbeat, so the platform knows what each machine is running rather than assuming. A run that needs a repository is only handed to a runner at 0.6.0 or above. An older runner is not cut off: it keeps claiming everything else, and it finishes the repository work it already holds. A repository run simply waits until a machine that meets the floor is available, so upgrade that machine and the work starts flowing again. See upgrades and uninstall.
A runner reports which languages it can run. When it starts, a runner looks along its PATH for Node, Python, Go, Rust and Java and tells the platform which of them it found. A task whose language no runner on your workspace can run now waits with a reason instead of starting a run that fails its own verify command minutes later. A toolchain installed on a machine that is already running is picked up when that runner restarts. Managed runners run Node.
Upgrade by re-running the installer on that machine:
Three fixes to the text a stranded operator reads, all found reviewing 0.5.0.
The recovery command a stopped runner prints now works in the state that runner leaves behind. A runner that stops because its credential was refused exits, and on Linux the service manager parks the unit after a few restarts. A plain systemctl --user restart in that state answers “Start request repeated too quickly” and does nothing, which is exactly what both messages told you to run. The runner’s own log line and the pairing-failure hint now lead with systemctl --user reset-failed, which is a silent no-op on a healthy unit. See troubleshooting.
Pairing a machine again keeps the name it already had.--display-name is set at install time, so pairing again by hand fell back to <user>@<hostname>: a runner installed as maya-macbook came back as something nobody chose, and you had to work out which row in the fleet was which. connect now resolves the name as the flag you passed, else the name this machine already carries for that instance, else the host default. Renaming on purpose still works. See pairing.
install.sh --status names the log file before the service journal. The journal holds the unit’s start and stop records and nothing the runner itself printed, so it answered a different question than the one being asked. It is still listed, second, for the question it does answer: whether the unit is restarting in a loop.
Upgrade by re-running the installer on that machine:
The runner opens on a menu, and a runner nobody can authenticate fails where you can see it.
Running commandchain-runner with no arguments now pairs and runs.connect is the default command. It used to print help, which taught people to reach for --pair-only: that is the installer’s verb, it exits by design, and it leaves the browser waiting for a runner that has already gone.
The status screen has a menu. Install agents, push a login, re-detect and quit are rows down the left, moved with the arrow keys, each showing the hotkey that still works. A row you cannot use right now stays visible and says why, instead of disappearing. Piped, under a service manager, in CI, or with --plain, the output is the same structured JSON as before. See the runner CLI.
A runner whose credential this workspace no longer recognises stops instead of retrying forever. It used to beat every two seconds for as long as the machine was up, while the service manager reported the unit healthy and the fleet page showed the runner offline. Every one of those beats was answered with the sentence that would have fixed it, and nobody ever saw it. After five unbroken minutes of rejection the runner now gives up, records the rejection so a restart cannot walk back into the loop, and lets the unit land in a failed state a person can find. Pair the machine again to recover. See troubleshooting.
Errors in runner.log carry their message and stack again. The log scrubber rebuilt every object it wrote, and an error’s message and stack do not survive being rebuilt that way, so every error the runner had ever logged came out as its leftovers. That is why the message above was invisible.
On the managed pool, your coding agent runs as its own user. It previously shared the runner’s identity, which put the runner’s own secrets within reach of an agent that has a shell. The agent now runs under a separate account declared inside the image, is handed its workspace by group rather than by ownership, and the runner refuses to start at all if it cannot honour that. Self-hosted runners were never exposed: their containment boundary already denied it. See security.
A repository checkout no longer records your access token. The token was embedded in the clone URL, which git writes verbatim into .git/config inside the workspace the agent can read. It now reaches git without appearing in a URL, on a command line, or in any file, and every checkout is checked afterwards. See workspaces and git.
Run callbacks verify with the pairing credential the installer already wrote, so a runner installed with the one-liner has nothing to configure, and the process no longer holds a key that would be useful for anything beyond its own attempts.
Upgrade by re-running the installer on that machine:
Your tool servers and a real browser reach coding runs, and two loops that could not stop now stop.
The MCP servers your workspace registered reach coding runs. Every Active tenant-scoped server, plus the position-scoped servers for the role the assigned agent holds, is attached when the run is dispatched. The runner enforces each server’s tool allowlist itself rather than trusting the agent to respect it, and a server’s credential is released to one attempt at a time. Chat and huddle turns deliberately get none of this. See MCP servers in runs.
Disconnecting an integration no longer fails the whole run. A server whose connection is disconnected is skipped, named in the run log, and the run continues with its siblings. A server whose stored credential has vanished still stops the run loudly: disconnecting an integration is a routine thing for a user to do, deleting a secret out from under a live registration is not.
A coding agent can open a real browser to check its work. One headless Chromium per attempt, torn down when the attempt ends: navigate, read the page as text, click, type, wait for an element, and attach screenshots to the run. file:// URLs are refused at two layers. A runner with no Chromium reports the browser as unavailable, in doctor and to the platform, rather than failing the runs that ask for it. See browser in runs.
A coding run can ask you for a credential it turns out to need. Instead of failing on a missing key, the run raises a setup task against the work it is doing, with a form for the value. What you type goes straight into the project environment’s write-only storage. A run can only ever raise this against its own task. See environment variables and secrets.
A cancelled run actually stops now. The runner had no case for the stop signal the platform sends, so the message arrived, matched nothing, and was discarded. A run past its wall clock, or one an admin force-cancelled, kept executing and kept spending until it finished on its own, and you watched a cancelled run go on costing money. Work the agent had already committed is still pushed.
A runner the platform has forgotten stops beating. A heartbeat answered “no such runner” or “deregistered” was retried forever, which held a pool slot open and produced tens of thousands of doomed requests a day with nothing in the design that could ever stop it. Both answers are now terminal: the runner logs which runner id was refused and exits. Network errors, timeouts and server errors are still retried, because those describe the path to the platform rather than its verdict.
Upgrade by re-running the installer on that machine:
Meetings are called huddles now, and this release is the runner half of that rename.
Upgrade every self-hosted runner. This release changes the names the runner and the platform use to talk to each other, and both sides changed at once. A runner older than 0.3.0 cannot execute huddle chat runs against the current platform: it will pair and claim work as before, but a chat run started from a huddle fails until that machine is upgraded. Task runs are unaffected. See upgrades and uninstall.
The huddle tools your coding agent sees kept their names. Agents reach these tools as mcp__cc__*, and that prefix is unchanged, so an agent allowlist written against it keeps working. What changed is the server behind it, now announced as commandchain-huddle-tools.
A chat run’s working directory moved from meeting-chat/ to huddle-chat/. A chat session that was mid-run when you upgraded starts fresh in the new directory rather than resuming in the old one. Finished work is unaffected. See workspaces and git.
Upgrade by re-running the installer on that machine:
A task runs before you have connected any repository.
A task whose project has no repository attached no longer fails. Coding agents will not start without a git checkout to work in, so a task with nothing to check out stopped before the agent ran and reported only a generic runner error. The runner now gives that task a scratch working directory of its own, removed when the run ends. The first task in a new project was the likeliest to hit this. See workspaces and git.
Upgrade by re-running the installer on that machine:
Pairing is something you watch now, not something you grep.
connect draws a status screen when it has an interactive terminal: the pairing code spaced out to be typed, its approval URL, which coding agents are installed, and a live activity pane. Piped, under a service manager, in CI, or with --plain (or COMMANDCHAIN_RUNNER_PLAIN=1), the output stays the structured JSON logs earlier releases wrote, unchanged for anything that greps them.
agents lists and installs coding agents.agents list shows which supported agents this machine has; agents install fetches the missing ones using the vendors’ own installers, and asks first unless you pass --yes.
--tui became --dashboard. The opt-in observation dashboard now replaces the status screen rather than fighting it for the terminal. q on the status screen stops the runner you started there; q on the dashboard closes the view and leaves the runner running.
Upgrade by re-running the installer on that machine:
You no longer have to tell the installer where CommandChain is.
The installer pairs with the hosted CommandChain by default.--server became optional, so the one-line install is now just curl -fsSL <installer> | sh. Pass --server only if you run CommandChain yourself, or point a machine at a local core. COMMANDCHAIN_URL still overrides the default, and an explicit flag still beats both.
The same default reaches the commands you run by hand.connect, logout, and creds --url all resolve to the hosted API when nothing else names one. connect with no URL previously meant a core on your own machine, so a local core now has to be named.
Pairing opens the right page. The approval URL the runner opens in your browser pointed at the API address rather than the app, which served no page. It now resolves to the app for every deployment shape.
Upgrade by re-running the installer on that machine:
Self-hosted runners stay online across socket drops, and survive you logging out.
Lingering is enabled on Linux. A user service is torn down when your last session ends, so a runner installed over SSH used to stop the moment the shell closed and then read as offline. The installer now enables lingering for your own user, needs no privilege to do it, and reports the result in its final message.
A safety-net heartbeat while the socket is up. A runner holding a live control-plane socket now keeps reporting in on a slower cadence rather than stopping entirely, so a socket that closes without warning can no longer leave the runner looking offline across the gap.
A wrong-family model fails loudly instead of being swapped. Asking a coding agent for a model from another provider’s family now stops before the tool is launched and says so, rather than quietly running something else. Every result also reports which model actually ran.
Adapters are re-advertised on every heartbeat, so what a runner can execute cannot go stale between restarts.
Upgrade by re-running the installer on that machine:
A containment fix. Upgrade from 0.1.0, which is withdrawn.
The runner grants its own binary, not the directory holding it. A compiled runner used to grant contained agents read and execute on the whole directory its binary lived in. With the binary in ~/.local/bin or directly in your home directory, that pulled neighbouring paths such as ~/.ssh inside the sandbox. The runner’s own re-exec target is now granted as a single file. Verified on real Apple Silicon and Linux hardware: a secret sitting beside the binary is unreadable from inside the boundary, and doctor passes with the binary placed directly in your home directory.
macOS installs refuse cleanly when there is no graphical login session, before writing anything, rather than installing a service that cannot be supervised. See install a runner.
macOS release binaries are signed, and were executed on real Apple Silicon both natively and under Rosetta.
Verify any download against the release’s SHA256SUMS. The installer does this for you before it runs anything.