{"_id":"stash","_rev":"26-5bf5993c8bcd29ab15f435548693028b","name":"stash","dist-tags":{"latest":"0.11.0"},"versions":{"0.0.2":{"name":"stash","version":"0.0.2","author":{"name":"Young Hahn"},"_id":"stash@0.0.2","dist":{"shasum":"fb141f9782be687c73ba490cd5211cdf366225ee","tarball":"https://registry.npmjs.org/stash/-/stash-0.0.2.tgz","integrity":"sha512-9Ok3h8eDOqdEpXJaKui7S1cTwWNFoQjd0GzUCW61yimZHYMcsMTUr2QBix8Zett+2fNc6gf91IOj7U5mRM1jVg==","signatures":[{"sig":"MEQCIE+oUpI505wUfUljXZMnaDKn7sWUIh2DwKUW7cqcVy70AiBRlXoOe4+2jrU2GQ8199KACiQ36u9r87IsRKltg2e4TQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"./stash","engines":{"node":"*"},"licenses":[{"type":"BSD"}],"_npmVersion":"1.0.1rc4","directories":{},"_nodeVersion":"v0.4.3","_defaultsLoaded":true,"_engineSupported":true},"0.0.3":{"name":"stash","version":"0.0.3","author":{"name":"Young Hahn"},"_id":"stash@0.0.3","dist":{"shasum":"1235d26df12055635d70b46ad849394146d6ada5","tarball":"https://registry.npmjs.org/stash/-/stash-0.0.3.tgz","integrity":"sha512-m8D5gmEfEno5HRUQYr1MPQbRIowuSjlOFjQweyb+UPQTdY1HU4sJtpsokeqO+2+9YOVboXYskEOM72Q0Yox8Rw==","signatures":[{"sig":"MEUCIHJz4VRTr8zP4r5pNINAotHwMTf8Q7qm2ywZZcmye5dHAiEA+W48cG4ssHfViJSFUEWMxAcVRUqQ0ISRMX4LXsf1bnA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"./stash","engines":{"node":"*"},"scripts":{},"licenses":[{"type":"BSD"}],"_npmVersion":"1.0.3","directories":{},"_nodeVersion":"v0.4.6","dependencies":{},"_defaultsLoaded":true,"devDependencies":{},"_engineSupported":true},"0.10.1":{"name":"stash","version":"0.10.1","author":{"name":"CipherStash","email":"hello@cipherstash.com"},"license":"MIT","_id":"stash@0.10.1","maintainers":[{"name":"cs-zcjbrewer","email":"cj@cipherstash.com"}],"bin":{"stash":"dist/bin/stash.js"},"dist":{"shasum":"cc99b0b54ca2ab159c362a96e3591888dd2207ac","tarball":"https://registry.npmjs.org/stash/-/stash-0.10.1.tgz","fileCount":24,"integrity":"sha512-PkeeWmcP8kppirSVBKQgUf+9wpij7vHExXaSawVYc28+m2Vurp47O65PecqKVHdTt2yFEtnzeHe2GMgD5jdGFg==","signatures":[{"sig":"MEUCIQDR+eAjOtELhnjqt8atjt687v5awSqd6hbbQX+YvVZVKAIgHHOr18Mn18qGe1UShXXA74oLHenN19KvVusCtSpn8AU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":905221},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"e3c54c44634d7a92f8d2b116f5b8e18b27f4114f","scripts":{"dev":"tsup --watch","lint":"biome check .","test":"vitest run","build":"tsup","test:e2e":"vitest run --config vitest.integration.config.ts","postbuild":"chmod +x ./dist/bin/stash.js"},"_npmUser":{"name":"cs-zcjbrewer","email":"cj@cipherstash.com"},"_npmVersion":"10.9.2","description":"CipherStash CLI — the one stash command for auth, init, encryption schema, database setup, and secrets.","directories":{},"sideEffects":false,"_nodeVersion":"23.11.0","dependencies":{"pg":"8.13.1","zod":"^4.3.6","jiti":"2.6.1","dotenv":"16.4.7","picocolors":"^1.1.1","posthog-node":"^5.28.9","@clack/prompts":"0.10.1","@cipherstash/auth":"catalog:repo"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"catalog:repo","tsup":"catalog:repo","vitest":"catalog:repo","node-pty":"^1.1.0","@types/pg":"^8.11.11","strip-ansi":"^7.2.0","typescript":"catalog:repo","@cipherstash/stack":"workspace:*"},"peerDependencies":{"@cipherstash/stack":">=0.6.0"},"peerDependenciesMeta":{"@cipherstash/stack":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/stash_0.10.1_1777578022953_0.15950766884451606","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"stash","version":"0.11.0","description":"CipherStash CLI — the one stash command for auth, init, encryption schema, database setup, and secrets.","license":"MIT","author":{"name":"CipherStash","email":"hello@cipherstash.com"},"type":"module","bin":{"stash":"dist/bin/stash.js"},"main":"./dist/index.cjs","module":"./dist/index.js","sideEffects":false,"types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"dependencies":{"@cipherstash/auth":"0.36.0","@clack/prompts":"0.10.1","dotenv":"16.4.7","jiti":"2.6.1","pg":"8.13.1","picocolors":"^1.1.1","posthog-node":"^5.28.9","zod":"^4.3.6"},"peerDependencies":{"@cipherstash/stack":">=0.6.0"},"peerDependenciesMeta":{"@cipherstash/stack":{"optional":true}},"devDependencies":{"@types/pg":"^8.11.11","node-pty":"^1.1.0","strip-ansi":"^7.2.0","tsup":"8.4.0","tsx":"4.19.3","typescript":"5.6.3","vitest":"3.1.3","@cipherstash/stack":"0.15.3"},"publishConfig":{"access":"public"},"engines":{"node":">=22"},"scripts":{"build":"tsup","postbuild":"chmod +x ./dist/bin/stash.js","dev":"tsup --watch","test":"vitest run","test:e2e":"vitest run --config vitest.integration.config.ts","lint":"biome check ."},"_id":"stash@0.11.0","_integrity":"sha512-ABzGAk4A/xNtgzE5V5YuQYYO/VDI48Vn2XWHdpJCoj9MDSunLjCgzvnGkGWvc+648Xrzkfo7xslhzZWGaJC1wg==","_resolved":"/tmp/53df265c94c3f63a1c97ae764837aafa/stash-0.11.0.tgz","_from":"file:stash-0.11.0.tgz","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-ABzGAk4A/xNtgzE5V5YuQYYO/VDI48Vn2XWHdpJCoj9MDSunLjCgzvnGkGWvc+648Xrzkfo7xslhzZWGaJC1wg==","shasum":"d87457d6ec64a1ab2da04b1db9795fccc89d471a","tarball":"https://registry.npmjs.org/stash/-/stash-0.11.0.tgz","fileCount":27,"unpackedSize":984652,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGbgzy4QDz4QujkNLE6SRrTsmBuMn/xTN56Urm+b/r5EAiEA0TWm4iYH1Z58wrgvRepRSr9CowAkZWR+xO9Tvg8oyHk="}]},"_npmUser":{"name":"cs-zcjbrewer","email":"cj@cipherstash.com"},"directories":{},"maintainers":[{"name":"cs-zcjbrewer","email":"cj@cipherstash.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/stash_0.11.0_1777658785162_0.09471942832647051"},"_hasShrinkwrap":false}},"time":{"created":"2011-04-07T17:47:25.993Z","modified":"2026-05-01T18:06:25.813Z","0.0.2":"2011-04-07T17:47:26.157Z","0.0.3":"2011-05-03T21:23:00.502Z","0.10.1":"2026-04-30T19:40:23.239Z","0.11.0":"2026-05-01T18:06:25.326Z"},"author":{"name":"CipherStash","email":"hello@cipherstash.com"},"license":"MIT","description":"CipherStash CLI — the one stash command for auth, init, encryption schema, database setup, and secrets.","maintainers":[{"name":"cs-zcjbrewer","email":"cj@cipherstash.com"}],"readme":"# stash\n\n[![npm version](https://img.shields.io/npm/v/stash.svg?style=for-the-badge&labelColor=000000)](https://www.npmjs.com/package/stash)\n[![License: MIT](https://img.shields.io/npm/l/stash.svg?style=for-the-badge&labelColor=000000)](https://github.com/cipherstash/protectjs/blob/main/LICENSE.md)\n\nThe single CLI for CipherStash. It handles authentication, project initialization, EQL database lifecycle (install, upgrade, validate, push, migrate), schema building, and encrypted secrets management. Install it as a devDependency alongside the runtime SDK `@cipherstash/stack`.\n\n---\n\n## Quickstart\n\n```bash\nnpm install -D stash\nnpx stash auth login    # authenticate with CipherStash\nnpx stash init          # scaffold encryption schema and install dependencies\nnpx stash db install    # scaffold stash.config.ts (if missing) and install EQL\n```\n\nWhat each step does:\n\n- `auth login` — opens a browser-based device code flow and saves a token to `~/.cipherstash/auth.json`.\n- `init` — generates your encryption client file and installs `stash` as a dev dependency. Pass `--supabase` or `--drizzle` for provider-specific setup.\n- `db install` — detects your encryption client, writes `stash.config.ts` if it's missing, and installs EQL extensions in a single step.\n\nAfter `db install`, declare which columns to encrypt — either run [`@cipherstash/wizard`](https://www.npmjs.com/package/@cipherstash/wizard) to do it automatically, or edit your encryption client file (default `./src/encryption/index.ts`) by hand.\n\n---\n\n## Recommended flow\n\n```\nnpx stash auth login\n    └── npx stash init\n            └── npx stash db install\n                    └── npx @cipherstash/wizard       ← fast path: AI edits your files\n                            OR\n                        Edit schema files by hand     ← escape hatch\n```\n\n`stash` covers authentication, initialization, EQL install/upgrade/validate/push/migrate, and schema introspection. The wizard ([`@cipherstash/wizard`](https://www.npmjs.com/package/@cipherstash/wizard)) is a separate package that calls back into these cli commands after its AI agent finishes editing your schema files.\n\n---\n\n## Configuration\n\n`stash.config.ts` is the single source of truth for database-touching commands. Create it in your project root:\n\n```typescript filename=\"stash.config.ts\"\nimport { defineConfig } from 'stash'\n\nexport default defineConfig({\n  databaseUrl: process.env.DATABASE_URL!,\n  client: './src/encryption/index.ts',\n})\n```\n\n| Option | Required | Default | Description |\n|--------|----------|---------|-------------|\n| `databaseUrl` | Yes | — | PostgreSQL connection string |\n| `client` | No | `./src/encryption/index.ts` | Path to your encryption client file |\n\nThe CLI loads `.env` files automatically before reading the config, so `process.env` references work without extra setup. The config file is resolved by walking up from the current working directory.\n\nCommands that consume `stash.config.ts`: `db install`, `db upgrade`, `db push`, `db validate`, `db status`, `db test-connection`, `schema build`. `db install` will scaffold `stash.config.ts` for you if it's missing.\n\n---\n\n## Commands reference\n\n### `npx stash init`\n\nScaffold CipherStash for your project. Generates an encryption client file, writes initial schema code, and installs `stash` as a dev dependency.\n\n```bash\nnpx stash init [--supabase] [--drizzle]\n```\n\n| Flag | Description |\n|------|-------------|\n| `--supabase` | Use the Supabase-specific setup flow |\n| `--drizzle` | Use the Drizzle-specific setup flow |\n\nAfter `init` completes, the Next Steps output tells you to run `npx stash db install`, then edit your encryption client file directly.\n\n---\n\n### `npx stash auth login`\n\nAuthenticate with CipherStash using a browser-based device code flow.\n\n```bash\nnpx stash auth login\n```\n\nSaves the token to `~/.cipherstash/auth.json`. Database-touching commands check for this file before running.\n\n---\n\n### `npx stash secrets`\n\nManage end-to-end encrypted secrets.\n\n```bash\nnpx stash secrets <subcommand> [options]\n```\n\n| Subcommand | Description |\n|------------|-------------|\n| `set` | Store an encrypted secret |\n| `get` | Retrieve and decrypt a secret |\n| `get-many` | Retrieve and decrypt multiple secrets (2–100) |\n| `list` | List all secrets in an environment |\n| `delete` | Delete a secret |\n\n**Flags:**\n\n| Flag | Alias | Description |\n|------|-------|-------------|\n| `--name` | `-n` | Secret name (comma-separated for `get-many`) |\n| `--value` | `-V` | Secret value (`set` only) |\n| `--environment` | `-e` | Environment name |\n| `--yes` | `-y` | Skip confirmation (`delete` only) |\n\n**Examples:**\n\n```bash\nnpx stash secrets set -n DATABASE_URL -V \"postgres://...\" -e production\nnpx stash secrets get -n DATABASE_URL -e production\nnpx stash secrets get-many -n DATABASE_URL,API_KEY -e production\nnpx stash secrets list -e production\nnpx stash secrets delete -n DATABASE_URL -e production -y\n```\n\n---\n\n### `npx stash db install`\n\nConfigure your database and install CipherStash EQL extensions in a single command. Run this after `npx stash init`.\n\nWhen `stash.config.ts` is missing, the command auto-detects your encryption client file (or asks for the path) and writes the config before installing. Supabase and Drizzle are detected from your `DATABASE_URL` and project files, so the matching flags default on. Install uses bundled SQL for offline, deterministic runs.\n\n```bash\nnpx stash db install [options]\n```\n\n| Flag | Description |\n|------|-------------|\n| `--force` | Reinstall even if EQL is already installed |\n| `--dry-run` | Show what would happen without making changes |\n| `--supabase` | Supabase-compatible install (no operator families + grants Supabase roles) |\n| `--exclude-operator-family` | Skip operator family creation |\n| `--drizzle` | Generate a Drizzle migration instead of direct install |\n| `--latest` | Fetch the latest EQL from GitHub |\n| `--name <value>` | Migration name (Drizzle mode, default: `install-eql`) |\n| `--out <value>` | Drizzle output directory (default: `drizzle`) |\n\nThe `--supabase` flag uses a Supabase-specific SQL variant and grants `USAGE`, table, routine, and sequence permissions on the `eql_v2` schema to the `anon`, `authenticated`, and `service_role` roles.\n\n> **Good to know:** Without operator families, `ORDER BY` on encrypted columns is not supported. Sort application-side after decrypting results as a workaround. This applies to both `--supabase` and `--exclude-operator-family` installs.\n\n---\n\n### `npx stash db upgrade`\n\nUpgrade an existing EQL installation to the version bundled with the package (or the latest from GitHub).\n\n```bash\nnpx stash db upgrade [options]\n```\n\n| Flag | Description |\n|------|-------------|\n| `--dry-run` | Show what would happen without making changes |\n| `--supabase` | Use Supabase-compatible upgrade |\n| `--exclude-operator-family` | Skip operator family creation |\n| `--latest` | Fetch the latest EQL from GitHub |\n\nThe install SQL is idempotent and safe to re-run. If EQL is not installed, the command suggests running `npx stash db install` instead.\n\n---\n\n### `npx stash db push`\n\nPush your encryption schema to the database. **Only required when using CipherStash Proxy.** If you use the SDK directly with Drizzle, Supabase, or plain PostgreSQL, skip this step.\n\n```bash\nnpx stash db push [--dry-run]\n```\n\n| Flag | Description |\n|------|-------------|\n| `--dry-run` | Load and validate the schema, print as JSON. No database changes. |\n\nWhen pushing, the CLI loads the encryption client from `stash.config.ts`, runs schema validation (warns but does not block), maps SDK types to EQL types, and upserts the config row in `eql_v2_configuration`.\n\n**SDK to EQL type mapping:**\n\n| SDK `dataType()` | EQL `cast_as` |\n|------------------|---------------|\n| `string` / `text` | `text` |\n| `number` | `double` |\n| `bigint` | `big_int` |\n| `boolean` | `boolean` |\n| `date` | `date` |\n| `json` | `jsonb` |\n\n---\n\n### `npx stash db validate`\n\nValidate your encryption schema for common misconfigurations.\n\n```bash\nnpx stash db validate [--supabase] [--exclude-operator-family]\n```\n\n| Rule | Severity |\n|------|----------|\n| `freeTextSearch` on a non-string column | Warning |\n| `orderAndRange` without operator families | Warning |\n| No indexes on an encrypted column | Info |\n| `searchableJson` without `dataType(\"json\")` | Error |\n\nThe command exits with code 1 on errors (not on warnings or info). Validation also runs automatically before `db push`.\n\n---\n\n### `npx stash db migrate`\n\nRun pending encrypt config migrations.\n\n```bash\nnpx stash db migrate\n```\n\n> **Good to know:** This command is not yet implemented.\n\n---\n\n### `npx stash db status`\n\nShow the current state of EQL in your database.\n\n```bash\nnpx stash db status\n```\n\nReports EQL installation status and version, database permission status, and whether an active encrypt config exists in `eql_v2_configuration` (relevant only for CipherStash Proxy).\n\n---\n\n### `npx stash db test-connection`\n\nVerify that the database URL in your config is valid and the database is reachable.\n\n```bash\nnpx stash db test-connection\n```\n\nReports the database name, connected role, and PostgreSQL server version.\n\n---\n\n### `npx stash schema build`\n\nBuild an encryption client file from your database schema using DB introspection.\n\n```bash\nnpx stash schema build [--supabase]\n```\n\nConnects to your database, lets you select tables and columns to encrypt, asks about searchable indexes, and generates a typed encryption client file.\n\nReads `databaseUrl` from `stash.config.ts`.\n\n---\n\n## Drizzle migration mode\n\nUse `--drizzle` with `npx stash db install` to add EQL installation to your Drizzle migration history instead of applying it directly. `--drizzle` is auto-detected when your project has `drizzle-orm`, `drizzle-kit`, or a `drizzle.config.*` file, so you usually don't need to pass it explicitly.\n\n```bash\nnpx stash db install --drizzle\nnpx drizzle-kit migrate\n```\n\nHow it works:\n1. Runs `npx drizzle-kit generate --custom --name=<name>` to create an empty migration.\n2. Loads the bundled EQL SQL (or fetches from GitHub with `--latest`).\n3. Writes the EQL SQL into the generated migration file.\n\nWith a custom name or output directory:\n\n```bash\nnpx stash db install --drizzle --name setup-eql --out ./migrations\nnpx drizzle-kit migrate\n```\n\n`drizzle-kit` must be installed in your project (`npm install -D drizzle-kit`). The `--out` directory must match your `drizzle.config.ts`.\n\n---\n\n## Required database permissions\n\nBefore installing EQL, the CLI verifies that the connected role has:\n\n- `CREATE` on the database (for `CREATE SCHEMA` and `CREATE EXTENSION`).\n- `CREATE` on the `public` schema (for `CREATE TYPE public.eql_v2_encrypted`).\n- `SUPERUSER` or extension owner privileges (for `CREATE EXTENSION pgcrypto`, if not already installed).\n\nIf permissions are insufficient, the CLI exits with a message listing what is missing.\n\n---\n\n## Programmatic API\n\n```typescript\nimport {\n  defineConfig,\n  loadStashConfig,\n  EQLInstaller,\n  loadBundledEqlSql,\n  downloadEqlSql,\n} from 'stash'\n```\n\n### `defineConfig`\n\nType-safe identity function for `stash.config.ts`:\n\n```typescript filename=\"stash.config.ts\"\nimport { defineConfig } from 'stash'\n\nexport default defineConfig({\n  databaseUrl: process.env.DATABASE_URL!,\n  client: './src/encryption/index.ts',\n})\n```\n\n### `loadStashConfig`\n\nFinds and loads the nearest `stash.config.ts`, validates it with Zod, applies defaults, and returns the typed config:\n\n```typescript\nimport { loadStashConfig } from 'stash'\n\nconst config = await loadStashConfig()\n// config.databaseUrl — validated non-empty string\n// config.client — defaults to './src/encryption/index.ts'\n```\n\n### `EQLInstaller`\n\nProgrammatic access to EQL installation:\n\n```typescript\nimport { EQLInstaller } from 'stash'\n\nconst installer = new EQLInstaller({ databaseUrl: process.env.DATABASE_URL! })\n\nconst permissions = await installer.checkPermissions()\nif (!permissions.ok) {\n  console.error('Missing permissions:', permissions.missing)\n  process.exit(1)\n}\n\nif (!(await installer.isInstalled())) {\n  await installer.install({ supabase: true })\n}\n```\n\n| Method | Returns | Description |\n|--------|---------|-------------|\n| `checkPermissions()` | `Promise<PermissionCheckResult>` | Check required database permissions |\n| `isInstalled()` | `Promise<boolean>` | Check if the `eql_v2` schema exists |\n| `getInstalledVersion()` | `Promise<string \\| null>` | Get the installed EQL version |\n| `install(options?)` | `Promise<void>` | Execute the EQL install SQL in a transaction |\n\nInstall options: `excludeOperatorFamily`, `supabase`, `latest` (all boolean).\n\n### `loadBundledEqlSql`\n\nLoad the bundled EQL install SQL as a string:\n\n```typescript\nimport { loadBundledEqlSql } from 'stash'\n\nconst sql = loadBundledEqlSql()\nconst sql = loadBundledEqlSql({ supabase: true })\nconst sql = loadBundledEqlSql({ excludeOperatorFamily: true })\n```\n\n### `downloadEqlSql`\n\nDownload the latest EQL install SQL from GitHub:\n\n```typescript\nimport { downloadEqlSql } from 'stash'\n\nconst sql = await downloadEqlSql()             // standard\nconst sql = await downloadEqlSql(true)         // no operator family variant\n```\n\n---\n\n## Relationship to `@cipherstash/stack`\n\n`@cipherstash/stack` is the runtime SDK. It stays lean with no heavy dependencies like `pg` and ships in your production bundle. `stash` is a devDependency: it handles database tooling and schema lifecycle at development time. Think of it like Drizzle Kit — a companion tool that prepares the database while the runtime SDK handles queries.\n\n---\n\n## Links\n\n- [Documentation](https://cipherstash.com/docs)\n- [Discord](https://discord.gg/cipherstash)\n- [Support](mailto:support@cipherstash.com)\n","readmeFilename":"README.md"}