{"slug": "show-hn-rust-implementation-of-symphony", "title": "Show HN: Rust Implementation of Symphony", "summary": "Symphony, a desktop app that automates software engineering by dispatching coding agents to work on Linear issues, has been released as an open-source Rust implementation. The app polls Linear boards, creates isolated workspaces, and runs agents like OpenAI Codex or Claude Code to implement features or fix bugs, with human triage and review. It runs locally, stores data in SQLite, and is available for macOS with Apple Silicon.", "body_md": "**An autonomous engineering team for your Linear project.** Symphony is a desktop app that watches your Linear board and dispatches coding agents — [Codex](https://github.com/openai/codex) or [Claude Code](https://claude.com/claude-code) — to work on issues, each in its own freshly cloned workspace. You triage and review; Symphony orchestrates. Based on the [spec](https://github.com/openai/symphony/blob/main/SPEC.md) from OpenAI.\n\n** ⬇ Download for macOS** (Apple Silicon) ·\n\n**Poll**— a local worker polls Linear for issues in the states you mark as active (e.g.`Todo`\n\n,`In Progress`\n\n,`Rework`\n\n).**Prepare**— for each issue, Symphony creates an isolated workspace and runs your`after_create`\n\nhook (typically`git clone`\n\n+ dependency install).**Dispatch**— it renders your prompt template with the issue's identifier, title, state, and description, then drives a Codex or Claude Code session natively over their structured event streams.**Track**— agent events, token counts, retries, failures, and provider rate-limit signals are recorded in a local SQLite database and streamed live to the dashboard.**Retry**— failed runs are retried with exponential backoff, and the retry prompt includes the previous run's error context.\n\nEverything runs on your machine. The only network calls are to Linear's API and whatever your agents and hooks do.\n\n**macOS**(primary target; Tauri builds for other platforms are untested)- A\n[Linear](https://linear.app)workspace and a[personal API key](https://linear.app/settings/account/security) - At least one agent CLI installed and authenticated:\n`codex`\n\n— OpenAI Codex CLI`claude`\n\n— Claude Code CLI\n\n`git`\n\n, plus whatever your repository's install step needs\n\n** Download Symphony.dmg** — the latest signed and notarized build for macOS (Apple Silicon). Open it, drag\n\n**Symphony** to Applications, and launch.\n\nOr build and run from source:\n\n```\ngit clone https://github.com/anantjain-xyz/symphony-rust.git\ncd symphony-rust\npnpm install\npnpm tauri dev      # or: pnpm tauri build\n```\n\nSee [Building](#building) for production bundles and signed releases.\n\nOn first launch the Overview shows a setup checklist:\n\n**Connect Linear**— paste your API key in*Settings → Linear*. It is stored in the macOS keychain, never on disk.**Add your repositories**— one or more Git URLs; each run clones the repo its issue routes to.** Start the worker**— the ▶ button in the top bar. Symphony begins polling and dispatching.\n\nOptional Linear filters (workspace slug, project ID, identifier prefix like `ENG`\n\n) narrow which issues Symphony picks up. Use **Validate** in Settings to check your configuration and confirm the agent CLIs are discoverable before starting.\n\nSymphony's behavior is configured entirely in *Settings* — no config file to edit:\n\n**Repositories**— the Git repos runs clone, each with its own install command, plus where per-run workspaces are created (one folder per repo, then per issue). With several repos configured, every issue routes to exactly one, first match wins: a`repo:<name>`\n\nlabel on the issue in Linear, then the repo claiming the issue's Linear project, then the repo claiming its team key (e.g.`ENG`\n\n), then the repo marked*default*. An issue whose`repo:`\n\nlabel matches no configured repo is skipped — an explicit label is never silently rerouted. Every run records the repo it was dispatched to; with several repos configured the dashboard tags runs with it and the Runs view can filter by repo.**Linear**— API key (keychain), optional workspace/project/team filters, and the workflow states that drive dispatch: issues in an*active state*(e.g.`Todo`\n\n,`In Progress`\n\n,`Rework`\n\n,`Merging`\n\n) get an agent; issues in a*terminal state*(e.g.`Done`\n\n,`Canceled`\n\n) are left alone.**Agent**— which CLI runs issues (`codex`\n\nor`claude`\n\n), an optional launch command (wrappers with arguments like`mycode --agent claude`\n\nare fine; Symphony appends its own flags), the per-turn timeout, and the backend's sandbox/permission options: approval policy, thread sandbox, and network access for Codex; permission mode and allowed/disallowed tool rules for Claude Code.**Worker**— polling interval, max concurrent agents, retry backoff cap, and the lifecycle hooks (under*Hooks (advanced)*):`after_create`\n\n,`before_run`\n\n,`after_run`\n\n,`before_remove`\n\n. Hooks are shell scripts that run in the workspace with`$REPO_URL`\n\n,`$REPO_NAME`\n\n,`$ISSUE_ID`\n\n,`$ISSUE_IDENTIFIER`\n\n,`$ISSUE_TITLE`\n\n,`$ISSUE_STATE`\n\n,`$ISSUE_BRANCH`\n\n,`$RUN_NUMBER`\n\n,`$SYMPHONY_INSTALL_CMD`\n\n, and`$SYMPHONY_HOOK`\n\nin their environment; the repo variables reflect the repo the issue routed to.\n\nThe **prompt template** at the bottom of Settings is the instruction document sent to the agent for each issue. Placeholders in `{{...}}`\n\nform are rendered from the Linear issue when a run starts; the reference panel next to the editor lists them and inserts one at the cursor on click:\n\n| Placeholder | Renders as |\n|---|---|\n`{{issue.id}}` |\nInternal Linear ID |\n`{{issue.identifier}}` |\nIssue key, e.g. `SYM-42` |\n`{{issue.title}}` |\nIssue title |\n`{{issue.description}}` |\nFull issue body (empty if none) |\n`{{issue.state}}` |\nCurrent Linear state |\n`{{issue.branch}}` |\nGit branch from Linear (may be empty) |\n`{{issue.labels}}` |\nLabels, comma-separated |\n`{{issue.blockers}}` |\nBlocking issue identifiers, one `- <id>` bullet per line |\n`{{repo.name}}` |\nName of the repo the issue routed to |\n`{{repo.url}}` |\nGit URL of the routed repo |\n\nRetried runs automatically get a `## Retry context`\n\nsection appended with the prior run's error and recent events.\n\n- Your Linear API key lives in the\n**OS keychain**, not in a file. - Runs, issues, and agent events are stored in a local\n**SQLite** database under the app data directory (`~/Library/Application Support/xyz.anantjain.symphony`\n\non macOS), alongside daily-rotated logs and per-run workspaces. - Agents run with the sandbox/permission settings you give them under\n*Settings → Agent*. The defaults (`approval_policy: never`\n\n,`permission_mode: auto`\n\n, network access on for Codex) are tuned for unattended runs in disposable workspaces — review them before pointing Symphony at anything sensitive.\n\n`src-tauri/`\n\n— Tauri desktop shell, commands, keychain-backed settings, event forwarding`src/`\n\n— React dashboard (Overview, Runs, Issues, Settings)`crates/symphony-core`\n\n— domain types, workflow config, prompt rendering`crates/symphony-storage`\n\n— SQLite schema, repository, broadcast event bus`crates/symphony-tracker`\n\n— Linear GraphQL client and issue normalization`crates/symphony-agents`\n\n— native Codex and Claude process drivers`crates/symphony-worker`\n\n— recovery, polling loop, retries, hooks, workspace lifecycle\n\nPrerequisites: **Rust** (stable), **Node.js** ≥ 20 with **pnpm**, and on macOS the Xcode Command Line Tools (`xcode-select --install`\n\n).\n\n```\npnpm install\npnpm tauri dev            # run the app with hot reload\npnpm tauri build          # production bundle: .app + .dmg\npnpm typecheck && pnpm test && cargo test --workspace   # the checks CI runs\n```\n\n`pnpm tauri build`\n\nwrites artifacts to `target/release/bundle/`\n\n(`macos/Symphony.app`\n\n, `dmg/*.dmg`\n\n); pass `--debug`\n\nfor a faster unoptimized bundle. On macOS the `pnpm tauri`\n\nwrapper sets `CI=true`\n\nduring builds so DMG creation uses Tauri's deterministic path instead of Finder AppleScript window decoration, which can time out in non-interactive shells (set `TAURI_BUNDLER_DMG_IGNORE_CI=true`\n\nto opt out).\n\n```\npnpm release:mac\n```\n\nThis builds, signs, notarizes, and staples the distributable DMG, then verifies the result with `spctl`\n\nand `stapler validate`\n\n. Signing and notarization credentials live in `~/.symphony-release.env`\n\n(override the location with `SYMPHONY_RELEASE_ENV`\n\n):\n\n```\nAPPLE_SIGNING_IDENTITY=... # e.g. \"Developer ID Application: Jane Doe (TEAMID1234)\"\nAPPLE_API_ISSUER=...       # App Store Connect issuer ID (UUID)\nAPPLE_API_KEY=...          # API key ID\nAPPLE_API_KEY_PATH=...     # absolute path to the AuthKey_<id>.p8 file\n```\n\nThe Developer ID Application certificate named by `APPLE_SIGNING_IDENTITY`\n\nmust be installed in the login keychain; the script validates it before building.\n\nThe finished DMG lands in `target/release/bundle/dmg/`\n\n.\n\n```\npnpm release:publish\n```\n\nThis runs the signed build above, then tags `v<version>`\n\n(read from `src-tauri/tauri.conf.json`\n\n) and creates a GitHub release with the DMG attached under both its versioned name and the stable name `Symphony.dmg`\n\n— the file behind the download link at the top of this README, which always serves the newest release. Bump the version in `src-tauri/tauri.conf.json`\n\n(and keep `package.json`\n\nin sync) before publishing.\n\nThe script refuses to run unless you're on a clean `main`\n\ncheckout matching `origin/main`\n\n, and it needs an authenticated [GitHub CLI](https://cli.github.com) (`gh`\n\n) with push access.\n\nSee [CONTRIBUTING.md](/anantjain-xyz/symphony-rust/blob/main/CONTRIBUTING.md) for the full contributor guide, including TypeScript bindings regeneration.", "url": "https://wpnews.pro/news/show-hn-rust-implementation-of-symphony", "canonical_source": "https://github.com/anantjain-xyz/symphony-rust", "published_at": "2026-06-12 21:25:16+00:00", "updated_at": "2026-06-12 21:44:53.125314+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "ai-products", "ai-infrastructure", "ai-startups"], "entities": ["Symphony", "Linear", "OpenAI Codex", "Claude Code", "OpenAI", "macOS", "SQLite", "Tauri"], "alternates": {"html": "https://wpnews.pro/news/show-hn-rust-implementation-of-symphony", "markdown": "https://wpnews.pro/news/show-hn-rust-implementation-of-symphony.md", "text": "https://wpnews.pro/news/show-hn-rust-implementation-of-symphony.txt", "jsonld": "https://wpnews.pro/news/show-hn-rust-implementation-of-symphony.jsonld"}}