opz is a small wrapper around the 1Password CLI. It finds items, turns valid field labels into environment variables, and runs commands with those secrets injected.
- Search 1Password items by title keyword.
- Check
opauthentication, optional CLI dependencies, and plaintext.env-style credential files withdoctor. - Show item field labels that are valid shell environment variable names.
- Manage 1Password Developer Environments through the 1Password MCP server without printing secret values.
- Run a command with secrets from one or more 1Password items, with repository-title auto-detection.
- Delegate command execution to native 1Password Environments with
--environmentwhen youropCLI supports it. - Generate env files containing
op://...references, preserving unrelated existing lines. - Migrate scripts from explicit items or
.envfiles to repository metadata. - Save private config files as Secure Notes.
- Store valid item fields as GitHub repository secrets, guarded by item repository metadata when present.
- Store valid item fields as Cloudflare Worker secrets through Wrangler.
- Print the bundled
opzAgent Skill. - Cache item lists and repository metadata for fuzzy lookup and legacy migration paths.
cargo install opzSearch item titles by keyword:
opz find <query>Example:
opz find github
# Output: <item-id> <vault-name> github-tokenCheck 1Password CLI status and external command dependencies:
opz doctordoctor exits non-zero when required op checks fail. Missing optional tools such as the 1Password MCP server, gh, wrangler, git, sh, or secretlint are reported as warnings. It also checks for plaintext .env-style credential files and, when secretlint is available, runs it against those files.
Show field labels that can be used as environment variable names:
opz show [OPTIONS] [--with-item] <ITEM>...Options:
--vault <NAME>- Vault name (optional, searches all vaults if omitted)--with-item- Show per-item headers
Examples:
# Label names only (one per line)
opz show foo bar
# Include item header sections
opz show --with-item foo barPrint the bundled Agent Skills SKILL.md for opz:
opz skillsThis lets other agents and tools load the current opz usage context directly in the Agent Skills standard format.
Use the 1Password MCP server to create, rename, inspect, and mount Developer Environments. If --account <ACCOUNT_ID> is omitted, opz authenticates through the 1Password app via MCP.
opz environment list
opz environment create dev
opz environment rename dev staging
opz environment variables dev
opz environment mount dev .env.local
opz environment mounts dev
# Short alias
opz env listopz environment variables prints variable names only. opz environment mount asks the MCP server to create a synced local .env mount; opz does not write secret values itself. Set OPZ_1PASSWORD_MCP_COMMAND if the MCP server executable is not named onepassword-mcp.
opz create no longer creates items. It remains as a hidden compatibility shim so older scripts get a clear migration error instead of an unknown-command failure.
Use these commands instead:
# Create an API_CREDENTIAL item from .env and migrate supported scripts
opz migrate --new
# Store a non-.env private file as Secure Note item(s)
opz note app.confRun a command with secrets from one or more 1Password items:
opz run [OPTIONS] [--env-file <ENV>] [<ITEM>...] -- <COMMAND>...
opz [OPTIONS] [--env-file <ENV>] [<ITEM>...] -- <COMMAND>...
opz run --environment <ENV> -- <COMMAND>...
opz --environment <ENV> -- <COMMAND>...Options:
--vault <NAME>- Vault name (optional, searches all vaults if omitted)--env-file <ENV>- Output env file path. If omitted, no file is written.--environment <ENV>/--environments <ENV>- Use native 1Password Environments injection throughop runinstead of item lookup.
Arguments:
<ITEM>...- Optional item titles to fetch secrets from. When omitted,opzauto-detects one item whose title exactly matches a current git remote repository name such asowner/repo.
When --env-file is set, the file remains after the command exits. Existing files are merged: unrelated lines stay in place, duplicate keys are overwritten, and new keys are appended. If multiple items define the same key, later items win (opz run foo bar ... prefers values from bar).
Examples:
# Run with one item and no .env file generated
opz run example-item -- your-command
# Auto-detect item from git remote title
opz run -- your-command
# Run command with multiple items (later items win on duplicate keys)
opz run foo bar -- your-command
# Generate an env file only when another tool requires op:// references
opz run --env-file .env foo bar -- your-command
# Top-level shorthand also supports multiple items
opz --env-file .env.local foo bar -- your-command
# Quote variables so your shell leaves them for opz to expand
opz run my-service -- curl -H 'Authorization: Bearer $API_TOKEN' https://api.example.test
# Specify vault
opz run --vault Private foo bar -- your-command
# Use a 1Password Environment without resolving values in opz
opz run --environment dev -- your-commandEnvironment mode is mutually exclusive with item arguments and --env-file in v1. opz delegates to op run and does not read Environment secret values. If your installed op CLI does not expose Environment runtime injection, opz reports a clear error and the item-backed workflow remains available.
Generate op://... env references without running a command:
opz gen [OPTIONS] [--env-file <ENV>] <ITEM>...Examples:
# Output sectioned env references to stdout
opz gen foo bar
# Generate .env file
opz gen --env-file .env foo bar
# Generate to custom path
opz gen --env-file .env.production foo bar
# Specify vault
opz --vault Private gen foo barStdout uses per-item comment headers such as # --- item: <title> ---. File output writes the merged key list without those section comments.
Migrate justfile/Justfile recipes and package.json scripts to repository item titles and metadata:
opz migrate [OPTIONS]Options:
--dry-run- Print metadata and file changes without editing 1Password items or files.--new- Create a new API_CREDENTIAL item from.envbefore rewriting.env-based scripts. The item title defaults to the first git remote repository name.--restore- Restore explicit item arguments in scripts that currently use itemlessopz run --.--vault <NAME>- Vault name (optional, searches all vaults if omitted)
Behavior:
opz run <ITEM> -- <COMMAND>andopz <ITEM> -- <COMMAND>stay explicit by default.migraterecords repository metadata and, when there is exactly one item and one repository, renames the item and matching Just item variable toowner/repo.opz migrate --restorechanges itemlessopz run -- <COMMAND>back to explicitopz run <ITEM> -- <COMMAND>where the item can be inferred from a Just recipe parameter or the current repository title.op item get <ITEM>is used as a metadata registration signal, but is not rewritten because it is not equivalent toopz run..env-based scripts are rewritten only with--new; without it, they are reported and skipped.--dry-runreports the repository metadata that would be ensured without fetching full item details.package.jsonis patched at the matching script string, so key order and formatting outside the changed value stay intact.
Examples:
# Preview migration
opz migrate --dry-run
# Rewrite scripts and update item metadata
opz migrate
# Create a new item from .env and migrate .env-based scripts
opz migrate --new
# Restore scripts that were previously migrated to itemless auto-detection
opz migrate --restoreStore a private config file as Secure Note item(s), titled from git remotes:
opz note <FILE>Behavior:
- Stores the file as a fenced note body:
```<file name>\n<content>\n```. - Uses git remote repository names (
org/repo) as item titles. - If multiple remotes exist, creates one item per remote; duplicate titles get
-2,-3, and so on. - Fails if no parseable git remote is available.
Examples:
opz note app.conf
opz --vault Private note app.confAdd or update github_repositories metadata on existing 1Password items:
opz github-repo [OPTIONS] <ITEM>...Options:
--repo <OWNER/REPO>- Repository to record. Repeat for multiple repositories. Defaults to parseable git remotes from the current repository.--dry-run- Print the metadata update without editing items.--vault <NAME>- Vault name (optional, searches all vaults if omitted)
Examples:
# Preview migration using current git remotes
opz github-repo --dry-run my-service shared-secrets
# Add current git remote repository metadata
opz github-repo my-service shared-secrets
# Add explicit repositories
opz github-repo --repo owner/repo --repo other/service my-serviceExisting github_repositories entries are preserved and merged with the requested repositories.
Store valid item fields as GitHub repository secrets:
opz github-secret [OPTIONS] <ITEM>...Options:
--repo <OWNER/REPO>- Target GitHub repository (defaults to the currentghrepository)--dry-run- Print the secret names that would be set without writing values--vault <NAME>- Vault name (optional, searches all vaults if omitted)
Examples:
# Preview secret names
opz github-secret --dry-run my-service
# Store secrets in the current repository
opz github-secret my-service
# Store secrets in a specific repository
opz github-secret --repo owner/repo my-service shared-secretsgithub-secret uses the same valid field labels as gen and run. Duplicate names across multiple items use the later item. Secret values are resolved in memory and passed to gh secret set through stdin; values are not printed or passed as command arguments. Names starting with GITHUB_ are rejected because GitHub reserves that prefix.
If a selected 1Password item has a github_repositories field, the target repository must match one of its owner/repo entries before opz resolves or writes secret values. Multiple repositories are allowed by separating entries with newlines or commas. Items without this metadata are still allowed, but opz prints a warning because the repository guard cannot be applied.
Store valid item fields as Cloudflare Worker secrets through Wrangler:
opz cloudflare-secret [OPTIONS] <ITEM>...Options:
--name <WORKER>- Worker name passed towrangler secret bulk --name--env <ENV>- Wrangler environment passed towrangler secret bulk --env--config <PATH>- Wrangler config path passed towrangler secret bulk --config--dry-run- Print the secret names that would be set without writing values--vault <NAME>- Vault name (optional, searches all vaults if omitted)
Examples:
# Preview secret names
opz cloudflare-secret --dry-run my-service
# Store secrets using the current Wrangler project config
opz cloudflare-secret my-service
# Store secrets for a specific Worker environment
opz cloudflare-secret --name worker-app --env production my-service shared-secretscloudflare-secret uses the same valid field labels as gen and run. Duplicate names across multiple items use the later item. Secret values are resolved in memory and passed to wrangler secret bulk through stdin as JSON; values are not printed or passed as command arguments.
- When item titles are provided,
opzfirst triesop item get <title>directly. - If direct lookup misses,
opzfetches and caches the item list for title-contains fuzzy matching. - When item titles are omitted,
opzreads git remotes and tries exact item titles such asowner/repodirectly. The legacygithub_repositoriesscan is only used whenOPZ_AUTODETECT_LEGACY_SCAN=1. - After the item is selected,
opzfetches it and buildsop://<vault_id>/<item_id>/<field>references for fields with valid env labels. - If
--env-fileis set,opzwrites references to that file and preserves unrelated existing lines. The usual path is file-freeopz run; env files are for tools that requireop://references. - Secret values are resolved with
op run --env-file <temp> -- sh -c 'env -0', withop readper reference as a fallback for non-timeout failures. opzruns the command with the resolved values in the environment.$VARand${VAR}in command arguments are expanded only for variables resolved from the selected items.
gen stops after writing references. show fetches items and prints valid labels without resolving secret values.
Secret-resolution op calls time out after 30 seconds by default. Set OPZ_OP_TIMEOUT_SECONDS=<seconds> to allow slower 1Password CLI operations. If batch resolution times out, opz stops immediately instead of retrying once per secret.
For security transparency, here's how opz uses the op CLI:
sequenceDiagram
participant opz
participant op as op CLI
Note over opz: User runs: opz example-item -- claude "hello"
opz->>op: op item list --format json
op-->>opz: [{id, title, vault}, ...]
Note over opz: Match "example-item" → get item ID
opz->>op: op item get <id> --format json
op-->>opz: {fields: [{label, value}, ...]}
Note over opz: Resolve secret values<br/>(inject as env vars)
Note over opz: Optional: write .env if specified
opz->>op: sh -c "claude \"hello\""
Note over opz: Execute with secrets in environment
op-->>opz: Exit status
Security: opz delegates secret access and authentication to the op CLI. The 60-second caches store item-list and repository metadata only, not secret values.
Install and authenticate 1Password CLI (op) before using secret-backed commands.
github-secret needs GitHub CLI (gh). cloudflare-secret needs Wrangler (wrangler). migrate and note need Git (git) when they read repository remotes.
opz environment needs the 1Password MCP server as onepassword-mcp, or set OPZ_1PASSWORD_MCP_COMMAND to its executable path.
opz complements 1Password Environments instead of replacing them. Use opz environment through the 1Password MCP server to create Environments, inspect variable names, and mount local .env files without exposing secret values to the agent. Use opz run --environment <ENV> -- <COMMAND> as repo-local command glue when native op run Environment injection is available. Keep item-backed opz run, migrate, github-secret, and cloudflare-secret for existing vault item workflows, repository-title auto-detection, and deploy secret sync.
Real 1Password e2e test is available in tests/e2e_real_op.rs.
It is gated for safety and runs only when OPZ_E2E=1 is set:
OPZ_E2E=1 cargo test --test e2e_real_op -- --nocaptureOr use just:
just e2e