diff --git a/docs/quickstart.md b/docs/quickstart.md index a0483d74..4f0f2ff7 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -7,20 +7,46 @@ This path is aligned to the current repository and current UI. It gets you from - Docker + Docker Compose v2 - Node.js 20+ - Go 1.25+ +- `jq` (for the template-registry clone in `setup.sh`) - One model/API key for the runtime you want to use - `ANTHROPIC_API_KEY` - `OPENAI_API_KEY` - `GOOGLE_API_KEY` - or another provider routed through LiteLLM -## Step 1: Clone the repository +## The one-command path + +```bash +git clone https://github.com/Molecule-AI/molecule-monorepo.git +cd molecule-monorepo +./scripts/dev-start.sh +``` + +That single script: + +1. Generates an `ADMIN_TOKEN` into `.env` (first run only — preserved on re-runs) +2. Brings up Postgres, Redis, Langfuse, ClickHouse, and Temporal via `infra/scripts/setup.sh` +3. Populates the workspace template + plugin registry from `manifest.json` +4. Builds and starts the platform on `http://localhost:8080` +5. Installs canvas deps (first run) and starts the canvas on `http://localhost:3000` +6. Prints next-step instructions and tails both processes — `Ctrl-C` tears everything down + +Total wall-clock: ~30 seconds for a re-run, ~2 minutes for a first run (npm install + docker pulls). + +Once the canvas is up: open it, add your model API key in **Config → Secrets & API Keys → Global**, then click a template card or **+ Create blank workspace**. + +## Manual setup (advanced) + +If you'd rather run each component yourself — useful when you're iterating on the platform binary or the canvas in isolation — follow the steps below. Each section is what `dev-start.sh` does internally; running them by hand gives you per-component logs and lets you keep one piece running while you restart another. + +### Step 1: Clone the repository ```bash git clone https://github.com/Molecule-AI/molecule-monorepo.git cd molecule-monorepo ``` -## Step 2: Start the shared infrastructure +### Step 2: Start the shared infrastructure Recommended: @@ -28,7 +54,7 @@ Recommended: ./infra/scripts/setup.sh ``` -That brings up Postgres, Redis, and Langfuse. +That brings up Postgres, Redis, Langfuse, ClickHouse, and Temporal. If you only want the raw compose flow: @@ -36,7 +62,7 @@ If you only want the raw compose flow: docker compose -f docker-compose.infra.yml up -d ``` -## Step 3: Start the platform +### Step 3: Start the platform ```bash cd workspace-server @@ -45,7 +71,7 @@ go run ./cmd/server The control plane listens on `http://localhost:8080`. -## Step 4: Start the canvas +### Step 4: Start the canvas In a new terminal: diff --git a/scripts/dev-start.sh b/scripts/dev-start.sh index 8eda6dd4..b99d1b4f 100755 --- a/scripts/dev-start.sh +++ b/scripts/dev-start.sh @@ -1,69 +1,182 @@ #!/bin/sh # dev-start.sh — one-command local development environment. # -# Starts: Postgres, Redis, Platform (Go :8080), Canvas (Next.js :3000) -# Stops all on Ctrl-C. +# What it does (in order): +# 1. Generates ADMIN_TOKEN into .env if missing (closes #684 fail-open) +# 2. Runs infra/scripts/setup.sh (postgres + redis + langfuse + clickhouse +# + temporal + populates template/plugin registry from manifest.json) +# 3. Starts the platform (Go :8080), waits for /health +# 4. Starts the canvas (Next.js :3000), waits for HTTP 200 +# 5. Prints a readiness banner with API-key add instructions +# 6. On Ctrl-C, kills both background processes and tears down infra # # Prerequisites: -# - Docker (for Postgres + Redis) -# - Go 1.25+ (for platform) -# - Node.js 20+ (for canvas) +# - Docker + Docker Compose v2 (for postgres/redis/langfuse/etc) +# - Go 1.25+ (for the platform binary) +# - Node.js 20+ (for the canvas) +# - jq (for setup.sh's manifest clone — optional; +# without it, template palette will be +# empty until you run clone-manifest.sh +# manually) # # Usage: # ./scripts/dev-start.sh -# # Open http://localhost:3000 +# # Open http://localhost:3000, add your model API key in +# # Config → Secrets & API Keys, then create your first workspace. +# +# Idempotent: re-running picks up where the last run left off (existing +# .env is preserved, npm install skipped if node_modules present, etc). set -e ROOT="$(cd "$(dirname "$0")/.." && pwd)" +ENV_FILE="$ROOT/.env" cleanup() { echo "" - echo "Shutting down..." + echo "==> Shutting down..." kill $PLATFORM_PID $CANVAS_PID 2>/dev/null || true + # Use setup.sh's compose file (full infra) since that's what we + # brought up. `down` keeps named volumes by default — call with + # --volumes here only if you want a clean slate (we don't, since + # idempotent re-runs are the usual case). docker compose -f "$ROOT/docker-compose.infra.yml" down 2>/dev/null || true - echo "Done." + echo " Done." } trap cleanup EXIT INT TERM -echo "==> Starting infrastructure (Postgres, Redis)..." -docker compose -f "$ROOT/docker-compose.infra.yml" up -d +# ─────────────────────────────────────────────── 1. dev-mode auth posture -echo "==> Waiting for Postgres..." -until docker compose -f "$ROOT/docker-compose.infra.yml" exec -T postgres pg_isready -q 2>/dev/null; do - sleep 1 -done -echo " Postgres ready." +# The AdminAuth middleware closes its fail-open the moment the first +# workspace token lands in the DB — at which point /workspaces and +# other admin routes 401 unless the caller has either ADMIN_TOKEN or +# the dev-mode escape hatch. The canvas at localhost:3000 has no +# bearer token to send, so without one of those two paths it can't +# call admin endpoints after a workspace exists. +# +# For local dev the right posture is the dev-mode escape hatch: +# +# MOLECULE_ENV=development AND ADMIN_TOKEN unset +# +# That makes middleware.isDevModeFailOpen() return true and lets the +# canvas keep working without a bearer. Setting ADMIN_TOKEN here +# would BREAK the canvas (it has no way to read that token in dev). +# +# For SaaS the platform is provisioned with ADMIN_TOKEN set AND +# MOLECULE_ENV=production — either one closes the hatch. So the dev +# mode signal here is safe (it's only active when both other knobs +# are absent). +if [ -f "$ENV_FILE" ] && grep -q '^MOLECULE_ENV=' "$ENV_FILE"; then + echo "==> Reusing MOLECULE_ENV from existing .env" +else + echo "==> Setting MOLECULE_ENV=development in .env (dev-mode auth hatch)" + { + if [ -f "$ENV_FILE" ]; then + cat "$ENV_FILE" + echo "" + fi + echo "# Generated by scripts/dev-start.sh on $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "# Local-dev auth posture: dev-mode fail-open lets the canvas at" + echo "# localhost:3000 call admin endpoints without a bearer token." + echo "# DO NOT set ADMIN_TOKEN here in dev — it would close the hatch" + echo "# and the canvas would 401 on every admin call." + echo "MOLECULE_ENV=development" + } > "$ENV_FILE.tmp" + mv "$ENV_FILE.tmp" "$ENV_FILE" + echo " Saved to $ENV_FILE" +fi -echo "==> Starting Platform (Go :8080)..." +# Source .env so the platform inherits ADMIN_TOKEN (and anything else +# the user has added — e.g. ANTHROPIC_API_KEY for skipping the canvas +# Secrets UI). `set -a` exports every assignment in the sourced file +# without us having to know the var names. +set -a +# shellcheck disable=SC1090 +. "$ENV_FILE" +set +a + +# ─────────────────────────────────────────────── 2. infra + templates + +# Use setup.sh (not raw docker-compose) so the template registry gets +# populated from manifest.json. Without that, the canvas template +# palette is empty and the user has to manually clone repos — exactly +# the friction this script exists to eliminate. +echo "==> Running infra/scripts/setup.sh (infra + template registry)" +"$ROOT/infra/scripts/setup.sh" + +# ─────────────────────────────────────────────── 3. platform + +echo "==> Starting Platform (Go :8080)" cd "$ROOT/workspace-server" -go run ./cmd/server & +go run ./cmd/server > /tmp/molecule-platform.log 2>&1 & PLATFORM_PID=$! -echo "==> Waiting for Platform health..." -until curl -sf http://localhost:8080/health >/dev/null 2>&1; do +echo " Waiting for Platform /health..." +PLATFORM_READY=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \ + 21 22 23 24 25 26 27 28 29 30; do + if curl -sf http://localhost:8080/health >/dev/null 2>&1; then + echo " Platform ready (t+${i}s)" + PLATFORM_READY=1 + break + fi sleep 1 done -echo " Platform ready." +if [ "$PLATFORM_READY" -ne 1 ]; then + echo " ✗ Platform did not respond in 30s — check /tmp/molecule-platform.log" + exit 1 +fi -echo "==> Starting Canvas (Next.js :3000)..." +# ─────────────────────────────────────────────── 4. canvas + +echo "==> Starting Canvas (Next.js :3000)" cd "$ROOT/canvas" if [ ! -d node_modules ]; then + echo " First-run: npm install (~30-60s)" npm install fi -npm run dev & +npm run dev > /tmp/molecule-canvas.log 2>&1 & CANVAS_PID=$! -echo "" -echo "============================================" -echo " Molecule AI dev environment running" -echo "" -echo " Canvas: http://localhost:3000" -echo " Platform: http://localhost:8080" -echo " Postgres: localhost:5432" -echo " Redis: localhost:6379" -echo "" -echo " Press Ctrl-C to stop all services" -echo "============================================" +echo " Waiting for Canvas HTTP 200..." +CANVAS_READY=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \ + 21 22 23 24 25 26 27 28 29 30; do + code=$(curl -sf -o /dev/null -w "%{http_code}" http://localhost:3000/ 2>/dev/null || echo "0") + if [ "$code" = "200" ]; then + echo " Canvas ready (t+${i}s)" + CANVAS_READY=1 + break + fi + sleep 1 +done +if [ "$CANVAS_READY" -ne 1 ]; then + echo " ✗ Canvas did not respond in 30s — check /tmp/molecule-canvas.log" + exit 1 +fi + +# ─────────────────────────────────────────────── 5. readiness banner + +cat <