Skip to content

Commit 53a7874

Browse files
authored
Add dev-start script for KiloClaw local development (#1093)
## Summary - One-command dev environment setup: `./scripts/dev-start.sh` - Auto-manages `.dev.vars` (creates from example, syncs secrets from Vercel, refreshes Fly tokens, sets tunnel URL) - `--display tabs|split|tmux` flag for terminal layout preference - Persistent config via `.dev-start.conf` (per-worktree or user-global) - Updated DEVELOPMENT_LOCAL.md to document the script ## Test plan - [x] Run `./scripts/dev-start.sh` with no `.dev.vars` (should auto-create) - [x] Test `--display tabs`, `--display split`, `--display tmux` - [x] Test `--tunnel-name` with a named tunnel - [x] Test config file override via `scripts/.dev-start.conf`
2 parents 314238d + 014f018 commit 53a7874

5 files changed

Lines changed: 629 additions & 103 deletions

File tree

kiloclaw/.dev.vars.example

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
1-
# Copy this to .dev.vars and fill in your values
2-
# .dev.vars is gitignored and used by wrangler dev
1+
# KiloClaw worker secrets (used by wrangler dev).
2+
# The dev-start script creates .dev.vars from this file on first run.
3+
#
4+
# Most values below are working defaults. The script auto-manages:
5+
# NEXTAUTH_SECRET, INTERNAL_API_SECRET (synced from Vercel)
6+
# FLY_API_TOKEN (auto-created/refreshed)
7+
# KILOCODE_API_BASE_URL (set from tunnel URL)
8+
#
9+
# Values you may need to set manually:
10+
# AGENT_ENV_VARS_PRIVATE_KEY (get from 1Password)
11+
# FLY_IMAGE_TAG / FLY_IMAGE_DIGEST / OPENCLAW_VERSION
12+
# (set by scripts/push-dev.sh,
13+
# or ask a team member for values)
314

4-
# Auth
15+
# Auth (synced automatically from Vercel by the dev-start script)
516
NEXTAUTH_SECRET=dev-secret-change-me
617
INTERNAL_API_SECRET=dev-internal-secret
18+
19+
# Auth (static defaults — these work as-is for local dev)
720
GATEWAY_TOKEN_SECRET=dev-gateway-secret-kiloclaw
821
# Override WORKER_ENV to "development" for local development.
922
# Production default is set in wrangler.jsonc. This selects the development
1023
# Fly app naming prefix ("dev-") for per-user app creation.
1124
WORKER_ENV=development
1225

13-
# Optional: Override KiloCode provider base URL (local dev only)
26+
# Tunnel URL (set automatically by the dev-start script)
1427
# OpenClaw's native kilocode provider hardcodes https://api.kilo.ai/api/gateway/.
15-
# In dev, set this to a Cloudflare tunnel or ngrok URL pointing to your local Next.js app
16-
# so that Fly machines route model requests through the tunnel instead of production.
17-
# e.g.: `cloudflared tunnel --url http://localhost:3000`
28+
# In dev, the script sets this to the Cloudflare tunnel URL pointing to your
29+
# local Next.js app so Fly machines route model requests through the tunnel.
1830
# KILOCODE_API_BASE_URL=https://<tunnel>.trycloudflare.com/api/gateway/
1931

2032
# Fly.io Machines API
21-
# Get an org-scoped token (run: `fly tokens create -o kilo-dev my-dev-token`)
33+
# Token is auto-created/refreshed by the dev-start script.
2234
FLY_API_TOKEN=fo1_...
23-
# Your Fly org slug (run: `fly orgs list`). Use `kilo-dev` for Kilo team
24-
# members, or `personal` if you're running under your own Fly account.
35+
# Fly org slug. The dev-start script reads this value for token creation.
36+
# Use "kilo-dev" for Kilo team members, or "personal" for your own Fly account.
2537
FLY_ORG_SLUG=kilo-dev
2638
# Shared Docker image registry app (images are pushed here, referenced by all per-user apps)
2739
FLY_REGISTRY_APP=kiloclaw-dev
@@ -31,8 +43,7 @@ FLY_REGISTRY_APP=kiloclaw-dev
3143
# The platform API can override per-user at provision time.
3244
FLY_REGION=us,eu
3345
# Docker image tag on registry.fly.io/{FLY_REGISTRY_APP}:{tag}.
34-
# In dev, use "latest" or run scripts/push-dev.sh which sets a timestamped tag.
35-
# In production, pin to a version (e.g., v40, sha-abc1234).
46+
# Set automatically by scripts/push-dev.sh, or use "latest" to start.
3647
FLY_IMAGE_TAG=latest
3748
# OpenClaw version (must match the openclaw@x.x.x version in the Dockerfile).
3849
# Used by the worker to self-register the version → image tag mapping in KV,
@@ -51,6 +62,7 @@ FLY_APP_NAME=kiloclaw-dev
5162
OPENCLAW_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8795,http://claw.kilosessions.ai
5263

5364
# Encryption (for user secrets)
65+
# Get the dev version from 1Password (engineering vault). Quote the value.
5466
# AGENT_ENV_VARS_PRIVATE_KEY=...
5567

5668
# Hyperdrive is configured in wrangler.jsonc, not here.

kiloclaw/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ dist
162162

163163
.dev.vars*
164164
!.dev.vars.example
165+
scripts/.dev-start.conf
165166
.env*
166167
!.env.example
167168
.wrangler/

kiloclaw/DEVELOPMENT_LOCAL.md

Lines changed: 86 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -55,77 +55,74 @@ app as a kind of image registry for all other apps -- in dev, that app is
5555
1. Accept the Fly.io org invite(s) from your email (there should be two --
5656
check spam if you only see one).
5757
2. Verify with `fly orgs list` -- the dev org should appear.
58-
3. Create an org-scoped token for dev use (personal tokens also have production
59-
access):
58+
3. Log in to the Fly CLI: `fly auth login`
6059

61-
```bash
62-
fly tokens create -o kilo-dev my-dev-token
63-
```
64-
65-
Save this token -- you'll need it for `FLY_API_TOKEN` in `.dev.vars`.
60+
The dev-start script creates and refreshes Fly API tokens automatically -- you
61+
don't need to manage tokens manually.
6662

6763
## Quick Start
6864

69-
```bash
70-
# 1. Install dependencies (run from monorepo root)
71-
pnpm install
65+
One-time prerequisites:
7266

73-
# 2. Copy the example env file (from kiloclaw/)
74-
cp kiloclaw/.dev.vars.example kiloclaw/.dev.vars
67+
1. Link the Vercel project (from monorepo root): `vercel link`
68+
2. Accept Fly.io org invites and `fly auth login` (see above)
7569

76-
# 3. Edit .dev.vars -- see "Environment Variables" below
70+
Then, from the `kiloclaw/` directory:
7771

78-
# 4. Ensure Next.js has KiloClaw env vars (from monorepo root).
79-
# `vercel env pull` includes KILOCLAW_API_URL and
80-
# KILOCLAW_INTERNAL_API_SECRET. If you haven't run it yet, see
81-
# the root DEVELOPMENT.md for Next.js setup.
72+
```bash
73+
./scripts/dev-start.sh
74+
```
8275

83-
# 5. Start the local database (from monorepo root)
84-
docker compose -f dev/docker-compose.yml up -d
76+
The script handles everything: creates `.dev.vars` if missing, pulls Vercel
77+
env, syncs secrets, validates/refreshes the Fly token, installs dependencies,
78+
starts the database, runs migrations, starts a Cloudflare tunnel (and captures
79+
the URL into `.dev.vars`), and launches all three processes.
8580

86-
# 6. Run database migrations (from monorepo root)
87-
pnpm drizzle migrate
81+
Open <http://localhost:3000> to use the dashboard.
8882

89-
# 7. Start the tunnel (separate terminal)
90-
cloudflared tunnel --url http://localhost:3000
91-
# Copy the tunnel URL into KILOCODE_API_BASE_URL in .dev.vars
83+
### Display modes
9284

93-
# 8. Start Next.js (separate terminal, from monorepo root)
94-
pnpm dev
85+
Control how the three processes are displayed with `--display <mode>`:
9586

96-
# 9. Start the KiloClaw worker (separate terminal, from kiloclaw/)
97-
pnpm run dev
98-
```
87+
| Mode | Description |
88+
| ------- | --------------------------------------------------------------------- |
89+
| `tabs` | Separate terminal tabs (default; auto-detects iTerm2 vs Terminal.app) |
90+
| `split` | Single tab with split panes (requires iTerm2) |
91+
| `tmux` | tmux session `kiloclaw` (attach with `tmux attach -t kiloclaw`) |
9992

100-
Each of the three long-running processes (tunnel, Next.js, worker) needs its
101-
own terminal tab. The Next.js app must run on port 3000 -- other services
102-
depend on it.
93+
### Other flags
10394

104-
## Tunnel setup
95+
| Flag | Description |
96+
| -------------------------- | ---------------------------------------------------- |
97+
| `--has-controller-changes` | Build and push a new Docker image before starting |
98+
| `--tunnel-name <name>` | Use a named Cloudflare tunnel instead of a quick one |
10599

106-
Use Cloudflare Tunnel (recommended) or ngrok to expose your local Next.js:
100+
### Script configuration
107101

108-
```bash
109-
# Cloudflare Tunnel (free, no account needed for quick tunnels)
110-
cloudflared tunnel --url http://localhost:3000
102+
Save defaults in a config file so you don't need to pass flags every time.
103+
The script checks two locations (project-local overrides user-global):
111104

112-
# Or ngrok
113-
ngrok http 3000
114-
```
105+
| Location | Scope |
106+
| ----------------------------------- | --------------------------- |
107+
| `kiloclaw/scripts/.dev-start.conf` | Per-worktree (gitignored) |
108+
| `~/.config/kiloclaw/dev-start.conf` | Shared across all worktrees |
115109

116-
Copy the tunnel URL and set it in `.dev.vars`:
110+
See `scripts/.dev-start.conf.example` for available options. CLI flags
111+
override config file values.
117112

118-
```
119-
KILOCODE_API_BASE_URL=https://<your-tunnel>.trycloudflare.com/api/gateway/
120-
```
113+
## Tunnel setup
114+
115+
The dev-start script automatically starts a Cloudflare quick tunnel, captures
116+
its URL, and writes `KILOCODE_API_BASE_URL` into `.dev.vars`. You generally
117+
don't need to manage this manually.
121118

122119
### Free vs named tunnels
123120

124-
- **Free quick tunnel**: hostname changes on every restart of `cloudflared`.
125-
Update `.dev.vars` and restart the worker when the URL changes.
121+
- **Free quick tunnel** (default): hostname changes on every restart. The
122+
script handles this automatically.
126123
- **Named tunnel**: preconfigure in the Cloudflare dashboard for a persistent
127-
hostname (e.g., `yourname.devclaw.dev`). Avoids updating the URL on each
128-
restart.
124+
hostname (e.g., `yourname.devclaw.dev`). Use `--tunnel-name <name>` or set
125+
`TUNNEL_NAME` and `TUNNEL_HOSTNAME` in your config file.
129126

130127
### If the tunnel isn't working
131128

@@ -136,71 +133,68 @@ The error manifests in OpenClaw as one of:
136133

137134
If you see either, check:
138135

139-
- `cloudflared` (or ngrok) is running
136+
- `cloudflared` is running (check its terminal tab/window)
140137
- `KILOCODE_API_BASE_URL` in `.dev.vars` matches the current tunnel URL
141138
- The KiloClaw worker was restarted after changing `.dev.vars`
142139

143140
## Environment Variables
144141

145-
There are two env files to configure:
146-
147-
### 1. `kiloclaw/.dev.vars` (worker secrets)
148-
149-
Copy `.dev.vars.example` and fill in:
142+
### `kiloclaw/.dev.vars` (worker secrets)
150143

151-
**Auth** -- must match the Next.js app's values:
144+
The dev-start script creates `.dev.vars` from `.dev.vars.example` on first run
145+
and automatically manages several values. The table below shows which variables
146+
are auto-managed and which require manual setup.
152147

153-
| Variable | Description |
154-
| ---------------------- | --------------------------------------------------------------------------- |
155-
| `NEXTAUTH_SECRET` | JWT signing key. Must match the Next.js app's `NEXTAUTH_SECRET` |
156-
| `INTERNAL_API_SECRET` | Platform API key. Must match Next.js `KILOCLAW_INTERNAL_API_SECRET` |
157-
| `GATEWAY_TOKEN_SECRET` | HMAC key for per-sandbox gateway tokens. Can be any arbitrary value in dev. |
158-
| `WORKER_ENV` | Set to `development` |
148+
**Auth:**
159149

160-
`NEXTAUTH_SECRET` and `INTERNAL_API_SECRET` must match the Next.js app's
161-
values. Pull them from Vercel (`vercel env pull` from the monorepo root) or
162-
get them from a team member.
150+
| Variable | Description | Source | Auto-managed |
151+
| ---------------------- | --------------------------------------------------------------------------- | ------- | ------------ |
152+
| `NEXTAUTH_SECRET` | JWT signing key. Must match the Next.js app's `NEXTAUTH_SECRET` | Vercel | Yes |
153+
| `INTERNAL_API_SECRET` | Platform API key. Must match Next.js `KILOCLAW_INTERNAL_API_SECRET` | Vercel | Yes |
154+
| `GATEWAY_TOKEN_SECRET` | HMAC key for per-sandbox gateway tokens. Can be any arbitrary value in dev. | Example | No |
155+
| `WORKER_ENV` | Set to `development` | Example | No |
163156

164-
**Fly.io** -- requires access to the Kilo (dev) org:
157+
**Fly.io:**
165158

166-
| Variable | Description |
167-
| ------------------ | --------------------------------------------------------------------------------------- |
168-
| `FLY_API_TOKEN` | Fly org token. Generate with `fly tokens create -o kilo-dev my-dev-token` |
169-
| `FLY_ORG_SLUG` | Fly org slug (run `fly orgs list` to find it) |
170-
| `FLY_REGISTRY_APP` | Shared Fly app that holds Docker images (e.g., `kiloclaw-dev`) |
171-
| `FLY_APP_NAME` | Legacy fallback app name for existing instances (may be removed in future) |
172-
| `FLY_REGION` | Region priority list, e.g. `us,eu`. Tries US first, falls back to EU, then gives up. |
173-
| `FLY_IMAGE_TAG` | Docker image tag. Set automatically by `scripts/push-dev.sh`, or use `latest` to start. |
174-
| `FLY_IMAGE_DIGEST` | Docker image digest. Set automatically by `scripts/push-dev.sh`. |
175-
| `OPENCLAW_VERSION` | OpenClaw version in the image. Set automatically by `scripts/push-dev.sh`. |
159+
| Variable | Description | Source | Auto-managed |
160+
| ------------------ | --------------------------------------------------------------------------------------- | ------------ | ------------ |
161+
| `FLY_API_TOKEN` | Fly org token | dev-start.sh | Yes |
162+
| `FLY_ORG_SLUG` | Fly org slug (read by script for token creation) | Example | No |
163+
| `FLY_REGISTRY_APP` | Shared Fly app that holds Docker images (e.g., `kiloclaw-dev`) | Example | No |
164+
| `FLY_APP_NAME` | Legacy fallback app name for existing instances (may be removed in future) | Example | No |
165+
| `FLY_REGION` | Region priority list, e.g. `us,eu`. Tries US first, falls back to EU, then gives up. | Example | No |
166+
| `FLY_IMAGE_TAG` | Docker image tag. Set automatically by `scripts/push-dev.sh`, or use `latest` to start. | push-dev.sh | Yes |
167+
| `FLY_IMAGE_DIGEST` | Docker image digest. Set automatically by `scripts/push-dev.sh`. | push-dev.sh | Yes |
168+
| `OPENCLAW_VERSION` | OpenClaw version in the image. Set automatically by `scripts/push-dev.sh`. | push-dev.sh | Yes |
176169

177170
`FLY_IMAGE_TAG`, `FLY_IMAGE_DIGEST`, and `OPENCLAW_VERSION` together control
178171
what version gets deployed by default for your dev instances. The build script
179172
auto-updates all three. For initial setup, ask a team member for known-working
180173
values or use `latest` (if a `latest` tag exists in the registry).
181174

182-
**Tunnel / API** -- so Fly machines can reach your local Next.js:
175+
**Tunnel / API:**
183176

184-
| Variable | Description |
185-
| ----------------------- | ---------------------------------------------------------- |
186-
| `KILOCODE_API_BASE_URL` | Your tunnel URL + `/api/gateway/` (see tunnel setup above) |
177+
| Variable | Description | Source | Auto-managed |
178+
| ----------------------- | --------------------------------- | ------------ | ------------ |
179+
| `KILOCODE_API_BASE_URL` | Your tunnel URL + `/api/gateway/` | dev-start.sh | Yes |
187180

188-
**Encryption** -- for decrypting user-provided secrets:
181+
**Encryption:**
189182

190-
| Variable | Description |
191-
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ |
192-
| `AGENT_ENV_VARS_PRIVATE_KEY` | RSA private key (PEM). Get the **dev** version from 1Password (engineering vault). Quote the value in `.dev.vars`. |
183+
| Variable | Description | Source | Auto-managed |
184+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | --------- | ------------ |
185+
| `AGENT_ENV_VARS_PRIVATE_KEY` | RSA private key (PEM). Get the **dev** version from 1Password (engineering vault). Quote the value in `.dev.vars`. | 1Password | No |
193186

194187
**Other:**
195188

196-
| Variable | Description |
197-
| -------------------------- | ------------------------------------------------- |
198-
| `OPENCLAW_ALLOWED_ORIGINS` | Comma-separated origins for WebSocket connections |
189+
| Variable | Description | Source | Auto-managed |
190+
| -------------------------- | ------------------------------------------------- | ------- | ------------ |
191+
| `OPENCLAW_ALLOWED_ORIGINS` | Comma-separated origins for WebSocket connections | Example | No |
199192

200-
### 2. `.env.local` (Next.js, monorepo root)
193+
### `.env.local` (Next.js, monorepo root)
201194

202195
The Next.js app also needs these two variables to talk to the KiloClaw worker.
203-
Both are included in `vercel env pull` (see root `DEVELOPMENT.md`):
196+
Both are included in `vercel env pull` (run automatically by the dev-start
197+
script):
204198

205199
| Variable | Description |
206200
| ------------------------------ | ----------------------------------------------- |
@@ -469,9 +463,10 @@ All scripts support overrides via env vars (`IMAGE`, `PORT`, `TOKEN`).
469463

470464
**Fly machine can't reach your Next.js / "models require auth":**
471465
Check that the tunnel is running and `KILOCODE_API_BASE_URL` in `.dev.vars`
472-
matches the current tunnel URL. Restart the worker after changing it. Symptoms
473-
are either silent failure (three dots, then nothing) or "models require
474-
authentication."
466+
matches the current tunnel URL. The dev-start script sets this automatically,
467+
but if the tunnel restarts you'll need to re-run the script or update the URL
468+
manually and restart the worker. Symptoms are either silent failure (three
469+
dots, then nothing) or "models require authentication."
475470

476471
**"tag latest unknown manifest":**
477472
The image tag in `FLY_IMAGE_TAG` doesn't exist in the Fly registry. Get
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Dev-start script configuration.
2+
# CLI flags override these values.
3+
#
4+
# Place this file in either location:
5+
# ~/.config/kiloclaw/dev-start.conf (shared across all worktrees)
6+
# kiloclaw/scripts/.dev-start.conf (per-worktree override, gitignored)
7+
8+
# Named Cloudflare tunnel (leave empty for temporary quick tunnel)
9+
# TUNNEL_NAME= # tunnel
10+
# TUNNEL_HOSTNAME= # tunnel.yourdomain.com
11+
12+
# RSA private key for agent env var encryption (get from 1Password, engineering vault)
13+
# AGENT_ENV_VARS_PRIVATE_KEY=
14+
15+
# How to display the 3 dev processes:
16+
# tabs — separate terminal tabs (default; auto-detects iTerm2 vs Terminal.app)
17+
# split — single tab with split panes (requires iTerm2)
18+
# tmux — tmux session "kiloclaw"
19+
DISPLAY_MODE=tabs

0 commit comments

Comments
 (0)