{"id":45902331,"url":"https://github.com/gabrielkoerich/orch","last_synced_at":"2026-06-13T01:03:51.427Z","repository":{"id":340538338,"uuid":"1164287378","full_name":"gabrielkoerich/orch","owner":"gabrielkoerich","description":"Autonomous Agents Orchestrator Experiment","archived":false,"fork":false,"pushed_at":"2026-05-29T23:07:29.000Z","size":6849,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T23:21:17.908Z","etag":null,"topics":["claude","claude-code","codex","opencode","orchestrator","rust"],"latest_commit_sha":null,"homepage":"http://orch.gabrielkoerich.com/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gabrielkoerich.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-22T22:40:01.000Z","updated_at":"2026-05-29T23:07:32.000Z","dependencies_parsed_at":"2026-04-06T23:01:36.175Z","dependency_job_id":null,"html_url":"https://github.com/gabrielkoerich/orch","commit_stats":null,"previous_names":["gabrielkoerich/orch"],"tags_count":1017,"template":false,"template_full_name":null,"purl":"pkg:github/gabrielkoerich/orch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielkoerich%2Forch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielkoerich%2Forch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielkoerich%2Forch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielkoerich%2Forch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gabrielkoerich","download_url":"https://codeload.github.com/gabrielkoerich/orch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielkoerich%2Forch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33928631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","claude-code","codex","opencode","orchestrator","rust"],"created_at":"2026-02-27T23:56:46.136Z","updated_at":"2026-06-13T01:03:51.416Z","avatar_url":"https://github.com/gabrielkoerich.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Orch\n\n[![CI](https://github.com/gabrielkoerich/orch/actions/workflows/release.yml/badge.svg)](https://github.com/gabrielkoerich/orch/actions/workflows/release.yml)\n\nAn autonomous task orchestration engine that delegates work to AI coding agents (Claude, Codex, OpenCode, Kimi, MiniMax). Runs as a background service, manages isolated worktrees, syncs with GitHub Issues, and handles the full task lifecycle from routing to PR creation.\n\n## Features\n\n- **Multi-agent support** — Route tasks to Claude, Codex, OpenCode, Kimi, or MiniMax based on task complexity\n- **Multi-project** — Manage multiple repositories from a single service\n- **GitHub Issues integration** — Two-way sync with GitHub Issues as the source of truth\n- **GitHub Projects V2** — Automatic project board column sync on status changes\n- **Isolated worktrees** — Each task runs in its own git worktree, never touching the main repo\n- **Live session streaming** — Watch agents work in real-time via `orch stream` (all sessions) or `orch stream \u003ctask_id\u003e`\n- **Control session** — Conversational ops assistant via `orch chat` — ask about tasks, create new ones, check status in natural language\n- **Internal tasks** — SQLite-backed tasks for cron jobs and maintenance (no GitHub issue clutter)\n- **Job scheduler** — Cron-like scheduled tasks with native Rust cron matching\n- **Automatic PR creation** — Branches pushed, PRs created, and comments posted automatically\n- **Complexity-based routing** — Router assigns `simple|medium|complex` and config maps to models\n- **Agent memory** — Learnings persist across retries so agents don't repeat mistakes\n- **Per-task artifacts** — Organized per-repo, per-task, per-attempt directory structure\n\n## Installation\n\n```bash\nbrew tap gabrielkoerich/homebrew-tap\nbrew install orch\n```\n\n## Quick Start\n\n### 1. Initialize orch for your project\n\n```bash\ncd /path/to/your/project\norch init\n```\n\nThis creates:\n- `~/.orch/config.yml` — global configuration (shared defaults + project registry)\n- `.orch.yml` — project-specific configuration (in your project root)\n\n### 2. Start the service\n\n```bash\norch service start\n```\n\nOr use Homebrew services:\n```bash\nbrew services start orch\n```\n\n### 3. Create a task\n\n```bash\n# Create an internal task (SQLite only, no GitHub issue)\norch task add \"Fix authentication bug\" --body \"Users can't login with OAuth\"\n\n# Create a GitHub issue task\norch task add \"Update README\" --labels \"documentation,good-first-issue\"\n```\n\n### 4. Watch the magic\n\nThe service automatically:\n1. Routes tasks to the best agent based on content\n2. Creates isolated worktrees\n3. Runs the agent in a tmux session\n4. Pushes branches and creates PRs\n5. Updates GitHub issue status and project board\n\n## GitHub Authentication\n\nOrch needs a GitHub token to sync issues and open PRs. The simplest setup is `gh auth login` — no extra config needed.\n\nTokens are resolved in this order (first match wins):\n\n1. `GH_TOKEN` environment variable\n2. `GITHUB_TOKEN` environment variable\n3. `gh.auth.token` in `~/.orch/config.yml`\n4. `gh auth token` CLI (enabled by default via `gh.allow_gh_fallback: true`)\n\nFor organizations, GitHub App auth is supported:\n\n```yaml\n# ~/.orch/config.yml\ngithub:\n  token_mode: github_app\n  app_id: \"123456\"\n  private_key_path: \"/path/to/app-private-key.pem\"\n```\n\nOrch generates JWTs from the private key (valid for 9 minutes) and caches the installation token until expiry.\n\n### Security: Service Deployments (Homebrew / launchd)\n\nWhen running as a background service (e.g., `brew services start orch`), the service process does **not** inherit your shell environment. Pass the token securely:\n\n**Option A — `~/.private` file** (sourced automatically by runner scripts):\n```bash\n# ~/.private  (chmod 600)\nexport GH_TOKEN=\"ghp_xxxxxxxxxxxxxxxxxxxx\"\n```\n\n**Option B — launchd `EnvironmentVariables`** in the plist:\n```xml\n\u003ckey\u003eEnvironmentVariables\u003c/key\u003e\n\u003cdict\u003e\n  \u003ckey\u003eGH_TOKEN\u003c/key\u003e\n  \u003cstring\u003eghp_xxxxxxxxxxxxxxxxxxxx\u003c/string\u003e\n\u003c/dict\u003e\n```\n\n**Option C — GitHub App** (recommended for teams): no long-lived token needed; the service exchanges a short-lived JWT for an installation token automatically.\n\n\u003e **Important:** Orch never writes `GH_TOKEN` into runner scripts on disk. Tokens are injected into the tmux session environment at spawn time and exist only in process memory.\n\n## CLI Reference\n\n### Service Management\n\n```bash\norch serve                    # Run orch service (foreground)\norch service start            # Start background service\norch service stop             # Stop background service\norch service restart          # Restart service\norch service status           # Check service status\n```\n\n### Task Management\n\n```bash\norch task list                # List all tasks\norch task list --status new   # Filter by status\norch task get \u003cid\u003e            # Get task details\norch task add \"Title\"         # Create internal task\norch task add \"Title\" --labels \"bug,urgent\"  # Create GitHub issue\norch task route \u003cid\u003e          # Manually route a task to an agent\norch task run \u003cid\u003e            # Manually run a task\norch task run                 # Run next available routed task\norch task retry \u003cid\u003e          # Reset task to new for re-routing\norch task unblock \u003cid\u003e        # Unblock a blocked task\norch task unblock all         # Unblock all blocked/needs_review tasks\norch task publish \u003cid\u003e        # Promote internal task to GitHub issue\norch task attach \u003cid\u003e         # Attach to running tmux session\norch task live                # List active agent sessions\norch task kill \u003cid\u003e           # Kill a running agent session\norch task cost \u003cid\u003e           # Show token cost breakdown\norch task close \u003cid\u003e          # Manually mark a task as done\norch task close \u003cid\u003e --note \"msg\"  # Mark done with a comment\n```\n\n### Project Management\n\n```bash\norch project list                        # List all registered projects\norch project add .                       # Register current directory\norch project add /path/to/repo           # Register a local path\norch project add owner/repo              # Bare clone + import issues\norch project add https://github.com/o/r  # Same, from a URL\norch project remove /path                # Unregister a project\n```\n\n### GitHub Projects V2 Board\n\n```bash\norch project board list               # List accessible GitHub Projects V2 boards\norch project board link \u003cid\u003e          # Link current repo to a board by ID\norch project board sync               # Re-discover field IDs and update config\norch project board info               # Show current board config\n```\n\n### Job Management (Scheduled Tasks)\n\n```bash\norch job list                 # List scheduled jobs\norch job add \"0 9 * * *\" \"Morning review\"     # Daily at 9am\norch job add \"*/30 * * * *\" \"Check CI\" --type bash --command \"scripts/ci-check.sh\"\norch job remove \u003cid\u003e          # Remove a job\norch job enable \u003cid\u003e          # Enable a job\norch job disable \u003cid\u003e         # Disable a job\norch job tick                 # Run one scheduler tick (for testing)\n```\n\n### Utility Commands\n\n```bash\norch init                     # Initialize orch for current project\norch init --repo owner/repo   # Initialize with specific repo\norch config agents            # List installed agent CLIs\norch stats dashboard          # Full dashboard view (tasks, sessions, activity)\norch stats metrics            # Show task metrics summary\norch stats cost               # Cost tracking and token usage\norch stats                    # Throughput / per-project rollups\norch stats overview           # Explicit stats overview subcommand\norch task events              # Tail task events live\norch stream                   # Stream ALL running agent sessions\norch stream \u003ctask_id\u003e         # Stream a single task\norch log                      # Show last 50 log lines\norch log 100                  # Show last N lines\norch log -f                   # Tail service logs live\norch log -f --task \u003ctask_id\u003e  # Stream a single task\norch service doctor           # Diagnose SQLite ↔ GitHub drift\norch service prune            # Remove orphaned worktrees\norch cooldown list            # Show active agent/model cooldowns\norch cooldown clear \u003ckey\u003e     # Clear a specific cooldown\norch webhook status           # Show webhook server health (hidden, rare public-host use)\norch task session export \u003cid\u003e # Export a task's session\norch notify \"message\"         # Send a Telegram notification\norch -V                       # Show CLI version\norch config \u003ckey\u003e             # Read config value (e.g., orch config gh.repo)\norch completions \u003cshell\u003e      # Generate shell completions (bash, zsh, fish)\n```\n\n### Smart Commits\n\n```bash\norch commit                         # Group changes and draft messages with the LLM\norch commit --dry-run               # Show the plan without committing\norch commit --yes                   # Accept the drafted messages without prompting\norch commit -m \"fix: ...\"           # Force a single commit with this exact message (skips LLM)\norch commit --no-llm                # Use the path/hunk heuristic instead of an LLM call\n```\n\n`orch commit` groups the working tree's staged + unstaged + untracked changes\ninto one or more logical commits by path, then asks the current chat agent\n(`orch chat`'s sticky `/agent` + `/model`) to draft a Conventional Commits\nmessage for each group from the file list and unified diff. The diff is capped\nat `commit.max_diff_bytes` bytes per group (default 32 KB) so the call stays\ncheap and predictable. Edit, accept, or reject the drafts interactively; pass\n`--yes` to skip the prompt or `-m` to override entirely.\n\nFallback behaviour: if no agent is available (all cooled, no API key, offline)\nthe heuristic message survives, a one-line warning is logged, and you still get\nthe editor unless `--yes` was passed. Use `--no-llm` to force the heuristic\npath (handy for scripts and tests). The agent prompt lives at\n[`prompts/commit_message.md`](prompts/commit_message.md).\n\n### Control Session (Chat)\n\n```bash\norch chat                           # Interactive REPL\norch chat \"what's running?\"         # Single message mode\norch chat --session ops             # Use a named session profile\norch chat history                   # Show recent messages\norch chat history --with-cost       # Include per-message token/cost info\norch chat stats                     # Show session token/cost summary\norch chat history --search \"bean\"   # Search past conversations\n```\n\nIn the REPL, use `/model` and `/agent` to manage the sticky agent:model selection:\n```\norch\u003e /model sonnet                 # Infer agent (claude)\norch\u003e /model minimax:sonnet         # Explicit agent:model\norch\u003e /model opencode:minimax-m2.5-free  # OpenCode with specific model\norch\u003e /agent codex                  # Switch agent and its default model\norch\u003e /agent                        # Show current agent:model\norch\u003e /model                        # Show current agent:model\n```\n\n## Configuration\n\n### Global config (`~/.orch/config.yml`)\n\nShared defaults and project registry. All settings here apply to every project unless overridden.\n\n```yaml\n# Project registry — list of local paths\n# Each path must contain a .orch.yml with gh.repo\nprojects:\n  - /Users/me/Projects/my-app\n  - /Users/me/Projects/my-lib\n\nworkflow:\n  auto_close: true\n  review_owner: \"@owner\"\n  enable_review_agent: false\n  max_attempts: 10\n  timeout_seconds: 1800\n\nrouter:\n  mode: \"llm\"              # \"llm\" | \"round_robin\" | \"local\" (Ollama)\n  agent: \"claude\"          # which LLM performs routing\n  model: \"haiku\"           # fast/cheap model for classification\n  timeout_seconds: 60\n  max_route_attempts: 3    # LLM failures before falling back to round-robin\n  max_tasks_per_tick: 1    # max routing decisions per engine tick\n  weighted_round_robin: false\n  fallback_executor: \"codex\"\n\nmodel_map:\n  simple:\n    claude: haiku\n    codex: gpt-5.1-codex-mini\n  medium:\n    claude: sonnet\n    codex: gpt-5.2\n  complex:\n    claude: opus\n    codex: gpt-5.3-codex\n  review:\n    claude: sonnet\n    codex: gpt-5.2\n\n# Agent CLIs to discover in $PATH\nagents:\n  - claude\n  - codex\n  - opencode\n  - kimi\n  - minimax\n\ngit:\n  name: \"orch[bot]\"\n  email: \"orch@orch.bot\"\n```\n\n### Project config (`.orch.yml`)\n\nPlace in your project root. Values here override global defaults.\n\nSee [`.orch.yml`](.orch.yml) for a real-world example — orch uses itself to build, review, and improve its own codebase.\n\n```yaml\n# Required — identifies this project on GitHub\ngh:\n  repo: \"owner/repo\"\n  project_id: \"PVT_...\"           # optional: GitHub Projects V2\n  project_status_field_id: \"...\"   # optional\n  project_status_map:              # optional\n    backlog: \"option-id-1\"\n    in_progress: \"option-id-2\"\n    review: \"option-id-3\"\n    done: \"option-id-4\"\n\n# Optional overrides\nworkflow:\n  max_attempts: 5\n\nrouter:\n  fallback_executor: \"codex\"\n\nrequired_tools:\n  - cargo\n  - bun\n\n# Per-project scheduled jobs\njobs:\n  - id: code-review\n    schedule: \"0 4,17 * * *\"\n    task:\n      title: \"Code review\"\n      body: \"Review the codebase for bugs and improvements\"\n      labels: [review]\n    enabled: true\n```\n\n## Task Statuses\n\n| Status | Description |\n|--------|-------------|\n| `new` | Task created, awaiting routing |\n| `routed` | Agent assigned, awaiting dispatch |\n| `in_progress` | Agent actively working in tmux session |\n| `needs_review` | Agent completed, awaiting review agent dispatch (automatic) |\n| `in_review` | Review agent actively reviewing the PR |\n| `done` | PR merged, worktree cleaned up |\n| `blocked` | Requires human attention (max review cycles, agent failures) |\n\n## Label-Based Routing\n\nOverride the router by adding labels to GitHub issues:\n\n| Label | Effect |\n|-------|--------|\n| `agent:claude` | Force Claude executor |\n| `agent:codex` | Force Codex executor |\n| `agent:opencode` | Force OpenCode executor |\n| `agent:kimi` | Force Kimi executor |\n| `agent:minimax` | Force MiniMax executor |\n| `complexity:simple` | Use simple model tier |\n| `complexity:medium` | Use medium model tier |\n| `complexity:complex` | Use complex model tier |\n| `no-agent` | Skip agent routing (manual task) |\n\n## Architecture\n\nOrch is built in Rust with a modular architecture:\n\n```\nsrc/\n├── main.rs              # CLI entrypoint (clap)\n├── control.rs           # Control session (orch chat) — context assembly, agent invocation\n├── config/\n│   └── mod.rs           # Config loading, hot-reload, multi-project\n├── store/               # Unified SQLite task store (tasks, metrics, KV, rate limits)\n├── parser.rs            # Agent response normalization\n├── cron.rs              # Cron expression matching\n├── template.rs          # Template rendering\n├── tmux.rs              # tmux session management\n├── security.rs          # Secret scanning + redaction\n├── home.rs              # Home directory (~/.orch/) + per-repo state paths\n├── cmd.rs               # Command execution helpers with error context\n├── cmd_cache.rs         # Cached command results\n├── repo_context.rs      # Per-repo task-local context\n├── webhook_status.rs    # Webhook health tracking\n├── backends/            # External task backends\n│   ├── mod.rs           # ExternalBackend trait\n│   └── github.rs        # GitHub Issues + Projects V2 sync\n├── channels/            # Communication channels\n│   ├── transport.rs     # Output broadcasting\n│   ├── capture.rs       # tmux output capture\n│   ├── notification.rs  # Unified notifications\n│   ├── stream.rs        # Live output streaming\n│   ├── tmux.rs          # tmux bridge\n│   ├── github.rs        # GitHub webhooks\n│   ├── slack.rs         # Slack integration\n│   ├── telegram.rs      # Telegram bot\n│   ├── discord.rs       # Discord registration + REST helpers\n│   └── discord_ws.rs    # Discord Gateway websocket (real-time events)\n├── cli/                 # CLI command implementations\n│   ├── mod.rs           # Init, agents, board, project, metrics, stream\n│   ├── chat.rs          # Control session (REPL, single-message, history)\n│   ├── task.rs          # Task CRUD\n│   ├── job.rs           # Job management\n│   └── service.rs       # Service lifecycle\n├── github/              # GitHub API helpers\n│   ├── cli_wrapper.rs   # gh CLI wrapper\n│   ├── http.rs          # Native HTTP client (reqwest, connection pooling)\n│   ├── token.rs         # Token resolution (env, config, gh CLI, GitHub App)\n│   ├── types.rs         # Issue, Comment, Label, PR review types\n│   └── projects.rs      # Projects V2 GraphQL operations\n└── engine/              # Core orchestration\n    ├── mod.rs           # Main event loop, project init, struct defs\n    ├── tick.rs          # Core tick phases (sessions, routing, dispatch, unblock)\n    ├── sync.rs          # Periodic sync (cleanup, PR review, mentions, skills)\n    ├── review.rs        # PR review pipeline (review agent, auto-merge, re-route)\n    ├── cleanup.rs       # Worktree cleanup, merged-PR detection, store helpers\n    ├── commands.rs      # Owner /slash commands in issue comments\n    ├── tasks.rs         # Task manager (internal + external, unified store)\n    ├── router/          # Agent routing (label, round-robin, LLM)\n    │   ├── mod.rs       # Router logic and RouteResult\n    │   ├── config.rs    # Router configuration\n    │   └── weights.rs   # Routing weight signals\n    ├── jobs.rs          # Job scheduler + self-review\n    └── runner/          # Task execution\n        ├── mod.rs       # Full task lifecycle\n        ├── task_init.rs # Guard checks, worktree setup, invocation building\n        ├── session.rs   # tmux session lifecycle and output collection\n        ├── context.rs   # Prompt context building\n        ├── worktree.rs  # Git worktree management\n        ├── agent.rs     # Agent invocation + prompt building\n        ├── agents/      # Per-agent runners (Claude, Codex, OpenCode, Kimi, MiniMax)\n        ├── response.rs  # Response parsing, weight signals\n        ├── response_handler.rs # Success path: commit, push, PR\n        ├── fallback.rs  # Error classification and recovery strategies\n        └── git_ops.rs   # Auto-commit, push, PR creation\n```\n\n## Task Artifacts\n\nTask artifacts are organized per-repo, per-task, per-attempt:\n\n```\n~/.orch/state/{owner}/{repo}/tasks/{id}/\n  attempts/\n    1/\n      prompt-sys.md         # System prompt\n      prompt-msg.md         # Task prompt\n      runner.sh             # Runner script\n      exit.txt              # Exit code\n      stderr.txt            # Agent stderr\n      output.json           # Agent response\n      result.json           # Parsed result (status, summary, etc.)\n    2/                      # Retry attempt\n      ...\n```\n\nTask metadata (branch, worktree, agent, model, attempts, pr_number, memory, etc.) is stored in the unified SQLite database at `~/.orch/orch.db`, not in per-task JSON files.\n\n## Development\n\n### Building from source\n\n```bash\ngit clone https://github.com/gabrielkoerich/orch.git\ncd orch\ncargo build --release\n```\n\n### Running tests\n\n```bash\ncargo nextest run            # preferred (matches CI)\ncargo test                   # fallback if nextest is not installed\n```\n\nInstall nextest: `cargo binstall cargo-nextest` (requires [cargo-binstall](https://github.com/cargo-bins/cargo-binstall)).\n\n### Logs\n\n- Service log: `~/.orch/state/orch.log`\n- Homebrew stdout: `/opt/homebrew/var/log/orch.log`\n- Homebrew stderr: `/opt/homebrew/var/log/orch.error.log`\n\n## Documentation\n\n- [AGENTS.md](AGENTS.md) — Agent and developer notes (also exposed as `CLAUDE.md` via symlink)\n- [docs/architecture.md](docs/architecture.md) — System architecture and diagrams\n- [docs/content/](docs/content/) — User-facing reference: getting started, CLI, configuration, routing, jobs, channels, agents, alerting, GitHub sync, workflow\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielkoerich%2Forch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgabrielkoerich%2Forch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielkoerich%2Forch/lists"}