Skip to main content

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

Create terraform/config/developers/<handle>.tfvars. Replace alice with the developer’s chosen handle and their actual email:
developer_id    = "alice"
developer_email = "alice@horizon.ai"
Commit and push this file to main.

② Apply foundation terraform

Add the developer’s email to the developer_emails list in terraform/config/environments/foundation.tfvars, then apply:
./scripts/tf foundation apply
This grants the developer 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

git clone <repo-url>
cd v0-shokunin-ai-platform

④ 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.
GitHub Codespaces alternative: Open the repo on GitHub → Code → Codespaces → Create codespace on main. No local Docker required.

⑤ Authenticate with GCP

In the container terminal, run both commands:
gcloud auth login
gcloud auth application-default login
The first authenticates your 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

./scripts/dev-setup <your-handle> <your-email>
Example:
./scripts/dev-setup alice alice@horizon.ai
This single script handles everything:
StepWhat it does
Verify prereqsChecks gcloud, terraform, bun are available and authenticated
Create tfvarsCreates config/developers/<handle>.tfvars if not already committed
Apply sandboxRuns ./scripts/tf dev <handle> apply — creates your Firestore database and grants Secret Manager read access
Sync secretsRuns ./scripts/env-sync — pulls all platform secrets from GCP Secret Manager into your .env
Health checkInstalls dependencies and verifies the build
The admin must complete step ② before you run dev-setup. Without it, the terraform apply will fail with a permission denied error on SA impersonation.

⑦ 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:
opencode auth login
Select Zen as the provider and paste your API key when prompted. This is a one-time step per machine — credentials are stored locally.

⑧ Start OpenCode and local services

In separate terminals:
# Terminal 1 — AI coding assistant
opencode

# Terminal 2 — local platform services
docker-compose up -d
The platform is now running at http://localhost:3000.

Verify the Setup

docker-compose ps     # all containers: Up (healthy)
bd status             # Beads CLI: connected
gcloud auth list      # your account: ACTIVE

Development Commands

CommandDescription
bun run devNext.js dev server with hot reload (faster than Docker for active development)
bun run buildProduction build with type checking
bun run lintESLint
docker-compose up -dStart all local services
docker-compose psCheck service health
./scripts/env-syncRe-sync secrets from GCP (safe to re-run at any time)

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
lsof -ti:3000 | xargs kill -9   # free port 3000
lsof -ti:3307 | xargs kill -9   # free port 3307 (Dolt)