Coding Agents

Coding agents run alongside a workspace and report their lifecycle to Spaces, so you always know which one is waiting for you next.

What Is a Coding Agent?

A coding agent is a tool like Claude Code, Codex, or opencode that you run in a terminal to help you write code. Spaces tracks each agent as a row in the workspace so you can focus its terminal by shortcut and see at a glance whether it is working, blocked on you, or done.

  • • Run one in any workspace terminal; Spaces attaches it to the workspace when it reports an event or its process is detected running.
  • • Rows render under Coding Agents in the workspace, after browser and process rows.

Lifecycle Events

Agents report their own state through spaces agent signal <event>. In a Spaces-managed terminal, the command reads the workspace and session from environment; outside one, it exits successfully without reporting an event. Spaces uses each event to update the agent row. Both blocked and done raise Alerts and dock attention; blocked clears when the agent's state changes, while done stays in Alerts until you dismiss it.

  • init — identify the terminal and attach it to a tracked row.
  • working — agent is working; row shows a spinner.
  • blocked — agent is blocked on you; row shows a warning and raises attention.
  • done — agent finished; row shows a green dot and raises attention until dismissed.
  • exit — agent ended; row returns to idle, or is removed if the terminal is gone.

Events are accepted only from Spaces-managed terminal sessions. Start agents in a workspace terminal opened by Spaces so the session can be tracked and focused reliably. Events after init update the row that init created or attached; a foreground process Spaces recognizes as a known agent can also establish the row before the monitor tick runs.

Setting Up Hooks

Spaces sets these lifecycle hooks up for you, but never behind your back: it asks first. On first launch it offers to install spaces agent signal hooks for every supported agent CLI it detects — Claude Code in ~/.claude/settings.json, Codex in ~/.codex/hooks.json, and opencode as a plugin in ~/.config/opencode/plugin/. You can skip that step and install later, or never. Each hook calls the Spaces CLI by the absolute path found when the hooks were installed, so it runs no matter what PATH your agent hands it; if you move or reinstall the CLI, reinstall the hooks from Settings → Coding Agents. The command only reports from Spaces-managed terminals and does nothing anywhere else, so nothing else in your setup changes.

Installation preserves your existing hooks and settings and never duplicates an entry, so it is safe to run again. If a later Spaces release changes the hooks it installs, your agents show as out of date and Spaces offers to update them once — updating replaces the old hooks rather than adding to them.

Agents install independently, so one that Spaces will not touch — a Codex config.toml that already defines features in a shape Spaces refuses to rewrite, say — does not stop the others. That agent's row explains what stopped it.

Managing Hooks in Settings

Open Settings → Coding Agents to see, for This Mac or any paired remote, which supported agent CLIs are detected and whether their Spaces hooks are installed, out of date, or missing. Detected agents have an Install, Update, or Reinstall button; unsupported or missing CLIs remain visible without an install action.

Manual Setup

You normally never need this — Spaces installs and manages the hooks for you. If you want to configure an agent by hand, paste one of these prompts into it. Both preserve any existing hooks and only add the Spaces entries. Claude Code edits ~/.claude/settings.json; Codex edits ~/.codex/config.toml to enable hooks and adds the lifecycle entries. Codex has no session-end event, so its setup omits exit.

Add global Spaces lifecycle hooks to ~/.claude/settings.json so this agent
reports its state to Spaces.

  SessionStart      ->  '/usr/local/bin/spaces' agent signal init >/dev/null 2>&1 || true # spaces-agent-hook v1
  UserPromptSubmit  ->  '/usr/local/bin/spaces' agent signal working >/dev/null 2>&1 || true # spaces-agent-hook v1
  Stop              ->  '/usr/local/bin/spaces' agent signal done >/dev/null 2>&1 || true # spaces-agent-hook v1
  PermissionRequest ->  '/usr/local/bin/spaces' agent signal blocked >/dev/null 2>&1 || true # spaces-agent-hook v1
  SessionEnd        ->  '/usr/local/bin/spaces' agent signal exit >/dev/null 2>&1 || true # spaces-agent-hook v1

Use an empty matcher ("") for every entry. Do not add or remove any
other keys. Replace '/usr/local/bin/spaces' with the absolute path to my
spaces CLI. These hooks run quietly, ignore transient Spaces failures,
and keep the # spaces-agent-hook v1 marker.
After writing the file, show me the diff.
Enable Codex hooks with [features].hooks in ~/.codex/config.toml and add global Spaces lifecycle hooks so this agent
reports its state to Spaces.

  SessionStart      ->  '/usr/local/bin/spaces' agent signal init >/dev/null 2>&1 || true # spaces-agent-hook v1
  UserPromptSubmit  ->  '/usr/local/bin/spaces' agent signal working >/dev/null 2>&1 || true # spaces-agent-hook v1
  Stop              ->  '/usr/local/bin/spaces' agent signal done >/dev/null 2>&1 || true # spaces-agent-hook v1
  PermissionRequest ->  '/usr/local/bin/spaces' agent signal blocked >/dev/null 2>&1 || true # spaces-agent-hook v1

Use an empty matcher ("") for every entry. Do not add or remove any
other keys. Replace '/usr/local/bin/spaces' with the absolute path to my
spaces CLI. These hooks run quietly, ignore transient Spaces failures,
and keep the # spaces-agent-hook v1 marker.
After writing the file, show me the diff.

Orchestrate Agents From One Terminal

Once agents report their state, one agent — or you at a single terminal — can drive the others. spaces agent list and spaces agent status show every agent and whether it is working, blocked, or done, and spaces agent annotate leaves a short note on one so you remember what it was doing. Each row includes a clickable spaces://terminal/<id> link that jumps straight to that agent's pane.

  • Start one that's ready. spaces agent spawn --command claude opens a supported agent (Claude Code, Codex, or opencode) in a new workspace terminal and waits until Spaces detects it running before returning — no hooks required. Spawn sends no prompt of its own; deliver the first prompt with spaces terminal send once it returns.
  • Get told when one needs you. spaces agent subscribe watches a child agent from your terminal; when it goes blocked, done, or exits, Spaces drops a single line into your terminal with a link to open it — only while you are idle, so it never lands mid-task.
  • Steer or stop it. spaces terminal send types into a child — a follow-up turn, an answer, or a keystroke such as Escape. What a key does is up to the agent's own interface, so a keystroke never changes what Spaces says the agent is doing; only the agent's own reports do. spaces agent kill ends it and its terminal outright.
  • Across devices. These commands take --device to drive agents on a paired Mac or Linux box, and the same actions are available to an MCP client such as Claude Code (agent lifecycle signals stay off the tool surface, so an agent can read another's state but never forge it).

See Also

  • CLI Reference — full flag list for spaces agent signal.
  • Processes — how agents launched as processes share the process runtime.
  • Window Management — how tracked agent terminals become focusable by shortcut.