Docs
Prerequisites
Before you start, make sure you have the following in place.
A host machine
Last Light runs as a single Node process (locally) or a single Docker container
(in production). Each workflow phase runs inside its own isolated sandbox so the
agent cannot touch your host filesystem, credentials, or git identity. The
sandbox backend is selected by LASTLIGHT_SANDBOX:
gondolin (default — QEMU micro-VM via agentic-pi, uses HVF on macOS
and KVM on Linux, no Docker needed), docker (sibling Docker container
per phase), or none (in-process, dev only).
- Node.js 20+ — for local development (
npm run dev). - Docker — required only when
LASTLIGHT_SANDBOX=dockeror for the bundled docker-compose deploy. The default gondolin sandbox does not need it. - KVM (Linux) or HVF (macOS) — required by gondolin for nested virtualisation. Bare-metal Linux and Apple Silicon Macs both have it; most managed container hosts do not.
- Git — for cloning the repo you want to deploy.
A GitHub App
Last Light authenticates to GitHub as its own GitHub App rather than as a personal
access token. This keeps the bot's actions clearly attributed (last-light[bot]),
lets you downscope permissions per workflow, and makes installation per-repo
instead of per-user.
The Create a GitHub App page walks through the exact
permissions and events to request. You'll end up with four values you need to
paste into .env: App ID, Installation ID, webhook secret, and a
.pem private key.
Model provider credentials
The agent runtime is agentic-pi —
provider-agnostic, so any provider/model string pi-ai supports works
(openai/…, anthropic/…, etc.). The default is
anthropic/claude-sonnet-4-6. Set the matching API key in .env:
OPENAI_API_KEY— required ifLASTLIGHT_MODELresolves to an OpenAI model.ANTHROPIC_API_KEY— required ifLASTLIGHT_MODELresolves to an Anthropic model.OPENROUTER_API_KEY— required ifLASTLIGHT_MODELresolves to an OpenRouter model (openrouter/<vendor>/<model>). One key gives you access to Claude, GPT, Gemini, Llama, Mistral, DeepSeek, and most others through a single endpoint — at a small per-token markup over going direct. Sign up at openrouter.ai/keys.- You can set all three — phases routed via
LASTLIGHT_MODELSJSON can mix providers freely.
Optional: a Slack workspace
Slack integration is optional but recommended — it's how you chat with the bot outside GitHub. You'll need permission to create a Slack app and install it in your workspace. See Slack integration.
Optional: a public domain
To receive GitHub webhooks in real-time (instead of relying on cron polling), the harness needs to be publicly reachable over HTTPS. In production this is handled by the bundled Caddy reverse proxy, which provisions TLS automatically — you just point a DNS record at your host. For local testing, use ngrok or Cloudflare Tunnel.