
Security News
White House Authorizes Private Companies to Conduct Offensive Cyber Operations
A new federal program will let vetted U.S. cybersecurity firms help investigate and disrupt foreign cybercrime groups under government direction.
@ghostlygawd/symphony
Advanced tools
Claude Code-native orchestration: turn an issue tracker into autonomous, isolated implementation runs. Runs on a Claude subscription — no API key required.
Claude Code-native orchestration — turn an issue board into autonomous, isolated implementation runs.
Symphony watches an issue tracker, gives every open task its own isolated workspace and a Claude Code agent, lets those agents work autonomously, and surfaces the results for you to review. You manage work, not coding agents.
It runs on your Claude subscription through the claude CLI you already use. No ANTHROPIC_API_KEY required.
This is an independent, Claude-native implementation of the open-source Symphony spec (originally published by OpenAI for Codex, Apache-2.0). It is not affiliated with OpenAI or Anthropic. See NOTICE.
The original Symphony is an orchestration spec: Linear is the state machine, the coding agent is the worker, PRs are the output. Symphony polls the board, spins up an isolated run per ticket, restarts agents that crash, and keeps going until the work leaves the active states.
This implementation keeps that model but is built for Claude Code:
claude CLI you use interactively, so it authenticates with your Pro/Max subscription. The init event literally reports apiKeySource: "none". No API keys, no separate billing.npx-able. A built-in local file tracker means you can go from clone to a running orchestrator in under a minute with nothing but Claude Code installed.WORKFLOW.md), polling orchestrator with bounded concurrency, per-issue workspaces with lifecycle hooks, exponential-backoff retries, stall detection, tracker-state reconciliation, dynamic reload, and an optional status dashboard.Prerequisites: Node.js ≥ 18 and Claude Code installed and logged in (claude auth login).
Once published, the fastest path is npx — no clone, no install:
# 1. Scaffold a board + WORKFLOW.md in your project
cd /path/to/your/project
npx @ghostlygawd/symphony init
# 2. Check your environment (Claude Code present? logged in? config valid?)
npx @ghostlygawd/symphony doctor
# 3. Run it — opens a live dashboard at http://127.0.0.1:4173
npx @ghostlygawd/symphony start --port 4173
Prefer to run from a clone of this repo:
# 1. Get Symphony (from this repo)
git clone https://github.com/ghostlygawd/symphony-clone.git
cd symphony-clone
npm link # makes the `symphony` command available (optional)
# 2. Scaffold a board + WORKFLOW.md in your project
cd /path/to/your/project
symphony init
# 3. Check your environment (Claude Code present? logged in? config valid?)
symphony doctor
# 4. Run it — opens a live dashboard at http://127.0.0.1:4173
symphony start --port 4173
No global install? Run it directly:
node /path/to/symphony-clone/bin/symphony.js start --port 4173
That's it. Symphony will pick up every Todo issue from .symphony/issues/, give each its own workspace and a Claude Code agent, and run them in parallel. Edit an issue's state: (or let the agent do it) to move it through your workflow.
symphony start --once runs a single tick, lets the dispatched agents finish, and prints a snapshot — perfect for trying it out or for CI/cron:
symphony start --once
This is exactly the flow used to verify Symphony end-to-end: a real Claude Code agent picked up SYM-1, created WELCOME.md in its isolated workspace, transitioned the issue to In Review, and the orchestrator recorded the token usage and cost — all on a subscription with no API key.
WORKFLOW.md (YAML config + prompt template)
│ (hot-reloaded on change)
▼
┌──────────────┐ ┌───────────────────────────────────────────────┐
│ Issue tracker │◀────│ Orchestrator │
│ local/github/ │ │ poll → reconcile → retry queue → dispatch │
│ linear │────▶│ (bounded concurrency, stall detection) │
└──────────────┘ └───────────────┬───────────────────────────────┘
▲ state │ one worker per issue
│ transitions ▼
│ ┌──────────────────────┐
│ │ Workspace Manager │ per-issue dir +
│ │ after_create/before_ │ lifecycle hooks
│ │ run/after_run hooks │
│ └──────────┬────────────┘
│ ▼
│ ┌──────────────────────┐ claude -p
└───── agent edits ─────│ Claude Code agent │ --output-format
board / opens PR │ (subscription auth) │ stream-json
└──────────────────────┘
Each tick the orchestrator:
WORKFLOW.md if it changed on disk (no restart needed).A worker, in turn, creates the workspace, runs before_run, then runs Claude Code turn-by-turn (resuming the same session for continuations) — re-checking the tracker between turns — until the issue leaves the active states or max_turns is hit.
Handoff, not "Done". A successful run typically ends at a review state (e.g.
In Review), notDone. The agent does the work and hands it back to a human. Symphony stops working an issue the moment it leaves the active states.
WORKFLOW.mdA single Markdown file with YAML front matter (the config) and a Markdown body (the prompt template). The full default is created by symphony init; here's the shape:
---
tracker:
kind: local # local | github | linear
dir: .symphony/issues
active_states: [Todo, "In Progress"]
terminal_states: [Done, Cancelled]
polling:
interval_ms: 10000
workspace:
root: .symphony/workspaces
hooks:
after_create: | # runs once when a workspace is created
[ -n "$SYMPHONY_PROJECT_DIR" ] && cp -R "$SYMPHONY_PROJECT_DIR"/. .
before_run: | # runs before each agent attempt
npm install
timeout_ms: 120000
agent:
max_concurrent_agents: 3
max_turns: 8
permission_mode: bypassPermissions # full autonomy (sandboxed envs only)
claude:
command: claude
# model: sonnet
stall_timeout_ms: 300000
---
You are an autonomous engineer working on {{ issue.identifier }}: {{ issue.title }}.
{{ issue.description }}
{% if attempt %}This is a continuation (turn {{ attempt }}).{% endif %}
When finished, edit `{{ issue_file }}` and set its `state:` to `In Review`, then stop.
The prompt template supports {{ variable }}, {% if %}/{% elsif %}/{% else %}, {% for x in list %}, and filters (default, upcase, downcase, join, length, truncate). Available variables: issue (all fields + labels/blocked_by), attempt, turn, max_turns, issue_file, board_dir, project_dir.
Run symphony validate to check it. See docs/configuration.md for every setting and default.
Every hook and agent run is given these environment variables: SYMPHONY_ISSUE_ID, SYMPHONY_ISSUE_IDENTIFIER, SYMPHONY_ISSUE_TITLE, SYMPHONY_ISSUE_STATE, SYMPHONY_ISSUE_FILE, SYMPHONY_BOARD_DIR, SYMPHONY_PROJECT_DIR, SYMPHONY_WORKSPACE.
| Tracker | State lives in | Auth | Out of the box? |
|---|---|---|---|
| local (default) | Markdown files in .symphony/issues/ | none | ✅ yes |
| github | GitHub issue + a status:<state> label | GITHUB_TOKEN | needs a token |
| linear | Linear workflow states | LINEAR_API_KEY | needs a key |
With the local tracker, each issue is a Markdown file with front matter (identifier, title, state, priority, labels, blocked_by) and a Markdown body (the description). State transitions are just edits to state: — which the agent performs as part of its run. Fully local, no external service. See docs/trackers.md.
All three trackers can transition an issue, not just read it: the agent (or symphony move) swaps a GitHub status:<state> label and closes/reopens the issue, or moves a Linear workflow state. For a real-repo clone → branch → PR workflow driven by GitHub Issues, see the worked example in examples/github-pr/.
Symphony never asks for an API key. It launches claude exactly as you would interactively, so it uses whatever the CLI is logged in with:
claude auth login (or claude setup-token).ANTHROPIC_API_KEY happens to be set in your environment, Claude Code will use it (API billing). To force subscription usage, unset it — or set claude.unset_api_key: true in WORKFLOW.md and Symphony will drop it for the agent processes.symphony doctor tells you which mode you're in. More in docs/claude-code.md.
Autonomous agents that edit files and run commands are powerful — and a footgun outside a sandbox. Symphony makes the trust boundary explicit:
permission_mode: acceptEdits (the code default) auto-accepts file edits but limits command execution.permission_mode: bypassPermissions gives the agent full autonomy (the default in the scaffolded WORKFLOW.md). Use it only in isolated/sandboxed environments — containers, CI runners, VMs, or throwaway machines. When Symphony runs as root in a container it automatically sets IS_SANDBOX=1 so this works.workspace.root; the agent's working directory is validated before launch.$VAR indirection and are never logged.Recommended hardening: run Symphony in a container with scoped credentials and a restricted network, filter which labels/projects are eligible, and keep max_concurrent_agents sane for your budget.
The repo ships a Dockerfile and docker-compose.yml so you get that sandbox out of the box — Node 22, the Claude Code CLI, and Symphony, with IS_SANDBOX=1 set so bypassPermissions is honored safely inside the container:
# Mounts the current repo into /work and your Claude login (read-only)
docker compose up # dashboard at http://127.0.0.1:4173
Use your Claude subscription (mount ~/.claude read-only or claude setup-token); keep ANTHROPIC_API_KEY unset. Full guide — credentials and network-egress posture — in docs/sandbox.md.
symphony init [dir] Scaffold WORKFLOW.md + an example local board
symphony start Run the orchestrator (poll the tracker, dispatch agents)
--port <n> Serve the live dashboard
--host <addr> Dashboard bind address (default 127.0.0.1; non-loopback requires a token)
--once Run a single tick, wait for workers, print a snapshot, exit
--verbose Debug logging
symphony status Show a runtime snapshot (from a running server, or one-shot)
symphony validate Load and validate WORKFLOW.md
symphony doctor Check your environment (Claude Code, auth, config)
symphony move <id> <st> Transition an issue's state — local, github, or linear (handoff helper)
symphony version | help
--workflow <path> Use a specific WORKFLOW.md (default ./WORKFLOW.md)
Watch it from your phone. Set
SYMPHONY_DASHBOARD_TOKEN(orserver.auth_tokeninWORKFLOW.md) to put a login on the dashboard, then expose127.0.0.1:4173through a tunnel (ngrok / Cloudflare / Tailscale) and openhttps://<tunnel-url>/?token=YOUR_TOKEN. Symphony refuses to bind a non-loopback address without a token. Full recipe: docs/remote-access.md.
| OpenAI Symphony | This project |
|---|---|
Coding agent: Codex app-server subprocess | Claude Code: claude -p --output-format stream-json |
| Auth: Codex / API | Claude subscription via the CLI (no API key) |
| Reference impl: Elixir/BEAM | Node.js (zero deps), tested with node --test |
| Tracker: Linear | local (default) · GitHub · Linear |
linear_graphql client-side tool | agent edits the board via an auto --add-dir, or symphony move |
WORKFLOW.md, polling loop, concurrency, retries, stall detection, reconciliation, dynamic reload, snapshot API | ✅ all implemented |
See SPEC.md for the Claude-native specification.
npm test # run the full suite (node --test), zero dependencies
The suite is the gate. A git pre-push hook (.githooks/pre-push) runs node --test before every push and blocks on failure; npm install wires it automatically (or run git config core.hooksPath .githooks once). GitHub Actions (.github/workflows/test.yml) is manual-only (Actions-minutes), triggerable from the Actions tab.
The codebase is small and readable: src/yaml.js (mini YAML), src/workflow.js (config), src/template.js (prompt rendering), src/trackers/*, src/workspace.js, src/agent/claude.js (the Claude Code adapter), src/runner.js, src/orchestrator.js, src/server.js, src/cli.js.
The original follow-up backlog — GitHub & Linear state-transition write paths, a real-repo clone→branch→PR example, a publishable npx release, a sandboxed container image, and a gated live test (BL-1…BL-6) — is now implemented. See docs/BACKLOG.md for per-item status and the remaining nice-to-haves (durable runtime state, per-issue cost caps, webhook-driven polling, dashboard per-issue drill-down).
Apache-2.0. Not affiliated with OpenAI or Anthropic; see NOTICE.
FAQs
Claude Code-native orchestration: turn an issue tracker into autonomous, isolated implementation runs. Runs on a Claude subscription — no API key required.
The npm package @ghostlygawd/symphony receives a total of 2 weekly downloads. As such, @ghostlygawd/symphony popularity was classified as not popular.
We found that @ghostlygawd/symphony demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A new federal program will let vetted U.S. cybersecurity firms help investigate and disrupt foreign cybercrime groups under government direction.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.