{"id":47620342,"url":"https://github.com/jonwiggins/optio","last_synced_at":"2026-04-02T12:09:17.965Z","repository":{"id":346631126,"uuid":"1186598756","full_name":"jonwiggins/optio","owner":"jonwiggins","description":"AI Agent Workflow Orchestration","archived":false,"fork":false,"pushed_at":"2026-03-25T22:56:50.000Z","size":1891,"stargazers_count":1,"open_issues_count":20,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T22:56:51.793Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonwiggins.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-19T19:50:11.000Z","updated_at":"2026-03-25T22:56:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jonwiggins/optio","commit_stats":null,"previous_names":["jonwiggins/optio"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jonwiggins/optio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonwiggins%2Foptio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonwiggins%2Foptio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonwiggins%2Foptio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonwiggins%2Foptio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonwiggins","download_url":"https://codeload.github.com/jonwiggins/optio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonwiggins%2Foptio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31305973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T09:48:21.550Z","status":"ssl_error","status_checked_at":"2026-04-02T09:48:19.196Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-04-01T22:00:30.194Z","updated_at":"2026-04-02T12:09:17.956Z","avatar_url":"https://github.com/jonwiggins.png","language":"TypeScript","funding_links":[],"categories":["Cross-Agent References","TypeScript"],"sub_categories":[],"readme":"# Optio\n\n**Workflow orchestration for AI coding agents, from task to merged PR.**\n\n[![CI](https://github.com/jonwiggins/optio/actions/workflows/ci.yml/badge.svg)](https://github.com/jonwiggins/optio/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)\n\nOptio turns coding tasks into merged pull requests — without human babysitting. Submit a task (manually, from a GitHub Issue, Linear, Jira, or Notion), and Optio handles the rest: provisions an isolated environment, runs an AI agent, opens a PR, monitors CI, triggers code review, auto-fixes failures, and merges when everything passes.\n\nThe feedback loop is what makes it different. When CI fails, the agent is automatically resumed with the failure context. When a reviewer requests changes, the agent picks up the review comments and pushes a fix. When everything passes, the PR is squash-merged and the issue is closed. You describe the work; Optio drives it to completion.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/overview.png\" alt=\"Optio dashboard showing 10 running tasks, 19 completed, with Claude Max usage, active pods, and recent task activity\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eDashboard — real-time overview of running agents, pod status, costs, and recent activity\u003c/em\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/task-detail.png\" alt=\"Task detail view showing live agent logs, pipeline progress through stages (queued, setup, running, PR, CI checks, review, merge, done), and cost tracking\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eTask detail — live-streamed agent output with pipeline progress, PR tracking, and cost breakdown\u003c/em\u003e\u003c/p\u003e\n\n## How It Works\n\n```\nYou create a task          Optio runs the agent           Optio closes the loop\n─────────────────          ──────────────────────         ──────────────────────\n\n  GitHub Issue              Provision repo pod             CI fails?\n  Manual task       ──→     Create git worktree    ──→       → Resume agent with failure context\n  Linear / Jira / Notion    Run Claude / Codex / Copilot   Review requests changes?\n                            Open a PR                        → Resume agent with feedback\n                                                           CI passes + approved?\n                                                             → Squash-merge + close issue\n```\n\n1. **Intake** — tasks come from the web UI, GitHub Issues (one-click assign), Linear, Jira, or Notion\n2. **Provisioning** — Optio finds or creates a Kubernetes pod for the repo, creates a git worktree for isolation\n3. **Execution** — the AI agent (Claude Code, OpenAI Codex, or GitHub Copilot) runs with your configured prompt, model, and settings\n4. **PR lifecycle** — Optio polls the PR every 30s for CI status, review state, and merge readiness\n5. **Feedback loop** — CI failures, merge conflicts, and review feedback automatically resume the agent with context\n6. **Completion** — PR is squash-merged, linked issues are closed, costs are recorded\n\n## Key Features\n\n- **Autonomous feedback loop** — auto-resumes the agent on CI failures, merge conflicts, and review feedback; auto-merges when everything passes\n- **Pod-per-repo architecture** — one long-lived Kubernetes pod per repo with git worktree isolation, multi-pod scaling, and idle cleanup\n- **Code review agent** — automatically launches a review agent as a subtask, with a separate prompt and model\n- **Per-repo configuration** — model, prompt template, container image, concurrency limits, and setup commands, all tunable per repository\n- **GitHub Issues, Linear, Jira, and Notion intake** — assign issues to Optio from the UI or via ticket sync\n- **Real-time dashboard** — live log streaming, pipeline progress, cost analytics, and cluster health\n\n## Architecture\n\n```\n┌──────────────┐     ┌────────────────────┐     ┌───────────────────────────┐\n│   Web UI     │────→│    API Server      │────→│      Kubernetes           │\n│   Next.js    │     │    Fastify         │     │                           │\n│   :3100      │     │                    │     │  ┌── Repo Pod A ───────┐  │\n│              │←ws──│  Workers:          │     │  │ clone + sleep       │  │\n│  Dashboard   │     │  ├─ Task Queue     │     │  │ ├─ worktree 1  ⚡    │  │\n│  Tasks       │     │  ├─ PR Watcher     │     │  │ ├─ worktree 2  ⚡    │  │\n│  Repos       │     │  ├─ Health Mon     │     │  │ └─ worktree N  ⚡    │  │\n│  Cluster     │     │  └─ Ticket Sync    │     │  └─────────────────────┘  │\n│  Costs       │     │                    │     │  ┌── Repo Pod B ───────┐  │\n│  Issues      │     │  Services:         │     │  │ clone + sleep       │  │\n│              │     │  ├─ Repo Pool      │     │  │ └─ worktree 1  ⚡    │  │\n│              │     │  ├─ Review Agent   │     │  └─────────────────────┘  │\n│              │     │  └─ Auth/Secrets   │     │                           │\n└──────────────┘     └─────────┬──────────┘     └───────────────────────────┘\n                               │                  ⚡ = Claude Code / Codex / Copilot\n                        ┌──────┴──────┐\n                        │  Postgres   │  Tasks, logs, events, secrets, repos\n                        │  Redis      │  Job queue, pub/sub, live streaming\n                        └─────────────┘\n```\n\n### Task lifecycle\n\n```\n  ┌──────────────────────────────────────────────────┐\n  │                     INTAKE                       │\n  │                                                  │\n  │   GitHub Issue ───→ ┌──────────┐                 │\n  │   Manual Task ───→  │  QUEUED  │                 │\n  │   Ticket Sync ───→  └────┬─────┘                 │\n  └───────────────────────────┼──────────────────────┘\n                              │\n  ┌───────────────────────────┼──────────────────────┐\n  │                 EXECUTION ▼                      │\n  │                                                  │\n  │   ┌──────────────┐    ┌─────────────────┐        │\n  │   │ PROVISIONING │───→│     RUNNING     │        │\n  │   │ get/create   │    │  agent writes   │        │\n  │   │ repo pod     │    │  code in        │        │\n  │   └──────────────┘    │  worktree       │        │\n  │                       └───────┬─────────┘        │\n  └───────────────────────────────┼──────────────────┘\n                                  │\n                ┌─────────────┐   │   ┌──────────────────┐\n                │   FAILED    │←──┴──→│    PR OPENED     │\n                │             │       │                  │\n                │ (auto-retry │       │  PR watcher      │\n                │  if stale)  │       │  polls every 30s │\n                └─────────────┘       └─────────┬────────┘\n                                                │\n  ┌─────────────────────────────────────────────┼─────────┐\n  │                 FEEDBACK LOOP               │         │\n  │                                             │         │\n  │   CI fails?  ────────→  Resume agent  ←─────┤         │\n  │                          to fix build       │         │\n  │                                             │         │\n  │   Merge conflicts? ──→  Resume agent  ←─────┤         │\n  │                          to rebase          │         │\n  │                                             │         │\n  │   Review requests ───→  Resume agent  ←─────┤         │\n  │   changes?               with feedback      │         │\n  │                                             │         │\n  │   CI passes + ───────→  Auto-merge    ──────┤         │\n  │   review done?           \u0026 close issue      │         │\n  │                                             ▼         │\n  │                                  ┌──────────────┐     │\n  │                                  │ COMPLETED    │     │\n  │                                  │ PR merged    │     │\n  │                                  │ Issue closed │     │\n  │                                  └──────────────┘     │\n  └───────────────────────────────────────────────────────┘\n```\n\n## Quick Start\n\n### Prerequisites\n\n- **Docker Desktop** with Kubernetes enabled (Settings → Kubernetes → Enable)\n- **Node.js 22+** and **pnpm 10+**\n- **Helm** (`brew install helm`)\n\n### Setup\n\n```bash\ngit clone https://github.com/jonwiggins/optio.git \u0026\u0026 cd optio\n./scripts/setup-local.sh\n```\n\nThat's it. The setup script installs dependencies, builds all Docker images (API, web, and agent presets), deploys the full stack to your local Kubernetes cluster via Helm, and installs metrics-server.\n\n```\nWeb UI ...... http://localhost:30310\nAPI ......... http://localhost:30400\n```\n\nOpen the web UI and the setup wizard will walk you through configuring GitHub access, agent credentials (API key or Max/Pro subscription), and adding your first repository.\n\n### Updating\n\n```bash\n./scripts/update-local.sh\n```\n\nPulls latest code, rebuilds images, applies Helm changes, and rolling-restarts the deployments.\n\n### Teardown\n\n```bash\nhelm uninstall optio -n optio\n```\n\n## Project Structure\n\n```\napps/\n  api/          Fastify API server, BullMQ workers, WebSocket endpoints,\n                review service, subtask system, OAuth providers\n  web/          Next.js dashboard with real-time streaming, cost analytics\n\npackages/\n  shared/             Types, task state machine, prompt templates, error classifier\n  container-runtime/  Kubernetes pod lifecycle, exec, log streaming\n  agent-adapters/     Claude Code + Codex + Copilot prompt/auth adapters\n  ticket-providers/   GitHub Issues, Linear, Jira, Notion\n\nimages/               Container Dockerfiles: base, node, python, go, rust, full\nhelm/optio/           Helm chart for production Kubernetes deployment\nscripts/              Setup, init, and entrypoint scripts\n```\n\n## GitHub App Setup\n\nOptio can use a [GitHub App](https://docs.github.com/en/apps/creating-github-apps) instead of a Personal Access Token for GitHub operations. This provides user-scoped access (respecting CODEOWNERS, branch protection, and repository permissions), automatic token refresh, and clear attribution on PRs and commits.\n\n### Creating the GitHub App\n\nRegister a new GitHub App at `https://github.com/organizations/{org}/settings/apps/new` with these settings:\n\n**Repository permissions:**\n\n| Permission    | Access       | Used for                           |\n| ------------- | ------------ | ---------------------------------- |\n| Contents      | Read \u0026 Write | git clone, push, branch management |\n| Pull requests | Read \u0026 Write | create PRs, post comments, merge   |\n| Issues        | Read \u0026 Write | issue sync, label management       |\n| Checks        | Read         | CI status polling in PR watcher    |\n| Metadata      | Read         | repo listing, auto-detection       |\n\n**Account permissions:**\n\n| Permission      | Access | Used for                           |\n| --------------- | ------ | ---------------------------------- |\n| Email addresses | Read   | user email for login (recommended) |\n\n**Organisation permissions:**\n\n| Permission | Access | Used for                |\n| ---------- | ------ | ----------------------- |\n| Members    | Read   | repo listing (optional) |\n\n**Other settings:**\n\n- **Callback URL:** `{PUBLIC_URL}/api/auth/github/callback`\n- **Request user authorization (OAuth) during installation:** Yes\n- **Expire user authorization tokens:** Yes (recommended, 8-hour lifetime with refresh)\n- **Webhook:** Can be left disabled (Optio uses polling)\n\n### Configuration\n\nAfter creating the app and installing it on your organisation, configure Optio via Helm values:\n\n```yaml\ngithub:\n  app:\n    id: \"123456\" # App ID (from app settings page)\n    clientId: \"Iv1.abc123\" # Client ID (for user OAuth login)\n    clientSecret: \"...\" # Client secret\n    installationId: \"789\" # Installation ID (from org install URL)\n    privateKey: | # PEM private key (for server-side tokens)\n      -----BEGIN RSA PRIVATE KEY-----\n      ...\n      -----END RSA PRIVATE KEY-----\n```\n\nWhen configured, users who log in via GitHub get a user access token that is used for all their git and API operations. Background workers (PR watcher, ticket sync) use the app's installation token. If the GitHub App is not configured, Optio falls back to the `GITHUB_TOKEN` PAT.\n\n### Using an existing secret\n\nIf you manage secrets externally (e.g., with [external-secrets-operator](https://external-secrets.io/), sealed-secrets, or vault-injector), you can reference an existing Kubernetes Secret instead of providing the values inline:\n\n```yaml\ngithub:\n  app:\n    existingSecret: \"my-github-app-secret\"\n```\n\nThe secret must contain these keys: `GITHUB_APP_ID`, `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_SECRET`, `GITHUB_APP_INSTALLATION_ID`, `GITHUB_APP_PRIVATE_KEY`.\n\n## Production Deployment\n\nOptio ships with a Helm chart for production Kubernetes clusters:\n\n```bash\nhelm install optio helm/optio \\\n  --set encryption.key=$(openssl rand -hex 32) \\\n  --set postgresql.enabled=false \\\n  --set externalDatabase.url=\"postgres://...\" \\\n  --set redis.enabled=false \\\n  --set externalRedis.url=\"redis://...\" \\\n  --set ingress.enabled=true \\\n  --set ingress.hosts[0].host=optio.example.com\n```\n\nSee the [Helm chart values](helm/optio/values.yaml) for full configuration options including OAuth providers, resource limits, and agent image settings.\n\n## Tech Stack\n\n| Layer    | Technology                                                       |\n| -------- | ---------------------------------------------------------------- |\n| Monorepo | Turborepo + pnpm                                                 |\n| API      | Fastify 5, Drizzle ORM, BullMQ                                   |\n| Web      | Next.js 15, Tailwind CSS 4, Zustand                              |\n| Database | PostgreSQL 16                                                    |\n| Queue    | Redis 7 + BullMQ                                                 |\n| Runtime  | Kubernetes (Docker Desktop for local dev)                        |\n| Deploy   | Helm chart                                                       |\n| Auth     | Multi-provider OAuth (GitHub, Google, GitLab)                    |\n| CI       | GitHub Actions (format, typecheck, test, build-web, build-image) |\n| Agents   | Claude Code, OpenAI Codex, GitHub Copilot                        |\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup, workflow, and conventions.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonwiggins%2Foptio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonwiggins%2Foptio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonwiggins%2Foptio/lists"}