Releases: cipherstash/stack
stash@0.13.0
Minor Changes
-
e16b282: Split agent handoff out of
stash initinto a newstash implcommand.initnow owns scaffolding only (auth, database, encryption client, EQL extension) and exits at a clean checkpoint pointing atstash impl.stash implderives plan-vs-implement mode from disk state — if.cipherstash/plan.mdis missing it asks the agent to draft a plan; if it exists, the agent executes the plan as the source of truth.--continue-without-planskips the planning checkpoint after an interactive confirmation. The earlier in-initPlan first / Go straight to implementationpicker is removed in favour of the new command boundary. -
db163e1:
stash implnow renders a plan summary panel and asks the user to confirm before launching the implementation agent. When a plan exists, the CLI parses a machine-readable<!-- cipherstash:plan-summary {...} -->block (the planning agent is instructed to emit one at the top of.cipherstash/plan.md) and prints column counts, per-column paths, and whether the work is single-deploy or staged across 4 deploys. Default-yes on the confirm so the path of least resistance is to proceed; saying No exits cleanly. Older plans without the summary block fall back to a soft "open in your editor" panel — never an error. Non-TTY runs (CI, pipes) skip the confirm and proceed. -
59b138b: Extract planning into its own
stash plancommand. Three commands now own the setup lifecycle:stash init— scaffold (auth, db, deps, EQL). Ends with a chain prompt tostash plan.stash plan— draft a reviewable plan at.cipherstash/plan.md. Ends with a chain prompt tostash impl.stash impl— execute. With a plan, shows the summary panel and confirms. Without one, presents aDraft a plan first / Continue without a planpicker (the second option goes through a security confirm).--continue-without-planskips the picker.
stash statusreflects the new flow — its "Plan written" stage andNext:line route tostash planwhen init is done but no plan exists. Non-TTY runs ofstash implwithout a plan now error out with a clear next-action rather than guessing intent. -
db163e1: Add
stash status— a top-level lifecycle map for the project. Reads.cipherstash/context.json,.cipherstash/plan.md, and.cipherstash/setup-prompt.mdfrom disk to render a panel showing whether init is done, whether a plan has been written, and whether an agent has been engaged. Points atstash db statusfor EQL install info andstash encrypt statusfor per-column migration phase. Runs in milliseconds — no auth, no database connection required. The existingstash db statusis unchanged.
stash@0.12.1
Patch Changes
- 439c63e: Fix backfill CLI wrapper to resolve schema column metadata correctly and surface configuration errors with author-controlled messages while keeping generic diagnostics for unexpected failures.
stash@0.12.0
Minor Changes
-
f315334:
stash initcan now hand off the rest of setup to whichever coding agent the user is set up with — and it leaves them with a project-specific action plan and the right reference material, not just generic rules.The new pipeline:
- Authenticate (unchanged).
- Resolve
DATABASE_URL— uses the same resolver asstash db install(flag → env →supabase status→ interactive prompt). Hard-fails with an actionable message if nothing resolves. - Build the encryption client. When the database has tables,
initintrospects them and generates a real client from the user's selection. When the database is empty, it falls back to a placeholder so fresh projects still work — and the action prompt notes the placeholder so the agent reshapes it later. - Install dependencies —
@cipherstash/stack(runtime) +stash(CLI dev dep). - Install EQL into the database — y/N confirm, then runs
stash db installprogrammatically against the URL we already resolved. No second prompt for credentials. - Pick a handoff from the four-option menu. Each handoff installs the right artifacts for the chosen tool:
- Hand off to Claude Code — copies the per-integration set of authored skills (
stash-encryption+stash-<integration>+stash-cli) into.claude/skills/, writes.cipherstash/context.jsonand.cipherstash/setup-prompt.md, spawnsclaude. Default whenclaudeis on PATH. - Hand off to Codex — writes a sentinel-managed
AGENTS.md(durable doctrine) + copies the same skills into.codex/skills/(procedural workflows), writescontext.json+setup-prompt.md, spawnscodex. Default whencodexis on PATH andclaudeis not. Follows OpenAI's Codex guidance: AGENTS.md for repo doctrine, skills for repeatable workflows. - Use the CipherStash Agent — writes
context.jsonand runsstash wizard. Fallback for users without a local CLI agent. The wizard installs its own skills. - Write AGENTS.md — for editor agents (Cursor, Windsurf, Cline) that don't auto-load skill directories. Writes a single
AGENTS.mdwith the doctrine plus the relevant skill content inlined under a sentinel block, so the agent has the API details without needing to follow file references. Pluscontext.json+setup-prompt.md. No spawn.
- Hand off to Claude Code — copies the per-integration set of authored skills (
Detection is non-blocking: if the chosen CLI agent (
claudeorcodex) isn't installed, init still writes the artifacts and prints install + manual-launch instructions. Progress is never wasted..cipherstash/setup-prompt.mdis the headline artifact. It's the project-specific action plan — "init has done X and Y; you need to do Z next, with these exact commands and paths" — generated from the current init state. The launch prompt for Claude / Codex points the agent at this file first; the installed skills provide the reusable rulebook the prompt references. For IDE users, it's ready to paste into the first chat.Per-integration skill subset:
drizzle → stash-encryption + stash-drizzle + stash-cli supabase → stash-encryption + stash-supabase + stash-cli postgresql → stash-encryption + stash-cliThe skills themselves are the authored ones at the repo root (
/skills/); they ship inside the CLI tarball viatsupso init can copy them locally without a network round-trip. The AGENTS.md doctrine fragment ships the same way.Re-running
initis safe —AGENTS.mduses sentinel-marker upsert (<!-- cipherstash:rulebook start/end -->), so the managed region is replaced in place and any user edits outside it are preserved. Skill directories are overwritten so the user always gets the latest content.setup-prompt.mdis regenerated wholesale each run since it's meant to reflect the current state..cipherstash/context.jsonis the universal "what shape is this project" payload — integration, encryption client path, schema, env key names (never values), package manager, install command, CLI version, names of installed skills, generation timestamp. -
ce70b4d: Add
stash wizardas a thin wrapper subcommand around@cipherstash/wizard.The wizard ships as a separate npm package so the heavy agent SDK stays out of the
stashCLI bundle. Until now, users had to remember a second tool name (npx @cipherstash/wizard); the wrapper exposes the same capability under the existingstashsurface so the user only has to think about one CLI.stash wizarddetects the project's package manager and spawns the wizard via the matching one-shot runner —npx,pnpm dlx,yarn dlx, orbunx— withstdio: 'inherit'so the wizard owns the terminal cleanly. Any flags afterwizardare forwarded verbatim, sostash wizard --debugworks.On a cold cache (the wizard package isn't installed in the project) the runner downloads it before launching — a few seconds. The wrapper prints an explicit "first run downloads ~5s" line in that case so the CLI doesn't appear hung. On a warm cache, just a "Launching the CipherStash wizard…" line, then the wizard takes over.
Existing copy that pointed at
npx @cipherstash/wizard(init's next-steps for base / Drizzle / Supabase,db install's post-install note) now usesstash wizard. -
add4357: Add
stash encryptcommand group and@cipherstash/migratelibrary for plaintext → encrypted column migrations.New CLI commands:
stash encrypt status— per-column migration status (phase, backfill progress, drift between intent and state, EQL registration).stash encrypt plan— diff.cipherstash/migrations.json(intent) vs observed state.stash encrypt backfill --table <t> --column <c>— resumable, idempotent, chunked encryption of plaintext into<col>_encrypted. Uses the user's encryption client (Protect/Stack). SIGINT-safe; re-run to resume. The first run on a column prompts to confirm dual-writes are deployed (or accept--confirm-dual-writes-deployedfor non-interactive contexts), records thedual_writingtransition incs_migrations, then runs the chunked encryption loop.--forcere-encrypts every plaintext row regardless of current state — recovery path for drift caused by an earlier backfill running before dual-writes were actually live.stash encrypt cutover --table <t> --column <c>— runseql_v2.rename_encrypted_columns()inside a transaction; optionally forces Proxy config refresh viaCIPHERSTASH_PROXY_URL. After cutover, apps reading<col>transparently receive the encrypted column.stash encrypt drop --table <t> --column <c>— generates a migration file that drops the old plaintext column.
stash db installnow also installs acipherstash.cs_migrationstable used to track per-column migration runtime state (current phase, backfill cursor, rows processed). The table is append-only (event-log shape) and kept separate fromeql_v2_configurationwhich remains the authoritative EQL intent store used by Proxy.The new
@cipherstash/migratepackage exposes the same primitives as a library for users who want to embed backfill in their own workers or cron jobs — all commands are thin wrappers around its exports (runBackfill,appendEvent,latestByColumn,progress,renameEncryptedColumns,reloadConfig,readManifest,writeManifest).
Patch Changes
-
39af183: Make
--helpbanners and the post-install "Next steps" panel show commands using the package manager the user actually invoked the CLI with, instead of always emittingnpx.A user who runs
bunx @cipherstash/cli --helpnow sees:Usage: bunx @cipherstash/cli <command> [options] … Examples: bunx @cipherstash/cli init bunx @cipherstash/cli auth login bunx @cipherstash/cli db installinstead of
npx @cipherstash/cli …regardless of how they invoked it. Same forpnpm dlx,yarn dlx, and the defaultnpxpath.Concretely:
--help(top-level) — usage line and all six examples inbin/stash.ts.--help(auth) — usage line and the twoauth loginexamples incommands/auth/index.ts.db install's "Next steps" note — thewizardinvocation now matches the user's runner.- The
@cipherstash/stack is required for this commandhint shown byrequireStack(whendb push/validate/schema buildare run before the runtime SDK is installed) now suggests the package manager's install command and the user's runner for the follow-upinitinvocation.
No public-API change. Detection sources unchanged from #379:
npm_config_user_agentfirst, then lockfile, thennpxfallback. -
a8dbb65: Render every user-facing CLI string and execute every shell-out under the detected package manager (
npx/bunx/pnpm dlx/yarn dlx), completing the work started in #379. Affected surfaces:@cipherstash/clitop-level +auth+envhelp,db installDrizzle migration steps,db migratenot-implemented warning, the Supabase migration SQL header, the Supabase status fallback exec, the@cipherstash/protectstashStricli help (set/get/list/delete), the@cipherstash/wizardusage line and agent command allowlist, and the@cipherstash/drizzlegenerate-eql-migrationhelp + drizzle-kit invocation. A newpnpm run lint:runnerslint runs in CI and fails on any reintroduction of a hardcoded runner literal. -
Updated dependencies [add4357]
- @cipherstash/migrate@0.2.0
@cipherstash/wizard@0.1.3
Patch Changes
- a8dbb65: Render every user-facing CLI string and execute every shell-out under the detected package manager (
npx/bunx/pnpm dlx/yarn dlx), completing the work started in #379. Affected surfaces:@cipherstash/clitop-level +auth+envhelp,db installDrizzle migration steps,db migratenot-implemented warning, the Supabase migration SQL header, the Supabase status fallback exec, the@cipherstash/protectstashStricli help (set/get/list/delete), the@cipherstash/wizardusage line and agent command allowlist, and the@cipherstash/drizzlegenerate-eql-migrationhelp + drizzle-kit invocation. A newpnpm run lint:runnerslint runs in CI and fails on any reintroduction of a hardcoded runner literal.
@cipherstash/protect@11.1.2
Patch Changes
- a8dbb65: Render every user-facing CLI string and execute every shell-out under the detected package manager (
npx/bunx/pnpm dlx/yarn dlx), completing the work started in #379. Affected surfaces:@cipherstash/clitop-level +auth+envhelp,db installDrizzle migration steps,db migratenot-implemented warning, the Supabase migration SQL header, the Supabase status fallback exec, the@cipherstash/protectstashStricli help (set/get/list/delete), the@cipherstash/wizardusage line and agent command allowlist, and the@cipherstash/drizzlegenerate-eql-migrationhelp + drizzle-kit invocation. A newpnpm run lint:runnerslint runs in CI and fails on any reintroduction of a hardcoded runner literal.
@cipherstash/protect-dynamodb@11.0.2
Patch Changes
- Updated dependencies [a8dbb65]
- @cipherstash/protect@11.1.2
@cipherstash/migrate@0.2.0
Minor Changes
-
add4357: Add
stash encryptcommand group and@cipherstash/migratelibrary for plaintext → encrypted column migrations.New CLI commands:
stash encrypt status— per-column migration status (phase, backfill progress, drift between intent and state, EQL registration).stash encrypt plan— diff.cipherstash/migrations.json(intent) vs observed state.stash encrypt backfill --table <t> --column <c>— resumable, idempotent, chunked encryption of plaintext into<col>_encrypted. Uses the user's encryption client (Protect/Stack). SIGINT-safe; re-run to resume. The first run on a column prompts to confirm dual-writes are deployed (or accept--confirm-dual-writes-deployedfor non-interactive contexts), records thedual_writingtransition incs_migrations, then runs the chunked encryption loop.--forcere-encrypts every plaintext row regardless of current state — recovery path for drift caused by an earlier backfill running before dual-writes were actually live.stash encrypt cutover --table <t> --column <c>— runseql_v2.rename_encrypted_columns()inside a transaction; optionally forces Proxy config refresh viaCIPHERSTASH_PROXY_URL. After cutover, apps reading<col>transparently receive the encrypted column.stash encrypt drop --table <t> --column <c>— generates a migration file that drops the old plaintext column.
stash db installnow also installs acipherstash.cs_migrationstable used to track per-column migration runtime state (current phase, backfill cursor, rows processed). The table is append-only (event-log shape) and kept separate fromeql_v2_configurationwhich remains the authoritative EQL intent store used by Proxy.The new
@cipherstash/migratepackage exposes the same primitives as a library for users who want to embed backfill in their own workers or cron jobs — all commands are thin wrappers around its exports (runBackfill,appendEvent,latestByColumn,progress,renameEncryptedColumns,reloadConfig,readManifest,writeManifest).
@cipherstash/drizzle@3.0.2
Patch Changes
- a8dbb65: Render every user-facing CLI string and execute every shell-out under the detected package manager (
npx/bunx/pnpm dlx/yarn dlx), completing the work started in #379. Affected surfaces:@cipherstash/clitop-level +auth+envhelp,db installDrizzle migration steps,db migratenot-implemented warning, the Supabase migration SQL header, the Supabase status fallback exec, the@cipherstash/protectstashStricli help (set/get/list/delete), the@cipherstash/wizardusage line and agent command allowlist, and the@cipherstash/drizzlegenerate-eql-migrationhelp + drizzle-kit invocation. A newpnpm run lint:runnerslint runs in CI and fails on any reintroduction of a hardcoded runner literal.
stash@0.11.0
Minor Changes
-
de9c02c: Rename the CLI package from
@cipherstash/clitostash. The published code, commands, and flags are unchanged — this is a pure rename so the day-to-day invocation drops fromnpx @cipherstash/cli ...tonpx stash ....Migration
-
Update your
package.jsondevDependencies:- "@cipherstash/cli": "^0.10.0" + "stash": "^0.10.1"
-
Update the
defineConfigimport instash.config.ts:- import { defineConfig } from '@cipherstash/cli' + import { defineConfig } from 'stash'
-
Update any
npx @cipherstash/cli .../bunx @cipherstash/cli .../pnpm dlx @cipherstash/cli .../yarn dlx @cipherstash/cli ...invocations in scripts, CI, READMEs, and team docs to usestashinstead. Programmatic exports (defineConfig,loadStashConfig,EQLInstaller,loadBundledEqlSql,downloadEqlSql,PermissionCheckResult) are re-exported fromstashwith the same shapes.
Wizard impact (
@cipherstash/wizard)The wizard's post-agent step and its prerequisite / agent-error hints now reference
stash(e.g.Run: bunx stash auth login,Running bunx stash db install...) rather than@cipherstash/cli. The wizard package name andstash-wizardbinary are unchanged — only the strings the wizard prints and the commands it shells out to are affected. -
-
8ee11fd: Layered
DATABASE_URLresolution for DB / schema commands.Previously, any DB-touching command (
db install,db push,db upgrade,db status,db validate,db test-connection,schema build) failed with the cryptic Zod error:Error: Invalid stash.config.ts - databaseUrl: Invalid input: expected nonoptional, received undefinedif
DATABASE_URLwasn't already in the environment. The CLI auto-loaded.env.local/.env.development.local/.env.development/.env, but had no story for--database-urlflags, local Supabase, or pasted-once values.The scaffolded
stash.config.tsnow calls a resolver directly:import { defineConfig, resolveDatabaseUrl } from "stash"; export default defineConfig({ databaseUrl: await resolveDatabaseUrl(), client: "./src/encryption/index.ts", });
resolveDatabaseUrl()walks sources in order; first hit wins:--database-url <url>flag — new, accepted on all seven DB / schema commands. Used for this run only; never written to disk.process.env.DATABASE_URL— covers shell exports, mise, direnv, dotenv-cli, the existing dotenv loads.supabase status --output env→DB_URL— auto-engaged when--supabaseis set or asupabase/config.tomlis detected. Useful for local Supabase users who haven't exported the URL yet.- Interactive prompt — opens with a tip listing the alternatives (flag, env, the user's actual dotenv file). Skipped under
CI=trueor non-TTY stdin. - Hard fail with a source-naming error message.
The connection string is never persisted to disk —
stash.config.tsonly contains theawait resolveDatabaseUrl()call, never a literal URL. The resolver also doesn't mutateprocess.env; CLI flag context is threaded into the config evaluation viaAsyncLocalStorageso concurrent loads stay isolated. Source labels are logged on non-env paths (Using DATABASE_URL from --database-url flag/from supabase status/from prompt) but the URL itself is never echoed.db test-connection's connection-failure hint is now source-aware: it points users at--database-url, the env var, and the actual dotenv file in their project (.env.localif present,.envotherwise) — not the misleadingstash.config.tsit used to suggest.
@cipherstash/wizard@0.1.2
Patch Changes
-
de9c02c: Rename the CLI package from
@cipherstash/clitostash. The published code, commands, and flags are unchanged — this is a pure rename so the day-to-day invocation drops fromnpx @cipherstash/cli ...tonpx stash ....Migration
-
Update your
package.jsondevDependencies:- "@cipherstash/cli": "^0.10.0" + "stash": "^0.10.1"
-
Update the
defineConfigimport instash.config.ts:- import { defineConfig } from '@cipherstash/cli' + import { defineConfig } from 'stash'
-
Update any
npx @cipherstash/cli .../bunx @cipherstash/cli .../pnpm dlx @cipherstash/cli .../yarn dlx @cipherstash/cli ...invocations in scripts, CI, READMEs, and team docs to usestashinstead. Programmatic exports (defineConfig,loadStashConfig,EQLInstaller,loadBundledEqlSql,downloadEqlSql,PermissionCheckResult) are re-exported fromstashwith the same shapes.
Wizard impact (
@cipherstash/wizard)The wizard's post-agent step and its prerequisite / agent-error hints now reference
stash(e.g.Run: bunx stash auth login,Running bunx stash db install...) rather than@cipherstash/cli. The wizard package name andstash-wizardbinary are unchanged — only the strings the wizard prints and the commands it shells out to are affected. -