Backends

The office doesn't care which brain the boss has.

Two real transports today — opencode over a live server, or Claude Code as a per-turn child process. Same floor, same board, same queue; only the wiring under the chat changes.

The two transports, side by side

opencode (default)

The office spawns — or attaches to — an opencode serve process and streams its events over SSE. One shared server fronts every session for the working directory; this is what pre-existing brain.json files silently mean.

backend.name: "opencode"

claudecode

The office runs the claude CLI in headless stream-json mode as a child process — one process per turn, streamed line by line into the same chat surface. Needs the claude CLI on PATH; absent, the office warns instead of failing.

backend.name: "claudecode"

Also on the menu: Codex (Coming Soon) · Cursor (Coming Soon) · Pi (Coming Soon)

opencode (default)
theboringfloor on the opencode backend: floor, chat thread, and panels
claudecode — stream-json child
theboringfloor on the claudecode backend: claude CLI child streaming a boss reply

Same office either way — the topbar badge tells you which brain is on duty.

Picking it, three ways

Flag beats env, env beats brain, brain beats default.

The precedence chain is short and total: --backend flag on the binary overrides THEBORINGFLOOR_BACKEND (with GRAFEIO_BACKEND as the upgrade-era fallback), which overrides brain.json's backend.name — which install.sh --backend seeds for you. Nothing set anywhere means opencode. An invalid name is rejected with a stderr warning and the office falls back to opencode rather than refusing to boot.

# 1 · seed it at install time

... | sh -s -- --backend claudecode

# 2 · pin it in ~/.theboringfloor/configs/brain.json

"backend": { "name": "claudecode" }

# 3 · pin one boot from the shell

THEBORINGFLOOR_BACKEND=claudecode theboringfloor

How the office primes your agent

One charter, both brains — primed before the first turn.

On boot the office writes the bundled oikonomos manager protocol to .opencode/oikonomos.md in your working directory and hands it to whichever transport is on duty. That one file is what turns a raw model into the boss: decomposition discipline (wide parallel dispatches, one owner per file), permission etiquette (asks are for commands, questions are for product forks), and the proof-of-work return contract every developer answers with — DONE, FILES, VERIFY, PROOF, ISSUES.

The delivery depends on the brain. On opencode the office merges ./.opencode/oikonomos.md into the instructions array of .opencode/opencode.json — a surgical, field-preserving merge; every other key survives verbatim. On claudecode it writes CLAUDE.md instead — created with @.opencode/oikonomos.md when absent, and when you already keep one, an idempotent marked block appended below your content. Either way the same system prompt reaches the boss.

# your CLAUDE.md, after one office boot

...everything you wrote, untouched...

<!-- theboringfloor charter -->

@.opencode/oikonomos.md

<!-- /theboringfloor charter -->

Your own files take precedence — the office appends, never overwrites: an existing CLAUDE.md keeps every byte above the block, and every other opencode.json field rides through untouched.

Swapping mid-flight

/backend swaps live — but only from an idle office.

Bare /backend prints the active transport. With a name — /backend claudecode — it swaps mid-flight, archives the current turn, persists the name to brain.json, and lands one status line: [theboringfloor] backend: opencode → claudecode. The topbar shows the active name between mode and agents at all times.

The gate is strict by design: a boss turn in flight, a queued backlog, live workers, or an unanswered question or permission each get a refusal that names the blockers — the swap never preempts work. Settle the floor first (/stop helps), then swap.

Sessions don't cross the aisle: session.json pins session IDs per transport (primaryIDs), so swapping back later resumes that transport's own session instead of cross-pinning IDs between backends. Resuming a specific session by ID is covered in getting started, and the key chip for every other slash command lives in keys & slash commands.

What this doesn't do yet

Role models are best-effort — sub-agent model dispatch is opencode's call, not the office's. And Codex, Cursor, and Pi remain "(Coming Soon)" tags; the two transports above are the whole menu today.

The desks are empty. Your agents are waiting.