Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 77 additions & 11 deletions bun.lock

Large diffs are not rendered by default.

135 changes: 135 additions & 0 deletions content/stack/cipherstash/cli/impl.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Execute an encryption plan
description: Use stash impl to hand off to a coding agent and execute your encryption plan
---

# Execute an encryption plan

`stash impl` is the third step in the setup lifecycle. It reads your plan, confirms the scope, and hands off to a coding agent to make the changes. Run `stash plan` first to produce `.cipherstash/plan.md`.

```bash
npx stash impl
```

## Prerequisites

`stash impl` reads `.cipherstash/context.json`, which is written by `stash init`. If that file is missing, the command errors with a message pointing you to run `stash init` first.

## Behaviour overview

`stash impl` branches based on three conditions: whether a plan file exists, whether you are in a TTY, and whether `--continue-without-plan` is set.

| Condition | Behaviour |
|---|---|
| Plan exists, TTY | Render plan summary. Ask "Proceed with implementation against this plan?" (default-yes). |
| Plan exists, non-TTY | Log the plan path and proceed without confirmation. |
| No plan, `--continue-without-plan` | Ask "Implementation can take some time. Continue?" (default-no). Proceed if confirmed. |
| No plan, TTY | Show a picker: "Draft a plan first (recommended)" or "Continue without a plan". |
| No plan, non-TTY | Error with a clear message. Requires `stash plan` or `--continue-without-plan`. |

## Plan-summary confirmation

When `.cipherstash/plan.md` exists and a machine-readable summary block is present, `stash impl` renders a panel like:

```
Plan summary
3 columns across 2 tables

◇ users.email add new encrypted column
◇ users.phone migrate existing column
◇ orders.notes migrate existing column

Includes migrate-existing columns — implementation is staged across
4 deploys (schema-add → backfill → cutover → drop).
```

It then asks:

```
Proceed with implementation against this plan? (Y/n)
```

Answering no cancels cleanly. Answering yes dispatches to the agent.

If the plan file has no summary block (older plans or plans produced without the structured header), `stash impl` shows a soft prompt to open the file in your editor before proceeding, then continues to the agent picker.

## No-plan picker

If no plan exists and you are in a TTY (without `--continue-without-plan`), `stash impl` shows:

```
No plan found. What would you like to do?
> Draft a plan first (recommended) [runs `stash plan` — usually 1–3 min]
Continue without a plan [skip the planning checkpoint]
```

Selecting "Draft a plan first" delegates to `stash plan`. When `stash plan` completes, you return to `stash impl` automatically.

Selecting "Continue without a plan" shows the security confirm (default-no) before proceeding.

## Security confirm (no-plan path)

When bypassing the plan checkpoint, the command asks:

```
Implementation can take some time. Continue? (y/N)
```

This prompt defaults to no. It requires an explicit `y` or `yes`. Pressing enter cancels.

## Flags

| Flag | Description |
|---|---|
| `--continue-without-plan` | Skip the no-plan picker. Goes straight to the security confirm (default-no). |

There is no `--yes` or `--force` that bypasses the security confirm. The confirm on the no-plan path always requires an explicit affirmative. This is intentional: implementation can take tens of minutes and makes real changes to your codebase.

## Agent options

`stash impl` offers four handoff targets:

| Agent | Detected by | Notes |
|---|---|---|
| Claude Code | `claude` on `$PATH` | Launched interactively if detected. |
| Codex | `codex` on `$PATH` | Launched interactively if detected. |
| CipherStash Agent | Always available | Runs `stash wizard`. |
| Write AGENTS.md | Always available | Works with Cursor, Windsurf, Cline, and others. |

The command defaults to Claude Code if detected, then Codex, then AGENTS.md (the broadest "works without anything else installed" option). The CipherStash Agent is never selected by default.

## Non-TTY behaviour

In CI and piped contexts, `stash impl` requires either a plan on disk or `--continue-without-plan`:

```bash
# CI with a plan already committed
npx stash impl

# CI without a plan
npx stash impl --continue-without-plan
```

Without `--continue-without-plan` and no plan on disk, the command errors:

```
No plan at `.cipherstash/plan.md`. Run `stash plan` first, or pass --continue-without-plan to skip planning.
```

## After implementation

When the agent handoff completes, `stash impl` prints:

```
Implementation handoff complete. Run `stash db status` to verify state.
```

Run `stash db status` to check EQL installation and `stash encrypt status` for per-column migration state.

## Next steps

<Cards>
<Card title="Check project status" href="/stack/cipherstash/cli/status" description="Use stash status to see where you are in the lifecycle." />
<Card title="Push and status" href="/stack/cipherstash/cli/push" description="Push your encryption schema and check EQL installation state." />
<Card title="Draft an encryption plan" href="/stack/cipherstash/cli/plan" description="Use stash plan to draft a reviewable plan before implementation." />
</Cards>
49 changes: 29 additions & 20 deletions content/stack/cipherstash/cli/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,48 @@ Think of it like Prisma CLI or Drizzle Kit. It sets up the database while the ma

### Interactive (recommended)

The setup lifecycle has three explicit save-points. Each command can be run standalone; the chain prompts after `init` and `plan` are convenience for first-time users.

<Steps>
<Step>
### Run init

The `npx stash init` command authenticates you, generates your encryption schema, and installs dependencies.
`stash init` authenticates you, resolves your database, scaffolds an encryption client, installs dependencies, installs EQL, and writes `.cipherstash/context.json`.

```bash
npx stash init
```

When init finishes, it asks (default-yes) whether to continue to `stash plan`.
</Step>

<Step>
### Install EQL in your database
### Draft an encryption plan

Run `db install` to write `stash.config.ts` (if missing), check permissions, and install EQL:
`stash plan` hands off to a coding agent (Claude Code or Codex), which reads your project and writes `.cipherstash/plan.md`. The plan lists the tables and columns to encrypt. Review it before proceeding.

```bash
npx stash db install
npx stash plan
```

The CLI auto-detects your Postgres provider and selects the right install variant. EQL is now installed and your encryption schema is ready.

After install, the CLI prints a next-steps block with two paths: the AI-powered wizard (`npx @cipherstash/wizard`) or direct SDK usage.
When plan finishes, it asks (default-yes) whether to continue to `stash impl`.
</Step>

<Step>
### Wire up encryption (optional)
### Execute the plan

Use the AI-powered wizard to edit your schema and application code automatically:
`stash impl` reads the plan, shows a summary panel, asks you to confirm, and dispatches to the agent to make the changes.

```bash
npx @cipherstash/wizard
npx stash impl
```

`@cipherstash/wizard` is a separate package. It runs once per project and requires no permanent install.
</Step>
</Steps>

### Manual setup

If you prefer to configure things yourself rather than running `stash init`, you can scaffold the config file manually and run `stash db install` directly.

<Steps>
<Step>
### Install the CLI
Expand Down Expand Up @@ -124,9 +126,17 @@ The CLI loads `.env.local`, `.env.development.local`, `.env.development`, then `

## Wizard

`@cipherstash/wizard` is an AI-powered tool that reads your codebase, asks which columns to encrypt, and wires up `@cipherstash/stack` for you. It is a separate package from `stash`.
`stash wizard` (also available as `@cipherstash/wizard`) is the CipherStash-hosted AI setup tool. It reads your codebase, asks which columns to encrypt, and wires up `@cipherstash/stack` for you.

Run it with your package manager's runner:
The primary setup path is `stash init` → `stash plan` → `stash impl`, which can hand off to Claude Code, Codex, AGENTS.md (Cursor, Windsurf, Cline), or the wizard. The wizard is one handoff target among these options.

Run it directly with:

```bash
npx stash wizard
```

Or via the package runner:

```bash
npx @cipherstash/wizard # npm / Node
Expand All @@ -135,14 +145,12 @@ bunx @cipherstash/wizard # bun
yarn dlx @cipherstash/wizard # yarn
```

The wizard installs nothing permanently and is intended to be invoked once per project.

### Prerequisites

Before running the wizard, your project should have:

- An authenticated CipherStash session (`npx stash auth login`)
- A `stash.config.ts` (run `npx stash db install` to scaffold one)
- A `stash.config.ts` (run `npx stash init` or `npx stash db install` to scaffold one)
- A reachable database via `DATABASE_URL`

### What the wizard does
Expand Down Expand Up @@ -179,9 +187,10 @@ This command is experimental and gated behind the `STASH_EXPERIMENTAL_ENV_CMD=1`
## Next steps

<Cards>
<Card title="Init" href="/stack/cipherstash/cli/init" description="Use the interactive init command to set up the CLI in your project." />
<Card title="Init" href="/stack/cipherstash/cli/init" description="Use the interactive init command to scaffold your project and generate context.json." />
<Card title="Plan" href="/stack/cipherstash/cli/plan" description="Draft a reviewable encryption plan before any code changes are made." />
<Card title="Impl" href="/stack/cipherstash/cli/impl" description="Execute the plan with a local coding agent." />
<Card title="Status" href="/stack/cipherstash/cli/status" description="Check where you are in the setup lifecycle at a glance." />
<Card title="Install and upgrade" href="/stack/cipherstash/cli/install" description="Install or upgrade EQL in your database." />
<Card title="Schema validation" href="/stack/cipherstash/cli/validate" description="Validate your encryption schema for common misconfigurations." />
<Card title="Push to database" href="/stack/cipherstash/cli/push" description="Push your encryption schema to the database for use with CipherStash Proxy." />
<Card title="Programmatic API" href="/stack/cipherstash/cli/api" description="Use the CLI as a library in your own scripts and tooling." />
</Cards>
66 changes: 45 additions & 21 deletions content/stack/cipherstash/cli/init.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,35 @@ description: Set up your CipherStash project with the init command

# Interactive setup

The `npx stash init` command authenticates you, generates your encryption schema, and installs dependencies.
`npx stash init` is the first step in the CipherStash setup lifecycle. It authenticates you, resolves your database, scaffolds an encryption client, installs dependencies, installs the EQL extension, and writes a context file. When it finishes, it prompts you to continue to `stash plan`.

```bash
npx stash init
```

## What init does

Init runs four steps with minimal prompts:
Init runs six steps with minimal prompts:

1. **Authenticates with CipherStash**: If you are already authenticated, it logs `Using workspace <id> (region)` and moves on. No prompt. If you are not authenticated, it opens your browser for device-based authentication. Your token is saved to `~/.cipherstash/auth.json`.
2. **Generates the encryption client file**: Auto-detects your integration (Drizzle from `drizzle.config.*` or `drizzle-orm`/`drizzle-kit` in `package.json`, Supabase from the `DATABASE_URL` host, or generic Postgres). Writes a placeholder client to `./src/encryption/index.ts` silently. If that file already exists, it prompts you to keep it or overwrite it.
3. **Installs dependencies**: Checks whether `@cipherstash/stack` and `stash` are already in `node_modules`. If both are present, skips silently. If either is missing, shows a single combined install prompt. Detects your package manager (npm, pnpm, yarn, bun) automatically.
4. **Shows next steps**: Prints a note with the recommended commands to complete setup.
2. **Resolves the database**: Reads your `DATABASE_URL` and verifies a connection can be made. Detects your Postgres provider (Supabase from the URL host, or generic Postgres).
3. **Generates the encryption client file**: Auto-detects your integration (Drizzle from `drizzle.config.*` or `drizzle-orm`/`drizzle-kit` in `package.json`, Supabase from the `DATABASE_URL` host, or generic Postgres). Writes a placeholder client to `./src/encryption/index.ts` silently. If that file already exists, it prompts you to keep it or overwrite it.
4. **Installs dependencies**: Checks whether `@cipherstash/stack` and `stash` are already in `node_modules`. If both are present, skips silently. If either is missing, shows a single combined install prompt. Detects your package manager (npm, pnpm, yarn, bun) automatically.
5. **Installs EQL**: Runs the same logic as `stash db install`. Scaffolds `stash.config.ts` if missing, detects your provider, and installs the EQL extension into your database. You do not need to run `stash db install` separately after init.
6. **Gathers context**: Writes `.cipherstash/context.json` with the detected integration, package manager, schemas, environment keys, and available agents. This file is required by `stash plan` and `stash impl`.

Best case: 0 prompts (already authenticated, both packages installed, no existing client file). Worst case: 2 prompts (region selection for first-time login, install confirmation for missing packages).
Best case: 0 prompts (already authenticated, both packages installed, no existing client file, database reachable). Worst case: 2 prompts (region selection for first-time login, install confirmation for missing packages).

| Flag | Description |
|---|---|
| `--supabase` | Changes the intro message and next-steps output to the Supabase path. Detection handles file scaffolding regardless of this flag. |
| `--drizzle` | Changes the intro message and next-steps output to the Drizzle path. Detection handles file scaffolding regardless of this flag. |

## Generated file
## Generated files

Init writes a placeholder encryption client to `./src/encryption/index.ts`. The template matches your detected integration. For a generic Postgres project it generates:
Init produces two files:

**`./src/encryption/index.ts`**: A placeholder encryption client. The template matches your detected integration. For a generic Postgres project it generates:

```typescript filename="src/encryption/index.ts"
import { Encryption } from "@cipherstash/stack"
Expand All @@ -43,32 +47,52 @@ const users = encryptedTable("users", {
export default await Encryption({ schemas: [users] })
```

Edit this file to define the tables and columns you want to encrypt. Or run `npx @cipherstash/wizard` to have the AI do it for you.
**`.cipherstash/context.json`**: Detected facts about your project. `stash plan` and `stash impl` read this file. It includes your integration type, package manager, detected schemas, environment keys, and available coding agents.

## After init

Install EQL in your database:
When init completes, it shows a summary panel:

```bash
npx stash db install
```
Setup complete
✓ Authenticated to CipherStash
✓ Database connection verified
✓ Encryption client scaffolded
✓ `@cipherstash/stack` installed
✓ `stash` CLI installed
✓ EQL extension installed
```

This scaffolds `stash.config.ts` if it is missing, detects your Postgres provider, and installs EQL. See [install](/stack/cipherstash/cli/install#install) for details.
Then it asks (default-yes):

After `db install`, you have two paths to wire up encryption:
```
Continue to `stash plan` now to draft your encryption plan? (Y/n)
```

```bash
npx @cipherstash/wizard # AI-guided: edits your schema and call sites automatically
Answering yes launches `stash plan` immediately. Answering no (or running non-interactively) prints:

```
Next: run `stash plan` to draft your encryption plan.
```

Or edit `./src/encryption/index.ts` directly and add `encryptModel`/`decryptModel` calls where needed.
## db install flags

If you need to run EQL installation with specific flags (for example, writing a Supabase migration file), use `stash db install` directly after init:

```bash
npx stash db install
npx stash db install --drizzle # Generate a Drizzle migration instead
npx stash db install --supabase # Supabase-compatible install
npx stash db install --supabase --migration
npx stash db install --drizzle
npx stash db install --drizzle --supabase
```

> **Good to know**: You can pass `--drizzle` and `--supabase` together. The CLI combines both behaviors: Supabase-compatible SQL output as a Drizzle migration.

For production deployments, see [Going to production](/stack/deploy/going-to-production).
See [Install and upgrade EQL](/stack/cipherstash/cli/install) for the full flag reference.

## Next steps

<Cards>
<Card title="Draft an encryption plan" href="/stack/cipherstash/cli/plan" description="Run stash plan to hand off to a coding agent and produce a reviewable plan." />
<Card title="Execute an encryption plan" href="/stack/cipherstash/cli/impl" description="Run stash impl to execute the plan with a local agent." />
<Card title="Going to production" href="/stack/deploy/going-to-production" description="Transition from device-based auth to environment variables for deployment." />
</Cards>
2 changes: 1 addition & 1 deletion content/stack/cipherstash/cli/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ npx stash db install [options]
3. **Checks permissions** and auto-selects the right SQL variant based on your database role.
4. **Installs EQL extensions** in your database.

After a successful install, the CLI prints a next-steps block with two paths: run `npx @cipherstash/wizard` for AI-guided setup, or use `@cipherstash/stack` directly with `Encryption`/`encryptModel`.
After a successful install, the CLI prints a summary of what was installed. If you reached this step via `stash init`, EQL was already installed as part of init. Manual invocation is useful when you need specific flags (for example, `--supabase --migration` to write a Supabase migration file) or when you skipped the database connection during init.

| Option | Description |
|---|---|
Expand Down
6 changes: 6 additions & 0 deletions content/stack/cipherstash/cli/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
"title": "CipherStash CLI",
"pages": [
"index",
"---Setup---",
"init",
"plan",
"impl",
"status",
"---Database---",
"install",
"validate",
"push",
"---Reference---",
"api",
"troubleshooting"
]
Expand Down
Loading