opz
1Password CLI wrapper for seamless secret injection into commands.
Features
- Find items by keyword search
- Show valid env labels from 1Password items with
showsubcommand - Run commands with secrets from 1Password items as environment variables
- Generate env files with
gensubcommand (appends to existing, overwrites duplicates) - Create 1Password items from
.envfiles or private config files withcreatesubcommand - Item list caching for faster repeated runs
- Fuzzy matching when exact title match is not found
Installation
Trusted publishing
This repository is configured for crates.io trusted publishing.
Create a tag such as v2025.12.0 and push it to trigger the Publish to crates.io workflow, which mints a short-lived token via OIDC and runs cargo publish --locked.
You must enable trusted publishing for the opz crate in the crates.io UI (linked repository: f4ah6o/opx) before the workflow is allowed to request tokens.
Usage
Find Items
Search for 1Password items by keyword:
Example:
# Output: item-1 item-2 item-3
Show Item Labels
Show valid env labels from item fields:
Options:
--vault <NAME>- Vault name (optional, searches all vaults if omitted)--with-item- Show per-item headers
Examples:
# Label names only (one per line)
# Include item header sections
Run Commands with Secrets
Run a command with secrets from a 1Password item as environment variables:
Options:
--vault <NAME>- Vault name (optional, searches all vaults if omitted)--env-file <ENV>- Output env file path (optional, no file generated if omitted)
Arguments:
<ITEM>...- One or more item titles to fetch secrets from
When --env-file is specified, the env file is preserved after command execution. If the file already exists, new entries are appended and duplicate keys are overwritten. If duplicate keys exist across items, later items win (opz run foo bar ... prefers bar values).
Examples:
# Run command with one item (no .env file generated)
# Run command with multiple items (later items win on duplicate keys)
# Run with secrets and generate .env file
# Top-level shorthand also supports multiple items
# Specify vault
Generate Env File
Generate env file only without running a command:
Examples:
# Output sectioned env references to stdout
# Generate .env file
# Generate to custom path
# Specify vault
Stdout output includes per-item comment headers like # --- item: <title> ---; comments are ignored by .env parsers.
Create Item from .env or Private Config
create has two modes depending on [ENV]:
Arguments:
<ITEM>- New item title for.envmode[ENV]- Source file path (optional, defaults to.env)
Behavior:
- If
[ENV]is exactly.env:- Creates an item in category
API Credential - Uses
<ITEM>as title - Adds each
KEY=VALUEas a custom text fieldKEY[text]=VALUE - Supports
export KEY=..., inline comments (KEY=value # note), and keeps#inside quotes - For duplicate keys, the last entry wins
- Creates an item in category
- If
[ENV]is anything other than.env:- Creates item(s) in category
Secure Note - Builds note body as
```<file name>\n<content>\n``` - Uses git remote repo name (
org/repo) as item title - If multiple remotes exist, creates one item per remote; duplicate titles get
-2,-3, ... - Fails if no parseable git remote is available
- Creates item(s) in category
Examples:
# Create item from .env
# Save private config as Secure Note (title from git remote org/repo)
# Create item in specific vault
How It Works
- Fetches item list from 1Password (cached for 60 seconds)
- Finds the matching item by title (exact or fuzzy match)
- Builds
op://<vault_id>/<item>/<field>references for each field (uses vault ID to avoid special/non-ASCII name issues) - If env file is specified, writes the file with references (appends to existing, overwrites duplicate keys); otherwise outputs to stdout
- Runs the command with secrets injected as environment variables
With gen and show subcommands, only steps 1-4 are executed (no command run).
op Command Usage
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 all secret access and authentication to op CLI. Item list is cached (60s) with metadata only.
Tracing (OpenTelemetry + Jaeger)
opz can emit OTLP traces, but it is disabled by default. If OTEL_EXPORTER_OTLP_ENDPOINT is not set, tracing is a no-op.
Local setup
E2E trace on Jaeger
If you want to inspect traces generated by tests/e2e_real_op.rs:
In Jaeger Search, select service opz-e2e.
Then open Jaeger Search and select service opz (or your OTEL_SERVICE_NAME) to inspect spans such as:
cli.<command>(root)parse_argsload_configload_inputsmain_operationwrite_outputs
Environment variables
OTEL_EXPORTER_OTLP_ENDPOINT- Enables OTLP export when set (example:http://localhost:4317)OTEL_SERVICE_NAME- Optional service name override (default:opz)OTEL_TRACES_SAMPLER- Optional sampler setting (always_on,traceidratio, etc.)OTEL_TRACES_SAMPLER_ARG- Optional sampler parameter (for ratio-based samplers)OPZ_TRACE_CAPTURE_ARGS-1to include sanitizedcli.argsin trace attributes (default: disabled)
Requirements
- 1Password CLI (
op) installed and authenticated
E2E Test
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
Or use just: