Skip to content
New in 0.6: opv ui, start from .env, delivery receipts

Secrets in 1Password.
Apps that just run.

opv syncs secrets and settings from 1Password into the places your apps run, without ever printing, logging or writing a value. No server, no state, no encryption of its own.

$ npm install -g @matthew-cochran/opv
~/myapp
$ opv run dev -- npm run dev
# your app, with dev's settings as env vars

$ opv status prod
prod: 2 keys · 0 saved · 0 skipped · 2 findings
PRODUCT  KEY             KIND    STATE
api      LOG_LEVEL       config  failed enum
api      OPENAI_API_KEY  secret  missing
Next: opv open api/LOG_LEVEL --env prod

$ opv plan prod
plan 412a5b23 (1Password item v7)
$ opv sync prod --deploy --expect-plan 412a5b23
opv bridges secrets from a 1Password vault to local development (shell, IDE, Docker), Fly.io and Azure, with AWS and GCP planned. Example command: opv run dev -- npm run dev

How it works

1Password owns the values. Your runtime consumes them. opv connects the two.

Values travel only on stdin to the official op and target CLIs, or in your app's environment. They never land in argv, files, logs, errors or CI output.

1Password vault · myapp-prod

  • DATABASE_URL••••••••
  • OPENAI_API_KEY••••••••
  • STRIPE_SECRET_KEY••••••••
  • LOG_LEVEL••••••••
  • Your shell (opv run)
  • Fly.io
  • GitHub Actions
  • Azure Key Vault + Container Apps
  • Kubernetes
  1. 01

    Declare

    A small configuration of IDs, key names, kinds and rules. Never values. It lives in 1Password next to the secrets, or in a committed secrets.toml.

    opv init dev --from .env
  2. 02

    Check

    Every value is checked against its rules before it ships. Problems come first, each with its reason, a link to the item, and one runnable Next: command.

    opv status prod
  3. 03

    Review

    The plan says what a sync would write, hold and prune, with a plan id that covers names, states and versions, never a value.

    opv plan prod
  4. 04

    Apply

    Apply exactly the plan you reviewed, or nothing. Nothing is deployed without --deploy and nothing is deleted without --prune.

    opv sync prod --deploy --expect-plan <id>

Security model

Values stay out of your tooling.

The configuration says where each value lives and the rules it must pass. Only 1Password ever holds the value, and the 1Password app is the only place one is typed.

# a failing CLI's stderr, as opv shows it (illustrative)

error: token __SECRET__ was rejected

# what a status row looks like

api STRIPE_SECRET_KEY secret saved ••••

The model, and its documented limits, are in the usage guide. Report vulnerabilities privately per SECURITY.md.

  • No command prints a secret

    Values are held in redacting, zeroizing types. --json documents hold names, states and counts only.

  • stdin or a child's environment, nothing else

    Never argv, files, logs, errors or Debug output. opv run passes op:// references, so op run masks values in your app's output.

  • Scrubbed failures

    When a CLI fails, its last few stderr lines are shown with every known value and secret-shaped token masked as __SECRET__.

  • Least privilege by default

    Deploy credentials are a least-privilege identity per environment. opv access warns when CI has no read-only reader, or a service account can write.

Features

Explicit, never surprising.

No prompts in automation, --json on every reporting command, stable error codes, and every failure ends with one runnable Next: command.

  • opv ui

    new in 0.6

    A terminal UI over every environment, product, key, shared value and account. Secrets show as ••••; every action is the exact opv command, shown before it runs.

  • Start from a .env

    new in 0.6

    opv init dev --from .env --apply declares every key and imports the values, read back and verified, in one step. No value is printed.

  • Personal keys

    new in 0.6

    personal = true keeps each developer's own value, like an LLM key billed to them, in their own vault. Never deployed or mixed with team values.

  • Settings health

    new in 0.6

    Warns about the same secret in two environments, placeholders, stray whitespace, localhost in a deployed environment, and test or live keys in the wrong place.

  • Delivery receipts

    new in 0.6

    Each confirmed sync records an opaque revision per product. opv delivery verify says whether the target still holds exactly what was delivered.

  • History and access

    new in 0.6

    opv history shows what opv last wrote and what changed outside it. opv access shows who can read each vault, people counted, never named.

  • Typed and checked

    Each key declares its kind, secret or config, and rules such as prefix, base64_bytes, enum and https_url. A bad value fails with the key, the rule and a reason.

  • Shared values, one home

    from = "product/KEY" points many keys at one value, so it has one copy and one place to rotate.

  • Safe to re-run

    Reads are retried, writes are checked, and an interrupted run converges when you run it again. Exit 9 means: re-run as is.

opv ui

Everything opv knows, in one screen.

Browse environments, products, keys, shared values and accounts. A sync runs exactly the plan you reviewed; a guarded environment only after you type its name. Sign-in and value entry hand off to 1Password.

  • s sync via plan and --expect-plan
  • i review values to adopt, key by key
  • h write history · o open in 1Password · n next step

Without an interactive terminal, or with OPV_UI_TEXT=1 for screen readers, it prints opv ready. More

opv ui · myappaccount: you@example.com

PRODUCT dev staging prod

api 6/6 6/6 5/6 ·1

web 3/3 3/3 3/3

worker 2/2 not here 2/2

NEEDS ATTENTION

prod api/OPENAI_API_KEY missing ••••

Next: opv open api/OPENAI_API_KEY --env prod

s sync · i adopt · o open · h history · n next · a accounts · q quit

Targets

Same commands, every target.

Each environment names one target, and every command is the same for all of them. Local development needs no target at all.

On Azure and Kubernetes a secret is written as a new version, and the app keeps the old one until sync --deploy. Target configuration

TARGETSTATUS
Fly.iosupported
GitHub Actions (repository and environment secrets and variables)supported
Azure Key Vault + Container Appssupported
Kubernetes (Secrets + Deployment)supported
Azure Key Vault → Kubernetes (External Secrets Operator)supported
Azure App Serviceplanned
AWS (Secrets Manager + ECS)planned
GCP (Secret Manager + Cloud Run)planned

For AI coding assistants

Your assistant sets it up. It never sees a secret.

The agent skill, versioned with the binary, starts every Claude Code, Codex or Cursor session from opv guide agent, opv schema and opv ready --json. It asks before anything that writes, and hands sign-in and value entry to you.

$ opv skill install --user

Point your assistant at opv.dev/INSTALL.md or the agent setup guide.

$ opv ready --json

{
  "receipt_id": "rcpt-3f9a1c0d2e7b",
  "findings": [
    { "code": "key_missing",
      "scope": { "environment": "staging",
                 "product": "api", "key": "STRIPE_KEY" },
      "blocking": true,
      "actor": "owner",
      "effect": "writes_1password",
      "prerequisite": "opv open api/STRIPE_KEY --env staging",
      "verify": "…" }
  ]
}

# illustrative excerpt: names, states and next steps, never values

Install opv

macOS, Linux, WSL and Windows. npm picks the prebuilt binary for your system; the command is opv.

$ npm install -g @matthew-cochran/opv
$ curl -fsSL https://raw.githubusercontent.com/matt-cochran/1password-vault/main/install.sh | sh

The script needs no Node.js, installs to ~/.local/bin without sudo, and verifies the download against the release's SHA256SUMS (and its attestation when gh is present). You also need the 1Password CLI.