{"id":51262539,"url":"https://github.com/georgebuilds/kalos","last_synced_at":"2026-06-29T13:01:55.889Z","repository":{"id":355845884,"uuid":"1225054894","full_name":"georgebuilds/kalos","owner":"georgebuilds","description":"Open-source alternative to cloud coding agents. Self-hosted orchestrator that accepts tasks via REST API or MCP, runs AI agents in isolated Docker containers, and opens pull requests. Bring your own LLM: Anthropic, OpenRouter, Ollama, and more.","archived":false,"fork":false,"pushed_at":"2026-05-05T13:24:46.000Z","size":135,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T15:33:08.702Z","etag":null,"topics":["ai-agent","anthropic","automation","bun","coding-agent","developer-tools","devtools","docker","github-app","llm","ollama","open-source","orchestrator","pull-request","rest-api","self-hosted","typescript"],"latest_commit_sha":null,"homepage":"https://georgebuilds.github.io/kalos/","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/georgebuilds.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","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-04-29T22:45:10.000Z","updated_at":"2026-05-05T13:58:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/georgebuilds/kalos","commit_stats":null,"previous_names":["georgebuilds/kalos"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/georgebuilds/kalos","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgebuilds%2Fkalos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgebuilds%2Fkalos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgebuilds%2Fkalos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgebuilds%2Fkalos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/georgebuilds","download_url":"https://codeload.github.com/georgebuilds/kalos/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgebuilds%2Fkalos/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34927687,"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-29T02:00:05.398Z","response_time":58,"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":["ai-agent","anthropic","automation","bun","coding-agent","developer-tools","devtools","docker","github-app","llm","ollama","open-source","orchestrator","pull-request","rest-api","self-hosted","typescript"],"created_at":"2026-06-29T13:01:54.722Z","updated_at":"2026-06-29T13:01:55.875Z","avatar_url":"https://github.com/georgebuilds.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kalos\n\nKalos is an open-source, self-hosted coding agent orchestrator. You give it a task via REST API, it spins up Claude Code against the target repo (clone → branch → write code → commit → open PR), and hands you back a pull request URL. Optionally, it can also review PRs and retry failed CI automatically.\n\n---\n\n## How it works\n\n1. You `POST /tasks` with a repo and a description of what you want done\n2. Kalos queues the task and dispatches an agent when a slot is free\n3. The agent clones the repo, primes mise, runs `claude -p \"\u003cyour task\u003e\"` headless, then commits, pushes, and opens a PR\n4. Task status and logs are available via REST + SSE in real time\n5. Optionally: Kalos reviews the PR via webhook, and re-queues a fix task if CI fails\n\n---\n\n## Stack\n\n- **Runtime:** Node 22 everywhere — orchestrator, agent, Dockerfiles. TypeScript runs via `tsx` (no compile step).\n- **HTTP:** Hono on `@hono/node-server`\n- **Database:** `better-sqlite3` — raw SQL, WAL mode, no ORM\n- **Agent loop:** [Claude Code](https://docs.claude.com/en/docs/claude-code/overview) in headless mode (`claude -p ...`). Anthropic-only.\n- **Models:** registry of 6 anthropic models in [`packages/shared/src/models/index.ts`](packages/shared/src/models/index.ts) — Opus / Sonnet / Haiku, current + previous gen each\n- **GitHub:** `@octokit/rest`, GitHub App auth via hand-rolled JWT\n- **Docker:** hand-rolled Unix socket client over `node:http` — used only when `EXECUTOR=docker`\n- **MCP:** Streamable HTTP server exposing task management tools to MCP clients (Claude Desktop, etc.)\n- **Tests:** vitest\n- **Monorepo:** npm workspaces — `packages/orchestrator`, `packages/agent`, `packages/shared`\n\n---\n\n## Self-hosting\n\nThere are two deployment paths. Both require a GitHub App and an Anthropic API key. The difference is how agent tasks are executed.\n\n| | PaaS | VPS + Docker |\n|---|---|---|\n| `EXECUTOR` | `process` (default) | `docker` |\n| Docker required | No | Yes |\n| Deploy to | Railway, Fly, Render, etc. | Any Linux VPS |\n| Isolation | OS process | Docker container |\n| On orchestrator restart | Running tasks fail | Running tasks re-attach |\n\n### Step 0 — Create a GitHub App (required for both paths)\n\nGo to **GitHub → Settings → Developer settings → GitHub Apps → New GitHub App** and configure:\n\n- **Homepage URL:** anything (e.g. `http://localhost`)\n- **Webhook URL:** your deployment URL + `/webhooks/github` (e.g. `https://kalos.example.com/webhooks/github`) — required only for PR review and CI fix features\n\n**Permissions:**\n\n| Permission | Level | Required for |\n|---|---|---|\n| Contents | Read \u0026 Write | clone, branch, commit, push |\n| Pull requests | Read \u0026 Write | open and review PRs |\n| Metadata | Read-only | repo access |\n| Checks | Read-only | CI follow-through |\n\n**Subscribe to events** (only needed for PR review / CI fix):\n- Pull request\n- Check run\n\nAfter saving: generate a **private key** (downloads as a `.pem` file), then **install the app** on your account or org. Note the **App ID** (shown on the app settings page) and the **Installation ID** (the number at the end of the install URL: `github.com/settings/installations/XXXXXXX`).\n\n---\n\n### Path A — PaaS deployment (no Docker, recommended for individuals)\n\n`EXECUTOR=process` runs the agent as a child Node process on the same machine as the orchestrator. No Docker daemon needed, so you can deploy to any platform that runs a persistent Node process.\n\n**Works on:** Railway, Fly.io, Render, any VPS, your laptop.\n\n**Requirements:**\n- Node 22 on the host. (The orchestrator and agent both run as Node processes; in process mode the agent shares the orchestrator's host.)\n- Persistent disk for the SQLite database (`DATABASE_URL`). Most PaaS platforms offer this as a volume.\n- Claude Code on PATH: `npm install -g @anthropic-ai/claude-code`. The agent shells out to `claude` for every task.\n- Recommended: install [mise](https://mise.jdx.dev) on the host (`curl https://mise.run | sh`). The agent reads the target repo's `.tool-versions` / `.nvmrc` / `go.mod` / `composer.json` and uses mise to provide the right node/go/php version when running tests. Without mise the agent falls back to whatever interpreters are already on PATH. Cache lives at `KALOS_TOOLCHAIN_DIR` (default `~/.local/share/kalos/mise`) and is shared across tasks.\n\n\u003e Process mode means the host carries the full agent toolchain (node, mise, claude code, build-essential for any compiled languages) plus per-task workspace disk. Docker mode keeps the orchestrator host slim — the heavy stuff lives inside the per-task container instead.\n\n#### 1. Clone the repo\n\n```bash\ngit clone https://github.com/georgebuilds/kalos\ncd kalos\nnpm install\n```\n\n#### 2. Run the wizard\n\n```bash\nnpm run dev:orchestrator\n```\n\nThe first run drops you into an interactive setup wizard that prompts for your Anthropic key, default model, and GitHub App config, validates each against the live API, and writes the result to `.env` + the kalos database. Re-run the orchestrator after the wizard completes.\n\nIf you'd rather skip the wizard, set `setup_complete=true` in the `settings` table and provide these env vars manually:\n\n```env\nEXECUTOR=process\n\nANTHROPIC_API_KEY=sk-ant-...\n\nGITHUB_APP_ID=\nGITHUB_APP_PRIVATE_KEY_PATH=kalos.pem   # path to the .pem file you downloaded\nGITHUB_INSTALLATION_ID=\n\nKALOS_API_KEY=...                       # required — generate with: openssl rand -hex 32\nKALOS_TRUST_PROXY=true                  # set this if running behind a reverse proxy\n```\n\n**`KALOS_API_KEY` is required.** The orchestrator refuses to start without it (the wizard auto-generates one for new installs). Set `KALOS_ALLOW_OPEN=true` to opt back into open auth — intended for trusted localhost dev only; do not set in production.\n\n#### 3. Verify\n\n```bash\ncurl http://localhost:3000/health\n```\n\nYou should get `{\"ok\":true}`.\n\n**Security note:** with `EXECUTOR=process` the agent shares the orchestrator's OS user and filesystem. Only run tasks from repos and users you trust.\n\n---\n\n### Path B — VPS with Docker\n\n`EXECUTOR=docker` runs each agent inside an isolated Docker container (512 MB RAM cap, `--cap-drop ALL`). Use this for team deployments or when you want stronger isolation.\n\n**Requires:** a Linux VPS with Docker daemon, and the `kalos-agent` image built or pulled. The agent image already includes Claude Code (`@anthropic-ai/claude-code` installed globally), node 22, and mise.\n\nPre-built images are published to GHCR at `ghcr.io/georgebuilds/kalos-orchestrator:latest` and `ghcr.io/georgebuilds/kalos-agent:latest`.\n\nThe agent image ships with [mise](https://mise.jdx.dev) and pre-seeded copies of node 20/22 and go 1.23. A named Docker volume (`KALOS_TOOLCHAIN_VOLUME`, default `kalos-mise-cache`) persists the cache across tasks so first-task latency for any new (language, version) pair is paid once. PHP is **not** pre-seeded — its plugin compiles from source — but the build deps are baked in, so the first task that wants `php@8.x` will install it (slow), and every task after will reuse the volume.\n\n**Minimum spec:** 1 vCPU / 1 GB RAM / 25 GB disk (a $7/mo Hetzner or DigitalOcean box works fine).\n\n#### 1. Provision the server\n\nSSH into a fresh Ubuntu 24.04 server and run:\n\n```bash\ncurl -fsSL https://get.docker.com | sh \u0026\u0026 \\\n  fallocate -l 2G /swapfile \u0026\u0026 chmod 600 /swapfile \u0026\u0026 mkswap /swapfile \u0026\u0026 swapon /swapfile \u0026\u0026 \\\n  echo '/swapfile none swap sw 0 0' \u003e\u003e /etc/fstab \u0026\u0026 \\\n  git clone https://github.com/georgebuilds/kalos.git /opt/kalos \u0026\u0026 \\\n  chmod +x /opt/kalos/deploy/setup.sh\n```\n\n#### 2. Upload your PEM\n\nFrom your local machine:\n\n```bash\nscp ~/Downloads/your-app.pem root@YOUR_SERVER_IP:/opt/kalos/kalos.pem\n```\n\n#### 3. Run the setup script\n\n```bash\nbash /opt/kalos/deploy/setup.sh\n```\n\nThe script walks you through every environment variable interactively, pulls the published images, and starts the stack. Takes about two minutes.\n\n#### 4. Verify\n\n```bash\ncurl http://localhost:3000/health\n```\n\n**Day-to-day commands** (run from `/opt/kalos`):\n\n```bash\nmake deploy    # pull the latest image and restart\nmake logs-prod # tail live logs\n```\n\n---\n\n## Local development\n\n```bash\ngit clone https://github.com/georgebuilds/kalos\ncd kalos\nnpm install\nnpm run dev:orchestrator\n```\n\nThe first invocation runs the setup wizard. After that, `npm run dev:orchestrator` reloads on file changes via `tsx watch`.\n\nDocker is not required for local development — `EXECUTOR=process` is the default.\n\nIf you want to test the Docker executor locally:\n\n```bash\nmake agent-image      # builds kalos-agent:latest\nEXECUTOR=docker npm run dev:orchestrator\n```\n\n---\n\n## Dashboard\n\nVisit `http://localhost:3000/` in a browser for a live read-only view of recent tasks, env-var health checks, and the active default model. Same `X-Api-Key` (passed via `?key=` on the URL or the `X-Api-Key` header) — gated by the same auth as the REST API.\n\n---\n\n## REST API\n\nAll endpoints require the `X-Api-Key` header. (The orchestrator refuses to start without `KALOS_API_KEY`; the only way to run open is to explicitly set `KALOS_ALLOW_OPEN=true`.)\n\n### Create a task\n\n```http\nPOST /tasks\nContent-Type: application/json\nX-Api-Key: your-api-key\n\n{\n  \"repo\": \"owner/repo\",\n  \"description\": \"Add input validation to the login form\",\n  \"baseBranch\": \"main\",        // optional, defaults to \"main\"\n  \"modelId\": \"opus-4.7\"        // optional; defaults to repo override → global default\n}\n```\n\nResponse:\n\n```json\n{ \"id\": \"01HXYZ...\" }\n```\n\n### List recent tasks\n\n```http\nGET /tasks\nGET /tasks?status=pending,running        // filter — comma-separated\nGET /tasks?status=running\u0026limit=50\n```\n\n### Get a task\n\n```http\nGET /tasks/:id\n```\n\nTask statuses: `pending` → `running` → `completed` | `failed` | `cancelled`.\n\nCompleted tasks include a `prUrl` field with the pull request URL.\n\n### Cancel a task\n\n```http\nPOST /tasks/:id/cancel\n```\n\nCancels a pending or running task. Returns 409 if the task is already in a terminal state.\n\n### Stream task logs\n\n```http\nGET /tasks/:id/logs\n```\n\nReturns a Server-Sent Events stream. Each event is a JSON object with `line` and `ts`. A final `event: done` is emitted when the task finishes.\n\n```bash\ncurl -N -H \"X-Api-Key: your-key\" http://localhost:3000/tasks/01HXYZ.../logs\n```\n\n### Models \u0026 defaults\n\n```http\nGET /models                              # list registry entries\nGET  /settings/default_model\nPUT  /settings/default_model             # body: { \"modelId\": \"sonnet-4.6\" }\nGET  /repos/:owner/:repo/settings        # per-repo override\nPUT  /repos/:owner/:repo/settings        # body: { \"modelId\": \"opus-4.7\" } or { \"modelId\": null }\nDELETE /repos/:owner/:repo/settings\n```\n\nModel precedence at dispatch: per-task `modelId` → per-repo override → global default → registry fallback (`sonnet-4.6`).\n\n### GitHub webhook\n\n```http\nPOST /webhooks/github\n```\n\nHandles `pull_request` events (triggers automatic PR review) and `check_run` events (triggers CI fix retry). Requires `GITHUB_WEBHOOK_SECRET`.\n\n---\n\n## MCP server\n\nKalos exposes its task management as an MCP server via Streamable HTTP at `/mcp`. Tools: `create_task`, `get_task`, `list_tasks` (with optional `status` filter), `cancel_task`, `get_task_logs`. See [AGENTS.md](./AGENTS.md) for the full schema and a Claude Desktop config snippet.\n\n---\n\n## Environment variables\n\n| Variable | Default | Description |\n|---|---|---|\n| `EXECUTOR` | `process` | `process` — agent runs as a child process; `docker` — agent runs in a container |\n| `PORT` | `3000` | HTTP port |\n| `DATABASE_URL` | `kalos.db` | SQLite file path (must be on persistent storage in PaaS deployments) |\n| `KALOS_API_KEY` | — | Bearer token for the REST API + MCP server. **Required** — orchestrator refuses to start without it (wizard auto-generates one) |\n| `KALOS_ALLOW_OPEN` | `false` | Opt back into open auth when `KALOS_API_KEY` is unset. Localhost dev only — do not set in production |\n| `KALOS_TRUST_PROXY` | `false` | Trust `X-Forwarded-For` for rate limiting — set to `true` behind a reverse proxy |\n| `MAX_CONCURRENT_TASKS` | `1` | Max agents running simultaneously |\n| `WORKER_POLL_INTERVAL_MS` | `2000` | How often the worker checks for pending tasks |\n| `TASK_TIMEOUT_MS` | `600000` | Per-task timeout in ms |\n| `CI_FIX_MAX_ATTEMPTS` | `3` | Max CI fix retries per task. Set to `0` to disable |\n| `ANTHROPIC_API_KEY` | — | Anthropic API key — passed to Claude Code as the agent loop's auth |\n| `GITHUB_APP_ID` | — | GitHub App ID |\n| `GITHUB_APP_PRIVATE_KEY_PATH` | `kalos.pem` | Path to the GitHub App private key PEM file |\n| `GITHUB_APP_PRIVATE_KEY` | — | Inline PEM string (alternative to path) |\n| `GITHUB_INSTALLATION_ID` | — | GitHub App installation ID |\n| `GITHUB_WEBHOOK_SECRET` | — | HMAC secret for validating GitHub webhook payloads |\n| `KALOS_WORKSPACE_ROOT` | `~/.local/share/kalos/workspaces` | Per-task clone scratch (`EXECUTOR=process` only) |\n| `KALOS_TOOLCHAIN_DIR` | `~/.local/share/kalos/mise` | Shared mise data dir for cached runtimes (`EXECUTOR=process` only) |\n| `DOCKER_SOCKET` | `/var/run/docker.sock` | Docker daemon socket (`EXECUTOR=docker` only) |\n| `AGENT_IMAGE` | `kalos-agent:latest` | Docker image for agent containers (`EXECUTOR=docker` only) |\n| `KALOS_TOOLCHAIN_VOLUME` | `kalos-mise-cache` | Docker named volume backing the in-container mise cache (`EXECUTOR=docker` only) |\n\nThe default model lives in the kalos database (`settings.default_model_id`), set by the wizard or via `PUT /settings/default_model`.\n\n---\n\n## Concurrency\n\nKalos defaults to `MAX_CONCURRENT_TASKS=1` — one agent runs at a time, the rest queue. This is the right default for personal use.\n\nFor team or org deployments, increase `MAX_CONCURRENT_TASKS` to match your resources. With `EXECUTOR=docker`, each agent is capped at 512 MB RAM. With `EXECUTOR=process`, agents share the host's memory — size accordingly.\n\n---\n\n## Security\n\n- **`EXECUTOR=process`:** the agent runs as the orchestrator's OS user with access to the host filesystem. Set `KALOS_API_KEY` and only accept tasks from repos you trust. Not suitable for multi-tenant use.\n- **`EXECUTOR=docker`:** containers run with `--cap-drop ALL` and a 512 MB memory limit. The only mount is the named toolchain volume (`kalos-mise-cache`) at `/cache/mise` — agents have no access to the host filesystem. Better isolation than process mode, but prompt injection could still exfiltrate data over the network.\n- The agent strips secrets (`ANTHROPIC_API_KEY`, `GITHUB_TOKEN`) from the env it hands to Claude Code's Bash tool. Claude can't `env | curl` your tokens to a third party.\n- API key auth via `KALOS_API_KEY` (strongly recommended in both cases)\n- Webhook payloads validated with HMAC-SHA256 against `GITHUB_WEBHOOK_SECRET`\n- Rate limiting on task creation: 20 requests per IP per minute\n\n---\n\n## Development\n\n```bash\n# Type check all packages\nnpm run typecheck\n\n# Run tests (vitest)\nnpm test\n\n# Format\nnpm run format\n\n# Format check (used in CI)\nnpm run format:check\n```\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines and [AGENTS.md](./AGENTS.md) for the full architecture reference.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgebuilds%2Fkalos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeorgebuilds%2Fkalos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgebuilds%2Fkalos/lists"}