Getting Started
Two actors are involved in onboarding: an admin who provisions your GCP access once, and you (the developer) who runs the rest. The admin steps must happen before you begin.Admin Steps
① Create the developer config
Createterraform/config/developers/<handle>.tfvars. Replace alice with the developer’s chosen handle and their actual email:
② Apply foundation terraform
Add the developer’s email to thedeveloper_emails list in terraform/config/environments/foundation.tfvars, then apply:
serviceAccountTokenCreator on the dev platform SA — the permission they need to apply their own sandbox in step ⑥. Without this step, ./scripts/dev-setup will fail.
Foundation only needs to be applied once per developer. Re-running it for subsequent developers is safe — it is idempotent.
Developer Steps
③ Clone the repo
④ Open the dev container
Open the repo in VS Code. When prompted, click Reopen in Container. The container provides Node.js 24, Bun, Docker-in-Docker, Terraform, gcloud CLI, and Python 3.12. The first build takes 3–5 minutes.⑤ Authenticate with GCP
In the container terminal, run both commands:gcloud CLI. The second sets up Application Default Credentials (ADC) — required by dev-setup and env-sync to read from Secret Manager.
⑥ Run dev-setup
⑦ Authenticate OpenCode
OpenCode requires an API key to run. If you are part of the Horizon organisation, request a Zen API key from an admin. Once you have the key, log in:⑧ Start OpenCode and local services
In separate terminals:Verify the Setup
Development Commands
Troubleshooting
dev-setup fails: Could not obtain an access token
The admin has not applied foundation yet (step ②), or the wrong email was added to foundation.tfvars. Ask your admin to check terraform/config/environments/foundation.tfvars and re-apply.
env-sync fails: secret not found or permission denied
Your sandbox terraform hasn’t been applied yet, or the apply failed partway. Re-run ./scripts/dev-setup — it is safe to run multiple times.
bd fails with CGO errors
Ensure CGO_ENABLED=1 is set in .env. It is included in .env.example — if missing from your .env, add it manually.
Port conflicts