{"id":51307440,"url":"https://github.com/jahilldev/olympian","last_synced_at":"2026-07-10T19:30:47.247Z","repository":{"id":361262023,"uuid":"1252318522","full_name":"jahilldev/olympian","owner":"jahilldev","description":"Hermes Agent orchestration for AI driven dark factory. Automate Github issue delivery for any project.","archived":false,"fork":false,"pushed_at":"2026-06-27T19:39:30.000Z","size":882,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-27T21:15:22.723Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/jahilldev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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-05-28T11:59:18.000Z","updated_at":"2026-06-27T19:39:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jahilldev/olympian","commit_stats":null,"previous_names":["jahilldev/olympian"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/jahilldev/olympian","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jahilldev%2Folympian","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jahilldev%2Folympian/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jahilldev%2Folympian/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jahilldev%2Folympian/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jahilldev","download_url":"https://codeload.github.com/jahilldev/olympian/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jahilldev%2Folympian/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35341768,"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-07-10T02:00:06.465Z","response_time":60,"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":[],"created_at":"2026-07-01T01:00:32.958Z","updated_at":"2026-07-10T19:30:47.240Z","avatar_url":"https://github.com/jahilldev.png","language":"TypeScript","funding_links":[],"categories":["Research, Multi-Agent, and Domain Projects"],"sub_categories":["Research and multi-agent work"],"readme":"# \u003cimg src=\"app/public/icons/icon.svg\" alt=\"\" width=\"50\" valign=\"middle\" /\u003e Olympian\n\nAn **AI dark factory**: label a GitHub issue and the service drives the\n[Hermes Agent](https://github.com/nousresearch/hermes-agent) CLI through the entire\ndelivery lifecycle — planning, implementation, self-review, and a draft PR — with a\nhuman only ever approving the plan and the final PR. No human writes code.\n\n```\nissue labeled ─▶ PLAN ─▶ (approve plan) ─▶ IMPLEMENT ─▶ VERIFY ─▶ SELF-REVIEW ─▶ OPEN DRAFT PR\n                  ▲          │                              ▲         │                  │\n                  └ feedback ┘                              └─ REVISE ◀─┘                ▼\n                                                  (verify OR review fails → revise → re-verify)\n                                                                                (approve PR) ─▶ DONE\n                                                                                         │\n                                                            changes requested ─▶ REVISE    ┘\n```\n\n## How it works\n\n1. **Trigger.** An issue is labeled with the trigger label (default `hermes`). A `Job` is created.\n2. **Plan.** Hermes reads the issue (in a clone of the repo) and posts an implementation\n   plan as an issue comment.\n3. **Plan approval loop.** A maintainer replies `/hermes approve` to proceed, or leaves a\n   comment with corrections — each comment re-plans until approved (capped by `MAX_PLAN_REVISIONS`).\n4. **Implement.** Hermes writes the code on a branch (`hermes/issue-\u003cn\u003e`) in a single pass.\n5. **Verify.** The repo's tests/build command — **discovered per-repo by the agent and\n   executed by the orchestrator** (ground truth) — runs as its own stage. A failure routes\n   to **Revise** and re-verifies, up to `MAX_VERIFY_ATTEMPTS` **per revision round**; a pass\n   advances to review.\n6. **Self-review.** Hermes reviews its own diff and returns a rubric verdict\n   `{confidence, verdict, dimensions{correctness,tests,planCoverage,security}, issues[]}`.\n   The PR gate is the **rubric** (all dimensions pass, no high/critical issues); confidence\n   is advisory only. A failure routes to **Revise** (→ Verify → review again), up to\n   `MAX_REVIEW_PASSES` **per revision round**. Every post-implement failure — verify or review —\n   funnels through Revise.\n7. **Draft PR.** The branch is pushed and a **draft** PR is opened, linking the issue.\n8. **PR approval loop.** Approve the PR review → the job is `DONE`. Request changes → a new\n   **revision round** opens: the feedback drives a scoped **Revise** (→ Verify → review again),\n   pushing an update — not a fresh full implementation.\n\n**Revision rounds.** `IMPLEMENT` is the first build only (round 1, opened on plan approval).\nEvery later round is a scoped `REVISE` of just the requested changes — each round of human\nfeedback (a PR change-request, a `/hermes revise` comment, or the dashboard's *Request changes*)\nincrements `revisionCycle` and starts a **fresh verify/review budget** so a new round is never\nshort-changed by the previous round's spent attempts. The orchestrator owns git; Hermes only\nedits files. **Prisma (SQLite) is the source of truth** for every job's state, plan revisions,\nagent runs, reviews, and the work queue — each Hermes prompt is rebuilt deterministically from\nthe database.\n\n## Tech stack\n\n- **NestJS** (ESM, `\"type\": \"module\"`, NodeNext) — modular service.\n- **Prisma + SQLite** — file-based; no DB server to provision.\n- **DB-backed queue** — a polling worker claims tasks with an atomic `UPDATE ... RETURNING`\n  (SQLite-safe), with exponential backoff/retry and per-job concurrency isolation.\n- **GitHub App** — webhooks, scoped installation tokens, comments, draft PRs, reviews.\n- **Hermes Agent CLI** — invoked headless: `hermes -z --yolo --source tool --max-turns N`.\n\nModule layout: `config`, `prisma`, `metrics`, `health`, `github`, `webhook`, `job`,\n`queue`, `worker`, `agent` (shared CLI runner + prompt fragments), `workspace`,\n`orchestrator`, and one module per agent work phase — `planning`, `implement`,\n`revise`, `review`, `verify`, `summary` — each owning that phase's prompts, models,\nand utilities.\n\n## Monorepo layout\n\nThis is an npm-workspaces monorepo, driven from the root:\n\n- **`api/`** — The orchestration service (API and agent orchestration).\n- **`app/`** — A management/overview UI for tasks (PWA application for monitoring).\n\nRoot scripts fan out to the workspaces: `npm run build`, `npm run lint`,\n`npm run typecheck`, `npm test`, `npm run test:e2e`, `npm run dev`, plus the\n`prisma:*` and `hermes:*` helpers. See the root [`package.json`](package.json).\n\n## Quick start\n\n### Development\n\n```bash\ncp api/.env.example api/.env    # fill in GitHub App + Hermes values\nnpm run setup                   # installs all workspaces + generates client + migrates\nnpm run dev                     # runs the api service in watch mode\n```\n\nProbe it:\n\n```bash\ncurl localhost:3030/health        # liveness\ncurl localhost:3030/health/ready  # readiness (DB)\ncurl localhost:3030/metrics       # Prometheus metrics\n```\n\n### Production (systemd)\n\nRun `setup.sh` once to register the `olympian` systemd service under your current user:\n\n```bash\n./setup.sh\n```\n\nThe script detects your Node/npm paths automatically and writes\n`/etc/systemd/system/olympian.service`, then enables it to start on boot. It uses `sudo`\nonly for the two privileged steps (writing the unit file and `systemctl daemon-reload`).\n\nAfter running the script:\n\n```bash\nsudo systemctl start olympian    # start the service\nsudo systemctl status olympian   # check it is running\nsudo journalctl -u olympian -f   # follow logs\n```\n\nOn every start the service runs `npm ci`, `npm run setup` (Prisma migrate), `npm run build` before launching the production server, so deployments are as\nsimple as `git pull \u0026\u0026 sudo systemctl restart olympian`.\n\nTo uninstall:\n\n```bash\nsudo systemctl disable --now olympian\nsudo rm /etc/systemd/system/olympian.service\nsudo systemctl daemon-reload\n```\n\n## Required external setup\n\nThese can't be scripted for you and gate the live run (not the build or tests):\n\n### 1. Register a GitHub App\n\n- **Permissions:** Issues _Read \u0026 write_, Pull requests _Read \u0026 write_, Contents _Read \u0026\n  write_, Metadata _Read-only_.\n- **Subscribe to events:** Issues, Issue comment, Pull request review, Installation.\n- **Webhook URL:** `https://\u003cyour-host\u003e/webhooks/github` and a **webhook secret**.\n- Generate a **private key** (PEM). Install the App on the target repos.\n- Put the values in `.env`: `GITHUB_APP_ID`, `GITHUB_WEBHOOK_SECRET`, and either\n  `GITHUB_APP_PRIVATE_KEY` (inline, `\\n`-escaped) or `GITHUB_APP_PRIVATE_KEY_PATH`.\n\nFor local dev, tunnel webhooks with [smee.io](https://smee.io) or ngrok to\n`localhost:3030/webhooks/github`.\n\n### 2. Provision Hermes\n\n```bash\nnpm run hermes:docker    # builds api/Dockerfile.agent; writes SANDBOX_MODE/DOCKER_AGENT_IMAGE/HERMES_HOME to api/.env\n```\n\nEach agent invocation runs inside an isolated container with only the job worktree and\nthe shared `HERMES_HOME` (`api/.hermes/`) bind-mounted. The orchestrator generates\n`config.yaml` from `config.base.yaml` at startup, injecting env-var overrides\n(`HERMES_CONTEXT_LENGTH`, `HERMES_COMPRESS_THRESHOLD`, `HERMES_MODEL_BASE_URL`) and\nrewriting `localhost` → `host.docker.internal` for in-container connectivity.\n\nAfter running the script, set your model and provider in `api/.env`:\n\n```\nHERMES_PRIMARY_MODEL=\u003cmodel\u003e\nHERMES_PRIMARY_PROVIDER=\u003cprovider\u003e\nHERMES_MODEL_BASE_URL=http://localhost:11434/v1   # if using a local endpoint\n```\n\nFor cloud providers, set each role's provider and add the matching API key to `api/.env` — keys are\nkeyed by provider, not by role:\n\n```\nHERMES_PRIMARY_PROVIDER=openai\nHERMES_JUDGE_PROVIDER=anthropic\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\n```\n\nHermes already knows each cloud provider's base URL, so `HERMES_MODEL_BASE_URL` is only needed for\nthe `custom` provider (local/self-hosted OpenAI-compatible endpoints). Keys are forwarded by name\ninto each agent container, so they never appear in the stored command line; the full list of\nrecognised provider env vars is in `api/.env.example`.\n\n**System mode (no Docker):** set in `api/.env`:\n\n```\nSANDBOX_MODE=none\nHERMES_HOME=~/.hermes   # your existing global Hermes home — credentials and model config already there\n```\n\nHermes reads its own `~/.hermes/config.yaml` directly. `HERMES_PRIMARY_MODEL`,\n`HERMES_PRIMARY_PROVIDER`, and `HERMES_TIMEOUT_MS` still apply as they are passed as\nCLI flags at invocation time.\n\n### 3. Camofox browser (optional)\n\n[Camofox](https://github.com/jo-inc/camofox-browser) is a self-hosted Firefox-based\nbrowser server with fingerprint spoofing. When configured, Hermes's browser tools\n(`browser_navigate`, `browser_click`, etc.) route through it instead of cloud providers\nlike Browserbase.\n\n**Start Camofox** (Docker, port 9377):\n\n```bash\ngit clone https://github.com/jo-inc/camofox-browser\ncd camofox-browser\nmake up          # builds + starts on port 9377\n```\n\n**Wire it to Olympian** — add to `api/.env`:\n\n```bash\nCAMOFOX_URL=http://localhost:9377\n```\n\nThat's all. In `SANDBOX_MODE=default` the orchestrator automatically rewrites the URL to\n`host.docker.internal:9377` before passing it into the agent container.\n\nTo opt out: leave `CAMOFOX_URL` empty (or unset) — Hermes falls back to `agent-browser`\n(a local Chromium install) or errors if no browser backend is available.\n\n## Using it\n\n1. Label an issue `hermes` (or your `TRIGGER_LABEL`).\n2. Hermes posts a plan. Reply with comments to iterate, or `/hermes approve` to build.\n3. A draft PR appears. **Approve** the PR review to finish, or **request changes** to loop.\n\nIssue-comment commands (maintainers only — write access required):\n\n- `/hermes approve` — approve the plan and start implementation\n- `/hermes cancel` — stop the job\n- `/hermes status` — report current state\n\n## Frontend\n\nA management dashboard is served at `http://localhost:3030` by the same NestJS process — no second server or Docker change required.\n\n**Job Planner** - Coming soon\n\n**Job list** — all jobs in reverse-chronological order, each showing state, confidence score, PR link, and the active task.\n\n**Job detail** — timeline of every state transition, all plan revisions (with diff), every review pass (confidence gauge, issues list), and the full list of agent runs.\n\n**Live stream** — while an agent is running, its LLM calls and tool invocations appear in real time. The Hermes agent ships a Langfuse/OTLP plugin that fires trace events during execution; the service receives them at `POST /langfuse/api/public/otel/v1/traces` and fans them out to the browser over SSE at `GET /stream/runs/:runId`.\n\nThe Astro + Preact frontend is built to `app/dist/` and served via NestJS `ServeStaticModule`. All routes not matching an API prefix fall back to `index.html` for client-side routing.\n\n## Sandboxing\n\n- `SANDBOX_MODE=default` (default) — each agent invocation runs inside `DOCKER_AGENT_IMAGE`.\n  Only the job's worktree and the Hermes memory files (`MEMORY.md`, `USER.md`, `skills/`,\n  `config.yaml`) are bind-mounted into the container. Requires Docker and a pre-built\n  image (`npm run hermes:docker`). Raising `WORKER_CONCURRENCY` runs N fully isolated\n  jobs in parallel.\n- `SANDBOX_MODE=none` — `hermes` runs as a subprocess directly in the job's worktree,\n  using the system-level Hermes binary (`HERMES_BIN`). No Docker required; useful for\n  local development or environments where Docker is unavailable.\n\n## Configuration\n\nAll config is validated at boot (see `src/config/config.model.ts`). Full reference and\ndefaults live in [`api/.env.example`](api/.env.example). Key knobs:\n\n| Variable                                                                        | Purpose                                                                                   |\n| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| `TRIGGER_LABEL`                                                                 | Label that starts a job (default `hermes`).                                               |\n| `REVIEW_CONFIDENCE_THRESHOLD`                                                   | Advisory self-review confidence shown in status/PR body (default 85); not the gate.       |\n| `MAX_PLAN_REVISIONS` / `MAX_VERIFY_ATTEMPTS` / `MAX_REVIEW_PASSES`              | Loop caps.                                                                                |\n| `WORKER_CONCURRENCY`                                                            | Parallel jobs (default 2).                                                                |\n| `SANDBOX_MODE`                                                                  | `default` (Docker container per run) or `none` (system Hermes binary, no container).      |\n| `HERMES_BIN` / `HERMES_HOME` / `HERMES_PRIMARY_MODEL`                           | Hermes invocation.                                                                        |\n| `HERMES_CONTEXT_LENGTH` / `HERMES_COMPRESS_THRESHOLD` / `HERMES_MODEL_BASE_URL` | Injected into Hermes `config.yaml` at startup; omit to let Hermes use its own defaults.   |\n| `HERMES_REVIEW_MODEL` / `HERMES_REVIEW_PROVIDER`                                | Optional independent model for the self-review cycle.                                     |\n| `HERMES_AUXILIARY_MODEL` / `HERMES_AUXILIARY_PROVIDER`                          | Optional model/provider for Hermes' background auxiliary tasks (compression, vision, web-extract); point at a smaller/faster model to speed up secondary work. |\n| `HERMES_TESTING_MODEL` / `HERMES_TESTING_PROVIDER`                              | Optional lighter-weight model for the testing step. Falls back to `HERMES_PRIMARY_MODEL`. |\n\n## Docker\n\n```bash\n# 1. Build the agent sandbox image.\nnpm run hermes:docker\n\n# 2. Configure the service.\ncd api \u0026\u0026 cp .env.example .env   # fill in GitHub App + model values\n\n# 3. Start.\ndocker compose up --build        # from repo root: builds the service image\n```\n\nSQLite lives on a named volume (`hermes-data`); there is no separate database container.\nAgent workspaces and the Hermes memory state (`MEMORY.md`, `USER.md`, `skills/`) are\nbind-mounted from `./workspaces/` and `./hermes-state/` at the **same absolute path**\ninside the service container, so sibling agent containers spawned via the Docker socket\ncan reference those directories using the same host path the service wrote to.\n\n## Operations\n\n- **Health:** `/health` (liveness), `/health/ready` (DB).\n- **Metrics:** `/metrics` — job counts by state, queue depth, agent run durations, webhook\n  counts, last review confidence.\n- **Audit trail:** every state transition (`JobStateTransition`) and every Hermes\n  invocation (`AgentRun`) is persisted; inspect with `npx prisma studio`.\n- **Retries:** failed tasks back off exponentially up to `QUEUE_MAX_ATTEMPTS`; exhausted\n  jobs are failed and a comment is posted. Orphaned tasks are reclaimed after `QUEUE_LOCK_TTL_MS`.\n\n## Tests\n\n```bash\ncd api\nnpm test        # unit\nnpm run test:e2e  # full webhook→plan→approve→implement→review→PR loop with a stub Hermes\n```\n\nThe e2e suite stubs the Hermes agent and fakes the GitHub API, so the entire pipeline runs\nin CI without real LLM or GitHub credentials.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjahilldev%2Folympian","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjahilldev%2Folympian","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjahilldev%2Folympian/lists"}