v0.2 and v0.2.1: the crew moved into the browser, and a free model landed six tasks in a row
v0.2 put the whole workbench in the browser and on the phone: 12 epics, every demo clear on its first verdict. v0.2.1 then ran a free model in every crew role on real tasks. It landed its work with no model-caused rescue. What failed was our ability to prove it.
This post covers two releases. v0.2.0 took 84 hours from the v0.1.5 tag to its own. It moved the workbench into the browser and onto the phone, and all twelve of its epic demos were clear on their first verdict. v0.2.1 followed 28 hours later. Most of it was a debt sweep, but it also held the experiment we were most curious about: a free model, run through OpenCode, did real crew work. It wrote code as an Implementer, reviewed as a Reviewer and checked an epic as QA. Six tasks in a row went from claim to landing with no rescue for a mistake of its own. The trouble came on our side: our records could not prove what it had done.
The crew was the one from the last three releases: a Coordinator on claude-opus-5-5, Implementers and Reviewers on gpt-6.1-sol through Codex, and QA on gpt-6-astra, which also drives a real browser when a brief needs one. In v0.2.1 a few seats went to deepseek-v4.1-flash through OpenCode.
What we set out to build
v0.2, the web workbench. Until now the human followed the crew from a Neovim workbench. v0.2 adds a browser client of the same hub, on the desktop and on the phone:
- The web edge.
cland webprints a one-time link and signs the browser in with a cookie that survives hub restarts. The browser never holds the hub’s secret. - One snapshot, then numbered deltas. A browser connects with one snapshot, about 0.6 MB on a copy of our live tracker with 1,050 items. The prototype needed 1.15 MB from eleven reads. After a dropped connection it resumes exactly the deltas it missed.
- Fields computed in the hub. Roll-ups, card facts, unread counts and read marks are computed once in the hub, so a topic read in Neovim also reads as read in every browser.
- An approvals relay. Codex and OpenCode command approvals are answered from the browser or from Neovim’s inbox. The first answer from any client wins, and nothing answers on a timer.
- Items, topics, the inbox, sessions, artifacts and accounts, all with Neovim’s keys. Keys match by physical position, so a Russian keyboard layout works too.
- The phone. A bottom bar, the inbox as home, and asks opening as a sheet. Nothing answers on a swipe, and with no connection nothing gets queued.
- What the browser cannot do. It cannot release, push, publish or stop the hub. Those stay in the terminal.
Midway, the maintainer raised a P1: the Neovim workbench took minutes to start, and one failed start reached 8.4 GB. The cause was a quadratic read loop, which re-copied its buffer on every chunk, plus startup replies that had grown to 76.5 MB, 72 MB of it suite history inside one status reply. They are now 439 KB in all. On the maintainer’s Mac with the live tracker the workbench starts in under three seconds. A test now fails if startup goes over its budget on a 1,000-item tracker.
v0.2.1, the debt sweep. It had eight epics: dependency advisories, merge queue safety, honest periodic tests, duration budgets, test hygiene, small hub fixes, Mermaid diagrams in the browser, and the epic this post is mostly about, OpenCode as a working harness for every role. The maintainer had called that one “the main killer feature”. v0.2.1 is also our public launch: an install script that uses a prebuilt web bundle, a Homebrew tap, and the docs on cland.app checked against what ships.
The numbers
- tasks landed: v0.2.0 in 84 h, v0.2.1 in 28 h
- 166 + 89
- v0.1.4: 315 in 91 h
- epics, each closed on an independent QA verdict
- 12 + 8
- v0.1.4: 14
- hub restarts in v0.2.0 with a gap over 60 s
- 0
- v0.1.4: 5
- merge-queue batch runs green; the other three failed on a real test
- 206 of 209
- none failed on infrastructure
- of droplets: 681 and 393 leases
- $27.71 + $13.25
- v0.1.4: $59.99
- tests in the v0.2.0 release run, 223 of them in a real headless browser
- 4,088
- v0.1.5: 3,319
The first-review rate fell for the third release in a row, from 71% to 61% to 47%. Review in v0.2.0 bounced mostly on failing or slow test runs and duration gates. Next came stale state, races and lifecycle bugs, then gaps in test coverage. In v0.2.1, part of the drop is the OpenCode experiment. More on that below.
The 16 questions that reached a human were not the same 16 each time. In v0.2.0 the stand-in, a session that answers on the maintainer’s behalf at night, took 11 of them. The median wait was 2 minutes, but one overnight question waited almost 12 hours. In v0.2.1 the maintainer was back and answered 14 of 16. Below the human, leads answered 137 agent questions in v0.2.0 and 72 in v0.2.1, and passed only 3 of them up.
The wait for tests, five releases
The merge queue and test tiers from v0.1.4 kept paying off. In v0.2.0 a task waited about a minute and a half for every hundred minutes its tests ran. The queue batched all 166 landings, and only one batch run in 141 went red. v0.2.1 ticked up to 4.8%, still well under any earlier release.
Moving the crew into a browser
v0.2 ran two lanes in parallel, the hub and the web. Every epic ran in stages, and each stage closed on a Linux run, a macOS run and a QA check. There were 31 stages, and QA recorded 43 verdicts. Two were not clear: once on stale README wording, once on a load race in a browser test. All twelve epic demos were clear the first time, each on its own short-lived droplet of 1 to 16 minutes, 42 cents in all. The phone epic’s four stages closed within five hours, each about half an hour after its last landing.
The suite gained a Web phase that runs pages in a real headless Chrome: 44 files and 223 tests, 490 seconds in the release run. QA also tested in the maintainer’s own browser through computer use, in a separate profile. That came with rules. On the first day an Implementer launched Chrome in a sealed test environment, and macOS put a “Keychain Not Found” dialog with a “Reset To Defaults” button on the maintainer’s desktop. Nobody pressed it. Now the browser QA session uses a dedicated profile, never presses Reset or touches system settings, and reports any dialog it cannot cancel. Other crew sessions do not drive the human’s browser or desktop at all.
The web client is 113 files and about 7,000 lines of React and TypeScript, with no UI library. The whole release came to 463 commits.
What cost time
One file, 123 of 166 landings. Every task that added a test also edited one shared document describing the tests, 2,929 lines long. Parallel lanes kept colliding there. Each collision meant merging dev into the branch, a fresh review of the change and a fresh verify. One phone task was clear at 17:25 and landed at 18:38. v0.2.1 split the document into one file per test file.
A night without a Coordinator. On the first night of the build Claude Code updated itself and restarted the Coordinator’s harness. The hub read that as a death and took the role away. The crew kept working its claimed tasks, but finished work piled up with nobody to merge it, and the hub’s heartbeat had no Coordinator to wake. By the retrospective’s count this happened twice that night, for about 5 h 20 min and then 2 h 26 min. The role now survives a restart of the harness.
An hour stuck on rm. On 23 October the Coordinator sat on a permission prompt in eight spells, about 62 minutes in all. The cause: a delete command whose path is computed needs approval, and nobody was there to give it. A hook now refuses such commands outright instead of stalling, and cland installs it for every project.
Briefs written too early. QA briefs written ahead of a stage guessed test counts and selectors before the code existed. One stage took two hours to clear, partly on corrections to its brief. cland qa lint now checks names and counts against the build.
Midnight. At 00:00 UTC on release day a test’s duration allowance expired, and every shard plan failed. The Coordinator renewed 25 allowances by hand. They now warn 48 hours ahead.
One thing went quiet: the hub. In v0.1.4 it restarted 30 times, five gaps ran over a minute, and one of them left the Coordinator deaf for almost three hours. In v0.2.0 there were 19 starts, all reached serving, and the longest gap was 47 seconds.
v0.2.1: a free model takes the job
cland has supported OpenCode as a third harness for a while, but no crew role had done real work on it. The question for v0.2.1 was simple: can a cheap model hold a seat on a real crew? The maintainer picked deepseek-v4.1-flash on its free tier, and later its paid plan. Reviews of its code stayed on Codex at first.
As an Implementer it took six real XS and S tasks from our backlog in a row: test fixes, a tracker command, routing in the hub, a flaky test on macOS. Each went from claim to ready in 34 to 101 minutes, and all six landed. The Coordinator never had to step in for a mistake of the model’s own. The stepping in it did was for gaps in our briefs and one gap in our adapter. Later, an M task touching the hub’s storage and all three harness adapters took 37 minutes to ready. One XS task on the paid plan used 5.6 million tokens, 97% of them cached re-reads, and cost 5 cents.
As a Reviewer it did a full source review in 5 minutes 49 seconds for 5 cents. As QA it checked an epic’s Definition of done in 11 minutes for 8 cents, and the hub closed the epic on its verdict.
It was not better at code. Tasks written through OpenCode cleared their first review 4 times out of 12, against 38 of 77 for Codex in the same window. It needed more rounds, and it fixed what the reviewers found. What surprised the Coordinator was something else: “its process discipline more than its code.”
- It found our bug. The first OpenCode Implementer noticed that its shell carried no cland identity, so
cland verifyran as “human”, and its run collided with another session’s. It reported this as a bug, with file and line references. We fixed it the same day. - It stopped at a refusal. Another one tried to cancel a duplicate run, and the hub refused: only the human may cancel any run. It stopped there and looked for no way round.
- It asked instead of guessing. A third saw that its brief told it to run a load test on the Mac, while our rules forbid local load runs without a granted window. It asked, offering three options. Then it ran the 22-second window it was given exactly as granted, and mentioned, unprompted, that another session had run a test at the same time.
Meanwhile Codex had a bad day. Five Codex turns failed with “Selected model is at capacity”, and each of those sessions sat idle until the Coordinator sent it a message. No OpenCode session stalled that way.
What failed was the proof
One acceptance criterion said that each run’s token use and cost must show in cland’s usage view. QA checked it and failed it, twice. The runs had happened, but the usage lived only in the hub’s memory, and every hub restart erased it. So the evidence for the first eight runs was gone. We made usage persist on the session row and ran the qualification again on fresh tasks. This time an OpenCode Implementer, an OpenCode Reviewer and an OpenCode QA session went through the whole loop, and every number survived.
“The model was fine,” the Coordinator said. “What failed was our ability to prove it was.”
In the whole v0.2.1 window OpenCode sessions landed 12 of 89 tasks. They used 0.23 billion tokens with a recorded cost of $1.05. Codex used 2.2 billion on subscriptions, and its usage records carry no cost.
Also in v0.2.1
- The hub ate its own coverage maps. On 24 October the hub died three times in five minutes. Test selection by coverage parsed all 170 coverage maps at once, about 2 GB of JSON against a 4 GB heap. Now it parses them lazily, newest first.
- The merge queue covers what it lands. Batches that touch the web client now run the browser tests too, and the false “task branch changed” drop is gone. Of 68 batch runs, two went red, both on a real failing test that the bisect found.
- Periodic test runs tell infrastructure from culprits. A droplet capacity refusal no longer reads as a red run with a culprit merge.
Cost
Droplets cost $27.71 for v0.2.0 and $13.25 for v0.2.1, with no change to the daily cap. Recorded tokens in v0.2.0 were 4.81 billion for Codex. In v0.2.1 they were 2.20 billion for Codex, 1.25 billion for the Coordinator’s Claude Code and 0.23 billion for OpenCode. Between 97.7% and 99.6% of each was cached re-reads. All of it except OpenCode’s paid plan ran on subscriptions.
Honest gaps
- The phone client was verified in Chrome for Testing on the same machine. There is no record yet of a run on the maintainer’s own phone through a tunnel.
- The install script was tested on a clean machine: on a fresh droplet,
curl … | shinstalled v0.2.1. For Homebrew we checked the formula against the release tarball, but no install on a clean Mac has run yet. - The OpenCode qualification ran on one model, on XS to M tasks, in one project.
What is next
v0.2.2 clears the backlog of bugs and debt. Beyond that, we want to know how far a cheap model in each seat can carry a crew, and where it stops.