Skip to main content
The AI-Implement orchestrator is configured entirely through environment variables. Variables fall into three contexts depending on where you configure them:
  • On the orchestrator service itself
  • As GitHub Actions secrets on the orchestrator’s own repo (for CI auto-deploy)
  • As GitHub Actions secrets on each target repo (read by the synced workflow files when Claude runs).
A few credentials are needed in more than one context, though only one pair changes names between contexts:
  • On the orchestrator: GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY
  • On each target repo: AI_IMPLEMENT_APP_ID and AI_IMPLEMENT_PRIVATE_KEY
These both refer to the same GitHub app’s credentials. Nothing else is renamed across contexts. The variables are read at startup; restart the app after changing them. Pick the tab that matches where you’re configuring right now.
Variables the AI-Implement Node service reads at startup.
  • For local development, set on the orchestrator’s .env file.
  • For Fly.io deployment, set on the Fly.io app via fly secrets set (for sensitive values) or in fly.toml’s [env] block (for non-sensitive defaults).

Required

The orchestrator needs the GitHub App credentials plus at least one ticketing provider’s credentials to start.
string
required
Numeric ID of the GitHub App the orchestrator uses to authenticate with GitHub and dispatch workflows. Find this on the app’s settings page under General → App ID.
string
required
RSA private key (PEM format) for the GitHub App, used to generate installation tokens. When passing this as an environment variable, newlines in the PEM file must be replaced with literal \n characters.
The private key PEM file contains real newlines. When you set it as an environment variable (e.g. with fly secrets set), those newlines must be expressed as the two-character sequence \n. Example: "-----BEGIN RSA PRIVATE KEY-----\nMIIE...\n-----END RSA PRIVATE KEY-----".

Ticketing

The orchestrator can use Linear, Jira, or both. Expand the provider(s) you use:
string
required
Required when any project mapping uses ticketingProvider: linear.Client ID of the Linear application the orchestrator authenticates as. See Create a Linear app for how to create it.
string
required
Required when any project mapping uses ticketingProvider: linear.Client secret for the same application. Both values remain visible on the application’s settings page, so you can re-copy them whenever you need to.
string
default:"https://linear.app"
User-facing Linear workspace URL, used to render issue links in dispatch logs and comments.
The orchestrator acts as the application itself, not as a person. Every status change, label, and comment it makes is attributed to the app in Linear’s activity feed.
Both authentication modes need JIRA_TOKEN and JIRA_SITE_URL. Which of the remaining two you set decides the mode.
string
required
Required when any project mapping uses ticketingProvider: jira.Either an Atlassian API token or an OAuth access token, depending on the mode you pick below.
string
required
Required when any mapping uses Jira.User-facing Atlassian site URL, e.g. https://acme.atlassian.net. Renders issue links in dispatch logs and comments, and serves as the API host in Basic auth mode.
string
Selects Basic auth — the recommended mode.The Atlassian account email paired with JIRA_TOKEN. Create the token under Security → API tokens on your Atlassian account.Calls go to JIRA_SITE_URL directly, and the token is long-lived with nothing to refresh.Leave this blank to use OAuth instead.
string
Required only for OAuth mode, meaning when JIRA_EMAIL is blank.Jira Cloud tenant ID, found at https://<your-site>.atlassian.net/_edge/tenant_info under cloudId. Routes calls through api.atlassian.com using short-lived access tokens.Not needed for Basic auth.
Variables beyond this section have defaults or are safely omitted. Set them to override the defaults or to enable optional features.

Service

string
Password for the admin UI at /admin. If this variable is not set, the admin UI is disabled entirely and all /admin and /api/ routes return 503, with a response body naming the missing variable.
string
default:"8080"
HTTP port the orchestrator listens on. The Fly.io internal proxy routes traffic to this port automatically, so you typically do not need to change it.
string
default:"60000"
How often the orchestrator polls for new AI-Implement issues, in milliseconds. Lower values increase ticketing-API usage; values below 10000 are not recommended.
string
default:"/data/dedup.sqlite"
Absolute path to the SQLite file used for deduplication, dispatch logging, and project-mapping storage. Defaults to /data/dedup.sqlite in production (the Fly.io volume mount point) and ./dedup.sqlite when running locally. Change this only if you are mounting the volume at a different path.
string
HMAC-SHA256 secret used to validate incoming GitHub webhook payloads. Set the same value on the GitHub App’s webhook configuration, pointed at https://<orchestrator-host>/api/github/webhook.Leaving it unset disables every webhook-driven behavior: automatic follow-up runs when a reviewer leaves blocking feedback, the faster merge-to-Done path, and — for target repos on the current workflow generation — handling of /ai-implement PR comments. Those repos have no fallback for the comment trigger once this secret is missing, since the orchestrator’s webhook is the only thing listening for it. A poll-based path still moves merged PRs to Done without the webhook, just on a slower cadence.
The webhook also needs the right event subscriptions to deliver anything; see Create a GitHub App.

Notifications

string
default:"slack"
Notification provider to use when a dispatch succeeds or fails. Accepted values: slack (default) or teams. Has no effect if NOTIFY_WEBHOOK_URL is not also set.
string
Incoming webhook URL for the notification provider. Notifications are skipped silently if this variable is unset. For Slack, this is the URL from your Incoming Webhooks app configuration. For Teams, use the connector webhook URL.

Runner mode

string
default:"default"
Global override for runner execution mode. Accepted values:
  • default (per-mapping setting wins)
  • gha (force GitHub Actions for all mappings)
  • fly (force Fly Machines)
  • local (force local Docker — for local development)
  • shadow (dispatch via GitHub Actions and additionally boot a Fly Machine for the same run)
shadow is a testing mode. Every run consumes a GitHub Actions job and a Fly Machine, so it roughly doubles Fly session load for as long as it is enabled.
The admin UI’s Reaper page also has a runner-mode toggle, backed by a setting stored in the database. Setting this variable always wins over that toggle — the UI toggle has no effect while the variable is set. To switch modes at runtime from the admin UI, leave this variable unset.
string
Required when RUNNER_MODE=fly or any mapping uses executionMode: fly-machines.Fly.io app name that hosts the session runners.
string
default:"iad"
Default Fly.io region for new session machines.
string
Required when RUNNER_MODE=fly or any mapping uses Fly Machines.Fly API token scoped to the sessions app. Used to create and destroy Fly Machines for runs.
string
default:"ghcr.io/builddownai/ai-implement-runner:latest"
Default container image for runner sessions, in both execution modes. A per-repo .ai-implement/image.yml takes precedence.
string
deprecated
Superseded by AI_IMPLEMENT_RUNNER_IMAGE, which covers both execution modes rather than Fly Machines alone.Still read when the newer variable is unset, and ignored when both are set.
string
default:"ai-implement-runner:local"
Container image to use when RUNNER_MODE=local. Built locally via npm run build:runner:local.
string
default:"http://host.docker.internal:8080"
Base URL the local Docker runner uses to call back to the orchestrator.The default works on native macOS and Windows. Use the host’s own IP on Linux, and on WSL2 use the distro’s IP instead of host.docker.internal (that points at the Windows host, not the distro running the orchestrator).
These configure how Fly Machine and local-Docker runners authenticate their callbacks to the orchestrator. Defaults are correct for most setups.
string
Public base URL the runner uses to call back to the orchestrator (e.g. https://your-orchestrator.fly.dev). Required for Fly Machines and local Docker runner modes.
string
Secret used to mint and validate short-lived runner-callback tokens. Required when RUNNER_CALLBACK_BASE_URL is set.
string
Shared bearer secret for the orchestrator’s /trigger/gap-fill endpoint, which starts a gap-fill run against an existing pull request. Leaving it unset disables the endpoint.This is a separate secret from GITHUB_WEBHOOK_SECRET and is not needed for the /ai-implement comment trigger — that path is authenticated by GITHUB_WEBHOOK_SECRET instead (on target repos still running the older, pre-sync workflow generation, it runs inside that repo’s own comment-trigger.yml workflow and needs neither secret). Set GAP_FILL_TRIGGER_SECRET only if you drive gap-fill runs from your own automation.
Controls the reconciliation sweep that cleans up stale Fly Machine sessions.
string
default:"false"
When true, the reaper logs what it would destroy but takes no action. Useful for verifying rules before enabling live cleanup.
string
default:"10"
Number of destructions in a single sweep above which the reaper emits an alert notification (via the configured NOTIFY_TYPE).The count resets on the next pass rather than accumulating over time. Helps catch runaway destruction bugs.
Identifiers used when deploying multiple AI-Implement instances as separate Fly apps from a single repo. Most single-client deployments leave these unset.
string
The client identifier matching this app’s clients/<slug>.toml file. Used in logs and notifications to disambiguate multi-tenant deployments.
string
Fly.io app name for this instance. Fly sets this automatically, so you rarely need to. It tags every session machine this instance creates, and the cleanup sweep uses that tag to avoid touching another tenant’s machines — in a shared sessions app, an incorrect value can cause one instance’s cleanup to destroy another tenant’s sessions.
These are read by the orchestrator and forwarded to runner sessions when RUNNER_MODE is fly or local.For GitHub Actions runner mode, the synced workflow uses its own repo secrets directly (see the Target-repo workflow secrets tab); these runtime values are unused.
string
Anthropic API key, forwarded to the runner session as the Claude auth fallback. Required when RUNNER_MODE=fly or local and no OAuth token is configured.
string
Claude Code OAuth token, forwarded to the runner session. Preferred over ANTHROPIC_API_KEY when both are set.