惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
O
OpenAI News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Google Online Security Blog
Google Online Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News and Events Feed by Topic
S
Security Affairs
SecWiki News
SecWiki News
Project Zero
Project Zero
L
Lohrmann on Cybersecurity
P
Proofpoint News Feed
P
Palo Alto Networks Blog
L
LINUX DO - 最新话题
H
Hacker News: Front Page
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
Intezer
Simon Willison's Weblog
Simon Willison's Weblog
W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
I
InfoQ
云风的 BLOG
云风的 BLOG
雷峰网
雷峰网
B
Blog
IT之家
IT之家
AWS News Blog
AWS News Blog
Jina AI
Jina AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Spread Privacy
Spread Privacy
N
News and Events Feed by Topic
Security Latest
Security Latest
美团技术团队
C
Check Point Blog
WordPress大学
WordPress大学
T
Tenable Blog
S
Security @ Cisco Blogs
Last Week in AI
Last Week in AI
博客园 - 聂微东
月光博客
月光博客
博客园 - 【当耐特】
S
Schneier on Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Secure Thoughts
Schneier on Security
Schneier on Security
C
Cisco Blogs
Cyberwarzone
Cyberwarzone

Show HN

暂无文章

GitHub - anantjain-xyz/symphony-rust: An autonomous engineering team for your Linear project. Symphony is a desktop app that watches your Linear board and dispatches coding agents — Codex or Claude Code — to work on issues, each in its own freshly cloned workspace. You triage and review; Symphony orchestrates.
anant90 · 2026-06-13 · via Show HN

An autonomous engineering team for your Linear project. Symphony is a desktop app that watches your Linear board and dispatches coding agents — Codex or Claude Code — to work on issues, each in its own freshly cloned workspace. You triage and review; Symphony orchestrates. Based on the spec from OpenAI.

⬇ Download for macOS (Apple Silicon) · Latest release

Symphony dashboard showing active agent runs, the retry queue, and provider rate limits

How it works

  1. Poll — a local worker polls Linear for issues in the states you mark as active (e.g. Todo, In Progress, Rework).
  2. Prepare — for each issue, Symphony creates an isolated workspace and runs your after_create hook (typically git clone + dependency install).
  3. 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.
  4. 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.
  5. Retry — failed runs are retried with exponential backoff, and the retry prompt includes the previous run's error context.

Everything runs on your machine. The only network calls are to Linear's API and whatever your agents and hooks do.

Requirements

  • macOS (primary target; Tauri builds for other platforms are untested)
  • A Linear workspace and a personal API key
  • At least one agent CLI installed and authenticated:
    • codex — OpenAI Codex CLI
    • claude — Claude Code CLI
  • git, plus whatever your repository's install step needs

Getting started

Download Symphony.dmg — the latest signed and notarized build for macOS (Apple Silicon). Open it, drag Symphony to Applications, and launch.

Or build and run from source:

git clone https://github.com/anantjain-xyz/symphony-rust.git
cd symphony-rust
pnpm install
pnpm tauri dev      # or: pnpm tauri build

See Building for production bundles and signed releases.

On first launch the Overview shows a setup checklist:

  1. Connect Linear — paste your API key in Settings → Linear. It is stored in the macOS keychain, never on disk.
  2. Add your repositories — one or more Git URLs; each run clones the repo its issue routes to.
  3. Start the worker — the ▶ button in the top bar. Symphony begins polling and dispatching.

Optional Linear filters (workspace slug, project ID, identifier prefix like ENG) narrow which issues Symphony picks up. Use Validate in Settings to check your configuration and confirm the agent CLIs are discoverable before starting.

Settings and the prompt template

Symphony's behavior is configured entirely in Settings — no config file to edit:

  • 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> label on the issue in Linear, then the repo claiming the issue's Linear project, then the repo claiming its team key (e.g. ENG), then the repo marked default. An issue whose repo: label 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, In Progress, Rework, Merging) get an agent; issues in a terminal state (e.g. Done, Canceled) are left alone.
  • Agent — which CLI runs issues (codex or claude), an optional launch command (wrappers with arguments like mycode --agent claude are 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, before_run, after_run, before_remove. Hooks are shell scripts that run in the workspace with $REPO_URL, $REPO_NAME, $ISSUE_ID, $ISSUE_IDENTIFIER, $ISSUE_TITLE, $ISSUE_STATE, $ISSUE_BRANCH, $RUN_NUMBER, $SYMPHONY_INSTALL_CMD, and $SYMPHONY_HOOK in their environment; the repo variables reflect the repo the issue routed to.

The prompt template at the bottom of Settings is the instruction document sent to the agent for each issue. Placeholders in {{...}} form 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:

Placeholder Renders as
{{issue.id}} Internal Linear ID
{{issue.identifier}} Issue key, e.g. SYM-42
{{issue.title}} Issue title
{{issue.description}} Full issue body (empty if none)
{{issue.state}} Current Linear state
{{issue.branch}} Git branch from Linear (may be empty)
{{issue.labels}} Labels, comma-separated
{{issue.blockers}} Blocking issue identifiers, one - <id> bullet per line
{{repo.name}} Name of the repo the issue routed to
{{repo.url}} Git URL of the routed repo

Retried runs automatically get a ## Retry context section appended with the prior run's error and recent events.

Data and security

  • Your Linear API key lives in the OS keychain, not in a file.
  • Runs, issues, and agent events are stored in a local SQLite database under the app data directory (~/Library/Application Support/xyz.anantjain.symphony on macOS), alongside daily-rotated logs and per-run workspaces.
  • Agents run with the sandbox/permission settings you give them under Settings → Agent. The defaults (approval_policy: never, permission_mode: auto, network access on for Codex) are tuned for unattended runs in disposable workspaces — review them before pointing Symphony at anything sensitive.

Architecture

  • src-tauri/ — Tauri desktop shell, commands, keychain-backed settings, event forwarding
  • src/ — React dashboard (Overview, Runs, Issues, Settings)
  • crates/symphony-core — domain types, workflow config, prompt rendering
  • crates/symphony-storage — SQLite schema, repository, broadcast event bus
  • crates/symphony-tracker — Linear GraphQL client and issue normalization
  • crates/symphony-agents — native Codex and Claude process drivers
  • crates/symphony-worker — recovery, polling loop, retries, hooks, workspace lifecycle

Building

Prerequisites: Rust (stable), Node.js ≥ 20 with pnpm, and on macOS the Xcode Command Line Tools (xcode-select --install).

pnpm install
pnpm tauri dev            # run the app with hot reload
pnpm tauri build          # production bundle: .app + .dmg
pnpm typecheck && pnpm test && cargo test --workspace   # the checks CI runs

pnpm tauri build writes artifacts to target/release/bundle/ (macos/Symphony.app, dmg/*.dmg); pass --debug for a faster unoptimized bundle. On macOS the pnpm tauri wrapper sets CI=true during 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 to opt out).

Signed macOS release

This builds, signs, notarizes, and staples the distributable DMG, then verifies the result with spctl and stapler validate. Signing and notarization credentials live in ~/.symphony-release.env (override the location with SYMPHONY_RELEASE_ENV):

APPLE_SIGNING_IDENTITY=... # e.g. "Developer ID Application: Jane Doe (TEAMID1234)"
APPLE_API_ISSUER=...       # App Store Connect issuer ID (UUID)
APPLE_API_KEY=...          # API key ID
APPLE_API_KEY_PATH=...     # absolute path to the AuthKey_<id>.p8 file

The Developer ID Application certificate named by APPLE_SIGNING_IDENTITY must be installed in the login keychain; the script validates it before building.

The finished DMG lands in target/release/bundle/dmg/.

Publishing a release

This runs the signed build above, then tags v<version> (read from src-tauri/tauri.conf.json) and creates a GitHub release with the DMG attached under both its versioned name and the stable name Symphony.dmg — 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 (and keep package.json in sync) before publishing.

The script refuses to run unless you're on a clean main checkout matching origin/main, and it needs an authenticated GitHub CLI (gh) with push access.

See CONTRIBUTING.md for the full contributor guide, including TypeScript bindings regeneration.

License

MIT