-
Notifications
You must be signed in to change notification settings - Fork 0
Installation
English | 日本語
Get maestro running and complete one successful run. Read this page top-to-bottom once; later jumps are linked from Home.
| Path | When to use | Time |
|---|---|---|
| A. Local | Try on a laptop / disposable repo | ~15 min |
| B. Container | Shared host, staging, simple deploy | ~20 min |
| C. Production shape | Public HTTPS, MCP Gateway, OIDC | longer |
| D. GCP Terraform | Cloud Run + Global LB + IAP + self-hosted worker | longer |
All paths need the same three secrets:
ANTHROPIC_API_KEYGITHUB_APP_ID-
GITHUB_APP_PRIVATE_KEYorGITHUB_APP_PRIVATE_KEY_PATH
There is no PAT mode. Authentication is GitHub App only.
-
GitHub → Settings → Developer settings → GitHub Apps → New GitHub App
-
Set a name and any homepage URL (can be
http://127.0.0.1:3000for local) -
Webhook: leave inactive unless you later enable review webhooks
-
Repository permissions (minimum):
Permission Access Metadata Read-only Contents Read and write Issues Read and write Pull requests Read and write -
Create the app → note the App ID
-
Generate a private key → download the
.pemfile -
Install App → choose the account/org → only the repositories maestro should touch
Optional later:
-
GITHUB_APP_INSTALLATION_ID— if omitted, maestro resolves the installation fromowner/repo - Narrow installation to specific repos (recommended for production)
- Create an API key in the Claude / Anthropic console
- Confirm your org can use Claude Managed Agents (sessions, agents, vaults)
- Export as
ANTHROPIC_API_KEY
-
mise (recommended) or Bun 1.3.14 (see
mise.toml) - Git, a terminal
- The GitHub App PEM from step 1
git clone https://github.com/ca-srg/maestro.git
cd maestro
mise install # installs pinned Bun
bun install
cp .env.example .envEdit .env (minimum):
ANTHROPIC_API_KEY=sk-ant-...
GITHUB_APP_ID=123456
GITHUB_APP_PRIVATE_KEY_PATH=/absolute/path/to/github-app.pemOr paste the PEM inline (escape newlines as \n):
GITHUB_APP_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"bun run start
# → Listening on http://127.0.0.1:3000Watch mode: bun run dev.
- Open http://127.0.0.1:3000
-
New run → repository
owner/name+ open issue number- You can also paste
https://github.com/owner/name/issues/42
- You can also paste
- Start the run
- Open the run detail page — events stream live
- When finished, open the PR URL from the run summary
- Dashboard → Repositories → add
owner/nameas a polled repository - On an open issue, either:
- add label
agent-run(default; override withGITHUB_TRIGGER_LABEL), or - comment
@bot run(default bot name; override withGITHUB_BOT_MENTION)
- add label
The poller always starts; with an empty repo list it is a no-op.
Managed Agents run in Anthropic’s cloud and cannot reach 127.0.0.1. For local stdio MCP servers:
ENABLE_DEV_TUNNEL=true
NGROK_AUTHTOKEN=...
MCP_GATEWAY_TOKEN=$(uuidgen) # keep this value stable in .envRequires pip install mcp-proxy and entries in mcp-proxy.json. Full detail: docs/DEVELOPMENT.md.
make docker-build VERSION=0.1.0
# or: docker build --platform=linux/amd64 -t maestro:0.1.0 .docker run --rm \
-p 3000:3000 \
-e ANTHROPIC_API_KEY \
-e GITHUB_APP_ID \
-e GITHUB_APP_PRIVATE_KEY_PATH=/secrets/github-app.pem \
-v /path/to/github-app.pem:/secrets/github-app.pem:ro \
-v maestro-data:/data \
maestro:0.1.0Image layout (from Dockerfile / scripts/start.sh):
| Path | Role |
|---|---|
/app |
Application (read-only at runtime) |
/data/app |
SQLite DB + agent state (DB_PATH default /data/app/dashboard.db) |
/app/.maestro |
Symlink into agent state under /data
|
Ports 3000
|
App (loopback behind ingress when used) |
Ports 8080 / 8096 / 8097
|
Ingress / mcp-proxy / mcp-gateway when sidecars enabled |
Persist /data across restarts. SQLite is single-writer — run one maestro instance against a given DB volume.
| Command | Use |
|---|---|
./scripts/start.sh (default) |
App + optional MCP sidecars / ingress / Litestream |
./scripts/start-mcp.sh |
MCP proxy + gateway only (split deploy) |
Not a single vendor recipe — a shape that matches how the container is built.
┌─ app.example.com ──► ingress-proxy ──► maestro :3000
Internet ───────────┤
└─ mcp.example.com ──► ingress-proxy ──► mcp-gateway :8097
└─ mcp-proxy :8096
└─ stdio MCPs
ANTHROPIC_API_KEY=...
GITHUB_APP_ID=...
GITHUB_APP_PRIVATE_KEY_PATH=/data/secrets/github-app.pem
# Hostnames
INGRESS_APP_HOSTNAME=app.example.com
INGRESS_MCP_HOSTNAME=mcp.example.com
INGRESS_AUTH_MODE=load-balancer
# MCP gateway
MCP_GATEWAY_TOKEN=<long-random-stable>
# Optional tighten (default includes Anthropic Managed Agents egress):
# MCP_GATEWAY_ALLOWED_CLIENT_CIDRS=160.79.104.0/21
# Dashboard auth (optional; all-or-nothing)
# OIDC_ISSUER_URL=...
# OIDC_CLIENT_ID=...
# OIDC_CLIENT_SECRET=...
# OIDC_REDIRECT_URI=https://app.example.com/auth/callback
# OIDC_ADMIN_EMAILS=you@example.comRegister each MCP server in the WebUI (/mcp-servers) with:
-
URL — public Streamable HTTP endpoint, e.g.
https://mcp.example.com/servers/figma/mcp -
token_env_name — env var name holding the Bearer (often
MCP_GATEWAY_TOKEN)
See MCP-Servers and Configuration.
To enqueue sessions onto your workers instead of Anthropic cloud environments:
ANTHROPIC_ENVIRONMENT_ID=env_...- Set this on the maestro app only (non-secret id)
- Keep
ANTHROPIC_ENVIRONMENT_KEYon the worker/poller only - Do not share a fixed
VAULT_IDin self-hosted mode
Details: docs/self-hosted-sandboxes.md
Production deploy on Google Cloud using the modules in terraform/:
- app — Cloud Run WebUI/API + Litestream
- mcp-gateway — dedicated Cloud Run MCP surface
- worker — self-hosted poller (Worker Pool) + session Job
- edge — Global HTTPS LB, IAP, Cloud Armor, Certificate Manager
cd terraform/examples/complete
cp terraform.tfvars.example terraform.tfvars
# edit hostnames, images, VPC, IAP, anthropic_environment_id
terraform init && terraform apply
# then inject Secret Manager versions (containers are empty)Full walkthrough (prerequisites, secret injection, DNS cutover, Litestream three-step revision updates): Terraform. Module variable tables: terraform/README.md.
| Check | How |
|---|---|
| Process up | Log line with listen address / no immediate exit |
| Dashboard | GET http://127.0.0.1:3000/ returns HTML |
| GitHub auth | Start a run on a repo the App can access; preflight fails fast on missing permissions |
| Anthropic | Invalid key → clear auth error at run start |
| End-to-end | Small open issue → PR opens → run status completed
|
Contributor verification (not required for operators):
bun run lint && bun run typecheck && bun test- Terraform — GCP modules (app / MCP / worker / edge)
- Architecture — how a run flows
- Configuration — every important knob
- Troubleshooting — when something fails