Skip to content
Getting started

Quickstart

From a fresh terminal to a provisioned Supabase project with MCP wired into Claude Code — in about five minutes.

Before you start

Stack is a thin orchestration layer; two other things do the heavy lifting and must be on your PATH:

  • Phantom Secrets — holds every secret. Stack refuses to run stack add without it.
  • Node 20+ or Bun 1.1+ — for the CLI itself and for the MCP npx shims certain providers wire up.

1. Install Stack

One-liner:

curl -fsSL stack.ashlr.ai/install.sh | bash

Or via your package manager:

bun add -g @ashlr/stack
# or
npm i -g @ashlr/stack
# or (macOS)
brew install ashlrai/stack/stack

And Phantom (required for anything that touches secrets):

brew install ashlrai/phantom/phantom
# or
npm i -g phantom-secrets

2. Verify the install

stack status

You should see something like:

  Ashlr Stack

  ● .stack.toml       missing — run `stack init`
  ● phantom           0 secrets in vault
  ● services          0 configured

Two red dots — that's fine. We haven't initialised anything yet. Phantom showing a green dot means Stack can talk to the vault.

3. Initialise a project

Inside any repo (Next.js, Astro, Rails, whatever):

cd path/to/your-app
stack init

Stack prompts for a starter template. Pick blank for now — we'll add services one at a time. Output:

┌  stack init

◇  Pick a starter template (or blank):
│  Blank — add services later with `stack add`

└  Wrote .stack.toml (stk_8f3c6a2e).

Two files appear on disk:

  • .stack.toml — committed. The shape of your stack.
  • .stack.local.toml — gitignored automatically. Your project_id and per-developer instance data.

Stack also appends .stack.local.toml to your .gitignore so you can't accidentally commit it. See the config reference for the full schema.

4. Add your first service

Let's wire up Supabase — the most interesting one, because it has a full upstream provisioning flow plus an MCP server.

stack add supabase

Stack will:

  1. Pop a browser window for Supabase OAuth (PKCE — no secrets pasted).
  2. Create a new project in your default org.
  3. Generate a DB password, store it in Phantom.
  4. Fetch the anon + service-role keys and route them into Phantom.
  5. Add a supabase MCP entry to .mcp.json scoped to the new project.
  6. Write the service into .stack.toml + .stack.local.toml.

You'll see something like:

┌  stack add supabase

◇  ● supabase (abcdefghijklmnop) · 3 secrets · mcp wired

└  ✓ supabase is live.
No Phantom prompts? Good. Stack wrote the secrets through Phantom's programmatic API — you'll never see the real values. See Phantom for the full story.

5. Sanity-check with doctor

Before you move on, verify everything is reachable. stack doctor hits each configured provider and confirms the stored credentials still work:

stack doctor
┌  stack doctor

◇  ● supabase (218ms)

└  All services healthy.

Run this before deploys, after a stale laptop comes out of a drawer, or any time something feels off. In CI, use stack doctor --json — exit code 0 if healthy, 1 if any service fails. See CI integration.

6. Run your app with secrets injected

Instead of bun dev, run stack exec -- bun dev. Phantom's proxy injects real secret values for any phm_ tokens at the network layer:

stack exec -- bun dev

Your app boots with SUPABASE_URL, SUPABASE_ANON_KEY, and SUPABASE_SERVICE_ROLE_KEY available in process.env — without any plaintext secret ever touching disk.

What now?