Skip to content

v0.15.0

Choose a tag to compare

@kvnwolf kvnwolf released this 04 Sep 00:15
· 5 commits to main since this release

🧭 dobby stops driving your environment and starts telling the model how to.

v0.14.0 put the host-specific mechanics behind one seam β€” open a cmux pane, spawn a detached process, open a browser, rename the workspace, tear it all down. That worked exactly as long as a CLI could control the host. Claude Desktop and t3 code drive their surfaces through MCP tools that only the model can call, so on those hosts the seam had nothing to execute and no way to say so.

v0.15.0 turns every adapter into a catalogue of instructions. dobby still executes what only it can execute β€” the setup phase, the liveness probe, pidfile registration, Neon branches, your setup[]/teardown[] extras. Everything host-shaped it now describes, per topic, and the model carries out. One shape everywhere, and two new hosts for free.


🧭 dobby instructions <topic> β€” the catalogue, readable on its own

Four topics: start, stop, browser, rename. Ask for one and you get the instruction for the environment you're actually in, as text or --json ({environment, topic, applies, text}). A topic that doesn't apply β€” rename on a plain terminal, which has no workspace to rename β€” answers applies: false with exit 0. That's a valid answer, not an error; you never have to know the environment/topic matrix to avoid a legitimate red. An unknown topic exits 1 and names the four.

πŸ–₯️ Four adapters, one file each

cmux, terminal, t3-code, claude-desktop, under cli/src/adapters/. Detection is an ordered cascade with terminal as the floor: CMUX_WORKSPACE_ID β†’ cmux; CLAUDE_CODE_ENTRYPOINT ∈ {claude-desktop, claude-desktop-3p, local-agent} β†’ Desktop; __CFBundleIdentifier starting with com.t3tools.t3code β†’ t3 code; anything else β†’ terminal, whose instructions (a background Bash, claude-in-chrome falling back to curl) work on any host. A new SDK host you've never heard of degrades instead of breaking.

The t3 code adapter was written against tool schemas loaded live in a t3 code session and verified against the vendor's source (v0.0.38). Its browser guide follows the vendor's own order β€” preview_status first, so the model reuses a tab instead of opening a second one β€” and names all 14 mcp__t3-code__preview_* tools. The Claude Desktop adapter is written from a field study and marked unverified in code until someone runs it against a live Desktop; public docs confirm the entrypoint values and the server name Claude Browser, not its method names. The study itself now lives in docs/field-studies/, so the adapter's provenance survives.

πŸ” up hands you what to do next β€” and does it in two steps

bunx dobby up --json no longer starts the server. It runs setup, probes the devUrl once, and returns live plus instructions[] β€” rename under cmux, start when nothing answers. You carry them out, run up again, and it sees the registered start in flight, waits in its liveness loop, and comes back live: true. A returned instruction is ok: true; it is the normal path, not a failure, and /dobby:scope's abort-or-degrade gate now fires only on real failures.

That two-step protocol is written once, in plugin/skills/execute/references/bring-up.md, and cited by every skill that used to promise "up ensures the run is up" β€” eight of them. If the contract changes again, one file changes.

bunx dobby down --json is new and symmetric: {cmux, instructions, ok, reason, slug, workroot}, with a stop instruction naming the exact panes to close when there are any.

πŸͺͺ dobby dev owns its pidfile β€” and survived six review rounds proving it

bunx dobby dev now registers itself in .dobby/dev.pid on startup, refuses a live twin (already running (pid N) β€” dobby down stops it, exit 1, nothing spawned), and clears it on teardown β€” so down finds the process no matter who launched it: the model, you by hand, or nobody. Greptile then spent six rounds on that registry, and it earned its keep: registration is an atomic O_EXCL create; a stale file is reclaimed by atomic rename with re-classification of what was actually captured; an ownership probe that can't answer (a failing ps, unparseable timing) never deletes and never reclaims β€” inconclusive is not dead; and down sweeps the dev.pid.stale.* sidecars a failed restore leaves behind. What's deliberately still open β€” a live registration stranded in a sidecar during a three-process race, visible to up only after down β€” is recorded in ADR-0032 as accepted residual risk, with the alternative that was rejected and why.

One more thing from that review, worth saying plainly: a repository path containing $(…) executed when the cmux start instruction was pasted into a shell. Every dynamic argument on every cmux command line is now single-quoted, nested where it has to nest, and the tests prove it by running the emitted lines through sh against a recording stub.

πŸ§ͺ CI runs the real dev now

The real-dev tests used to pass on CI by accident β€” portless wants sudo for port 443 and dies without a TTY, and the old test only waited for the pidfile to exist, which it did for an instant. They now run against a portless on an ephemeral unprivileged port with CI=1, and wait for the app to actually start.


⚠️ Breaking changes β€” read before you upgrade

dobby env --json no longer carries browserGuide. Anything that read it gets undefined. The guide moved to dobby instructions browser --json; dobby:qa already reads it there and now declares the three MCP tool families (claude-in-chrome, Claude_Browser, t3-code).

up no longer starts the dev server. It returns instructions[] and live. Any prompt or CLAUDE.md of yours that says "bunx dobby up ensures the run is up" is stale β€” point it at bring-up.md's two steps.

dev-start-failed is gone from reason; neon-branch-failed is new. A failed start is now diagnosed by the model that ran the command and can see its stderr β€” more than the old boolean ever told you.

dobby dev exits 1 when a live registered twin exists. dobby down stops it.

The Environment interface is reshaped β€” ensureRunSurface, ensureBrowserSurface, closeSurfaces, renameWorkspace and browserGuide are gone; what's left is id, cmux, discoverPanes and instruction(topic, ctx). Only relevant if you wrote an adapter.

Restart your session after upgrading. The dobby:qa agent's tools: frontmatter changed, and Claude Code pins the agent registry at startup.

Known limits. t3 code detection is macOS-only (the bundle id is an Info.plist artefact; t3 code injects no variable of its own β€” on Linux/Windows it falls to terminal and loses its browser guide). The Claude Desktop adapter is unverified against a live Desktop. .claude/launch.json is deliberately neither read nor written: dobby owns the devUrl model through portless.


πŸ“¦ Upgrading

bun update @kvnwolf/dobby

Then restart your Claude Code session before the next /dobby:execute. /dobby:upgrade walks the full v0.15 note if you're jumping several versions.

The decision, the four rejected alternatives and the accepted residual risk are in ADR-0032; ADR-0031's vendored cmux protocol is unchanged in content and changed in channel.