16 stable releases
| new 2026.3.1 | Mar 9, 2026 |
|---|---|
| 2026.2.6 | Feb 20, 2026 |
| 2026.1.0 | Jan 16, 2026 |
| 2025.12.5 | Dec 27, 2025 |
#80 in Authentication
115KB
2.5K
SLoC
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 - Emit bundled Agent Skills
SKILL.mdforopzwithskillssubcommand - Item list caching for faster repeated runs
- Fuzzy matching when exact title match is not found
Installation
cargo install opz
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:
opz find <query>
Example:
opz find <query>
# Output: item-1 item-2 item-3
Show Item Labels
Show valid env labels from item fields:
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 bar
Emit Agent Skill
Print the bundled Agent Skills SKILL.md for opz:
opz skills
This lets other agents and tools load the current opz usage context directly in the Agent Skills standard format.
Run Commands with Secrets
Run a command with secrets from a 1Password item as environment variables:
opz run [OPTIONS] [--env-file <ENV>] <ITEM>... -- <COMMAND>...
opz [OPTIONS] [--env-file <ENV>] <ITEM>... -- <COMMAND>...
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)
opz run example-item -- your-command
# Run command with multiple items (later items win on duplicate keys)
opz run foo bar -- your-command
# Run with secrets and generate .env file
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
# Specify vault
opz run --vault Private foo bar -- your-command
Generate Env File
Generate env file only 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 bar
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]:
opz [OPTIONS] create <ITEM> [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
opz create my-service
# Save private config as Secure Note (title from git remote org/repo)
opz create ignored-item app.conf
# Create item in specific vault
opz --vault Private create my-service .env
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
just jaeger-up
just trace-run item=<your-item-title>
just trace-ui
E2E trace on Jaeger
If you want to inspect traces generated by tests/e2e_real_op.rs:
just jaeger-up
just e2e-trace
just trace-ui
In Jaeger Search, select service opz-e2e.
just e2e-trace automatically sets OPZ_GIT_COMMIT=$(git rev-parse --short=12 HEAD).
Compare traces by ref or version
Generate traces on each target commit/tag (or release version), then compare:
just trace-report <ref-or-version>
just trace-compare <base-ref-or-version> <head-ref-or-version>
<ref-or-version> accepts commit hash, git tag (for example v2026.2.5), or service.version (for example 2026.2.5).
Both commands print markdown tables (duration and top child span) for easy copy into PRs.
For less noisy comparisons, aggregate multiple runs and ignore failed traces:
just trace-report-samples <ref-or-version> samples=5 status=ok
just trace-compare-samples <base-ref-or-version> <head-ref-or-version> samples=5 status=ok
samples uses latest N traces per operation and reports median/average.
status can be all, ok, or error.
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)OPZ_GIT_COMMIT- Optional override for trace resource attributegit.commit(default:git rev-parse --short=12 HEAD)
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 cargo test --test e2e_real_op -- --nocapture
Or use just:
just e2e
Dependencies
~20–31MB
~510K SLoC