Skip to content

Releases: selfhostr/orch

v0.9.1

Choose a tag to compare

@Theroxat Theroxat released this 04 Nov 14:36
55d67ee

Moved to selfhostr/orch

The project is now simply orch and lives at github.com/selfhostr/orch. The old Theroxat/claude_orch URLs redirect here. Documentation: https://orch.selfhostr.io/docs/

New image location

Releases are now published only as:

  • ghcr.io/selfhostr/orch-server
  • ghcr.io/selfhostr/orch-web
  • ghcr.io/selfhostr/orch-agent

ghcr.io/theroxat/orch-* gets no new releases. deploy/server/compose.yaml uses the new names. If your server .env pins ORCH_VERSION to an old release, set it to 0.9.1, and remove any ORCH_AGENT_IMAGE_REPO=ghcr.io/theroxat/orch-agent override (the default is now ghcr.io/selfhostr/orch-agent).

Members: switch your agent once

Agents installed with v0.9.0 or older only accept updates from ghcr.io/theroxat/orch-agent, so one-click update answers "This agent still uses the old image" for them. Run this once on the agent's machine (Linux; on macOS use sed -i ''):

cd ~/orch && sed -i 's#ghcr.io/theroxat/#ghcr.io/selfhostr/#g' compose.yaml .env && sed -i '/^ORCH_AGENT_TAG=/d' .env && docker compose pull agent && docker compose up -d agent

Later updates work with one click again. See Updating agents.

Fixes

  • Renamed or transferred repositories stay linked: the repository renamed/transferred, installation created and repositories added webhooks now update the project's stored full name and installation (both used to mint tokens), and restore a project that was archived after a lost access (#75)

Upgrade

Server: set ORCH_VERSION=0.9.1 (or keep latest), then from deploy/server:

git pull
docker compose pull
docker compose up -d

v0.9.0

Choose a tag to compare

@Theroxat Theroxat released this 26 Oct 20:34
2276ce1

Security

  • Compose guard completed (agent): strict allowlists on every key of the resolved docker compose config model (services, builds, deploy, volumes, networks, secrets, configs), hardened sidecars (cap_drop: ALL plus a harmless baseline, no-new-privileges, CPU/memory/PID limits, no published ports or fixed container names) and a corpus of real compose files tested against it. It also closes a host escape: a sidecar with a writable bind of a directory could swap a path that another sidecar mounts (including a top-level secrets/configs file) for a symlink to / before that mount. Such writable binds are now refused. Repositories whose compose files used one of the refused features have to adapt them (see the security docs) (#71, @laupernoe)
  • Private repository access re-checked: the stored project owner is only a hint. Every view and action on a private repository (usage, history, board, templates, pool, MCP tools, notifications, task offers and repository tokens) asks GitHub whether the user still has a role on it. Answers are cached, and webhooks invalidate them. A 403 or 404 denies at once. During a GitHub outage (5xx, 429, rate-limited 403 or 401), the last verified role is kept for a grace window, then access is denied (#67, @laupernoe)
  • Stronger secret redaction: one shared module masks secrets in live logs (agent and server), the local run log, failure messages and notifications. It covers common token formats and every value the agent knows for a run, in its common encodings (JSON-escaped, URL, hex, base64), also when a value is split across lines or batches. All rules run in linear time (#72, @laupernoe)
  • Signed webhooks: generic JSON webhooks are signed according to Standard Webhooks (webhook-id, webhook-timestamp, webhook-signature). A secret is generated or rotated in the notification settings and is shown only once. During a rotation, the previous secret also signs for 24 hours (#70, @laupernoe)

Changes

  • Several server instances: run orch behind a load balancer with Postgres as the only shared component. The dispatcher and the maintenance jobs each run on an elected leader, agent messages are relayed between instances and live output is mirrored to the instance that has viewers. Notification deliveries go through a durable queue that another instance takes over if the first one dies. The auth and agent-connect rate limits are shared across instances. See Running several server instances in the installation docs (#68, @laupernoe)
  • English and French interface: every page is translated through typed catalogs, and a CI check keeps the two locales in sync. English is the default; French is used only when chosen with the EN | FR switch, and the choice is remembered on the browser (#69, @laupernoe)
  • Faster history search: trigram index on task titles and indexes on issue and PR numbers (#73, @laupernoe)
  • Landing site: a static site in site/, published with GitHub Pages (#66, @laupernoe)

Many thanks to @laupernoe, who wrote every pull request in this release.

New configuration

Variable Default Meaning
ORCH_REPO_ACCESS_TTL_SEC 300 How long a user's role on a repository is cached
ORCH_REPO_ACCESS_GRACE_SEC 900 GitHub outage grace for private repositories
NOTIFY_QUEUE_POLL_MS 5000 How often the notification queue is polled for retries and leftovers of other instances
ORCH_INSTANCE_ID hostname Unique name of this instance among those sharing the database
ORCH_CLUSTER_NAME orch Instances with the same database and name cooperate
ORCH_INSTANCE_HEARTBEAT_MS 10000 Instance heartbeat; an instance silent for 3 heartbeats is considered gone
ORCH_LEADER_RETRY_MS 5000 How often a follower tries to take a free leadership

All of these are optional, and the defaults suit a single instance.

Upgrade

Server: set ORCH_VERSION=0.9.0 (or keep latest), then from deploy/server:

git pull
docker compose pull
docker compose up -d

git pull also brings the new deploy/server/upstream.caddy, which compose.yaml now mounts into Caddy. Three additive migrations run on start: the pg_trgm extension and the history search indexes, the webhook signing secret columns, and the multi-instance tables. pg_trgm is a trusted extension, so the database owner can create it. For several instances, add -f compose.replicas.yaml (see the installation docs). Every instance needs the same .env, including ORCH_ENCRYPTION_KEY.

Agents: orch update gets the completed compose guard and the new redaction.

Webhook receivers: verify the signature once a secret has been generated in the notification settings, and dedupe on webhook-id.

v0.8.1

Choose a tag to compare

@Theroxat Theroxat released this 24 Oct 04:13
ae9bc0d

Changes

  • E-mail address confirmation: notification e-mails (and test messages) only go to an address the member has confirmed through a single-use link valid 24 hours (only a hash of the token is stored). Confirmation e-mails are limited to 3 per hour and 10 per day per member (#62, @laupernoe)
  • Metrics: prom-client (deprecated) replaced by its official successor @prometheus-io/client; existing /metrics series are unchanged, two event-loop utilization series are added (#61, @laupernoe)
  • Accessibility: the welcome wizard moves focus to the step title as soon as the step is shown instead of after its animation, so a Tab pressed during the transition is no longer undone; this also fixes a flaky browser test (#63, @laupernoe)

Many thanks to @laupernoe, who wrote every pull request in this release.

Upgrade

Server: set ORCH_VERSION=0.8.1 (or keep latest), then from deploy/server:

git pull
docker compose pull
docker compose up -d

One additive migration applies on start (e-mail confirmation columns). E-mail addresses saved before this release are pending: members must press Resend confirmation in their notification settings and open the link before e-mail notifications resume. Without SMTP_HOST nothing changes. Agents: orch update.

v0.8.0

Choose a tag to compare

@Theroxat Theroxat released this 23 Oct 19:09
fc96bc3

Highlights

  • Live task logs: follow a running task's output in the web UI, streamed from the agent (SSE) (#48, @laupernoe)
  • Notifications: in-app bell plus Slack, Discord, generic webhook and e-mail channels, with per-event preferences (#49, @laupernoe)
  • Web Push: browser notifications, even with the tab closed (#58, @laupernoe)
  • Installable app (PWA): install orch from the browser, with an offline page and a "New version available" prompt (#54, @laupernoe)
  • Usage page: weighted tokens, runs, success rate and project budgets over 7/30/90 days (#50, @laupernoe)
  • Task history: search, filters and pagination over every task that ran (#51, @laupernoe)
  • Task templates: reusable task skeletons with {{placeholders}}, personal or shared with a project, plus 4 built-in ones (#60, @laupernoe)

Operations

  • Observability: Prometheus /metrics (internal network only), /readyz, optional OpenTelemetry traces and a ready-made Prometheus + Grafana stack in deploy/observability (#53, @laupernoe)
  • Scheduled backups: cron schedule, daily/weekly/monthly rotation, optional age encryption and S3-compatible upload, and backup/restore.sh to restore (#52, @laupernoe)
  • Rate limiting on every route family, with 429 + Retry-After and a per-connection cap on agent messages (#55, @laupernoe)
  • Server image down from 904 MB to ~384 MB (#59, @laupernoe)
  • Dispatcher loads one snapshot per tick instead of queries per task × member (#56, @laupernoe)
  • Faster browser-test CI (#57, @laupernoe) and Renovate for dependency updates, every PR reviewed by hand (#47, @laupernoe)

Many thanks to @laupernoe, who wrote every pull request in this release.

New optional settings (deploy/server/.env)

Everything below is off or has a safe default; nothing needs to be set to upgrade.

Feature Variables
E-mail notifications SMTP_HOST (enables the channel), SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASSWORD, SMTP_FROM
Web Push VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT (all three; generate the pair with docker run --rm node:22-alpine npx -y web-push generate-vapid-keys)
Metrics / tracing METRICS_ENABLED, METRICS_TOKEN, OTEL_EXPORTER_OTLP_ENDPOINT; GRAFANA_ADMIN_PASSWORD for deploy/observability
Backups BACKUP_SCHEDULE, BACKUP_KEEP_DAILY/WEEKLY/MONTHLY, BACKUP_VOLUME, BACKUP_AGE_RECIPIENT, BACKUP_S3_*, POSTGRES_MAJOR; ORCH_RESTORE_TMPDIR for restore.sh
Rate limits RATE_LIMIT_ENABLED, RATE_LIMIT_WINDOW_SEC, RATE_LIMIT_{API,AUTH,WEBHOOK,MCP,HEAVY,STREAM,AGENT_CONNECT}_MAX, RATE_LIMIT_AGENT_MSG_PER_SEC (see docs/configuration.md)
Notification delivery NOTIFY_MAX_ATTEMPTS, NOTIFY_RETRY_BASE_MS, NOTIFY_RETENTION_DAYS

BACKUP_HOUR_UTC and BACKUP_RETENTION_DAYS still work (they map to BACKUP_SCHEDULE and BACKUP_KEEP_DAILY).

Upgrade

Server: set ORCH_VERSION=0.8.0 (or keep latest), then from deploy/server:

git pull
docker compose pull
docker compose up -d
docker compose up -d --build backup   # the backup image is built locally and changed in this release

Five additive migrations apply on start (notifications, task history index, Web Push subscriptions, task templates). The Caddy routes changed (/metrics and /readyz are never public, PWA files are revalidated), so git pull before up -d. Agents: orch update.

Optional: to collect metrics, set METRICS_ENABLED=true and start deploy/observability (see the Observability docs page).

v0.7.0

Choose a tag to compare

@Theroxat Theroxat released this 22 Oct 11:57
bbdc881

Highlights

  • Documentation site on Read the Docs: https://claude-orch.readthedocs.io (quickstart, installation, concepts, CLI and MCP reference, configuration, security model, FAQ), built in CI with warnings as errors (#36, @laupernoe)
  • Web UI: Documentation and GitHub links in the header (#44) and a Claude orange palette, with ochre for "pending" (#45), both by @laupernoe
  • README refreshed, with screenshots and a link to the docs (#42)

Under the hood

  • Server: new indexes for the dispatcher hot paths (additive migration 20261031000000_hot_path_indexes), and GET /api/tasks now runs one query for every visible project (#41, @laupernoe)
  • Agent image: multi-stage build (#40, @laupernoe)
  • CI: production images built in parallel, actions bumped (#39, @laupernoe)
  • Root pnpm scripts, noUnusedLocals/noUnusedParameters, dead code removed (#43, @laupernoe)

Many thanks to @laupernoe for nearly all of this release.

Upgrade

Server: set ORCH_VERSION=0.7.0 (or keep latest), then docker compose pull && docker compose up -d; the migration applies on start. Agents: orch update.

v0.6.1

Choose a tag to compare

@Theroxat Theroxat released this 21 Oct 18:56
894dfcf

Web UI fixes found by a new browser (Playwright) test suite.

Fixes

  • No more CSP script-src eval violation on every page load (zod runs jitless in the browser).
  • OAuth consent: a double click on Approve sends a single request.
  • Backlog: Retry only appears on tasks that failed since the last retry or need attention; the Import label no longer shows literal backticks; the board fits at 1280px without horizontal scroll.
  • Unknown URLs show a "Page not found" page with a link home.
  • /welcome wizard: Log out next to Exit setup.
  • Pool: each member card lists their machines (paused, online, offline) and shows Paused when every online machine is paused (additive machines field in GET /api/pool).
  • Color contrast fixes (ok badge, wizard status, revoked token card, badges) in both themes.

Tests / CI

  • New test/ui Playwright suite, run with ./dev test:ui and in CI (screenshots and report uploaded on failure). CSP violations and axe serious/critical findings fail it.

Update: docker compose pull && docker compose up -d (server), orch update (agent).

v0.6.0

Choose a tag to compare

@Theroxat Theroxat released this 21 Oct 16:48
c0a3598

v0.6.0: new look, modern stack, owners in their own pool

Huge thanks to @laupernoe (Noé Lauper), who did most of this release: the full dependency upgrade (#5), the web redesign (#22), and four web fixes (#24, #26, #27, #28).

Web redesign (#22, @laupernoe)

  • A new "signal board" design for the whole web app, with self-hosted Overpass fonts. The CSP is unchanged.
  • Everything from v0.5.x carries over in the new style: the outdated-agent banner, failed-attempt info, Retry, why-not-running, the Claude login state, onboarding, Access and the version footer.

Web fixes (@laupernoe)

  • /backlog?task=<id> highlights the linked task (#24).
  • Removing a project refreshes the list of already-added repositories (#26).
  • Signing in takes you back to the page you asked for (#27).
  • The Access page clears an old error after a success (#28).

Dependency upgrade (#5, @laupernoe)

  • React 19, Vite 8, Zod 4, Prisma 7, pnpm 12 and Node 24, in every image.
  • Prisma 7 was checked against a copy of the production database: no schema drift and no data change.

New: owners can join their own pool (#34)

  • Each project card in the owner view has a Participate in my pool block with a budget % and a mode. An owner's own participation is approved automatically.
  • The onboarding step "Add your repository" offers the same block as an optional follow-up.
  • The dispatcher treats the owner like any other participant. The consent rule is unchanged: no work runs without an active participation that the member saved.

New: clearer member rejection (#34)

  • Owners can add an optional reason when rejecting. The member sees it next to "Rejected by owner".
  • The project card lists rejected members, with Undo: back to pending and Undo: approve.
  • When a previously rejected member asks again, the owner's pending list shows previously rejected (reason).
  • Everything is audited: participation.rejected with the reason, participation.rejection_undone, and reapplied and ownerAutoApproved on updates. This release also fixes the audit action name participation.rejectd, which is now participation.rejected.
  • Migration 20261030000000_participation_rejection adds two nullable columns. The README now documents how migrations are named.

Upgrade

Update the server first (docker compose pull && docker compose up -d). It applies the new migration automatically. Then update each agent with orch update.

v0.5.2

Choose a tag to compare

@Theroxat Theroxat released this 21 Oct 15:21
ded0f48

Fix: Claude 401 on auto runs ("OAuth access token is invalid")

Root cause. orch login read the token from the claude setup-token screen by stripping ANSI codes from the terminal stream. Claude Code's renderer is differential: it moves the cursor and skips cells that did not change. As a result, the saved token could silently lose characters, and every run then failed with a 401. v0.5.1 also cleared the server's "login invalid" flag on any report that said a token was present, which caused a loop of re-offers and new failures.

What changed

  • orch login
    • Reads the token from a real terminal emulation of the setup screen.
    • Checks its shape (sk-ant-oat…, length) before saving.
    • If it cannot read the token reliably, asks you to paste it (hidden input). Wrapped pastes are handled.
    • Then verifies the token with a real one-turn Claude call and prints ✓ Claude login verified or ✗ Claude rejected this token (401). Run orch login again.
  • orch doctor (new): shows the Claude binary and version, whether the token is present and well-formed, and runs the same real check.
  • Automatic re-check: the agent re-checks the token whenever the token file changes. It stores a hash, never the token. The result goes to the server as the new claude.auth message.
  • Server: only a successful real check, or a successful run, clears the "Claude login invalid" flag. A flagged agent gets no automatic offers. My Server, Pool and the getting-started checklist show when the login was last verified and why it failed.
  • Task sandbox: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL and the provider switches are blanked, so a repository image or containerEnv cannot override your Claude token.
  • CI: the agent image is smoke-tested ($ORCH_CLAUDE_BIN --version).

Upgrade

Update the server first, then each agent with orch update. Then run orch login again (the stored token may be corrupt) and orch doctor.
Agents still on v0.5.1 that are flagged stay flagged until they update and pass the check.

v0.5.1

Choose a tag to compare

@Theroxat Theroxat released this 21 Oct 13:46
b35a70a

Highlights

Stuck backlog fix (#32)

  • The agent now classifies failures as env, claude_auth, rate_limited, timeout or task. Only task and timeout count toward the 24 h shut-out.
  • An expired Claude login flags the agent ("Claude login expired: run orch login") and pauses AUTO offers.
  • Environment setup failures mark the task "needs attention" after 3 attempts.
  • Backlog cards show "Failed N times: last error" and a Retry button (owner/creator, audited). Also available as POST /api/tasks/:id/retry and the MCP tool retry_task.
  • New "Why isn't this running?" panel, computed by the dispatcher itself.
  • #31: duplicate agent.update_done audit entries are now deduplicated.

Other changes since v0.5.0

  • fix(pool): a submitter who does not participate can see the pool of the project (#25) - Thanks @laupernoe
  • fix(agent): a re-run can push over its task branch from an earlier attempt (#21) - Thanks @laupernoe
  • fix(agent): fence server cancels during the push and the preparation (#19) - Thanks @laupernoe
  • fix(agent): a stop during a run no longer loses its task.finished (#17) - Thanks @laupernoe
  • fix(agents): a duplicate ack no longer turns a refused accept or claim into a success (#16) - Thanks @laupernoe
  • fix(participation): concurrent PUTs could push a member's budget above 100% (#15) - Thanks @laupernoe

Upgrade notes

  • The DB migration 20261028000000_failure_classes applies automatically.
  • Update agents with orch update (old agents are still classified server-side).

v0.5.0

Choose a tag to compare

@Theroxat Theroxat released this 21 Oct 12:21
26f2ce7

Highlights

  • One-click agent update (#18): the web app shows a banner when an agent runs an older version and can update it with one click. The server version now appears in the footer.
  • Hardened task sandbox (#23): the compose guard now accepts only allowlisted keys, uses a real YAML parser, and refuses provider, privileged hooks, use_api_socket, gpus, foreign networks, volume and network driver options, and local build caches. Every symlink in the committed tree is checked, and the whole compose project is paused before a commit. This supersedes #8 and #9, closes #14, and includes commits by @laupernoe.

Fixes

  • #20: the env_file override now applies to every compose call (build/up). Compose files no longer set a fixed container_name. E2E runs are isolated with ORCH_E2E_PROJECT.
  • #7: a connected agent loses access when its owner's access is removed. A GitHub outage gets a grace period, and suspension (4403) is not fatal. Thanks @laupernoe.
  • #11: if orch done fails, the manual session keeps its .git. Thanks @laupernoe.
  • #12: the avatar fallback on the admin Access page was blocked by the CSP. Thanks @laupernoe.
  • #13: the OAuth consent page can no longer be submitted twice, and the server issues one authorization code per consent request. Thanks @laupernoe.

Known follow-up

  • #30: limit resource use by task containers (item 8 of #14).

Many thanks to @laupernoe for the review and the fixes in this release.