MCP server: One MCP server.

Codeman

@ark0nRun by its publisher: served from their own domain, namespace checked by the registry.MCP server · External

Start, prompt and read AI coding agent sessions (Claude Code, Codex, Gemini CLI and more) in Codeman

Agent collaborationv1.41.1MITTypeScript
Freeno charge per call

Runs on your machine from its package; the steps are below.

Codeman tile grid: six live agents (DeepSeek Harness, Claude Code, Pi, Codex, OpenCode and a shell) powering on and off with the CRT animation, with the live header strip showing CPU, memory and Claude plan usage
From the README · 1 of 8

What it does

  1. Reads
  2. Writes
  3. High impact

At most: moves money, runs code or commands, deletes data, or sends messages for you.

What it costs

Free

Odel charges nothing per call. The publisher may charge for its own service.

Runs locally over stdio

This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).

npmaicodemanv1.41.1

Run

npx -y aicodeman

MCP client config

{
  "mcpServers": {
    "codeman": {
      "command": "npx",
      "args": [
        "-y",
        "aicodeman"
      ]
    }
  }
}
README43 min read

Codeman

Mission control for AI coding agents

Claude Code • OpenCode • Codex • Antigravity • Gemini • Pi • Grok • DeepSeek • OMP • Terminal - One Dashboard • Any Device

License: MIT Node.js 22+ TypeScript 5.9 Fastify npm version GitHub stars Contributors Total commits

English • 简体中文

Codeman tile grid: six live agents (DeepSeek Harness, Claude Code, Pi, Codex, OpenCode and a shell) powering on and off with the CRT animation, with the live header strip showing CPU, memory and Claude plan usage

Codeman is a self-hosted mission control for AI coding agents. It spawns Claude Code, OpenCode, Codex, Antigravity, Gemini, Pi, Grok, DeepSeek Harness, or OMP inside persistent tmux sessions, streams the real terminal to any browser, and keeps agents productive after you walk away: it re-prompts on idle, resumes when a usage limit resets, runs scheduled jobs, and shows every background agent working in real time.

Get started in one line (macOS & Linux, Windows via WSL):

bash
curl -fsSL https://getcodeman.com/install | bash
bash
codeman web
# Open http://localhost:3000 and start your first session

The installer asks before every system change, and re-running the same line updates in place. Full details: Quick Start - Installation.

Codeman dashboard tour: session tabs per case, one-click Run for new agents, live plan usage in the header


Quick Start - Installation

bash
curl -fsSL https://getcodeman.com/install | bash

This installs Node.js, tmux and a build toolchain if missing (node-pty ships no Linux prebuilds, so it compiles from source), clones Codeman to ~/.codeman/app, and builds it. It looks at what is already on the machine, asks at most three questions, then does all the work unattended and ends on the URL with a QR code for your phone. A few things worth knowing:

  • Three questions, all up front. How the dashboard is reached, optionally what to call this machine on your tailnet, and whether to run Codeman as a background service (systemd/launchd, auto-start on boot; Enter says yes). Everything that needs you, including one consent for all missing packages, one sudo password, and the Tailscale login, happens before the build, so you can walk away while it compiles.
  • How it's reachable, your choice. Tailscale (loopback bind fronted by tailscale serve, so you get https://<machine>.<tailnet>.ts.net with a real certificate and your tailnet as the login, no password needed), any device on your network (0.0.0.0, with a strongly recommended password prompt), or this machine only (127.0.0.1, safest). Skipping the password on a network bind requires an explicit confirmation and ends with a loud warning. The highlighted default reflects what is already on the machine (Tailscale when it is already connected, your existing binding on a re-run), and a bare Enter never pulls in new software. If another app already owns :443 on your node, Codeman goes under https://<machine>.<tailnet>.ts.net/codeman or on a second port instead of replacing it. A bare codeman web started by hand still defaults to loopback.
  • The name is yours to choose. By default the URL uses the machine's existing tailnet name. Answering yes to the second question renames the machine to codeman-<hostname> (which also renames it for SSH, so the default is no); install.sh name does it later.
  • Re-run to update. The same one-liner updates a finished install in place: local changes in ~/.codeman/app are stashed (never discarded), and a running service is restarted and verified. If a first install was interrupted, re-running resumes the full setup instead. install.sh status prints the URLs and the QR code again; install.sh update, install.sh tailscale and install.sh uninstall also exist.
  • Flags for the impatient. curl -fsSL https://getcodeman.com/install | bash -s -- --tailscale --service answers the questions from the command line (--lan, --local, --run, --no-start, --name <n>, --port <n>, --yes too). CI / headless: without a terminal attached, steps that would change your system abort with instructions instead of running silently; set CODEMAN_NONINTERACTIVE=1 to approve them for automation.

You'll need at least one AI coding CLI installed — Claude Code, OpenCode, Codex, Antigravity, Gemini CLI, Pi, Grok Build, DeepSeek Harness, or OMP (any combination works; Gemini CLI is enterprise-only since Google's consumer cutover, and Antigravity is its successor). The installer detects whichever of the nine is present; if none is found, it offers to install any of them from a menu (DeepSeek excepted, since its npm package installs only a launcher with no runnable profile), or you can skip and install one yourself later. After install:

bash
codeman web
# Open http://localhost:3000 and start your first session

Sharing with a small team? Start it in multi-user mode instead: each person gets their own login and workspace.

bash
codeman users add alice --admin      # create the first admin account
codeman web --multiuser              # named logins + per-user case spaces

Prefer Docker Compose? A local-image Compose deployment ships in docker/: copy docker/.env.example to docker/.env, set CODEMAN_PASSWORD, then run bash docker/Start-Codeman.sh on Linux. Codeman runs in a container and spawns Docker cases as sibling containers through the host socket. After updating, run the script again rather than a plain docker compose up, so the rebuilt image, refreshed volumes and entrypoint arrive together. See the Docker deployment guide for direct Compose commands, storage and networking options.

Details in Multi-User Mode below.

Keep it running in the background

To outlive the shell you started it in, without setting anything up:

bash
codeman web -d          # detach; logs to ~/.codeman/web.log
codeman web --status    # is it up, and on which pid
codeman web --stop      # graceful SIGTERM; agents keep running in tmux

-d waits until the server actually answers before reporting success, and refuses to start a second one on the same data dir (two servers sharing a tmux socket attach to each other's sessions).

To have it come back after a reboot, install it as a service instead. The installer's final menu does this for you (option 2); codeman service is the equivalent for an npm i -g aicodeman install:

bash
codeman service install     # systemd user unit (Linux) or LaunchAgent (macOS)
codeman service status
codeman service uninstall

service install writes the unit with your current PATH baked in, which matters more than it sounds: launchd hands a job /usr/bin:/bin:/usr/sbin:/sbin, so a Homebrew or nvm node, tmux or claude is invisible to a hand-written plist. It never copies CODEMAN_PASSWORD into the unit file; add that yourself if the service needs auth.

To write the unit by hand instead:

Linux (systemd):

bash
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/codeman-web.service << EOF
[Unit]
Description=Codeman Web Server
After=network.target

[Service]
Type=simple
ExecStart=$(which node) $HOME/.codeman/app/dist/index.js web
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now codeman-web
loginctl enable-linger $USER

macOS (launchd):

bash
mkdir -p ~/Library/LaunchAgents
cat > ~/Library/LaunchAgents/com.codeman.web.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.codeman.web</string>
  <key>ProgramArguments</key>
  <array>
    <string>$(which node)</string>
    <string>$HOME/.codeman/app/dist/index.js</string>
    <string>web</string>
  </array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
  <key>StandardOutPath</key>
  <string>/tmp/codeman.log</string>
  <key>StandardErrorPath</key>
  <string>/tmp/codeman.log</string>
</dict>
</plist>
EOF
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.codeman.web.plist
Windows (WSL)
powershell
wsl bash -c "curl -fsSL https://getcodeman.com/install | bash"

Codeman requires tmux, so Windows users need WSL. If you don't have WSL yet: run wsl --install in an admin PowerShell, reboot, open Ubuntu, then install your preferred AI coding CLI inside WSL (Claude Code, OpenCode, Codex, Antigravity, Gemini CLI, Pi, Grok Build, DeepSeek Harness, or OMP). After installing, http://localhost:3000 is accessible from your Windows browser.


Mobile-Optimized Web UI

The most responsive AI coding agent experience on any phone. Full xterm.js terminal with local echo, swipe navigation, and a touch-optimized interface designed for real remote work — not a desktop UI crammed onto a small screen.

Mobile — answering an agent's plan prompt with the keyboard accessory bar and Enter buttonMobile toolbar: accessory bar with /init, /clear, clipboard and Esc above the Run, case, stop, Enter, voice and settings controls
Answering prompts by touchAccessory bar + dedicated Enter button
Terminal AppsCodeman Mobile
200-300ms input lag over remoteLocal echo — instant feedback
Tiny text, no contextFull xterm.js terminal
No session managementSwipe between sessions
No notificationsPush alerts for approvals and idle
Manual reconnecttmux persistence
No agent visibilityBackground agents in real-time
Copy-paste slash commandsOne-tap /init, /clear, /compact
Password typing on phoneQR code scan — instant auth
  • Keyboard accessory bar — /init, /clear, /compact quick-action buttons above the virtual keyboard; destructive commands require a double-press to confirm, so you never fire one by accident; on Codex sessions the bar also shows ⇧← / ⇧→ (Shift+Left / Shift+Right: edit the last queued message / return through the prompt stack)
  • Dedicated Enter button — replays the keypress through the terminal, so text buffered by local echo is flushed first rather than stranded
  • Attach button: the picture icon beside the mic opens the system photo and file sheet without raising the keyboard. Photos and camera-roll videos (mp4, mov, webm, up to 1 GB) upload into the session's folder and their path lands on your prompt, unsent
  • Paste in a shell: a multi-line paste goes in as one block and waits for your Enter, instead of running line by line as it arrives
  • Swipe navigation & smart keyboard handling — swipe left/right to switch sessions; toolbar and terminal shift up when the keyboard opens (visualViewport API)
  • Built for phones — safe-area insets for notch and home indicator, 44px touch targets, bottom-sheet case picker, native momentum scrolling; on a folding phone (iPhone Duo) dialogs stay clear of the hinge, and opening or closing the device is never mistaken for the keyboard
bash
codeman web --https
# Open on your phone: https://<your-ip>:3000

localhost works over plain HTTP. Use --https when accessing from another device, or use Tailscale (recommended): the installer can set it up for you (choose Tailscale at the network-access prompt, or run bash ~/.codeman/app/install.sh tailscale on an existing install). That gives you https://<your-machine>.<tailnet>.ts.net with a real certificate: private to your tailnet, no password required, and PWA install + push notifications work on your phone. The installer ends on that URL with a QR code to scan, and bash ~/.codeman/app/install.sh status prints it again any time.

Secure QR Code Authentication

Typing passwords on a phone keyboard is miserable. Codeman replaces it with cryptographically secure single-use QR tokens — scan the code displayed on your desktop and your phone is authenticated instantly.

Each QR encodes a URL containing a 6-character short code that maps to a 256-bit secret (crypto.randomBytes(32)) on the server. Tokens auto-rotate every 60 seconds, are atomically consumed on first scan (replays always fail), and use hash-based Map.get() lookup that leaks nothing through response timing. The short code is an opaque pointer — the real secret never appears in browser history, Referer headers, or Cloudflare edge logs.

The security design addresses all 6 critical QR auth flaws identified in "Demystifying the (In)Security of QR Code-based Login" (USENIX Security 2025, which found 47 of the top-100 websites vulnerable): single-use enforcement, short TTL, cryptographic randomness, server-side generation, real-time desktop notification on scan (QRLjacking detection), and IP + User-Agent session binding with manual revocation. Dual-layer rate limiting (per-IP + global) makes brute force infeasible across 62^6 = 56.8 billion possible codes. Full security analysis: docs/qr-auth-plan.md


Using Codeman — A Human's Guide

A start-to-finish walkthrough for driving Codeman from the browser. If you just installed, this is where to begin.

1. Launch the server

bash
codeman web                       # localhost:3000 (loopback only — safe default)
codeman web --port 8080           # custom port (or set CODEMAN_PORT)
codeman web --https               # self-signed TLS (only needed for remote access)
codeman web -H 0.0.0.0            # bind LAN — REQUIRES CODEMAN_PASSWORD (see Security)
codeman web -d                    # detach: survives closing the shell (--status, --stop)
codeman service install           # systemd/launchd service: comes back after reboots

Open the printed URL. The page is a single dashboard; everything below happens there.

2. Create your first session

Click + New Session (or Quick Start). A session is one AI CLI running in its own tmux-backed terminal. You choose:

FieldWhat it does
Working directory / caseThe folder the agent operates in. A "case" is just a named working dir Codeman remembers. Add Case creates one from scratch, links an existing folder, or clones a GitHub repo straight into one (Clone Repo).
CLI / run modeClaude (default), OpenCode, Codex, Antigravity, Gemini, Pi, Grok, DeepSeek, OMP, or Terminal (plain shell).
ModelPer-session model (App Settings → Models → New Claude sessions). A soft default — /model still works in-session.
Effort / UltracodeReasoning effort (low–max) or ultracode for dynamic multi-agent workflows. Switchable anytime with /effort.

Hit start — Codeman spawns the CLI via a real PTY and streams it to your browser over SSE.

3. Read the dashboard

  • Tabs (top) — one per session. Alt+1-9 to jump, Ctrl+Tab for next, drag to reorder (tab order syncs across your devices). Prefer a list? App Settings → Appearance → Tabs moves it into a left sidebar with a filter box (Alt+B collapses it) or a vertical rail whose rows sort by activity: blocked on you first, then longest running, then most recently quiet. The rail also has a Search sessions box, named tab groups (a group's menu starts a New session straight into it), and a Focus section of shortcuts to the tabs you keep coming back to.
  • Terminal (center) — a real xterm.js terminal; full TUIs render correctly. Type directly and press Enter to send. Shift+Enter inserts a newline.
  • Side panels — Respawn, Orchestrator, Cron, Subagents, Settings (toggled from the toolbar).

4. Talk to the agent

  • Type prompts straight into the terminal — input is delivered exactly-once even across reconnects (a dropped link never loses or double-sends a prompt).
  • Paste, drop or attach images and videos directly into the session. They are saved in a hidden .codeman-uploads/ folder in the workspace (it ignores itself in git and is swept after 7 days), and the file's path lands on your prompt, unsent.
  • Voice input — Ctrl+Shift+V (Deepgram Nova-3, or this machine's Claude Code login with no API key; auto-silence stop).
  • Attachments — register external files/docs and preview Office/PDF inline; any file path an agent prints is clickable, in the terminal and in the chat view, including ~/ and relative paths and paths broken across lines. An .html report opens as a real page, Markdown opens rendered, and a folder opens as a grid of its files.
  • When it needs you — the tab turns yellow (waiting for input) or red (a question is blocking). The Approvals Inbox (opt-in) queues every pending prompt across sessions, answerable from the header bell or the phone home screen, and 🧠 Read My Mind (opt-in) drafts your next prompt from the case's goals and recent work.
  • Copy what you see — Shift+drag selects text even while the CLI owns the mouse, right-click copies it, and Auto Copy (opt-in) copies a selection the moment you release it. A program that copies with OSC 52 (Claude Code's /copy, a tmux yank, vim) puts the text on your browser's clipboard too.

5. Make it autonomous

ModeUse it forWhere
RespawnLong unattended runs — auto-restarts the CLI on idle/limit, with adaptive timing. Presets: solo-work, overnight-autonomous, …Respawn tab
OrchestratorTurn one goal into a phased plan and drive it to completion across agents.Orchestrator panel
CronSaved, named jobs on a schedule (once/interval/daily/weekly) that spawn a session and send a prompt when due.⏰ Cron button (opt-in: App Settings → Header & Panels → Scheduling)
Auto-resumeAutomatically continue after a subscription rate-limit resets.Respawn tab (top)

6. Reach it from anywhere

  • Phone/tablet — the UI is fully touch-optimized; scan the desktop QR code to log in without typing a password.
  • Outside your network — ./scripts/tunnel.sh start opens a Cloudflare tunnel (set CODEMAN_PASSWORD first).
  • SSH — codeman tui is a full-screen dashboard in the terminal (codeman tui --list to list, codeman tui 2 to attach straight to one).

7. Operate & maintain

  • App Settings — model, effort, permission startup mode, theme/skin, terminal font family and weight, entrance and tile animations (their own Animations section), notifications (with adjustable toast and browser-notification display times), display toggles, per-CLI options, a synced custom display name, and per-device English/Simplified Chinese UI language. Apply saves without closing Settings.
  • Run it in the background — codeman web -d detaches from your shell (--status, --stop); codeman service install makes it a systemd user unit / macOS LaunchAgent that survives reboots. Both verify the server actually answers before reporting success, and both refuse to start a second server on one data dir. See Keep it running in the background.
  • Self-update — git-clone installs update in place from App Settings → System → Updates.
  • Deploy your own changes — see Development.

⚠️ Safety: if you're working inside a Codeman-managed session (echo $CODEMAN_MUX → 1), never run tmux kill-session / pkill claude directly — use the web UI or ./scripts/tmux-manager.sh.


Zero-Lag Input Overlay

Zerolag demo: instant local echo next to 600ms-2.7s server echo, side by side on two phones

When accessing your coding agent remotely (VPN, Tailscale, SSH tunnel), every keystroke normally takes 200-300ms to round-trip. Codeman implements a Mosh-inspired local echo system that makes typing feel instant regardless of latency.

A pixel-perfect DOM overlay inside xterm.js renders keystrokes at 0ms. Background forwarding silently sends every character to the PTY in 50ms debounced batches, so Tab completion, Ctrl+R history search, and all shell features work normally. When the server echo arrives 200-300ms later, the overlay seamlessly disappears and the real terminal text takes over — the transition is invisible.

  • Ink-proof architecture — lives as a <span> at z-index 7 inside .xterm-screen, completely immune to Ink's constant screen redraws (two previous attempts using terminal.write() failed because Ink corrupts injected buffer content)
  • Font-matched rendering — reads fontFamily, fontSize, fontWeight, and letterSpacing from xterm.js computed styles so overlay text is visually indistinguishable from real terminal output
  • Full editing — backspace, retype, paste (multi-char), cursor tracking, multi-line wrap when input exceeds terminal width
  • Persistent across reconnects — unsent input survives page reloads via localStorage
  • Enabled by default — works on both desktop and mobile, during idle and busy sessions

Extracted as a standalone library: xterm-zerolag-input — see Published Packages.


Live Agent Visualization

Watch background agents work in real-time. Codeman monitors agent activity and displays each agent in a draggable floating window with animated Matrix-style connection lines back to the parent session.

Subagent Visualization: three parallel Explore agents as floating windows with live tool-call feeds

  • Floating terminal windows — draggable, resizable panels for each agent with a live activity log showing every tool call, file read, and progress update as it happens
  • Connection lines — animated green lines linking parent sessions to their child agents, updating in real-time as agents spawn and complete
  • Status & model badges — green (active), yellow (idle), blue (completed) indicators with Haiku/Sonnet/Opus model color coding
  • Auto-behavior — windows auto-open on spawn, auto-minimize on completion, tab badge shows "AGENT" or "AGENTS (n)" count
  • Nested agents — supports 3-level hierarchies (lead session -> teammate agents -> sub-subagents)

Multi-agent Workflow runs ("ultracode") get the same treatment: a floating run window tracks the whole workflow live, with phases, per-agent token counts, and the current tool of every agent:

Ultracode workflow visualization: a live run window with per-agent tokens and phases

Agent Teams — first-class support for Claude Code's native multi-agent teams (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1). TeamWatcher polls ~/.claude/teams/, matches teammates to their lead session, and surfaces them as live subagent windows with team-aware idle detection — so the Respawn Controller won't fire while teammates are still working. See docs/agent-teams/.


Respawn Controller

The core of autonomous work. When the agent goes idle, the Respawn Controller detects it, sends a continue prompt, cycles context management commands for fresh context, and resumes — running 24+ hours completely unattended.

WATCHING → IDLE DETECTED → SEND UPDATE → /clear → /init → CONTINUE → WATCHING
  • Multi-layer idle detection — completion messages, AI-powered idle check, output silence, token stability
  • Auto-resume on usage limit (opt-in, off by default) — when Claude halts on a subscription limit ("You've hit your limit · resets 3pm"), Codeman parses the reset time, waits it out plus a 2-minute safety buffer, then dismisses the rate-limit dialog and sends continue — so an overnight run survives the 5-hour window instead of stalling until morning. Recognizes every Claude Code limit-message format, retries if still limited, survives Codeman restarts, and holds respawn cycles while paused so /clear can't wipe the waiting conversation. Enable per session at the top of the Respawn tab
  • Circuit breaker — prevents respawn thrashing when Claude is stuck (CLOSED -> HALF_OPEN -> OPEN states, tracks consecutive no-progress and repeated errors)
  • Health scoring — 0-100 health score with component scores for cycle success, circuit breaker state, iteration progress, and stuck recovery
  • Built-in presets — solo-work (3s idle, 60min), subagent-workflow (45s, 240min), team-lead (90s, 480min), ralph-todo (8s, 480min), overnight-autonomous (10s, 480min)

Orchestrator Loop

Beyond single-session respawn, the Orchestrator turns a high-level goal into a phased plan and drives it to completion across multiple agents — a state machine that runs idle → planning → approval → executing → verifying → (replanning) → completed.

  • Plan, then execute — generates a phased plan from your goal and pauses for approval before touching anything; reject with feedback to regenerate
  • Per-phase verification gates — each phase is verified before the next begins; on failure the orchestrator replans instead of barreling ahead
  • Multi-agent execution — fans phases out to team agents / a task queue, coordinating work too big for one session
  • Crash-safe — full state persists under the orchestrator key in state.json, so it survives restarts
  • Driven from the UI or API — the Orchestrator panel, or POST /api/orchestrator/start → /approve → /status (10 endpoints)

Full design: docs/orchestrator-loop-architecture.md.


Multi-Session Dashboard

Run 20 parallel sessions with full visibility — real-time xterm.js terminals at 60fps, per-session token and cost tracking, tab-based navigation, and one-click management.

Tile Grid

Tile grid: the Tiles button opens six live sessions side by side (DeepSeek Harness, Claude Code, Codex, a shell, OpenCode and Pi), and a second click returns to a single session

Watch and drive up to six sessions side by side in one window. Click Tiles in the header (or press Ctrl+Shift+G) and your sessions open as a grid of live terminals: every tile takes your keystrokes and shows its agent's logo, model and state in its header. Right-click Tiles to choose 2, 4 or 6 tiles, and drag a tile by its header to move it. Click Tiles again to return to a single session. Desktop only (a window about 1180px wide or more). Full guide: Tile Grid.

  • Opens what matters: with no grid arranged yet, it fills the tiles with the sessions that are working first, then the ones waiting on you, then the most recently used, and always includes the one you are on.
  • Keeps your layout: once you arrange a grid (which session sits where, empty cells, tile count, divider sizes, the focused and zoomed tile), the Tiles button brings it back exactly, and so does a page reload while it was open.
  • Tile animations (opt-in): App Settings → Animations → Tile Animations makes the grid open with a show: CRT (each tile switches on as a hot line, as in the GIF at the top), Fly from tab, Deal, Beam down, Cascade, Pop or Soft. Nothing moves under reduced motion.
  • Scrolls like the main terminal: the mouse wheel scrolls a fullscreen Claude conversation inside its tile, a Codex tile pages its transcript, and Shift+wheel scrolls the tile's local history.
  • Detach Tiles (beta, opt-in): with App Settings → Appearance → Detach Tiles on, drag a tile's header out of the browser and it pops out into its own window; drop it on another Codeman window's tiles and it moves there.
  • Hands-free: with the gesture overlay on, pinch a tile and carry it onto another tile to swap them, onto an empty cell to move it, or carry a tab onto the grid to add it.

Persistent Sessions

Every session runs inside tmux — sessions survive server restarts, network drops, and machine sleep. Auto-recovery on startup with dual redundancy. Ghost session discovery finds orphaned tmux sessions. Managed sessions are environment-tagged so the agent won't kill its own session.

Session Manager & Command Palette

Ctrl/Cmd/Alt+K opens a fuzzy session palette; Browse all sessions opens the Session Manager: one deduped list of everything Codeman knows about (live sessions, past sessions from state and lifecycle history, and Claude transcripts), each row showing its first and most recent prompt.

  • Pinning: pin a session to float it to the top of the list. Pinned sessions even survive kill (they demote to a lightweight stopped entry that stays visible and resumable).
  • Name retention: resuming a past session keeps its original name instead of minting a new one.
  • Cross-device tab order: drag-reordered tabs persist server-side, so your ordering follows you from desktop to phone.

Hostname-Aware Window Title

Running Codeman on multiple hosts (laptop, dev box, NAS)? The browser tab title is codeman:<hostname> so you can tell which backend each tab points at without clicking in:

bash
codeman web                                # codeman:<os.hostname()>
codeman web --title-hostname dev-box       # codeman:dev-box (manual override for noisy hostnames)

The title is templated into the served HTML on first byte, so it's correct from the very first paint and works without JavaScript. The same hostname prefix is applied to the tab-flash format (⚠️ (N) codeman:<host>) and to OS-level desktop notifications (codeman:<host>: <event>), so cross-host alerts in the system notification center are also unambiguous.

Smart Token Management

ThresholdActionResult
110k tokensAuto /compactContext summarized, work continues
140k tokensAuto /clearFresh start with /init

Tab Alerts

Tab states, annotated: a working tab with a spinning green ring, a red tab blocked on the agent's question shown below it, and a yellow tab whose turn is done, both alert tabs breathing

Every tab tells you its state at a glance. A running session keeps its green status dot. When a session stops and waits for input, its tab turns yellow: steady ring, tinted background, yellow dot, with a slow breathing glow on top. When a permission prompt or question is blocking the agent, the tab turns red with a faster pulse. The base tint never blinks off, so even a split-second glance (or a screenshot) reads the true state; the ring stays visible while the tab is selected, and a page reload re-arms pending alerts from the server, so a blocked session can never hide behind a fresh-looking tab.

Notifications

Real-time desktop alerts when sessions need attention — permission_prompt and elicitation_dialog trigger critical red tab blinks, idle_prompt triggers yellow blinks. Click any notification to jump directly to the affected session. Hooks auto-configured per case directory.

Run Summary

Click the chart icon on any session tab to see a timeline of everything that happened — respawn cycles, token milestones, auto-compact triggers, idle/working transitions, hook events, errors, and more.

Zero-Flicker Terminal

Terminal-based AI agents (Claude Code's Ink, OpenCode's Bubble Tea) redraw the screen on every state change. Codeman implements a 6-layer anti-flicker pipeline for smooth 60fps output across all sessions:

PTY Output → 16ms Server Batch → DEC 2026 Wrap → SSE → Client rAF → xterm.js (60fps)

More Features

  • Background daemon & service install — codeman web -d runs the server detached with a pidfile, ~/.codeman/web.log, and verified startup (it polls the server until it answers, so a port clash never reads as success); codeman service install writes a systemd user unit (Linux) or LaunchAgent (macOS) with your shell's PATH baked in, so an nvm or Homebrew node, tmux and claude are actually found. Secrets are never written into unit files
  • Diagnostics in Settings — App Settings → System → Diagnostics → Run checks runs codeman doctor on the server and lists Node, tmux, every agent CLI and the optional office tools with versions, paths and install hints. Besides the PATH, it also looks in each CLI's usual install directories (~/.local/bin, ~/.npm-global/bin and the like), so most installs are found under a service with a minimal PATH. Admin only in multi-user mode.
  • Self-update — git-clone installs under systemd/launchd update in place from App Settings → System → Updates: it detects the latest release, auto-stashes a dirty tree, and streams build progress across the service restart (npm installs report as non-updatable)
  • Git status in the bottom bar — off by default (App Settings → Header & Panels → Bottom bar → Git status, per device). A small indicator at the right of the bottom bar shows the active session's repository at a glance: ● 3 uncommitted files, ↑ 2 commits not pushed, ⚠ merge conflicts, ✓ all committed and pushed. Click it for a draggable window listing the staged, not-staged, untracked and conflicted files (grouped under collapsed folders, or as a flat list if you turn that setting off) and the unpushed commits; click a file to see its diff (new files as all additions, deleted files as all removals), with Open file to jump to the viewer. A folder that holds several projects gets one collapsible section per repository found up to two levels down, all collapsed until you open them. Read-only and offline (Codeman never fetches or changes the repo); not shown for Docker or remote sessions.
  • Clone a GitHub repo as a case — paste a repository URL into Add Case → Clone Repo and Codeman clones it into ~/codeman-cases/<name> and registers it as a normal case, ready to run an agent in. It preflights the URL while you type (tells you whether it can be cloned anonymously and offers the repo's real branches and tags for the optional branch/tag field), fills the case name in from the URL, and lets you pick which CLI the Run button should use. Public repositories over https://; Codeman never collects or stores credentials
  • Create a case in a custom folder — tick Create in a custom folder in Add Case → Create New, pick a parent folder (Browse included) and a name, and Codeman scaffolds the new case there instead of ~/codeman-cases. The target must be a new or empty folder; system directories, your home folder itself, credential trees such as ~/.ssh, and Codeman's own data folder are refused. Admin only in multi-user mode.
  • Multi-CLI — run Claude Code, OpenCode, Codex, Antigravity, Gemini, Pi, Grok, DeepSeek Harness, or OMP per session; env-var prefixes auto-gate (CLAUDE_CODE_* vs OPENCODE_* vs CODEX_* vs ANTIGRAVITY_* vs GEMINI_*/GOOGLE_* vs PI_* vs GROK_*/XAI_* vs DSH_*/DEEPSEEK_* vs OMP_*). See docs/opencode-integration.md, docs/pi-integration.md, docs/grok-integration.md, docs/deepseek-integration.md and docs/omp-integration.md
  • Custom model endpoints (new in 1.29.0, HTTP API for now) — point a session's CLI at any OpenAI-compatible endpoint instead of its native backend: a local llama.cpp, llama-swap, Ollama or vLLM box, or a cloud gateway such as Azure AI Foundry or OpenRouter. Save an endpoint once (POST /api/model-endpoints; its models are discovered from /v1/models), apply it to a session (POST /api/sessions/:id/custom-model), and the CLI restarts in place on that endpoint. Verified live for Claude, OpenCode, Pi, Grok and OMP; Codex, Gemini and DeepSeek have documented gaps, Antigravity has no mechanism. A toolbar picker is the follow-up. See docs/custom-model-endpoints.md
  • Web tabs — open Grafana, Uptime Kuma, a Vite dev server or any dashboard URL as a tab beside your sessions (Run dropdown → Web / URL → Add URL). Dashboards are proxied through Codeman's own origin, so an http:// target works from a phone over HTTPS and through the tunnel, single-page apps route on their own paths, and a frame that reloads recovers itself. A localhost link an agent prints opens as a web tab automatically. See docs/web-tabs.md
  • Docker sessions — run a case inside an isolated, hardened container. One checkbox on Create New spins up a container with sensible defaults and starts the agent inside it; multiple sessions share one per-case container, or attach a case to a container you already run; export a container + its workspace to a portable .tar.gz to move it to another machine. See docs/docker-cases.md
  • Remote SSH sessions — point a case at another machine and run the agent there inside a durable remote tmux: survives SSH drops, auto-reconnects, and can discover + attach sessions already running on the host; file previews and downloads come over the same ssh connection. See docs/remote-sessions.md
  • Effort & Ultracode — set a per-session default effort (low–max) or enable ultracode (dynamic multi-agent workflows). Soft defaults only — switchable anytime with /effort in-session. Extended-thinking budget is configurable too
  • Voice input — dictate prompts with Deepgram Nova-3, or through this machine's Claude Code login with no API key at all (App Settings → Voice; Web Speech API fallback): toggle recording, auto-silence stop, live level meter (Ctrl+Shift+V)
  • Image input — paste or drag-and-drop images straight into a session
  • Gesture control (opt-in) — a MediaPipe hand-tracking overlay to grab/drag session windows and pinch buttons, hands-free. Enable with CODEMAN_GESTURE=1 + App Settings → Terminal & Input
  • Multi-monitor span (macOS) — one click opens a browser window maximized across all displays, so floating agent/gesture panels can cross the physical seam
  • File Viewer button (opt-in) — a header button that toggles the built-in file browser panel with one tap; enable under App Settings → Header & Panels → Header buttons
  • HTML reports open as pages: click an .html path an agent printed (a test report, a coverage page, a dashboard) and the File Viewer shows it as a real page, with the scripts, styles, images and data files from its folder; the Page pill switches to the source and its Edit button. The page runs sandboxed with an opaque origin, so it cannot read Codeman's cookies, call Codeman's API or read files outside its own folder. Network access stays open, so a dashboard that loads Chart.js or fonts from a CDN works as it would from disk. Broad folders (/, your home, /tmp) are refused, so give a report a folder of its own. A .md path clicked in the terminal opens rendered too
  • Clickable paths and the folder grid: paths written as ~/…, relative to the session folder, or broken across terminal lines are clickable in the terminal and the Response Viewer, and so are folders: a folder opens a grid of its files (renders, screenshots, reports) that you page through with the arrow keys
  • OSC 52 clipboard: a program in a session that sets the clipboard with OSC 52 (Claude Code's /copy, a tmux yank, vim) puts the text on your browser's clipboard, in the main terminal and in every tile. Clipboard read requests are refused, and replaying a buffer never copies
  • MCP server sync (opt-in): copies the user-level MCP servers each installed CLI has (Claude, Codex, Gemini, OpenCode, Antigravity, and GitHub Copilot CLI) into the others' own config files. Additive only, a server you switched off is never copied, Preview shows the changes first, and the previous file is kept as .codeman-bak. App Settings → Agents & CLIs; admin only in multi-user mode
  • CJK / IME input — full composition support for Chinese / Japanese / Korean, with Ctrl- and Alt-modified navigation keys passed through to the CLI
  • Plan usage in the header — live Claude subscription usage (the 5-hour and weekly windows) from a statusline exporter Codeman hands to claude at spawn and never writes into your settings files, plus Codex limits from its own app-server; per device, on for desktops and off for phones
  • Prompt-cache readout: each Claude session shows whether its prompt cache is warm (cache:until HH:MM) or cold, in the footer (when you have no statusline of your own) and in Session Options → Respawn, with the cost of a re-cache and a note after a compaction. Display only; it survives a restart
  • Session list, your way — the header strip, a left sidebar with a filter box, or a vertical rail whose detailed rows carry created and state stamps and sort by activity; the phone home screen and the desktop home rail use the same order. On the rail, Search sessions narrows the list to the tabs that match, across every group, and a tab with an alert stays visible even when its name does not. Named tab groups collapse, reorder and take drags; a group's menu has New session, and a worker an agent spawns lands right after its parent (Spawned tabs follow their parent, off by default, keeps it moving with the parent). Add to Focus pins a shortcut to any tab in a section at the top of the rail, and CLI Logos on Tabs can be switched off per device
  • Terminal looks — seven skins, four of them light, per-device font family and weight (the bundled JetBrains Mono covers weights 100 to 800), and opt-in animations for tabs, agent windows, the terminal pane, connection lines and tile-grid tiles, all in App Settings → Animations (with a lab to try them)
  • OS notifications & hostname-aware titles — desktop alerts and tab titles are prefixed codeman:<host> so multi-host setups stay unambiguous

Isolated Docker Sessions

Run a case inside its own hardened Docker container instead of directly on your host — for security isolation, reproducible toolchains, and one-click portability.

  • One click — on New Case → Create New, tick 🐳 Run in an isolated Docker container. Codeman creates the case folder, spins up a container with default settings, and starts the agent inside it. No host/image/network fields to fill in.
  • Resource templates — expand the checkbox for a Small / Medium / Large / GPU preset (memory, CPUs, GPU), or set your own. Disk is elastic — storage grows as data flows in, no fixed cap.
  • Shared per-case container — many sessions can docker exec into the same container; killing one session never tears the container out from under the others.
  • Hardened by default — non-root, --cap-drop ALL, no-new-privileges, PID/memory caps, never --privileged or the docker socket; a sealed profile (no host credentials, network off) is one toggle away.
  • Seamless auth, isolated credentials — your host Claude / Codex / Antigravity / Gemini / OpenCode / Pi / Grok / OMP logins work inside the container out of the box: credentials are seeded (copied) in at launch and onboarding/trust prompts are pre-answered, so no login wizard appears. The container keeps its own copies and never writes back to your host credential stores; only conversation transcripts are shared, and exports never capture secrets.
  • Attach to a container you already run — tick Attach to an existing container on the Docker panel to link a case to it instead of creating one. Codeman only execs into it and never starts, stops, restarts or removes it; one adopted container can back several cases at different directories, and copy an existing case pre-fills the form from a sibling. Admin-only in multi-user mode, since the container's mounts belong to whoever started it.
  • Move it to another machine — export a container's whole environment (toolchain + workspace) to a portable .tar.gz, docker load it on the other side, and import it into a fresh case.
  • Durable — reconnect after a restart lands back in the same live agent; a container stop/reboot resumes the conversation from the bind-mounted transcript.

Prerequisite: just Docker (or Podman). The agent base image builds itself automatically on first use, with progress streamed to the UI (or pre-build it with node scripts/build-agent-image.mjs). Full guide: docs/docker-cases.md.


Remote SSH Sessions

Point a case at another machine and run the agent there, over SSH, with the same dashboard, mobile UI, and autonomy features. Your laptop is just a window onto a session that lives on the remote host.

  • Durable by design: the agent runs inside a dedicated tmux session on the remote host, so a dropped SSH connection, network change, or laptop sleep never kills the run. Reconnecting lands back in the same live conversation.
  • Auto-reconnect: a bounded-backoff watcher notices a dead SSH pane and silently reattaches to the still-running remote session (kill-switch in settings; intentional kills are never revived).
  • Discover & attach: list the codeman-* sessions already running on a host (started by that machine's own Codeman, or by another operator) and attach to one. Attached sessions you don't own detach on tab close, never kill.
  • Shared sessions: several clients can attach the same remote session at different window sizes without clamping each other; discovery shows a "shared" badge with the client count.
  • Injection-safe: every ssh command line flows through a single shell-escaping builder, and host/path/identity fields are schema-guarded.
  • Files too: previews, downloads and text reads in a remote case go over the same ssh connection (one realpath + stat probe, then a streamed cat, Range seeking included), so a clicked path opens the file on the machine the agent is on. Nothing is copied to the Codeman host; editing and Office previews answer a clear 400 instead of a misleading 404.
  • Full scrollback: loading a remote session's history reads it from the remote tmux in one bounded ssh round trip, so a session keeps its whole scrollback after a reattach or a tab switch, with no rows lost where the history meets the live screen.

Set it up under New Case → Remote (host, user, identity file, optional jump host). Full design: docs/remote-sessions.md.


Multi-User Mode (opt-in)

Share one Codeman with a small trusted team, each person getting their own login and workspace. Off by default — without the flag, nothing changes.

Enable with codeman web --multiuser (or CODEMAN_MULTIUSER=1). Create the first admin, then manage users from the CLI or the Users tab in App Settings:

bash
codeman users add alice --admin      # prompts for a password (or --password-stdin)
codeman users add bob                # a regular user
codeman users list
  • Per-user spaces — each user's cases live under ~/codeman-users/<name>/cases; sessions, cases, search, and real-time events are scoped to their owner. Admins see everything.
  • Individually revocable logins — named users with scrypt-hashed passwords in ~/.codeman/users.json; disable, reset (one-time password), or delete an account at any time. Admin actions are audited to ~/.codeman/admin-audit.jsonl.
  • Safer defaults for regular users — non-admins run Claude in --permission-mode auto (Anthropic's classifier-guarded mode); raw shell sessions, cron launchCommand, and skip-permissions require an explicit per-user grant.

⚠️ This separates workspaces; it does not sandbox users from each other. Every session runs as the same OS account, so a determined user's agent can still reach another user's files. For real isolation, pair users with Docker cases or run separate instances under separate OS accounts. See docs/multi-user-plan.md and the multi-user section of docs/security-architecture.md.


Remote Access — Cloudflare Tunnel

Access Codeman from your phone or any device outside your local network using a free Cloudflare quick tunnel — no port forwarding, no DNS, no static IP required.

Browser (phone/tablet) → Cloudflare Edge (HTTPS) → cloudflared → localhost:3000

Prerequisites: Install cloudflared and set CODEMAN_PASSWORD in your environment.

bash
# Quick start
./scripts/tunnel.sh start      # Start tunnel, prints public URL
./scripts/tunnel.sh url        # Show current URL
./scripts/tunnel.sh stop       # Stop tunnel
./scripts/tunnel.sh status     # Service status + URL

The script auto-installs a systemd user service on first run. The tunnel URL is a randomly generated *.trycloudflare.com address that changes each time the tunnel restarts.

Persistent tunnel (survives reboots)
bash
# Enable as a persistent service
systemctl --user enable codeman-tunnel
loginctl enable-linger $USER

# Or via the Codeman web UI: App Settings → System → Remote access → Cloudflare Tunnel
Authentication
  1. First request → browser shows Basic Auth prompt (username: admin or CODEMAN_USERNAME)
  2. On success → server issues a codeman_session cookie (24h TTL, auto-extends on activity)
  3. Subsequent requests authenticate silently via cookie
  4. 10 failed attempts per IP → 429 rate limit (15-minute decay)

Always set CODEMAN_PASSWORD before exposing via tunnel — without it, anyone with the URL has full access to your sessions.

QR Code Authentication

Typing a password on a phone keyboard is terrible. Codeman solves this with ephemeral single-use QR tokens — scan the code on your desktop, and your phone is instantly authenticated. No password prompt, no typing, no clipboard.

Desktop displays QR  →  Phone scans  →  GET /q/Xk9mQ3  →  Server validates
→  Token atomically consumed (single-use)  →  Session cookie issued  →  302 to /
→  Desktop notified: "Device authenticated via QR"  →  New QR auto-generated

Someone who only has the bare tunnel URL (without the QR) still hits the standard password prompt. The QR is the fast path; the password is the fallback.

How It Works

The server maintains a rotating pool of short-lived, single-use tokens. Each token consists of a 256-bit secret (crypto.randomBytes(32)) paired with a 6-character base62 short code used as an opaque lookup key in the URL path. The QR code encodes a URL like https://abc-xyz.trycloudflare.com/q/Xk9mQ3 — the short code is a pointer, not the secret itself, so it never leaks through browser history, Referer headers, or Cloudflare edge logs.

Every 60 seconds, the server automatically rotates to a fresh token. The previous token remains valid for a 90-second grace period to handle the race where you scan right as rotation happens — after that, it's dead. Each token is single-use: the moment a phone successfully scans it, the token is atomically consumed and a new one is immediately generated for the desktop display.

Security Design

The design is informed by "Demystifying the (In)Security of QR Code-based Login" (USENIX Security 2025), which found 47 of the top-100 websites vulnerable to QR auth attacks due to 6 critical design flaws across 42 CVEs. Codeman addresses all six:

USENIX FlawMitigation
Flaw-1: Missing single-use enforcementToken atomically consumed on first scan — replays always fail
Flaw-2: Long-lived tokens60s TTL with 90s grace, auto-rotation via timer
Flaw-3: Predictable token generationcrypto.randomBytes(32) — 256-bit entropy. Short codes use rejection sampling to eliminate modulo bias
Flaw-4: Client-side token generationServer-side only — tokens never leave the server until embedded in the QR
Flaw-5: Missing status notificationDesktop toast: "Device [IP] authenticated via QR (Safari). Not you? [Revoke]" — real-time QRLjacking detection
Flaw-6: Inadequate session bindingIP + User-Agent stored for audit. Manual session revocation via API. HttpOnly + Secure + SameSite=lax cookies

Timing-Safe Lookup

Short codes are stored in a Map<shortCode, TokenRecord>. Validation uses Map.get() — a hash-based O(1) lookup that reveals nothing about the target string through response timing. There is no character-by-character string comparison anywhere in the hot path, eliminating timing side-channel attacks entirely.

Rate Limiting (Dual Layer)

QR auth has its own rate limiting, completely independent from password auth:

  • Per-IP: 10 failed QR attempts per IP trigger a 429 block (15-minute decay window) — separate counter from Basic Auth failures, so a fat-fingered password doesn't burn your QR budget
  • Global: 30 QR attempts per minute across all IPs combined — defends against distributed brute force. With 62^6 = 56.8 billion possible short codes and only ~2 valid at any time, brute force is computationally infeasible regardless

QR Code Size Optimization

The URL is kept deliberately short (/q/ path + 6-char code = ~53-56 total characters) to target QR Version 4 (33x33 modules) instead of Version 5 (37x37). Smaller QR codes scan faster on budget phones — modern devices read Version 4 in 100-300ms. The /q/ prefix saves 7 bytes compared to /qr-auth/, which alone is the difference between QR versions.

Desktop Experience

The QR display auto-refreshes every 60 seconds via SSE with the SVG embedded directly in the event payload (~2-5KB) — no extra HTTP fetch, sub-50ms refresh. A countdown timer shows time remaining. A "Regenerate" button instantly invalidates all existing tokens and creates a fresh one (useful if you suspect the QR was photographed).

When someone authenticates via QR, the desktop shows a notification toast with the device's IP and browser — if it wasn't you, one click revokes all sessions.

Threat Coverage

ThreatWhy it doesn't work
QR screenshot sharedSingle-use: consumed on first scan. 60s TTL: expired before the attacker can act. Desktop notification alerts you immediately.
Replay attackAtomic single-use consumption + 60s TTL. Old URLs always return 401.
Cloudflare edge logsShort code is an opaque 6-char lookup key, not the real 256-bit token. Single-use means replaying from logs always fails.
Brute force56.8 billion combinations, ~2 valid at any time, dual-layer rate limiting blocks well before statistical feasibility.
QRLjacking60s rotation forces real-time relay. Desktop toast provides instant detection. Self-hosted single-user context makes phishing implausible.
Timing attackHash-based Map lookup — no string comparison timing leak.
Session cookie theftHttpOnly + Secure + SameSite=lax + 24h TTL. Manual revocation at POST /api/auth/revoke.

How It Compares

PlatformModelComparison
DiscordLong-lived token, no confirmation, repeatedly exploitedCodeman: single-use + TTL + notification
WhatsApp WebPhone confirms "Link device?", ~60s rotationComparable rotation; WhatsApp adds explicit confirmation (acceptable tradeoff for single-user)
SignalEphemeral public key, E2E encrypted channelStronger crypto, but exploited by Russian state actors in 2025 via social engineering despite it

Full design rationale, security analysis, and implementation details: docs/qr-auth-plan.md


Security

By default Codeman launches sessions with --dangerously-skip-permissions, so the web UI is by design a remote-code-execution surface for whoever can reach it — the whole security model exists to control who that is. (The startup permission mode is configurable; see below.) Recent hardening (v0.9.0 + v0.9.5) closes the browser-driven attack paths that bite self-hosted dev tools. Full model: docs/security-architecture.md. Found a vulnerability? See SECURITY.md for private disclosure and the list of known limitations.

Network & access

  • Loopback by default — the server binary binds 127.0.0.1, reachable only from the same machine, so the no-password default is safe out of the box (the guided installer asks about network access and configures the binding + password for you). Binding a non-loopback host without CODEMAN_PASSWORD starts but prints a loud warning with three concrete fixes (set a password, loopback + an authenticated tunnel, or explici

Similar modules

Browse Agent collaboration