Stack is versioned in lockstep with the root repo. Pre-1.0 releases are additive by default — new commands ship, existing commands don't disappear — with the occasional breaking change called out inline.
Unreleased
Reliability + hardening (auto-agent)
Retry + recovery + secret-redaction pass on packages/core/. No other package touched.
fetchWithRetryshipped (packages/core/src/http.ts) — exponential backoff with jitter,Retry-Afterheader honored (integer-seconds + HTTP-date), idempotency auto-derived frominit.method(GET/HEAD) with explicit opt-in for safe POSTs, abortable viaAbortSignal. Zero new runtime deps. Threaded through GET healthcheck + verify paths on all seven providers in scope (supabase, neon, vercel, github, cloudflare, sentry, plus everymakeApiKeyProvider-based provider via a newverifyFetchhelper in_helpers.ts). Provision POSTs are deliberately NOT retried — a second call could double-create an upstream resource or double-charge a provider API. Railway + Linear GraphQL POSTs explicitly opt in toidempotent: truebecause they use read-only{ me }/{ viewer }queries.- Partial-failure breadcrumb in the
addServicepipeline (packages/core/src/pipeline.ts) — ifmaterialize()throws afterprovision()succeeded, we now persist a minimalServiceEntry(provider,resource_id,region,meta, emptysecrets: [],created_by: "stack add (partial)") before re-throwing the original error. Leaves a breadcrumb forstack doctor --fixorstack removeto find and clean up the dangling upstream resource. Documented in a code comment with rationale. - Secret-redaction audit — 15 log sites reviewed across every provider (supabase, neon, vercel, github, cloudflare, sentry, turso, aws, plus the
_api-keyfactory); 0 were interpolating raw tokens — all cached-token-invalid warnings use static strings. Addedscrub(value, keepLast?)helper topackages/core/src/providers/_helpers.tsfor future use. VerifiedformatArgsForError()inphantom.tsstill redactsphantom add KEY VALUE's third argument correctly; added a regression test that exercises a failing phantom binary and asserts the raw value never appears in the thrownStackError. - Tests: 3 new files —
http.test.ts(13 cases: happy path, 429 retry, 500 max-out, Retry-After honored, POST no-retry, explicit idempotent opt-in, network-error retry for idempotent, non-idempotent network error bubbles, customretryOn, AbortSignal mid-retry, + 5parseRetryAftercases),pipeline-recovery.test.ts(2 cases: breadcrumb written on partial failure; dry-run skips breadcrumb),secret-redaction.test.ts(8 cases:scrubunit tests + cached-token-warning doesn't leak raw secret +formatArgsForErrorredactsphantom add's value). 120 tests, all green (was 97). - Sanity:
bun testgreen,bunx tsc --noEmit -p tsconfig.jsonclean.
Marketing surface (auto-agent)
Polish pass on packages/site/ — landing page + docs, no other package touched.
- Vercel Web Analytics —
@vercel/analyticsdependency added;/_vercel/insights/script.jsloaded defer-ed fromBase.astro, plus areferrer-when-downgrademeta for correct attribution. Ships regardless of plan; no-ops until the Vercel dashboard flag is on. /docs/changelog— renders the repo-rootCHANGELOG.mdas a docs page viamarked+ Vite?rawimport. Slots under a new "Meta" sidebar group./docs/roadmap— honest Shipped / In progress / Considering / Explicitly not doing list, dated where possible. Also under "Meta".- Launch copy drafts under
/launch/*—hn.md(Show HN, ≤200 words,noindex),twitter.md(7-tweet thread with the 🔺 mark,noindex),blog.mdx(~1000-word "Introducing Ashlr Stack" long-form, indexable, rendered through the Docs layout via a thinLaunchPost.astrowrapper). Non-indexable notes use a newLaunchNote.astrowith minimal self-contained prose styles. DemoReel.tsx— React island that replays astack init → stack add supabase → stack exec -- bun devsequence as an auto-looping scripted terminal. Shares visuals with the heroTerminal.tsx(magenta prompt, green checkmarks, dim notes), respectsprefers-reduced-motionby snapping to the last frame and pausing, and carriesrole="img"+ a descriptivearia-labelfor screen readers. Mounted on the homepage as "§ 03 · In motion — See it run" between the one-command section and the providers grid.- MDX integration —
@astrojs/mdxadded so the blog post can mix prose and code fences freely. - Build:
bunx astro check— 48 files, 0 errors / 0 warnings / 0 hints.bun run build— 17 pages, sitemap regenerated. Only the existing pre-launch@import-order CSS advisory remains.
Publish + Windows (auto-agent)
Windows support + npm-publish readiness without touching any owner-restricted code (packages/site/, packages/core/src/, packages/cli/src/, packages/mcp/src/, packages/plugin/):
scripts/install.ps1— Windows PowerShell one-liner installer mirroringscripts/install.sh. Detects Bun (installs viairm bun.sh/install.ps1 | iexif missing), falls back tonpm i -g phantom-secretsfor the vault (no brew on Windows), triesbun add -g @ashlr/stack ashlr-stack-mcpfirst, falls back to git-clone into$env:LOCALAPPDATA\ashlr-stackand writes astack.cmd+ashlr-stack-mcp.cmdshim into$env:USERPROFILE\.local\bin(preferred) or$env:LOCALAPPDATA\Programs\ashlr-stack\bin. Warns if the shim dir isn't on PATH. Install body wrapped inInstall-AshlrStack+ a top-level guard sopwsh -Command { . ./scripts/install.ps1 }parses without side-effects. Usage:irm stack.ashlr.ai/install.ps1 | iex.Per-package README + LICENSE:
packages/cli/README.md— technical overview, the three install paths, quickstart, command cheat-sheet for all 22 commands, links to docs.packages/core/README.md— short explainer that this is the shared library (not usually installed directly), public-API table (addService,readConfig/writeConfig,listProviderNames,getProvider,scanSource,detectProvider,parseEnv), example import.packages/mcp/README.md— what it is, install,.mcp.jsonsnippets for Claude Code / Cursor / Windsurf / Codex, 17 tools grouped by category, 3 resources, links tostack.ashlr.ai/docs/mcp.packages/cli/LICENSE,packages/core/LICENSE,packages/mcp/LICENSE— copies of the root MIT LICENSE (npm doesn't traverse up).
npm publish shape audit — verified each published package.json (
@ashlr/stack,@ashlr/stack-core,ashlr-stack-mcp) is ship-ready:filesarrays include onlysrc/**/*,README.md,LICENSE;publishConfig.access: "public"present on all three;binpaths correct (./src/index.ts);repository.directorycorrect;main/exportscorrect on core. Flagged:@ashlr/stackdepends on@ashlr/stack-coreviaworkspace:*— fine for monorepo dev, would break a barenpm install @ashlr/stack. Documented this in the root README "Publishing" section rather than hand-editing dev-critical dep ranges.scripts/publish.sh— automated publish dance. Accepts--version X.Y.Z(or prompts), backs up eachpackage.json, bumpsversion, rewrites everyworkspace:*→^X.Y.Z, runsnpm publish --dry-runfor each of the three packages first, prompts for explicit confirmation (bypass with--yes), publishes in dep ordercore → mcp → cli, always restoresworkspace:*via an EXIT trap so dev keeps working, then tagsv<version>and pushes the tag. Never publishes without an explicit confirmation.Root
README.mdpolish — added three badges at the top (CI, MIT license, npm version — latter renders "not found" until publish, by design). New "Install" section right under the tagline with three options (macOS/Linux one-liner, Windows PowerShell one-liner, manualbun add -g). Prominent link toSTACK.mdfor AI-agent readers. New "Publishing" subsection under "Monorepo layout" pointing atscripts/publish.shand explaining theworkspace:*caveat.Sanity checks:
bun install,bun test(97 / 0),bunx tsc --noEmit -p tsconfig.json, and PowerShell parse check forscripts/install.ps1all pass.
Documentation site — /docs subsection
10 documentation pages under packages/site/src/pages/docs/:
/docs— three-card hero to quickstart / providers / CLI/docs/quickstart— zero → first service in 5 minutes/docs/cli— full reference for all 22 commands (synopsis / flags / examples / subcommands)/docs/providers— all 23 providers with auth kind, secret slots, MCP wiring, dashboard + docs URLs/docs/templates— 5 starters with per-service breakdown/docs/config—.stack.tomlcommitted /.stack.local.tomllocal schema/docs/phantom— how Stack composes with Phantom Secrets/docs/mcp— 17 MCP tools + 3 resources for Claude Code / Cursor / Windsurf/docs/ci—stack doctor --jsonin CI, generated workflow, secrets setup/docs/faq— top 10 new-user questions
Docs layout (src/layouts/Docs.astro): sticky left sidebar (<select> on mobile), prose column with magenta-accented H2s + inline code, right on-this-page TOC with IntersectionObserver scrollspy, prev/next pagination at the foot of each page.
Reference data in src/lib/ (hand-mirrored from source — Node-only @ashlr/stack-core can't ship to the static site bundle):
cli-ref.ts— 22 commandsproviders-ref.ts— 23 providersmcp-ref.ts— 17 tools + 3 resourcestemplates-ref.ts— 5 templatesdocs-nav.ts— sidebar structure + prev/next helper
Build: bunx astro check — 41 files / 0 errors. bun run build — 11 pages (homepage + 10 docs routes) + sitemap-index.xml + sitemap-0.xml.
Landing page visual redesign + SEO/GEO package
Full editorial-technical makeover of the marketing site at packages/site/.
Typography & voice — swapped Inter for a two-font system: Instrument Serif (display, italic-capable) paired with Geist (body) and Geist Mono (code). Every section now opens with a small-caps § NN editorial rule + a display-serif headline that occasionally italicizes a single phrase for emphasis — trade-magazine-for-infrastructure vibe.
New motion primitives:
ScrollReveal.astro— IntersectionObserver-backed fade+lift on viewport enter; staggered children via--stagger-iCSS var. Idempotent install, honorsprefers-reduced-motion.Counter.tsx— ease-out-cubic count-up from 0→target on first view.MagneticButton.tsx— 6px-capped cursor-deflection on the primary CTA; falls back to plain button in reduced-motion.- On-load staggered hero sequence (7 elements, 40–660ms delays) via pure CSS — no JS cost.
- Provider card hover: border + background + 2px lift + brand-color radial underglow.
- Editorial
.edi-ruledividers (hairline with small-caps label, gradient-masked). - Sitewide SVG grain overlay for depth.
- Subtle sheen sweep on
btn-primaryvia::beforetransform. - Rotated display-serif "est. 2026" seal behind the hero terminal.
- "Vol. 01 · Issue 2026" corner marks on the hero — tiny but make the page feel designed.
Logo system: Logo.astro now ships three variants (mark, chip, wordmark) with a proper gradient fill and crisp SVG geometry. Same triangle, new precision.
SEO/GEO package (agent-delivered, verified):
- Favicon set (SVG + 32/192/512 sizes + apple-touch + PWA manifest).
- OG image (1200x630 SVG), Twitter card (1200x600 SVG).
Base.astrorewritten with typed props fortitle/description/canonical/ogImage/ogType/noindex/breadcrumbs; emits full OG + Twitter +theme-color+color-scheme+ manifest + RSS alternate.- Three JSON-LD schemas: Organization, WebSite, SoftwareApplication (version
0.1.0-pre-alpha, no fakeaggregateRating). @astrojs/sitemapwired;sitemap-index.xml+sitemap-0.xmlgenerate at build.robots.txtwith sitemap reference.llms.txt+llms-full.txt(llmstxt.org standard) — self-contained summaries so LLMs can answer "what is Stack?" without fetching anything else.
Build: bunx astro check — 0 errors / 0 warnings / 0 hints. bun run build — 1 page, ~45 KB gz client JS.
Commodity polish (env, dry-run, remove-all, picker, completion, CI)
Six week-one features comparable tools ship that Stack was missing:
stack add(no arg) → interactive picker — @clack/promptsselectwith the full 23-provider catalog grouped by category + authKind hints. Falls back to an error in non-TTY.stack add --dry-run— describes the four-stage pipeline (login → provision → materialize → persist) without touching Phantom, the network, or.mcp.json. Good for "what will this do?" confidence.stack env set <KEY> <VALUE>— direct secret injection. Auto-derives the service from the env-name pattern (falls back tomiscif unknown);--service <name>overrides.stack env unset <KEY>removes from both Phantom and.stack.toml.stack remove --all— tear down every service with a two-step confirmation (confirm+ typed"remove all"). Non-TTY runs without prompts.stack completion bash|zsh|fish— emits a completion script including live provider + template names baked at runtime. zsh uses_values, bash usescomplete -F, fish usescomplete -c.stack ci init— scaffolds.github/workflows/stack-ci.ymlthat runsstack doctor --jsonon push + pull_request + nightly cron, pulls from Phantom Cloud, and uploads the doctor report as an artifact.
22 CLI commands total · 5 new tests · 69 tests all green.
Landing page — stack.ashlr.ai
Premium marketing surface at packages/site/. Astro 5 + Tailwind v4 + Framer Motion + React islands. Dark-first, magenta accent.
Sections (in order):
- Hero — ▲ stack mark, gradient headline, working copy-button on the install one-liner, animated
<Terminal/>runningstack add supabaseend-to-end. - One-command moment — Framer Motion tab-group with shared
layoutIdpill; "Without Stack" (8 real steps, 45 min) vs "With Stack" (1 command). - Providers grid — all 23 providers grouped into 11 categories, simple-icons marks inlined at build time.
- How it works — 3-step panel (CLI → Phantom → wiring) with per-step mini terminals and a magenta connector.
- Templates — 5 real templates, each rendered as a card with the real
stack init --template <id>command. - Claude Code integration — scripted mock chat UI running
/stack:add supabase→ narration → tool_use → tool_result. - Ashlr constellation — Stack center + Phantom / ashlr-plugin / ashlrcode satellites connected in SVG.
- Footer — CTA panel + 3-column link tree + giant faded wordmark.
Ships with: preconnect on Google Fonts, skip-to-content link, focus-visible rings, role="tablist" keyboard nav, WCAG-AA body contrast, responsive 6→4→3→2 grid, prefers-reduced-motion respected at both CSS level and inside the two Framer islands. bun run build produces a static dist/ with ~45 KB gz client JS (framer-motion is the majority; only loads on the two interactive islands).
bunx astro check — 0 errors · 0 warnings · 0 hints.
Hardening pass (code review + UX polish)
Independent code review surfaced 6 real issues; independent UX review surfaced 10 gaps. All addressed:
- Security: redacted secret values from
phantom ${args}error messages (was leaking the raw value on non-zero exit). Fake-phantom test harness rewritten to pass all args viasys.argv— Python-injection surface closed.stack clonenow rejectsfile://,--option-prefixed, andext::URLs; passes--before positional args to git. AWSmaterializenow explicitly validates theaccessKeyId:secretAccessKeyshape instead of silently splitting. OAuth callback server binds port before registering the request handler — eliminates theredirectUri === ""race. - Correctness:
DATABASE_URLno longer auto-attributed to Neon (it's a generic Postgres convention — Supabase, Railway, Render, etc. all use it). Neon now stores connection URIs keyed by project id so cross-project pollution can't happen. SentryfetchIdentitywrapped in try/catch so network errors surface as healthcheck errors, not uncaught throws. - Polish:
stack --versionworks. Barestackprints a banner.outroErrorcallsprocess.exit(1)so CI actually sees non-zero. Unknown-provider errors group the catalog by category instead of wrapping a comma-soup line.stack doctor --fixasks for confirmation before re-running OAuth/provision flows.stack upgradereadspackage.jsonfor the current version instead of a hardcoded string. - Dedup: six providers shipped byte-identical
readLine+tryRevealSecret+bearerJsonHeaders— extracted topackages/core/src/providers/_helpers.ts.makeApiKeyProviderfactory now persists the verified key duringlogin()(matching hand-written providers), so a failure inprovision/materializedoesn't make users re-paste. - MCP server:
runStacknow surfacesENOENTas a structured"install the stack CLI or set STACK_BIN"hint instead of throwing an opaque error back to Claude. - Docs: README provider list updated from stale 20 → 23. Added a "dev install" path.
CHANGELOG.mdnow tracks hardening. - Tests: 4 new test files (security redaction, URL allowlist, helper behaviour, cross-project coexistence) — 64 tests, all green.
MCP richness, deps graph, CI output, 2 more providers
stack deps— ASCII tree of the current stack grouped by category, annotated with secret slots and MCP wirings. Good for onboarding and template sanity-checks.stack doctor --json— machine-readable per-project report ({ reports: [{ project, path, services: [{ name, status, detail, latencyMs }] }] }). Exits non-zero if anything errors. Drop-in for CI pipelines.- MCP server enrichment —
ashlr-stack-mcpnow exposes 17 tools (addedstack_import,stack_scan,stack_info,stack_env_show,stack_env_diff,stack_providers,stack_projects_list,stack_deps,stack_upgrade) and registers three resources (stack://current/.stack.toml,.stack.local.toml,.mcp.json) so Claude can read project state without a tool call. - Render — managed deploy platform. API-key paste +
/v1/ownersverification. - Firebase — service-account JSON blob storage; shape-verified (
type: service_account+project_id+client_email).
3 new providers + visibility commands
- Cloudflare — Workers / Pages / R2 / D1 / KV all behind one API token.
stack add cloudflareverifies the token and stashesCLOUDFLARE_API_TOKEN+CLOUDFLARE_ACCOUNT_ID. - Turso — LibSQL edge DB.
stack add tursocreates a new database, auto-mints an auth token, and writesTURSO_DATABASE_URL/TURSO_AUTH_TOKEN. - Convex — reactive backend. v1 accepts a deploy key; deploy-key shape is structurally validated before storage.
- Scanner rules for all three (including
wrangler.toml,@libsql/client,convex/,CONVEX_DEPLOY_KEYin.env.example, etc.). - New starter template
cloudflare-turso-clerkfor edge-first projects. stack info <service>— deep-dive on one service: resource, region, auth, docs, dashboard, MCP name, meta, vault presence, live healthcheck.stack env show/stack env diff— effective env-var surface. Shows which declared slots are present in Phantom (masked), surfaces vault orphans, or prints just the missing set.stack upgrade— checks the npm registry for a newer@ashlr/stackrelease.
Totals: 21 providers · 19 CLI commands · 5 templates · 49 tests.
Unified management system
Stack now works on any project or GitHub repo, not just one you started with stack init.
stack scan— detects providers from source:package.json/requirements.txt/pyproject.toml/go.mod/Cargo.tomlplus framework configs (vercel.json,fly.toml,railway.json,supabase/config.toml,sentry.*.config.ts,.github/workflows/) and.env.example. Confidence-tiered output.--autorunsstack addfor each detection.stack clone <github-url>— thin wrapper that git-clones a repo, then either recognizes a committed.stack.tomlor scans the checkout and prints next steps.stack projects list|register|remove|where— cross-project registry backed by~/.stack/projects.json. EverywriteConfigauto-registers. HonorsSTACK_REGISTRY_DIRfor test isolation.stack doctor --all— run healthchecks across every registered project in one command.- Config split —
.stack.toml(committed shape) +.stack.local.toml(gitignored instance). Safe to share in git without leaking another developer's Supabase project ref or timestamps. Legacy single-file configs are read transparently and migrated on next write..gitignoreis auto-appended on first write.
Foundations from earlier waves
- 18 curated providers across 7 categories (database / deploy / cloud / analytics / errors / ai / payments / code / tickets / email / auth).
stack import [--from .env]to migrate existing projects.- Phantom Secrets composition: every secret read/write shells out to
phantom, never stored by Stack. - MCP server (
ashlr-stack-mcp) + Claude Code plugin (/stack:add,/stack:list,/stack:doctor,/stack:status). - 47 tests across 12 files; fetch-mocked provider tests and fake-phantom integration harness.