Skip to main content

Local Agent Runtime

Specter runs coding agents on your machine, with your own CLIs and your own credentials. This page describes how a workflow node reaches an agent, and what stands between that agent and the rest of your filesystem.

:::caution The host runner is gone — and containerized runs need it back

Earlier versions ran a separate Python process on localhost:8765. The containerized backend had no agent binary and no credentials, so it posted to that process over HTTP and the process spawned the agent.

specter serve spawns agents itself when it runs on your host. There is no second process to start, no port to bind, and no bridge to keep alive.

That does not hold in Docker. A container has no agent binary and no credentials, so a containerized Specter currently cannot execute a workflow at all. The bridge is being restored as specter agent-host — a subcommand of the same binary rather than a separate program — so the app can stay contained while only agent execution happens on the host: #49.

The URL of this page is unchanged so existing links still resolve.

:::

How a node reaches an agent​

flowchart TD
Browser[Browser UI] -->|localhost| App[specter serve]
CLI[specter run] --> Engine
App --> Engine[Execution engine]
Engine -->|git worktree per run| Worktree[Isolated checkout]
Engine -->|sandbox-exec / bwrap| Agent[Agent CLI: claude, codex, cursor, gemini]
Agent --> Worktree
Engine -. writes .-> State[(Workflows, approvals, runs, audit trail)]

specter serve and specter run are the same binary with different entry points, so a run started from the terminal and a run started from the browser execute identical code. Both write to one database, which is why a CLI-started run appears in the web UI without the two processes ever talking to each other.

What runs where​

ComponentResponsibility
Browser UIRuntime status, approvals, run output, captured artifacts.
specter serveServes the API and the web UI, and executes workflow runs.
specter runExecutes a workflow in your terminal. No server needed.
Execution engineAgent detection, workspace allowlist, subprocess spawn, streaming, timeouts, cancellation.
Agent CLIYour own install, with your own credentials. Never bundled.

Agent CLIs are detected, never installed​

Specter does not install agent CLIs and does not hold their credentials. Run:

specter status

It reports which of claude, codex, cursor and gemini are on this machine, whether git and gh are present and what each one enables, which confinement mechanism is active, and which repositories are approved.

Detection deliberately searches more than PATH. Under launchd, PATH is /usr/bin:/bin:/usr/sbin:/sbin and every Homebrew-installed agent is invisible, so the usual install roots are searched as well.

Confinement​

An agent runs inside an OS-level sandbox — sandbox-exec on macOS, bwrap on Linux — that denies writes outside the run's worktree and denies reads of ~/.ssh, ~/.aws, ~/.gnupg and ~/.kube entirely.

This is defence in depth, and the layering matters. Each agent CLI has its own permission flag (--permission-mode plan, --sandbox read-only), but those are advisory — an agent can shell out past its own flag. The OS boundary cannot be shelled past.

Where no mechanism is available, the run reports mechanism: none rather than claiming confinement it does not have. An unconfined run that reads as confined is worse than one that admits it. To refuse instead of warning:

SPECTER_REQUIRE_CONFINEMENT=1 specter run <workflow>

A worktree per run​

Each run gets its own git worktree, not the repository you are working in. A bad run costs a discarded directory rather than your uncommitted work.

A worktree rather than a copy because it is nearly free — git shares the object store — and because it produces a real branch. That branch is what lets a read-write run arrive as a pull request instead of as edits already applied to your tree. Read-only runs detach at HEAD; a non-git directory falls back to a copy and says so in the run metadata rather than behaving differently in silence.

Worktrees live under ~/.specter/runs/. A failed run keeps its checkout so the failure can be inspected.

Approved workspaces​

A run against a path that is not on the allowlist is refused before any agent is spawned. Add repositories on the Connectors / Workspaces page in the web UI.

A missing allowlist rejects rather than allowing everything — a missing config is not consent.

Docker Sandbox​

Docker Sandboxes (sbx) remain available as an additional isolation layer for agent work, keeping model-driven commands inside a disposable microVM. See Docker Sandbox for setup.

Auto-start on login (macOS)​

The service supervises specter serve — the server itself, since there is no longer a separate runner to keep alive. Install it from the Models page, or:

launchctl load -w ~/Library/LaunchAgents/com.specter.agent.plist

Key properties: KeepAlive restarts on crash, RunAtLoad starts on login, ThrottleInterval prevents tight restart loops. Logs go to /tmp/specter-agent.log.

The Models page exposes Install, Restart and Remove, so day-to-day management needs no terminal.

Guardrails​

These hold regardless of which agent runs:

  • Require an allowlisted workspace before spawning any agent.
  • Never mount or copy an agent's credential directory (~/.codex, ~/.claude) into a container.
  • Never store agent access tokens or API keys in Specter's runtime data.
  • Require explicit approval for external writes, destructive commands, publishing, and repository changes that cross the configured policy boundary.
  • Capture command, workspace, start time, exit status, output summary and produced artifacts for audit.
  • Enforce subprocess timeouts, output limits and cancellation. Cancelling a running node kills the subprocess rather than orphaning it.