
Symphony
- 6 installs
- 9 repo stars
- Updated July 13, 2026
- broomva/symphony
symphony is a Rust orchestration engine (with a Claude skill guide) that polls issue trackers and runs coding agents automatically to implement issues and open PRs.
About
symphony is a Claude skill giving expert guidance for Symphony, a Rust orchestration engine for coding agents. Symphony polls issue trackers like Linear and GitHub, creates isolated workspaces, and runs coding agents to implement issues and open PRs automatically. A developer uses it to configure WORKFLOW.md, run daemon or one-shot mode, wire lifecycle hooks, and monitor via an HTTP dashboard and Prometheus metrics. It supports adding new trackers through a TrackerClient trait.
- Rust engine that polls Linear/GitHub and runs coding agents automatically
- Creates isolated workspaces and opens PRs per issue
- Ships a control metalayer, lifecycle hooks, and Prometheus metrics
Symphony by the numbers
- 6 all-time installs (skills.sh)
- Ranked #12,825 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
symphony capabilities & compatibility
- Capabilities
- agent orchestration · issue automation · pr creation
- Works with
- github
- Use cases
- orchestration · ci cd · code review
- Runs
- Runs locally
- Pricing
- Bring your own API key
What symphony says it does
Rust orchestration engine that polls issue trackers (Linear, GitHub), creates isolated workspaces, and runs coding agents automatically.
The control metalayer (CONTROL.md) grounds all development:
Implement `TrackerClient` trait (4 methods: `fetch_candidate_issues`, `fetch_issues_by_states`, `fetch_issue_states_by_ids`, `set_issue_state`).
npx skills add https://github.com/broomva/symphony --skill symphonyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 6 |
|---|---|
| repo stars | ★ 9 |
| Last updated | July 13, 2026 |
| Repository | broomva/symphony ↗ |
What it does
Orchestrate coding agents that poll issue trackers, run in isolated workspaces, and open PRs automatically.
Who is it for?
Automating coding-agent runs against Linear or GitHub issues with PR creation.
Skip if: Teams not using an issue tracker or wanting manual, per-task agent runs only.
When should I use this skill?
Installing Symphony, configuring WORKFLOW.md, running daemon or one-shot mode, or setting up hooks and monitoring.
What you get
An engine that auto-polls trackers, runs agents in isolated workspaces, and opens PRs.
- Scaffolded WORKFLOW.md
- Running daemon that dispatches agents
- Auto-created PRs per issue
By the numbers
- Three install paths (cargo, curl|sh, docker)
- Lifecycle hooks: after_create, before_run, after_run, pr_feedback
- TrackerClient trait requires 4 methods
Files
Symphony
Rust orchestration engine that polls issue trackers (Linear, GitHub), creates isolated workspaces, and runs coding agents automatically.
Install
cargo install symphony-cli # from source
curl -fsSL https://raw.githubusercontent.com/broomva/symphony/master/install.sh | sh # binary
docker pull ghcr.io/broomva/symphony:latest # containerQuick Start
symphony init # scaffold WORKFLOW.md (Linear default)
symphony init --tracker github # GitHub Issues template
# Edit WORKFLOW.md — fill in project details, API key, repo
symphony validate WORKFLOW.md # verify config
symphony start WORKFLOW.md # run daemonCommands
| Command | Purpose |
|---|---|
symphony init [--tracker github] | Scaffold WORKFLOW.md |
symphony start [WORKFLOW.md] | Start daemon (polls tracker) |
symphony run STI-123 --workflow-path WORKFLOW.md | One-shot single issue |
symphony status | Query daemon state |
symphony issues | List running + retrying |
symphony issue STI-123 | Detail for one issue |
symphony refresh | Trigger immediate poll |
symphony stop | Graceful shutdown |
symphony validate WORKFLOW.md | Validate config + template |
symphony config WORKFLOW.md | Show resolved config |
Flags: --port, --host, --token, --format json, --concurrency, --turns, --once, --tickets STI-1,STI-2
WORKFLOW.md
YAML frontmatter (config) + Liquid template body (agent prompt). For complete reference: references/workflow-config.md.
Minimal example:
---
tracker:
kind: linear # or github
api_key: $LINEAR_API_KEY
project_slug: your-slug
codex:
command: claude --dangerously-skip-permissions
---
Fix {{ issue.identifier }}: {{ issue.title }}
{{ issue.description }}Agent Lifecycle
Poll tracker → fetch active issues → sort by priority → dispatch workers
├─ after_create hook (clone repo)
├─ before_run hook (rebase)
├─ render prompt + run agent (max_turns)
├─ after_run hook (commit, push, create PR)
├─ pr_feedback hook (capture review comments)
├─ done_state transition (auto-close issue)
└─ retry (1s continuation / exponential backoff)Control Metalayer
The control metalayer (CONTROL.md) grounds all development:
CHECK setpoints → IMPLEMENT → MEASURE (make smoke) → VERIFY → DOCUMENT → FEEDBACKSet up: create CONTROL.md with setpoints, add sensors in Makefile, reference in agent prompt.
Extending
Implement TrackerClient trait (4 methods: fetch_candidate_issues, fetch_issues_by_states, fetch_issue_states_by_ids, set_issue_state). Register in create_tracker() factory.
Key Environment Variables
| Variable | Purpose |
|---|---|
LINEAR_API_KEY | Linear API auth |
GITHUB_TOKEN | GitHub API auth |
ANTHROPIC_API_KEY | Claude Code auth |
SYMPHONY_API_TOKEN | Symphony HTTP API auth |
SYMPHONY_PORT | HTTP server port |
Troubleshooting
See references/troubleshooting.md for auth failures, stuck retries, hook errors, missing PRs, and monitoring setup.
Symphony Troubleshooting
Common Issues
"Not logged in · Please run /login"
Cause: Claude Code CLI not authenticated in the environment. Fix: Set ANTHROPIC_API_KEY in the environment where Symphony runs.
export ANTHROPIC_API_KEY=sk-ant-...For Docker/Railway: add as environment variable in the service config.
Agent exits immediately (exit code 1)
Cause: The codex.command binary not found or not executable. Fix: Verify the command works standalone:
claude --version # must be installed and in PATH"tracker.api_key is required (after $VAR resolution)"
Cause: Environment variable not set. Fix: Export the variable before running:
export LINEAR_API_KEY=lin_api_... # for Linear
export GITHUB_TOKEN=ghp_... # for GitHub"unsupported_tracker_kind"
Cause: tracker.kind is not "linear" or "github". Fix: Check WORKFLOW.md frontmatter for typos.
Hooks failing with permission errors
Cause: gh CLI not authenticated. Fix: Run gh auth login in the environment. For Docker, mount ~/.config/gh/.
Issues stuck in retry (attempt 30+)
Cause: Agent keeps failing on the same issue. Fix: 1. Check logs: symphony logs --id STI-123 2. Common causes: agent auth, repo clone failure, test failures 3. Reduce max_turns to avoid burning tokens 4. Move the issue to a terminal state in the tracker to stop retries
PR not auto-created
Cause: after_run hook doesn't include PR creation. Fix: Add to hooks section:
after_run: |
git add -A && git commit -m "$SYMPHONY_ISSUE_ID: changes" || true
git push -u origin "symphony/$SYMPHONY_ISSUE_ID" --force-with-lease || true
gh pr view "symphony/$SYMPHONY_ISSUE_ID" --json state >/dev/null 2>&1 || \
gh pr create --base main --head "symphony/$SYMPHONY_ISSUE_ID" \
--title "$SYMPHONY_ISSUE_ID: $SYMPHONY_ISSUE_TITLE" \
--body "Automated by Symphony" || trueWorkspace path errors
Cause: workspace.root doesn't exist or uses unsupported path. Fix: Create the directory first, use absolute paths or ~:
mkdir -p ~/symphony-workspaces/projectMonitoring
HTTP Dashboard
http://localhost:8080 # HTML dashboard
http://localhost:8080/healthz # liveness (always 200)
http://localhost:8080/readyz # readiness (200 when initialized)
http://localhost:8080/metrics # Prometheus text formatAPI Endpoints (require SYMPHONY_API_TOKEN if set)
GET /api/v1/state # system summary JSON
GET /api/v1/{identifier} # single issue detail
GET /api/v1/workspaces # list workspaces
GET /api/v1/metrics # usage metrics JSON
POST /api/v1/refresh # trigger immediate poll
POST /api/v1/shutdown # graceful shutdownPrometheus Metrics
symphony_tokens_input_total
symphony_tokens_output_total
symphony_tokens_total
symphony_agent_seconds_total
symphony_sessions_running
symphony_sessions_retrying
symphony_issues_claimed
symphony_issues_completed
symphony_config_poll_interval_ms
symphony_config_max_concurrent_agentsWORKFLOW.md Configuration Reference
Structure
WORKFLOW.md has YAML frontmatter (config) + Liquid template body (agent prompt):
---
# YAML config
tracker:
kind: linear
...
---
Agent prompt with {{ issue.identifier }} template variablesTracker Section
Linear
tracker:
kind: linear
api_key: $LINEAR_API_KEY # env var expansion with $
endpoint: https://api.linear.app/graphql # default
project_slug: 71c211385593 # from Linear project URL
active_states: [Todo, In Progress]
terminal_states: [Done, Canceled, Duplicate]
done_state: Done # optional: auto-transition on successGitHub Issues
tracker:
kind: github
api_key: $GITHUB_TOKEN
project_slug: owner/repo # owner/repo format
active_states: [open] # labels can match too
terminal_states: [closed]
done_state: closed # optional: auto-close on successGitHub state mapping: if an issue has a label matching an active_states entry, that label is used as the state. Otherwise GitHub's native open/closed.
Polling Section
polling:
interval_ms: 30000 # poll every 30s (default)Workspace Section
workspace:
root: ~/symphony-workspaces/project # ~ and $VAR expandedHooks Section
hooks:
after_create: | # runs once on workspace creation (fatal on failure)
gh repo clone org/repo . -- --depth 50
git checkout -b "symphony/$SYMPHONY_ISSUE_ID"
before_run: | # runs before each turn (fatal on failure)
git fetch origin main && git rebase origin/main || git rebase --abort
after_run: | # runs after each turn (failure ignored)
git add -A && git commit -m "$SYMPHONY_ISSUE_ID: changes" || true
git push -u origin "symphony/$SYMPHONY_ISSUE_ID" --force-with-lease || true
before_remove: | # runs before workspace cleanup (failure ignored)
echo "cleaning up"
pr_feedback: | # captures stdout as PR review feedback for next turn
PR_NUM=$(gh pr view "symphony/$SYMPHONY_ISSUE_ID" --json number -q '.number' 2>/dev/null)
if [ -n "$PR_NUM" ]; then
gh api "repos/org/repo/pulls/$PR_NUM/comments" \
--jq '.[] | "**\(.user.login)**: \(.body)"' 2>/dev/null
fi
timeout_ms: 180000 # 3 min hook timeout (default: 60s)Hook env vars: $SYMPHONY_ISSUE_ID, $SYMPHONY_ISSUE_TITLE
Agent Section
agent:
max_concurrent_agents: 3 # parallel workers (default: 10)
max_turns: 5 # turns per issue (default: 20)
max_retry_backoff_ms: 300000 # max retry delay (default: 5min)
max_concurrent_agents_by_state:
todo: 1 # per-state concurrency limits
in progress: 2Codex Section
codex:
command: claude --dangerously-skip-permissions
turn_timeout_ms: 3600000 # 1hr per turn
read_timeout_ms: 5000 # handshake timeout
stall_timeout_ms: 300000 # inactivity kill timeoutServer Section
server:
port: 8080 # HTTP dashboard + APITemplate Variables
Available in the Liquid prompt body:
| Variable | Type | Description |
|---|---|---|
issue.identifier | string | e.g. "STI-123" |
issue.title | string | Issue title |
issue.description | string? | Issue body (may be null) |
issue.state | string | Current state |
issue.priority | int? | Priority (lower = higher) |
issue.labels | string[] | Lowercase labels |
issue.url | string? | Issue URL |
issue.blocked_by | object[] | Blocker references |
attempt | int? | Retry attempt (null on first run) |
Related skills
FAQ
Which trackers does it support?
Linear and GitHub Issues out of the box, and new trackers can be added by implementing the TrackerClient trait.
How do I run a single issue?
Use symphony run STI-123 --workflow-path WORKFLOW.md for one-shot single-issue mode.