Why this exists
Picking the right providers is the first friction point in a new project.
Stack's catalog has 39 curated providers across 13
categories — too many to hold in your head, too few to outsource to a
generic LLM. stack recommend closes the gap: free-text in,
ranked providers out, frozen to a reproducible Recipe that stack apply can replay.
Quick start
Save a recommendation, review it, then authorize setup in the intended directory:
stack recommend "B2B SaaS with auth, AI, and payments" --save
# → .stack/recipes/b2b-saas-with-auth-ai-and-paymen.toml
stack apply b2b-saas-with-auth-ai-and-paymen Two modes
Default recommendation is retrieval-only. Optional synthesis can contact the configured HTTP endpoint; a local default does not constrain overrides.
| Mode | When it fires | What does the reasoning |
|---|---|---|
| Claude Code (MCP) |
You're in a Claude / Cursor / Windsurf session and the agent calls stack_recommend.
| Claude consumes Stack's retrieval output as grounded context and may write its own rationale. The MCP wrapper returns CLI text; the external agent has its own provider settings. |
| Standalone CLI (local SLM) |
You run stack recommend --synth in a terminal, no agent
attached.
|
Stack speaks OpenAI-compatible HTTP to LM Studio (:1234)
or Ollama (:11434). Missing endpoint? Falls back to
retrieval-only output — command still exits 0.
|
stack recommend
Rank providers against a free-text description. Flags compose.
| Flag | Type | What it does |
|---|---|---|
--save | boolean |
Freeze the result as .stack/recipes/<id>.toml. The
id is slugified from the query. Feed it to stack apply.
|
--synth | boolean | Call the configured HTTP endpoint for model-authored rationales. Defaults are local; endpoint overrides may be remote. Inference failure can fall back to retrieval-only output. |
--json | boolean | CLI JSON output; the MCP wrapper carries this inside text content. |
--k | number |
Max hits to return. Default 6.
|
--category | string |
Restrict to one category: Database, Deploy, Cloud, AI, Analytics, Observability, FeatureFlags, Errors, Payments, Code, Tickets, Email, Auth.
|
Default output
Illustrative output and scores; actual matches depend on the current catalog. Retrieval scores are not measured provider quality.
$ stack recommend "B2B SaaS with auth, AI, and payments"
┌ stack recommend
query: B2B SaaS with auth, AI, and payments
● Clerk Auth (4.13)
Drop-in auth + users. Secret key stored in Phantom.
add with: stack add clerk
● Stripe Payments (3.70)
Billing, subscriptions, tax. Restricted / test-mode secret key stored in Phantom.
add with: stack add stripe
● xAI AI (2.90)
Grok + tool use. Key verified on paste.
add with: stack add xai
● Sentry Errors (2.48)
Error + performance tracking. Attaches to an existing project and reads its DSN when available.
add with: stack add sentry
● OpenAI AI (2.23)
GPT, Realtime, embeddings. Key verified against /v1/models on paste.
add with: stack add openai
● Anthropic AI (2.23)
Claude models + MCP. Key verified against the Messages API on paste.
add with: stack add anthropic
Top pick per category: Auth→clerk, Payments→stripe, AI→xai, Errors→sentry.
No matches surfaced for: Database, Deploy, Cloud, Analytics, Code, Tickets, Email.
Apply a chosen set with: stack add clerk && stack add stripe && stack add xai (one command per service).
Tip: rerun with `--save` to freeze as a recipe for `stack apply`.
│
└ Tell Claude or run `stack add <name>` to continue. --save — freeze to a Recipe
$ stack recommend "B2B SaaS with auth" --save
● Clerk Auth (4.13)
● Sentry Errors (2.48)
● Supabase Database (2.16)
● Firebase Database (2.16)
● Turso Database (0.79)
Saved recipe: b2b-saas-with-auth (/path/to/.stack/recipes/b2b-saas-with-auth.toml)
Apply with: stack apply b2b-saas-with-auth --synth — local-SLM rationales
With LM Studio or Ollama running, each hit gains a why: line authored by the model. Without either, the command
can fall back to retrieval-only output. Other I/O or setup errors remain possible. Illustrative synthesis output:
$ stack recommend "analytics + error tracking for a Next.js app" --synth
● PostHog Analytics (5.01)
Product analytics + session replay. Personal API key stored in Phantom.
why: PostHog gives you funnels, flags, and replay for a Next.js app in one SDK.
add with: stack add posthog
● Sentry Errors (4.77)
Error + performance tracking. Attaches to an existing project and reads its DSN when available.
why: Sentry captures unhandled exceptions and Web Vitals without extra glue.
add with: stack add sentry --json — machine-readable
This is illustrative CLI JSON, not the outer MCP text envelope. The example fields and scores are not a live acceptance receipt:
{
"query": "B2B SaaS with auth and payments",
"hits": [
{
"name": "clerk",
"displayName": "Clerk",
"category": "Auth",
"authKind": "api_key",
"secrets": ["CLERK_SECRET_KEY"],
"blurb": "Drop-in auth + users. Secret key stored in Phantom.",
"score": 4.125,
"matched": ["auth"]
},
{
"name": "stripe",
"displayName": "Stripe",
"category": "Payments",
"authKind": "api_key",
"secrets": ["STRIPE_SECRET_KEY"],
"blurb": "Billing, subscriptions, tax. …",
"score": 3.697,
"matched": ["payments"]
}
],
"byCategory": { "Auth": [{ "name": "clerk", "score": 4.125 }], "…": [] },
"guidance": "Top pick per category: Auth→clerk, Payments→stripe. …"
} --k — cap the hits
$ stack recommend "postgres database" --k 3
● Neon Database (5.76)
Serverless Postgres. Creates a project and pools the connection string.
● Supabase Database (5.49)
Postgres + Auth + Storage. Full upstream provisioning via the Management API.
● Turso Database (4.35)
Edge SQLite (libSQL). Creates a database in your default org. --category — restrict to one category
$ stack recommend "serverless" --category Database
● Neon Database (5.76)
Serverless Postgres. Creates a project and pools the connection string.
● Turso Database (2.18)
Edge SQLite (libSQL). Creates a database in your default org. stack apply
Replay a saved Recipe through the existing stack add pipeline,
then check which declared secrets are in the Phantom vault. Setup may
create or attach resources and write credentials/config; the vault check
only reads names, and webhook stubs are not verified handlers.
# Illustrative replay; inspect actual setup and optional wiring results
$ stack apply b2b-saas-with-auth
recipe b2b-saas-with-auth
query B2B SaaS with auth
providers clerk, sentry, supabase
› stack add clerk
› stack add sentry
› stack add supabase
secrets in vault 7 · missing 1 · webhooks 2
(not in Phantom: SENTRY_AUTH_TOKEN — store with `phantom add <NAME>`)
› stack doctor
✓ b2b-saas-with-auth applied. | Flag | What it does |
|---|---|
--noWire |
Skip the Phantom-wire layer — pure stack add replay, no
vault check or webhook stubs. Provider setup and credential/config writes
still occur; this flag is not a dry run.
|
--noRollback | Skip the multi-service cleanup attempt after partial failure. Existing provider resources, credentials or partial writes may remain; this flag is not a dry run or a guarantee about upstream deletion. |
What gets wired
After setup succeeds for an entry, the default flow can attempt these steps unless --noWire is set:
- Phantom vault check — reads names from
phantom list --json(never values) and lists each declared secret as in the vault or missing. It never writes to the vault; store missing values withphantom add <NAME>. - Webhook stubs — scaffolded verification + handler files
for selected providers in the helper:
stripe,clerk,supabase,github. Implement and verify handlers in the app before using them; generated comments are not signature verification. - Inline
stack doctor— runs at the end so you can inspect available checks. It is informational and not an all-services-success gate forapply.
stack apply is not a universal safe-retry guarantee.
MCP tools
Both commands are exposed as MCP tools so Claude Code (and any MCP-speaking editor) can request these operations when its actual tools and project context are configured. See the full MCP integration docs for setup.
stack_recommend stack recommend …
Retrieval-only. Returns ranked providers with scores, matched terms, and
per-category top picks. Pass save: true to also freeze a
Recipe to disk so you can follow up with stack_apply.
| Input | Type | Description |
|---|---|---|
query req | string | Free-text description of the project. |
k | number | Max results (default 6). |
category | string | Restrict to one category. |
save | boolean |
Freeze to .stack/recipes/<id>.toml; returns the
recipe id.
|
stack_apply stack apply …
Replay a saved Recipe. Runs stack add for each provider,
then checks the Phantom vault and writes webhook stubs. The returned text
can include failures; setup and cleanup are not atomic.
| Input | Type | Description |
|---|---|---|
recipe_id req | string |
Recipe id (filename stem in .stack/recipes/).
|
no_wire | boolean | Skip the Phantom vault check and webhook stubs. |
In-session example
Illustrative conversation, not a recorded customer or provider outcome:
You > Build me a SaaS — auth, payments, error tracking, Postgres.
Claude > I'll pick the providers first and freeze a recipe so you can
replay this.
(calls stack_recommend { query: "SaaS with auth, payments,
error tracking, and Postgres", save: true })
Top picks: clerk (Auth), stripe (Payments), sentry (Errors),
neon (Database). Saved as recipe "saas-with-auth-payments-error".
Want me to apply it now? This runs `stack add` for each and
checks which secrets are already in Phantom.
You > Yes.
Claude > (calls stack_apply { recipe_id: "saas-with-auth-payments-error" })
Setup report: inspect added, skipped and failed entries.
Optional wiring counts and doctor checks need separate verification. Recipe file format
Recipes are plain TOML under .stack/recipes/<id>.toml.
Recipes can include the original query and freeform rationales. Review
them before sharing; dedicated credential persistence uses
Phantom.
id = "b2b-saas-with-auth"
query = "B2B SaaS with auth"
createdAt = "2026-04-19T02:22:44.810Z"
guidance = "Top pick per category: Auth→clerk, Errors→sentry, Database→supabase."
[[providers]]
name = "clerk"
rationale = "auth"
[[providers]]
name = "sentry"
rationale = "auth"
[[providers]]
name = "supabase"
rationale = "auth"
The id is the first ~40 chars of the query, slugified. The rationale starts as the matched terms from retrieval and gets
may be updated when an authorized synthesis result is saved. An agent
writing prose externally does not itself rewrite the stored recipe.
How retrieval works
Zero-dep BM25 + IDF scorer over the curated provider catalog, with a small
table of hand-authored synonyms (db → database, billing → payments, auth → users, …) so natural-language queries map to the terms we
actually index. Scoring is deterministic — same query, same ranking. The
catalog itself lives in packages/core/src/catalog.ts and is
the same source the providers page renders
from.
FAQ
Can I use my own LLM?
Yes. Set STACK_LM_URL to any OpenAI-compatible endpoint. Stack
talks plain HTTP to LM Studio (localhost:1234) and Ollama
(localhost:11434) by default. An override may contact another
host; verify its access and privacy requirements.
Does anything call Anthropic or OpenAI?
Default retrieval uses no model. Optional synthesis can contact a configured endpoint, while the external coding agent has its own provider settings. Absence of an SDK is not a no-network proof.
What if the SLM isn't running?
--synth silently falls back to retrieval-only output. The
ranking remains retrieval-based, and --save can persist the
recipe. Endpoint fallback does not rule out other I/O errors or guarantee
an exit code of 0.
What now?
Browse every provider
The full catalog retrieval runs against — 39 providers across 13 categories.
MCP integration
Wire Stack's MCP server into Claude Code, Cursor, Windsurf, or Zed.
CLI reference
Every stack subcommand with
flags and defaults.
Phantom Secrets
Credential persistence and the limits of optional stack apply wiring.