A startup office in your terminal, staffed by real agents.
Chat with the boss. Watch the floor — employees walk, type, drop mail, hit the tea machine. Right panel is yours. Left pane is the floor (or the in-TUI browser).
Website · Docs · Get started · Discord
Under the wallpaper it is real: the manager is Oikonomos, employees are opencode sub-agents, the board is agentmemory actions, mail is agentmemory signals.
One-liner — binary plus agentmemory as a reboot-safe service:
curl -fsSL https://boringfloor.com/install.sh | shWindows (PowerShell):
irm https://boringfloor.com/install.ps1 | iexThe Windows installer downloads the matching theboringfloor_<version>_<os>_<arch>.tar.gz release archive, verifies its SHA-256 checksum, and installs theboringfloor.exe (plus tbo.exe) in %LOCALAPPDATA%\theboringfloor\bin. It adds that directory to your user PATH; open a new PowerShell window, then run theboringfloor --demo. To install manually, download the matching theboringfloor_<version>_<os>_<arch>.tar.gz archive and checksums file from Releases, verify the checksum, then put theboringfloor.exe in a directory on your PATH.
Pick the LLM transport at install (opencode default; claudecode needs the claude CLI):
curl -fsSL https://boringfloor.com/install.sh | sh -s -- --backend claudecodeThen:
theboringfloor # live office
theboringfloor --demo # touring mode
theboringfloor --version # stamp: version, commit, datePin a tag, or grab a prebuilt (macOS/Linux/Windows, amd64/arm64) from Releases:
go install github.com/theboringhumane/theboringfloor/cmd/theboringfloor@latestFull on-ramp: Getting started · local notes in docs/.
Manual lives on the site. This repo keeps a thin index so GitHub readers land in the right room.
| In-repo | Website |
|---|---|
| Docs hub | Docs home |
| Architecture | Vision |
| Website | Get started |
Commands (cmd/) |
Sounds |
| Scripts | Blog |
Install & setup
- Getting started — curl, demo, live office,
--session
Core
- Backends — opencode or claudecode, both primed with the same manager charter
- Chat & work threads
- Plan mode
- MCP server — let your configured agent read the office and present plan drafts
Workflow
Panels & reference
Config file: ~/.theboringfloor/configs/brain.json (theboringfloor --print-default-config). Details: backends + layout.
Whichever backend you pick, the office primes it with the same manager charter before the first turn: the bundled oikonomos protocol lands at .opencode/oikonomos.md in the served directory. On opencode the office merges ./.opencode/oikonomos.md into .opencode/opencode.json's instructions — a field-preserving merge, every other key survives. On claudecode it writes CLAUDE.md: created with @.opencode/oikonomos.md when absent, or — when you already keep one — an idempotent <!-- theboringfloor charter --> block appended below your content. Nothing member-owned is ever overwritten.
One line per key — the full table lives at keys & slash commands.
In plan mode, the boss can present or refresh the plan pane with explicit markers. These are agent-only protocol lines, not commands for members to type:
⟦plan-present⟧
# Goal
Add the requested capability.
# Steps
1. Inspect the current flow.
2. Make the focused change.
⟦/plan-present⟧
⟦plan-update⟧
# Goal
Add the requested capability with the clarified edge case.
⟦/plan-update⟧
plan-present and plan-update are multiline blocks. They fill the existing plan pane as a draft; they do not run work and they never bypass your approval. Review or edit the draft, then press ctrl+x twice to approve it. Only that second confirmation sends the plan to the build agent.
Once you have approved a plan, the office keeps that approved version across sessions (up to 20,000 runes). Later drafts and updates stay drafts: they do not replace the approved plan until you review and approve them. When the boss needs the current decision, it places this marker on its own line:
⟦plan-get-approved⟧
The office sends the latest approved plan back to the boss. If there is no approved plan yet, it does not substitute a draft.
thefloor_mcp is the MCP server for the office. It ships in the same release archive as theboringfloor and is registered automatically in your global OpenCode configuration; when the Claude CLI is present, it is also registered for Claude Code at user scope. It gives your configured agent a first-class path alongside the plan markers above — the markers still work.
| Tool | Args | What it does | Needs live office? |
|---|---|---|---|
plan_present |
{text} |
presents a plan draft in the plan pane | yes |
plan_update |
{text} |
updates the plan draft in the plan pane | yes |
plan_get_approved |
{} |
reads the member-approved plan | no — live or on-disk |
transcript_read |
{limit?} |
reads recent office transcript messages | no — live or on-disk |
transcript_search |
{query, limit?} |
searches this project's recent transcript tail | no — on-disk, current project only |
office_status |
{} |
reports whether the office is live, its backend, and message counts | no |
plan_present and plan_update only present drafts: they never execute work. Review or edit the draft, then press ctrl+x twice to approve it for the build agent. If the office is not running, these write tools return an error; they have no offline fallback.
The on-disk transcript is capped to its most recent 200 messages per project, so transcript_search searches that recent tail rather than complete history. It is scoped to the current project and cannot read another project's transcript.
| Environment variable | Effect |
|---|---|
THEFLOOR_NO_CONTROL=1 |
disables the office control API |
THEFLOOR_NO_MCP_INSTALL=1 |
disables automatic MCP registration |
THEFLOOR_PROJECT_DIR |
overrides the project directory that thefloor_mcp binds to |
The office control API listens only on loopback (127.0.0.1) on an ephemeral port and requires a bearer token. Its discovery file is ~/.theboringfloor/projects/<dirhash>/control.json, mode 0600; it holds the port and token for the current project.
| Key | Does |
|---|---|
tab / shift+tab / 1..7 |
switch the right panel: chat · terminal · agents · board · mail · activity · git |
ctrl+b |
flip the left pane: floor ↔ browser |
enter |
send to the boss — free-sends into the backlog while it's busy |
shift+enter / ctrl+j |
newline in the chat input |
@ |
attach-file picker — type to filter, enter/tab attach |
ctrl+v |
paste text — attaches the image instead when the clipboard holds one |
| big paste | chat pastes >20 lines or >2000 chars collapse to a [pasted N lines · M chars] chip — one backspace unit, full text sent on submit |
/model · /session · @ |
pickers filter as you type — N/M badge, esc clears the filter, then closes |
y a n esc |
answer a permission prompt — allow once / always / reject / defer |
| click a tool row | expand what the tool returned (all kinds — capped, tail-kept; no output as such when there's none) |
⟦recent-messages⟧ / ⟦recent-messages: N⟧ |
agent-only context recovery marker — on its own line once per reply; sends the boss the latest 20 messages by default, or N clamped to 1..50 |
/bypass |
toggle bypass-permissions mode — session-only, confirm-on-enable, ⚠ BYPASS rides the topbar while on |
ctrl+x twice |
plan mode: confirm and approve the current draft for the build agent |
ctrl+q |
arm quit — works everywhere |
/bypass is the deliberate escape hatch. Enabling asks for an explicit confirm — agents will run tools and browser actions WITHOUT asking, this office session only — disabling is instant. While on, every tab's topbar carries a loud ⚠ BYPASS segment, backend permission asks stop (claude spawns with --dangerously-skip-permissions; the office-owned opencode process gets an ephemeral OPENCODE_CONFIG_CONTENT={"permission":{"*":"allow"}} override), any stray ask is auto-approved with a dim log row, and the office's own browser-action prompt is skipped the same way. Toggling builds and starts a fresh backend before switching; the current backend stays usable until the replacement is live, and claude resumes your session context. Every boot starts with bypass OFF. brain.json, .opencode/opencode.json, and the parent process environment stay untouched.
If the boss loses context after compaction, it can place ⟦recent-messages⟧ (the default 20) or ⟦recent-messages: N⟧ (1..50) on its own line, once in a reply. The office removes the marker and sends a read-only synthetic follow-up containing recent user, boss, and tool transcript entries — newest content preserved, capped at 12KB — then shows context: sent N recent messages to the boss. It never asks permission.
Browser tab (the left pane, behind ctrl+b):
Built-in browser first. Members open a page with /open <url>. Agents put one of ⟦open-browser: URL⟧, ⟦browser-screenshot: URL⟧, or ⟦browser-snapshot: URL⟧ on its own line: open a page, render a PNG for the member, or read its text and links back to the agent. ⟦browser-action: URL | click: CSS-SELECTOR⟧ (or fill / eval) changes a page and is permission-gated. The built-in directives work for localhost and external https:// pages; agents use Chrome/Chromium, Playwright, Puppeteer, or a terminal browser only when the member explicitly asks, or when the built-in path fails and they explain why.
| Key | Does |
|---|---|
↑/↓ or j/k |
move the link cursor |
o |
open the focused link |
e |
edit the URL inline in the location bar — prefilled, enter opens, esc cancels |
O |
open the current page in the OS browser |
[ / ] |
back / forward, 100-page history ring |
r |
reload in place |
pgup / pgdn |
scroll the body |
q / esc |
back to the floor |
On kitty/ghostty with Chrome, pages render as headless screenshots — shot badge, PNGs under ~/.theboringfloor/shots/ — and the boss can screenshot pages for you, snapshot pages to read for itself, and (with your approve-once permission) click, fill and eval on them. Pastes into the terminal tab reach the shell bracketed-paste-wrapped. Everywhere else the browser is text on purpose.
Join the Discord — floor talk, backends, bugs, shots.
Office memory rides agentmemory. Install script wires it, or npm install -g @agentmemory/agentmemory.
Commits through the office can stamp Co-authored-by: TheBoringMajdoor — scripts.
MIT © theboringhumane / theboredteam



