{"slug": "i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose", "title": "I gave my AI agents an office (and made it read-only on purpose)", "summary": "A developer built Cubicle, an open-source dashboard that renders AI agents as characters in a pixel-art office, using a single Node server under 200 lines with no dependencies and a 352×208 canvas drawn entirely with fillRect. The tool is deliberately read-only: it only issues GET requests, allowing just three Paperclip endpoints and returning 405 for POST/PATCH/DELETE and 403 for other paths, with API keys added server-side so they never reach the browser. It integrates with Claude Code via official hooks and surfaces pending questions from Paperclip's reviewAttention.paths, which the developer says surfaced two waiting questions they hadn't noticed.", "body_md": "I run several AI agents at once: a handful of Claude Code sessions, plus a small \"company\" of agents on [Paperclip](https://github.com/paperclipai/paperclip) that works on our online store. Giving them work is easy. The hard part is knowing, at a glance, which one is working, which one is done, and which one has been waiting for my answer for twenty minutes.\n\nLogs don't answer that at a glance. So I drew an office.\n\n**[Live demo, no install](https://caglarutkuguler.github.io/cubicle/?lang=en)** · [GitHub](https://github.com/caglarutkuguler/cubicle) · `npx @caglarutkuguler/cubicle`\n\nEvery agent is a character:\n\nThe header keeps a count of how many agents need you. That single number turned out to be the most useful thing on the screen.\n\nThe server is a single Node file of under 200 lines, using only the standard library: it serves one HTML page and proxies a few requests. The page draws everything with `fillRect` on a 352×208 canvas. There are no image assets, no framework, and no build step.\n\nThis wasn't minimalism for its own sake. A tool that sits next to your agents all day should be something you can read in ten minutes and trust.\n\nCubicle only ever makes `GET` requests. In Paperclip mode it forwards exactly three endpoints and refuses everything else:\n\n``` js\nconst ALLOWED = [\n  /^\\/api\\/health$/,\n  /^\\/api\\/companies$/,\n  /^\\/api\\/companies\\/[\\w-]+\\/(agents|issues)$/,\n];\n```\n\n`POST`, `PATCH` and `DELETE` get a `405`, any other path gets a `403`. If you point it at an authenticated Paperclip, the API key is added on the server side only: it never reaches the browser, and the browser's own cookies are never forwarded upstream. There is deliberately no `--token` flag, because flags show up in the process list.\n\nFor Claude Code, Cubicle uses the official hooks. A tiny script rewrites `~/.cubicle/claude-code.json` on every event:\n\n| Claude Code event | In the office | \n|---|---|\n| `PreToolUse` ,`PostToolUse` | Types at the desk; bubble shows e.g. `Edit checkout.php` | \n| `PermissionRequest` | Raises its hand | \n| `Stop` | Goes to the lounge | \n| `SessionEnd` | Leaves the office | \n\nThe hook always exits 0 and prints nothing, so it can never block a tool call or add tokens to the context. One thing I had to handle: Claude Code also sends a notification after a minute of idling (\"waiting for your input\"). Treating that as \"needs you\" made every idle session raise its hand, so those are ignored.\n\nFor Paperclip, the interesting signal was hiding in the issue data. When an agent asks the board a question, Paperclip records it in the issue's `reviewAttention.paths` with the board as the responder. Often the agent is already busy with another issue, so its own status says `running`. Cubicle keeps it typing, but its bubble flashes the waiting issue's ID every few seconds and the card links straight to it. The first time I turned this on, it found two questions I didn't know were waiting for me.\n\n```\n# Paperclip (default, expects it on :3100)\nnpx @caglarutkuguler/cubicle\n\n# Claude Code\nnpx @caglarutkuguler/cubicle install-hooks\nnpx @caglarutkuguler/cubicle --source claude-code\n\n# anything that can write a small JSON file\nnpx @caglarutkuguler/cubicle --source ./agents.json\n```\n\nOpen `http://127.0.0.1:3200`. Add `?kiosk` for a full-screen view on a TV or second monitor.\n\nA few issues are open and labelled for first-time contributors: a new UI language, per-agent spend for Paperclip, an example adapter for Codex or Gemini CLI, and a replay mode to watch a whole day in 30 seconds. PRs welcome, as long as they keep the two rules: no dependencies, and read-only.\n\nIt's MIT licensed: [github.com/caglarutkuguler/cubicle](https://github.com/caglarutkuguler/cubicle)", "url": "https://wpnews.pro/news/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose", "canonical_source": "https://dev.to/megventure/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose-5dpd", "published_at": "2026-09-27 20:44:36+00:00", "updated_at": "2026-09-27 21:00:57.268483+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["Cubicle", "Paperclip", "Claude Code", "Codex", "Gemini CLI"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose", "markdown": "https://wpnews.pro/news/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose.md", "text": "https://wpnews.pro/news/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose.txt", "jsonld": "https://wpnews.pro/news/i-gave-my-ai-agents-an-office-and-made-it-read-only-on-purpose.jsonld"}}