Show HN: MulmoTerminal – Run many Claude Code sessions, see which needs you MulmoTerminal, a browser terminal for running multiple Claude Code and Codex sessions in parallel, was launched on Hacker News by receptron. The tool displays each session in a color-coded grid (blue for working, green for done, amber for needs you), supports git worktrees, phone push notifications, and runs via a single npx command. It requires Node ≥ 22.9 and the Claude CLI, and was built by the same team behind GraphAI. Run multiple Claude Code and Codex sessions in parallel — and see which one needs you. A browser terminal for parallel AI coding agents : several Claude Code and Codex sessions side by side, each in its own cell, with the one that needs you marked in colour. Vibe coding with a single agent needs nothing but a shell — this is for when you run several and lose track of which is waiting. Sessions survive a reload tmux , work isolates in git worktrees , and a phone push reaches you when a turn finishes. Every cell is a real pty. htop , lazygit , a dev server and Claude Code are the same kind of object here — which is why the one-session-per-worktree limit applies to agents only , and a shell or a yarn dev launcher can sit in the same worktree an agent is working in. The grid, live — each cell coloured working, done or needs you. mulmoterminal-launch-v8 en.mp4 90 seconds, with sound: one agent, then a grid of them. Zoom into one and the roster still holds what every other session asked, answered and did, so you go to whichever is lit and lose nothing catching up. Transcript of the narration When you ran one coding agent, the slowest thing in the room was the agent. Now that you run five, the slowest thing in the room is probably you. One of them is always stopped. A permission prompt. A question. Until you notice, it does nothing at all. MulmoTerminal puts every session on one screen. Blue is working. Green is done. Amber is waiting on you. You stop hunting. You go where the light is. The other kind of slow is: what did I even ask this one? The roster keeps one line per session — what you asked, and what came back. Nothing left to remember. When one is done, you don't go looking for its window. Click its row — the next order goes in right there. Then you pick the next one from whatever is lit. Click, answer, move on. You never go looking — the roster tells you. We built MulmoTerminal for exactly that: not to watch agents, but to triage them. That is the whole install. MulmoTerminal turns Claude Code https://claude.com/claude-code and OpenAI's Codex into a parallel, observable workspace: many agent sessions at once in a grid, each one color-coded so you see at a glance which are working , which need you , and which are done — plus rich GUI output, git worktrees with one-click PRs, cost readouts, and a ping to your phone when a task finishes. One npx command, no Electron, no config. npx mulmoterminal@latest starts on http://localhost:34567 and opens your browser Requires Node ≥ 22.9 and the claude https://claude.com/claude-code CLI on your PATH , already logged in. npx mulmoterminal@latest init reports what it can't find.Running agents in parallel was never the hard part — tmux does that fine. What gets lost is which of the five is waiting for you. A pane is opaque: working, finished and blocked-on-a-permission all look the same until you read it. Here every cell reports its state back to one grid — working blue , done green , needs you amber — with a chime when one goes amber off-screen, and a cockpit roster why-youll-want-it of one line per session so you can answer one without losing your place in the other four. It runs on tmux when you have it, for persistence across restarts session-persistence-tmux . Built by receptron — , software architect for Satoshi Nakajima https://x.com/snakajima Windows 95 at Microsoft, and ; the same two behind Isamu Arimoto https://github.com/isamu . GraphAI https://github.com/receptron/graphai More ↓ who-builds-this See every agent at once. A grid of live sessions, each cell color-coded by state — working blue , blocked / needs a permission amber , done, unreviewed blue , idle — with an attention chime and a toolbar tally, so an off-screen agent that's stuck never slips past you. Stop babysitting one terminal; supervise ten. Zoom into one and the cockpit roster keeps everyone else in view — one text row per session with its AI summary, last prompt, latest reply, and the branch's PR phase draft / CI fail / ready / merged . A GUI for your agents, not just a terminal. Beside the terminal, a Canvas panel renders what an agent produces over MCP — documents, forms, charts, generated images, HTML, collection cards — each drawn by its own plugin. The agent doesn't just print text; it hands you an interface. Get pulled back from anywhere. A finished — or input-waiting — task sends a Web Push to your phone , and the RemoteHost companion lets you watch sessions and answer with a tap yes / no / continue from the phone itself — walk away, get pinged, jump back in. Nothing is lost on a restart. With tmux , every session survives a server crash, restart, or node --watch reload — a mid-turn agent, a long build, a dev server all keep running and reattach when you come back. Ship without leaving the grid. Each repo cell shows a git branch chip , isolates work in a one-click git worktree , opens a diff panel, and does commit / push / open PR — so several agents can work the same repo without colliding. Know what it's costing. Per-session context % , token , and estimated $ readouts, an activity timeline of tool calls, and AI-summarized cell titles and command-output explanations — so a wall of parallel agents stays legible. Make it yours. Per-directory themes, colors, and name badges prod in red, staging in amber , a configurable header buttons + info chips , custom attention sounds, and Run / Skill menus to launch a project's scripts and .claude/skills right inside a cell. The grid is a cockpit for parallel agents — here, four live Claude sessions, each in its own color-coded project. Every cell's header carries what you need to triage at a glance: model · context %, token counts ⇡in ⇣out , the git branch / changes chip, and an AI summary of what the agent is doing. A cell's border color signals state — working blue , done green , needs-you amber — e.g. waiting on a permission , idle — with an attention chime so a stuck cell off-screen still pulls you back. Supervise many; only step in where you're called. Zoomed in, the cockpit roster replaces thumbnails with information: every session as a text row — directory, AI summary, your last prompt, the agent's latest reply, a status word, and the branch's PR phase badge. A row whose agent is waiting on you rings amber and blinks; one that has merely finished rings green and stays still Settings → Waiting rows turns the movement off . Click a row to swap the enlarged terminal. Each session runs as a real PTY on the server the agent CLI in a pseudo-terminal and is streamed to an xterm.js https://xtermjs.org/ terminal in the browser over a WebSocket. The cockpit roster lists every session and reflects, in real time, which are working the agent is thinking, a spinner , which are waiting on you a permission prompt or a question — an amber dot; nothing proceeds until you answer and which are finished with output you haven't seen a green dot — driven by Claude/Codex activity hooks the server injects per spawn. The horizontal tab bar carries the same two dots. To focus on one agent, zoom its cell: it takes the window, and the GUI panel "Canvas" opens beside it, where that agent's tool calls render as documents, forms, charts, images, and HTML rather than printed text. The app opens on the grid / , settling on /terminals , which is the only view; 3.x had a separate single view at /chat and 4.0.0 removed it, so that URL now lands on the grid like any other. Inserting a file path — like a native terminal, you can put a file's absolute path into the prompt: drag a file onto the terminal, or click the file button in the terminal header, which asks the local server to open the OS file dialog and inserts the chosen path. The path is inserted at the cursor — it is not submitted, so you can review it first. A drag inserts the file's own path where the browser exposes one via file:// Firefox/Safari , so editing it afterwards edits the file you dropped. Where the browser withholds it — Chrome , and every browser when MulmoTerminal is open from another machine , where a local path would name nothing on the host — the file's bytes are sent instead, saved to a private per-session directory under the OS temp dir, and that path is inserted. The session is granted that directory at launch Claude Code's --add-dir , so the agent reads it without a permission prompt; the copies are removed when the session ends, and any left by a crash are swept at the next start. Up to 110 MiB per file — the same ceiling as a phone attachment. A session already running when you upgrade was launched without that grant , so drops into it still prompt; new sessions don't. Pasting a screenshot — take a screenshot and paste it straight into the terminal Cmd / Ctrl + V . The image is saved to the session's own drop directory — the same place a dropped file goes, with the same grant, the same 110 MiB ceiling and the same cleanup when the session ends — and its absolute path is inserted at the cursor, so the agent can read it. Unlike a drop, this does not need the browser to expose a path — the bytes are on the clipboard — so it also covers Chrome, where dropping a file cannot insert a path. It works wherever the browser puts the image on the clipboard as image/png , image/jpeg , image/gif , or image/webp . Anything else is left to the terminal's own paste handling, exactly as before — including a paste that carries plain text next to the image, which copying from a web page usually does, so that pasting text keeps working. Clicking a file path — the other direction. A path an agent prints becomes a link, and what it opens is chosen by its extension , so each kind arrives as the thing it is rather than as bytes files within the session's working directory only : | A clicked … | opens as | |---|---| .md .markdown | rendered markdown in a new tab — the same sandboxed …/md HTML the Files preview uses. It follows your system light/dark setting, since under the sandbox CSP it can't ask the app which theme is on | .json | indented in a new tab Chrome and Safari otherwise show one long line | .csv .tsv | a table in a new tab, with a sticky header that scrolls inside its own box | source, config, logs, and .txt — 46 extensions | the app's own Files view /files?path= , where CodeMirror highlights it, the tree is right there, and it can be edited | | everything else — images, PDF, SVG, HTML, video | raw bytes in a new tab, which the browser renders better than an editor would | While a grid cell is enlarged, the Files pane takes the click first — every row above except the last one, since the pane is the same editor plus a Markdown preview. The file opens beside the terminal that printed it, and the pane opens itself if it was closed. It declines, leaving the routing above untouched, when nothing is enlarged, when the path is not under that cell's own directory the pane cannot walk above its root , or for the raw-bytes row, where it would only show an empty editor. Highlighting in the Files view covers the JS/TS family, JSON and Markdown the modes cmEditor.ts bundles ; other languages open as plain text. This set is deliberately asymmetric with the set the server serves as viewable text — .md goes to the rendered viewer rather than the Files view, .txt does the opposite, and dotfiles are server-only. The 45 extensions both sides agree on live in common/sourceExtensions.ts , each side adds its own extras, and test/common/sourceExtensions.spec.ts pins the asymmetry so it isn't "fixed" into symmetry. Changing this?The routing table is ROUTE BY EXTENSION / IN APP EXTENSIONS in src/composables/terminalFilePathLinkProvider.ts . Update this section, the docs/guide/{en,ja}/features.md row, and the link table in docs/terminal-notes.md together — all three went stale once already 834 . These are experiences reported by users who moved over from an IDE or a split terminal — not benchmarks, and not claims we measured. Your setup may differ. Keeping several agents apart by opening several IDE windows is expensive: each one brings its own editor, language server, extensions and file watchers. One user reported a 64 GB machine stuttering under that load, and running smoothly after moving over — here the agents are PTYs on a server and the UI is browser tabs. Six panes of scrolling text look identical. Users have described typing a reply into another agent's terminal , and losing track of what they had asked in the first place. As one put it, the windows all look the same, so switching between them costs time just to work out what you are looking at. The problem isn't attention — it's that N identical panes means holding N contexts in your head. Colour-coded state, a name badge and a per-directory colour move that onto the screen instead. Splitting a terminal six ways leaves every pane too small to read a long answer without constant scrolling and resizing — one user described exactly that with a 4,000-character reply. So you quietly accept worse reading every time you add an agent. Grid ↔ enlarge removes that. Watch all of them, then blow one up and read it properly — the cockpit roster keeps the rest in view as text while you do. Sessions resume as-is — same claude --resume , same transcripts. Point it at a directory you already work in and your history is there. Nothing to migrate, nothing to redo. One user said this alone made the switch worth it, having previously lost context to killed sessions. You don't need ten agents for this to pay off. Users have reported the switch being worth it at one to three parallel sessions. The wins above are about not losing track, not about running more. 📖 Documentation — receptron.github.io/mulmoterminal https://receptron.github.io/mulmoterminal/ receptron.github.io/mulmoterminal https://receptron.github.io/mulmoterminal/ User guide: English https://receptron.github.io/mulmoterminal/guide/en/ — the grid view, everyday workflows, the full feature list, configuration, and mobile push notifications. ユーザーガイド: 日本語 https://receptron.github.io/mulmoterminal/guide/ja/ — グリッドの使い方・日々のワークフロー・機能一覧・設定・スマホ通知の設定はこちら。 Updates / アップデート情報: new releases and features are announced in Japanese on X — 新バージョンや新機能のお知らせは X の Singularity Society @SingularitySoci https://x.com/SingularitySoci で。 Needs Node ≥ 22.9 , plus these CLIs on your PATH : Never installed any of this before?The guide walks it end to end, macOS and Windows, assuming no command-line experience: Getting started · はじめに — 起動するまで | Tool | What it gives you | Install | | |---|---|---|---| Required | claude | npm i -g @anthropic-ai/claude-code , then run claude once to log in Required git worktree isolation git-worktrees--pull-requests , each cell's branch / unsaved-dot / diff readout, the PR footer brew install git · sudo apt install git · sudo dnf install git · Windows: git-scm.com https://git-scm.com/download/win Required gh PRs & Issues view and one-click PR creation — it uses your gh login, so no token is stored cli.github.com https://cli.github.com , then gh auth login glab GitLab projects 981 — gitlab.com, and a self-hosted instance you declare in gitlabHosts 1332 . Same arrangement: the CLI holds the credentials, this app stores no token brew install glab , then glab auth login self-hosted: glab auth login --hostname gitlab.example.com tmux session persistence session-persistence-tmux — terminals survive a server restart brew install tmux · sudo apt install tmux · sudo dnf install tmux · no native Windows build falls back to plain PTYs codex Codex sessions agents-claude--codex in a cell, alongside Claude npm i -g @openai/codex ffmpeg mulmo-script panel wiki-collections--the-gui-panel its plugin ships enabled brew install ffmpeg · sudo apt install ffmpeg · sudo dnf install ffmpeg ollama — Claude Code against a fully local model https://receptron.github.io/mulmoterminal/guide/en/claude-ollama.html claude-ollama ollama.com/download https://ollama.com/download Choose a folder / Insert a file path buttons, which open an OS dialog on the machine the server runs on. macOS and Windows have one built in; WSL uses the Windows one over interop and needs nothing installed. A Linux desktop needs one of these — without any, the buttons say so and you type the path instead 1447 sudo apt install zenity · sudo dnf install zenity · kdialog , qarma and yad also workThe server starts without any of the non-required rows; you just lose that row's feature, and the header/panel for it says so. git and gh are marked required because losing them costs whole views rather than one button. npx mulmoterminal@latest init below reports which of these it can find. npx mulmoterminal@latest start on http://localhost:34567 and open the browser or install globally: npm install -g mulmoterminal mulmoterminal Stopping it. Ctrl+C in the terminal that started it — or, if you can no longer find that terminal, Settings → Quit MulmoTerminal in the browser, or npx mulmoterminal@latest stop from any terminal installed globally, just mulmoterminal stop . All three run the same shutdown: with tmux installed the agent sessions survive and come back under Settings → Sessions that survived a restart ; without it they end with the server. First-run setup optional . npx mulmoterminal@latest init checks your environment Node ≥ 22.9 and every CLI in the table above , seeds the launcher's directory presets from the projects in your Claude Code history, and writes ~/.mulmoterminal/config.json . It's idempotent — re-run it any time to refresh the presets; it overwrites the managed parts and keeps your other settings. When claude is installed it can hand off to the /mulmoterminal-config skill for interactive tweaks — it routes to the one that owns what you want to change. Once the app is up you can also reach them from Settings : each section that a skill can write ends in a button that starts that skill in a new session, which is how the settings with no UI a theme of your own, keymap get written without hand-editing JSON. Google account optional . Link a Google account to enable the chat's google tool and the phone's google.calendar. commands: read/create events on any calendar not just your primary , list the calendars you've subscribed to, and read the colour palettes. Sign in from Settings → Google account , or run npx mulmoterminal@latest google login — the CLI is the fallback for when you're driving MulmoTerminal from another machine, since consent finishes on a loopback listener and needs a browser on the host . Either way it needs a Desktop OAuth client JSON saved as ~/.secrets/client secret .json ; the refresh token lands in ~/.config/mulmo/google-token.json and is shared with MulmoClaude , so one link per machine covers both apps. Local models optional . The package also ships claude-ollama — a one-command launcher that runs Claude Code fully locally against an Ollama model no cloud, no API key . It starts a large-context Ollama server and launches claude with a minimal system prompt so small models aren't drowned: ollama pull qwen3:4b npx -p mulmoterminal claude-ollama qwen3:4b or, if installed globally: claude-ollama qwen3:4b See Local models with claude-ollama https://receptron.github.io/mulmoterminal/guide/en/claude-ollama.html for the details and model notes. Already linked before the calendar-list / colour features?They need a read scope your existing link doesn't have, so listCalendars and, in practice, colors fail with an insufficient-scope 403 until you re-authorize:Settings → Google account → Unlink, then sign in again or re-run google login . Reading/creating events on your primary calendar keeps working without re-linking. A global install isn't auto-updated, so on startup MulmoTerminal checks npm and prints a one-line notice when a newer version is available — and the web toolbar shows a clickable update badge with the exact command for your install npm i -g mulmoterminal , or git pull for a clone . The server repeats that check every few hours, so a release that ships while it is running still reaches the badge; the startup console notice is printed once and is not repeated. Disable with MULMOTERMINAL NO UPDATE CHECK=1 or NO UPDATE NOTIFIER=1 . Options: --cwd