launch

SkillMedia

Run the Inspector app locally, any mode (dev bucket / offline fixtures / live dev or prod Space), any worktree, conflict-free.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the launch skill

What this skill tells your AI

The instructions your AI receives, as published by qud-technologies/quranic-universal-audio in .claude/skills/launch/SKILL.md and read by ahel’s review.

One script runs every way of starting the Inspector and keeps parallel launches from colliding. You almost never need to think — just run it.

python scripts/devenv/launch.py [up] [--mode MODE] [flags]

The script (scripts/devenv/launch.py) owns everything that used to go wrong by hand: free-port allocation, per-worktree SQLite isolation (INSPECTOR_DB_PATH), interpreter pinning (sys.executable, so no python3-vs-Python313 split), Vite⇄backend proxy wiring, readiness polling (/healthz + the Vite port), and a machine-wide registry so it can list / down / doctor every stack. It prints human URLs and a LAUNCH_JSON {…} line an agent can parse.

Just run it

GoalCommand
Run the app (real DEV data, default)python scripts/devenv/launch.py
Read-only look at PROD data (local)python scripts/devenv/launch.py up --mode prod
Fully offline (no token/network)python scripts/devenv/launch.py up --mode fixtures
Run a different worktree`… up --worktree <name
Open in a browser too… up --open
What's running?python scripts/devenv/launch.py list
Stop this worktree's stackpython scripts/devenv/launch.py down
Stop everythingpython scripts/devenv/launch.py down --all
Fix "wrong port / two Flasks / stale Vite"python scripts/devenv/launch.py doctor --fix

Modes

Every mode is fully local — your branch's Flask backend + Vite, no HF Space proxy, no hf-mount. Bucket reads use the hffs fallback (sub-second on the dev bucket; the bigger prod bucket is slower, multi-second cold); audio CDN-falls-back via the proxy. The only thing that changes between modes is which data the backend reads. Needs HF_TOKEN (in .env) for the bucket modes.

  • dev (default) — backend reads the DEV bucket, read-write. The everyday mode: runs your branch end-to-end (audio + analysis included), HMR for FE changes.
  • prod — backend reads the PROD bucket, read-only (two guards: INSPECTOR_READ_ONLY=1 makes the storage backend refuse every write — segment saves, manifests, job records — and INSPECTOR_DB_SYNC=0 keeps DB commits local). Nothing local can mutate production by any path; an edit attempt fails loud rather than corrupting prod. A safe look at real production data. First reads are slow (big uncached prod bucket over hffs).
  • fixtures — fully offline: filesystem backend on seeded fixtures (auto-seeds on first run) + Vite. No token, no network.

Per-content read source

The bucket isn't the fastest source for every content type locally. By default in dev/prod:

  • Audio → CDN (not the bucket): the bucket's hffs full-MP3 read is slow locally, and the CDN is the same audio for most reciters. --bucket-audio forces the bucket (to verify the re-encoded/stereo-fixed audio that can differ from the CDN). fixtures always reads local audio (offline, no CDN).
  • Peaks → bucket (slim peaks/*.json.gz): --ffmpeg-peaks skips them so the FE computes per-segment peaks via ffmpeg instead.
  • Shards / detailed / manifest → bucket always (no toggle).

Knobs: INSPECTOR_AUDIO_FROM_BUCKET / INSPECTOR_PEAKS_FROM_BUCKET (the launcher owns these per mode; the flags above override).

For agents (driving the running app)

Run up (it starts both backend + Vite), read the LAUNCH_JSON line for the url, then drive that URL with a browser MCP. Use dev (the default).

Default driver: chrome-devtools-mcp. Measured on this app's Dashboard, its a11y snapshot is ~2.6× smaller than playwright's (≈14 KB vs ≈38 KB for the same page), its actions return a one-line ack (snapshot is opt-in, not forced on every call), and it carries the DevTools tools we actually use here — network request bodies, console, performance_start_trace, evaluate_script, throttling/emulation. Net: fewer tokens per step and the right debugging surface.

Reach for playwright instead only for pure interaction (multi-step forms, exploratory clicking) where its auto-snapshot-on-every-action is convenient and you don't need network/console/perf.

Typical loop: navigate_page → take_snapshot (grab the uids) → click/fill by uid → take_screenshot. There's no built-in liveness check — your first navigate + take_snapshot already tells you whether the stack is serving real data.

Parallel & conflict-safety

Two worktrees (or two stacks) can run at once: ports are allocated free + reserved in the registry, and each worktree gets its own INSPECTOR_DB_PATH so the local SQLite never clobbers. doctor detects the failure modes we actually hit — two processes bound to one port (serving stale code), a foreign/orphan Flask or Vite, dead registry entries — and --fix cleans them.

The bucket is NOT isolated, though. All dev stacks (and the live dev Space) share one dev bucket: the DB syncs full-file with a CAS guard (no row merge) and per-reciter content is last-write-wins, so two concurrent dev writers can clobber each other — the single-writer invariant. Launch warns when you start a 2nd dev stack while another is up. For a safe parallel stack use prod (read-only) or fixtures (local disk, fully isolated); only ever edit in one dev stack at a time.

Env ownership (.env vs launch)

The launcher owns every run-mode knob — INSPECTOR_BACKEND, INSPECTOR_FILESYSTEM_ROOT, INSPECTOR_ALLOW_PROD_BUCKET, INSPECTOR_READ_ONLY, INSPECTOR_DB_SYNC, INSPECTOR_AUTO_MOUNT, INSPECTOR_DB_PATH — and sets them per mode, so a stale .env can't perturb the profile. dev forces ALLOW_PROD_BUCKET=0 (can never touch prod; fails closed if .env names the prod repo). .env only supplies secrets + identity (HF/GitHub/QF tokens, session secret, dev-owner id) and the one per-machine choice the launcher reads in dev: your own INSPECTOR_BUCKET_REPO dev bucket. Those knobs in .env matter only when hand-running python inspector/app.py.

Notes

  • First run in a fresh worktree needs deps: scripts/devenv/setup.sh (or npm ci in inspector/frontend). The wt skill's setup does this.
  • The full app runs locally on Windows — audio + analysis included, no hf-mount needed. Bucket reads go through the hffs fallback (dev bucket sub-second; prod bucket multi-second cold) and audio CDN-falls-back via the proxy. A shard 404 in dev is the released-gate (the reciter isn't released in this worktree's isolated DB) or missing bucket data, not a platform limit. FE changes are always live via local Vite.
  • Logs: <worktree>/.local/launch/logs/. Registry: <main-worktree>/.local/launch/registry.json (gitignored).
  • Python changes need a down + up (Flask reloader is off by design — single-worker invariant). Vite changes hot-reload.

Signals

GitHub stars
33
Forks
4
Last commit
Sep 2026
Hacker News mentions
20
Advanced
Catalog kind
skill
Gateway key
launch-qud-technologies
Source
github.com/qud-technologies/quranic-universal-audio