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 addwithout it. - Node 20+ or Bun 1.1+ — for the CLI itself
and for the MCP
npxshims 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:
- Pop a browser window for Supabase OAuth (PKCE — no secrets pasted).
- Create a new project in your default org.
- Generate a DB password, store it in Phantom.
- Fetch the anon + service-role keys and route them into Phantom.
- Add a
supabaseMCP entry to.mcp.jsonscoped to the new project. - 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. 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.