1Password
Overview
This skill provides comprehensive guidance for working with 1Password's secrets management ecosystem. It covers the op CLI for local development, service accounts for automation, Developer Environments for project secrets, and Kubernetes integrations including the native 1Password Operator and External Secrets Operator.
Quick Reference
Command Structure
1Password CLI uses a noun-verb structure: op <noun> <verb> [flags]
Authentication
op signin # Sign in to account op signout # Sign out op whoami # Show signed-in account info
Secret retrieval
op read "op://vault/item/field" # Read single secret op run -- <command> # Inject secrets as env vars op inject -i template.env -o .env # Inject secrets into file
Item management
op item list # List all items op item get <item> # Get item details op item create --category login # Create new item op item edit <item> field=value # Edit item op item delete <item> # Delete item
Vault management
op vault list # List vaults op vault get <vault> # Get vault info op vault create <name> # Create vault
Document management
op document list # List documents op document get <document> # Download document op document create <file> --vault <vault> # Upload document
Workflow Decision Tree
What do you need to do? ├── Retrieve a secret for local development? │ └── Use: op read, op run, or op inject ├── Manage project environment variables? │ └── See: Developer Environments (below) ├── Manage items/vaults in 1Password? │ └── Use: op item, op vault, op document commands ├── Automate secrets in CI/CD? │ └── Use: Service Accounts with OP_SERVICE_ACCOUNT_TOKEN ├── Sync secrets to Kubernetes? │ ├── Using External Secrets Operator? │ │ └── See: External Secrets Operator Integration │ └── Using native 1Password Operator? │ └── See: 1Password Kubernetes Operator └── Configure shell plugins for CLI tools? └── Use: op plugin commands
Developer Environments
Developer Environments provide a dedicated location to store, organize, and manage project secrets as environment variables. CLI tools are available in both TypeScript/Bun and Python SDK variants.
Feature Overview
Feature GUI TypeScript CLI Python SDK CLI
Create environment Yes bun run create
uv run op-env-create
Update environment Yes bun run update
uv run op-env-update
Delete environment Yes bun run delete
uv run op-env-delete
Show environment Yes bun run show
uv run op-env-show
List environments Yes bun run list
uv run op-env-list
Export to .env Yes bun run export
uv run op-env-export
Mount .env file Yes (beta) No No
CLI Tools Setup (TypeScript)
Tools are written in TypeScript and require Bun runtime:
Navigate to tools directory
cd tools
Run any tool with bun
bun run src/op-env-create.ts --help bun run src/op-env-list.ts --help
Or use npm scripts
bun run create -- --help bun run list -- --help
CLI Tools Setup (Python SDK)
Python tools use the official onepassword-sdk package and require uv:
Navigate to tools-python directory
cd tools-python
Install dependencies
uv sync
Run any tool
uv run op-env-create --help uv run op-env-list --help
Requirements: Python 3.9+, OP_SERVICE_ACCOUNT_TOKEN environment variable.
When to Use SDK vs CLI
Use Case Recommended Why
Python applications (FastAPI, Django) Python SDK Native async, no subprocess overhead
Shell scripts, CI/CD pipelines TypeScript CLI or op CLI Direct CLI integration
Batch secret resolution Python SDK resolve_all() for efficiency
Tag-based filtering TypeScript CLI SDK lacks tag filter support
Interactive local development Either Both have identical interfaces
SecretsManager (Python SDK)
For Python applications that need runtime secret resolution:
from op_env.secrets_manager import SecretsManager
async def main(): sm = await SecretsManager.create()
# Single secret (with caching)
api_key = await sm.get("op://Production/API/key")
# Batch resolve
secrets = await sm.get_many([
"op://Production/DB/password",
"op://Production/DB/host",
])
# Load all vars from an environment item
env = await sm.resolve_environment("my-app-prod", "Production")
See references/python-sdk.md for full SDK reference and integration patterns.
Environment Workflow
- Create Environment
From inline variables
bun run src/op-env-create.ts my-app-dev Personal
API_KEY=secret
DB_HOST=localhost
DB_PORT=5432
From .env file
bun run src/op-env-create.ts my-app-prod Production --from-file .env.prod
Combine file + inline (inline overrides file)
bun run src/op-env-create.ts azure-config Shared --from-file .env EXTRA_KEY=value
With custom tags
bun run src/op-env-create.ts secrets DevOps --tags "env,production,api" KEY=value
- List Environments
List all environments (tagged with 'environment')
bun run src/op-env-list.ts
Filter by vault
bun run src/op-env-list.ts --vault Personal
Filter by tags
bun run src/op-env-list.ts --tags "production"
JSON output
bun run src/op-env-list.ts --json
- Show Environment Details
Show with masked values (default)
bun run src/op-env-show.ts my-app-dev Personal
Show with revealed values
bun run src/op-env-show.ts my-app-dev Personal --reveal
JSON output
bun run src/op-env-show.ts my-app-dev Personal --json
Show only variable names
bun run src/op-env-show.ts my-app-dev Personal --keys
- Update Environment
Update/add single variable
bun run src/op-env-update.ts my-app-dev Personal API_KEY=new-key
Merge from .env file
bun run src/op-env-update.ts my-app-dev Personal --from-file .env.local
Remove variables
bun run src/op-env-update.ts my-app-dev Personal --remove OLD_KEY,DEPRECATED
Update and remove in one command
bun run src/op-env-update.ts my-app-dev Personal NEW_KEY=value --remove OLD_KEY
- Export Environment
Export to .env file (standard format)
bun run src/op-env-export.ts my-app-dev Personal > .env
Docker-compatible format (quoted values)
bun run src/op-env-export.ts my-app-dev Personal --format docker > .env
op:// references template (for op run/inject)
bun run src/op-env-export.ts my-app-dev Personal --format op-refs > .env.tpl
JSON format
bun run src/op-env-export.ts my-app-dev Personal --format json
Add prefix to all variables
bun run src/op-env-export.ts azure-config Shared --prefix AZURE_ > .env
- Delete Environment
Interactive deletion (asks for confirmation)
bun run src/op-env-delete.ts my-app-dev Personal
Force delete without confirmation
bun run src/op-env-delete.ts my-app-dev Personal --force
Archive instead of permanent delete
bun run src/op-env-delete.ts my-app-dev Personal --archive
Environment Secret Reference
Access individual variables using the secret reference format:
op://<vault>/<environment>/variables/<key>
Example:
Read single variable
op read "op://Personal/my-app-dev/variables/API_KEY"
Use in template file (.env.tpl)
API_KEY=op://Personal/my-app-dev/variables/API_KEY DB_HOST=op://Personal/my-app-dev/variables/DB_HOST
Integration Patterns
With op run (recommended)
1. Export environment as op:// template
bun run src/op-env-export.ts my-app-dev Personal --format op-refs > .env.tpl
2. Run command with injected secrets
op run --env-file .env.tpl -- ./deploy.sh op run --env-file .env.tpl -- docker compose up op run --env-file .env.tpl -- npm start op run --env-file .env.tpl -- python app.py
With op inject
1. Create template with op:// references
bun run src/op-env-export.ts my-app-dev Personal --format op-refs > config.tpl
2. Inject secrets into file
op inject -i config.tpl -o .env
3. Use the generated .env file
source .env && ./app
With Docker Compose
1. Export environment
bun run src/op-env-export.ts my-app-dev Personal --format op-refs > .env.tpl
2. Run docker compose with secrets
op run --env-file .env.tpl -- docker compose up -d
In CI/CD (GitHub Actions)
name: Deploy on: [push]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install 1Password CLI
uses: 1password/install-cli-action@v1
- name: Load secrets
uses: 1password/load-secrets-action@v2
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
API_KEY: op://CI-CD/my-app-prod/variables/API_KEY
DB_PASSWORD: op://CI-CD/my-app-prod/variables/DB_PASSWORD
- name: Deploy
run: ./deploy.sh
Current Environments (Barbosa Account)
Environment Vault Description
hypera-azure-rg-hypera-cafehyna-web-dev
Azure RG - Cafehyna Web Dev
hypera-azure-devops-team-az-cli-pim
Azure DevOps Team - CLI PIM
devops-team-pim
DevOps Team PIM credentials
hypera-github-python-devops
GitHub - Python DevOps
hypera-azure-rg-hypera-cafehyna-web
Azure RG - Cafehyna Web Prod
repos-github-zsh
GitHub - ZSH repository
hypera
General Hypera infrastructure
Azure OpenAI-finops
Azure OpenAI FinOps config
See references/environments/inventory.md for detailed documentation.
Secret Retrieval
Secret Reference Format
The standard format for referencing secrets:
op://<vault>/<item>/<field>
Examples:
-
op://Development/AWS/access_key_id
-
op://Production/Database/password
-
op://Shared/API Keys/github_token
Reading Secrets Directly
Read a specific field
op read "op://Development/AWS/access_key_id"
Read with JSON output
op item get "AWS" --vault Development --format json
Read specific field from item
op item get "AWS" --vault Development --fields access_key_id
Injecting Secrets into Commands
The op run command injects secrets as environment variables:
Run command with secrets
op run --env-file=.env.tpl -- ./deploy.sh
Example .env.tpl file:
AWS_ACCESS_KEY_ID=op://Development/AWS/access_key_id
AWS_SECRET_ACCESS_KEY=op://Development/AWS/secret_access_key
Injecting Secrets into Files
The op inject command replaces secret references in template files:
Inject secrets from template to output file
op inject -i config.tpl.yaml -o config.yaml
Example config.tpl.yaml:
database:
host: localhost
password: op://Production/Database/password
Item Management
Creating Items
Create a login item
op item create --category login
--title "My Service"
--vault Development
username=admin
password=secretpassword
Create with generated password
op item create --category login
--title "New Account"
--generate-password
Create from JSON template
op item create --template item.json
Item Template (JSON)
{ "title": "my-service-credentials", "vault": {"id": "vault-uuid-or-name"}, "category": "LOGIN", "fields": [ {"label": "username", "value": "admin", "type": "STRING"}, {"label": "password", "value": "secret", "type": "CONCEALED"}, {"label": "api_key", "value": "key123", "type": "CONCEALED"} ] }
Editing Items
Edit a field
op item edit "My Service" password=newpassword
Add a new field
op item edit "My Service" api_key=newkey
Edit with specific vault
op item edit "My Service" --vault Development password=newpassword
Service Accounts
Service accounts enable automation without personal credentials.
Prerequisites
-
1Password CLI version 2.18.0 or later
-
Active 1Password subscription
-
Admin permissions to create service accounts
Creating Service Accounts
Via CLI:
Create with read-only access
op service-account create "CI/CD Pipeline"
--vault Production:read_items
Create with write access
op service-account create "Deployment Bot"
--vault Production:read_items,write_items
Create with vault creation permission
op service-account create "Provisioning Bot"
--vault Production:read_items,write_items
--can-create-vaults
Using Service Accounts
Export the service account token:
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
Then use normal CLI commands - they automatically authenticate with the service account.
Service Account Limitations
-
Cannot access Personal, Private, Employee, or default Shared vaults
-
Permissions cannot be modified after creation
-
Limited to 100 service accounts per account
-
Subject to rate limits
CI/CD Integration
GitHub Actions
name: Deploy on: [push]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install 1Password CLI
uses: 1password/install-cli-action@v1
- name: Load secrets
uses: 1password/load-secrets-action@v2
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
AWS_ACCESS_KEY_ID: op://CI-CD/AWS/access_key_id
AWS_SECRET_ACCESS_KEY: op://CI-CD/AWS/secret_access_key
- name: Deploy
run: ./deploy.sh
GitLab CI
deploy: image: 1password/op:2 variables: OP_SERVICE_ACCOUNT_TOKEN: $OP_SERVICE_ACCOUNT_TOKEN script: - export AWS_ACCESS_KEY_ID=$(op read "op://CI-CD/AWS/access_key_id") - export AWS_SECRET_ACCESS_KEY=$(op read "op://CI-CD/AWS/secret_access_key") - ./deploy.sh
CircleCI
version: 2.1 orbs: onepassword: onepassword/secrets@1
jobs: deploy: docker: - image: cimg/base:stable steps: - checkout - onepassword/exec: command: ./deploy.sh env: AWS_ACCESS_KEY_ID: op://CI-CD/AWS/access_key_id AWS_SECRET_ACCESS_KEY: op://CI-CD/AWS/secret_access_key
External Secrets Operator Integration
External Secrets Operator (ESO) syncs secrets from 1Password to Kubernetes.
Prerequisites
-
1Password Connect Server (v1.5.6+)
-
Credentials file (1password-credentials.json )
-
Access token for authentication
-
External Secrets Operator installed in cluster
Connect Server Setup
Create automation environment and get credentials
This generates 1password-credentials.json and an access token
Create Kubernetes secret for Connect Server credentials
kubectl create secret generic onepassword-credentials
--from-file=1password-credentials.json
Create secret for access token
kubectl create secret generic onepassword-token
--from-literal=token=your-access-token
Deploy Connect Server
apiVersion: apps/v1 kind: Deployment metadata: name: onepassword-connect spec: replicas: 1 selector: matchLabels: app: onepassword-connect template: metadata: labels: app: onepassword-connect spec: containers: - name: connect-api image: 1password/connect-api:latest ports: - containerPort: 8080 volumeMounts: - name: credentials mountPath: /home/opuser/.op/1password-credentials.json subPath: 1password-credentials.json volumes: - name: credentials secret: secretName: onepassword-credentials
apiVersion: v1 kind: Service metadata: name: onepassword-connect spec: selector: app: onepassword-connect ports: - port: 8080 targetPort: 8080
ClusterSecretStore Configuration
apiVersion: external-secrets.io/v1 kind: ClusterSecretStore metadata: name: onepassword spec: provider: onepassword: connectHost: http://onepassword-connect:8080 vaults: production: 1 staging: 2 auth: secretRef: connectTokenSecretRef: name: onepassword-token namespace: external-secrets key: token
ExternalSecret Examples
Basic secret retrieval:
apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: database-credentials spec: refreshInterval: 1h secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: database-credentials creationPolicy: Owner data: - secretKey: username remoteRef: key: Database # Item title in 1Password property: username # Field label - secretKey: password remoteRef: key: Database property: password
Using dataFrom with regex:
apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: env-config spec: refreshInterval: 1h secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: app-env dataFrom: - find: path: app-config # Item title name: regexp: "^[A-Z_]+$" # Match all uppercase env vars
PushSecret (Kubernetes to 1Password)
apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: push-generated-secret spec: refreshInterval: 1h secretStoreRefs: - name: onepassword kind: ClusterSecretStore selector: secret: name: generated-credentials data: - match: secretKey: api-key remoteRef: remoteKey: generated-api-key property: password metadata: apiVersion: kubernetes.external-secrets.io/v1alpha1 kind: PushSecretMetadata spec: vault: production tags: - generated - kubernetes
1Password Kubernetes Operator
The native 1Password Operator provides direct integration without External Secrets Operator.
Installation via Helm
helm repo add 1password https://1password.github.io/connect-helm-charts
helm install connect 1password/connect
--set-file connect.credentials=1password-credentials.json
--set operator.create=true
--set operator.token.value=your-access-token
OnePasswordItem CRD
apiVersion: onepassword.com/v1 kind: OnePasswordItem metadata: name: database-secret spec: itemPath: "vaults/Production/items/Database"
This creates a Kubernetes Secret named database-secret with all fields from the 1Password item.
Auto-Restart Configuration
Enable automatic deployment restarts when secrets change:
Operator-level (environment variable)
AUTO_RESTART=true
Namespace-level (annotation)
apiVersion: v1 kind: Namespace metadata: name: production annotations: operator.1password.io/auto-restart: "true"
Deployment-level (annotation)
apiVersion: apps/v1 kind: Deployment metadata: annotations: operator.1password.io/auto-restart: "true"
Shell Plugins
Shell plugins enable automatic authentication for third-party CLIs.
Available Plugins
List available plugins
op plugin list
Common plugins: aws, gh, stripe, vercel, fly, etc.
Plugin Setup
Initialize AWS plugin
op plugin init aws
This configures shell aliases to use 1Password for AWS credentials
Add to your shell profile as instructed
Git Workflow with 1Password
Use 1Password to manage GitHub authentication for git operations (push, pull, clone).
Quick Setup
Run the setup script to configure everything:
./scripts/setup-gh-plugin.sh
Manual Setup
Step 1: Initialize the gh plugin
Sign in to 1Password
op signin
Initialize gh plugin (interactive - select your GitHub token)
op plugin init gh
Step 2: Configure git credential helper
Remove any broken credential helpers
git config --global --unset-all credential.https://github.com.helper 2>/dev/null
Set gh as the credential helper for GitHub
git config --global credential.https://github.com.helper '!/opt/homebrew/bin/gh auth git-credential' git config --global credential.https://gist.github.com.helper '!/opt/homebrew/bin/gh auth git-credential'
Step 3: Add shell integration
Add to your ~/.zshrc or ~/.bashrc :
1Password CLI plugins
source ~/.config/op/plugins.sh
How It Works
┌─────────────────────────────────────────────────────────────────┐ │ Git Push Workflow │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ git push │ │ │ │ │ ▼ │ │ Git credential helper │ │ │ │ │ ▼ │ │ gh auth git-credential │ │ │ │ │ ▼ │ │ 1Password plugin (via op wrapper) │ │ │ │ │ ▼ │ │ 1Password (biometric/password unlock) │ │ │ │ │ ▼ │ │ Token retrieved and passed to git │ │ │ │ │ ▼ │ │ Push completes successfully │ │ │ └─────────────────────────────────────────────────────────────────┘
Multiple GitHub Accounts
If you work with multiple GitHub accounts, you can configure per-repo credentials:
For a specific repo, use a different 1Password item
cd /path/to/work-repo git config credential.https://github.com.helper '!/opt/homebrew/bin/gh auth git-credential'
Or use includeIf in ~/.gitconfig for path-based selection
[includeIf "gitdir:~/work/"] path = ~/.gitconfig-work
Fixing Common Issues
"Item not found in vault" error
This means the 1Password plugin is pointing to a deleted token:
Remove the broken plugin configuration
rm ~/.config/op/plugins/used_items/gh.json
Re-initialize
op plugin init gh
gh aliased to op plugin run
If gh is aliased to run through 1Password but failing:
Check the alias
which gh # Shows: gh: aliased to op plugin run -- gh
Run gh directly to bypass the alias
/opt/homebrew/bin/gh auth status
Git prompting for username/password
Verify the credential helper is configured:
git config --list | grep credential
Should show:
credential.https://github.com.helper=!/opt/homebrew/bin/gh auth git-credential
Troubleshooting
Common Issues
Authentication fails:
Check current session
op whoami
Sign in again
op signin
For service accounts, verify token
echo $OP_SERVICE_ACCOUNT_TOKEN | head -c 10
Item not found:
List items in vault to verify name
op item list --vault "Vault Name"
Use item ID instead of name for reliability
op item get --vault Development dh7fjsh3kd8fjs
Permission denied in CI/CD:
Verify service account has access to vault
op vault list # Should show accessible vaults
Check rate limits
op service-account ratelimit
External Secrets not syncing:
Check ExternalSecret status
kubectl describe externalsecret <name>
Check Connect Server logs
kubectl logs -l app=onepassword-connect
Verify SecretStore connection
kubectl describe secretstore <name>
Best Practices
-
Use secret references (op:// ) instead of hardcoding vault/item names in scripts
-
Prefer service accounts over personal accounts for automation
-
Scope permissions minimally - grant only necessary vault access
-
Use item IDs in scripts for stability (names can change)
-
Rotate service account tokens when sign-in addresses change
-
Enable auto-restart in Kubernetes for seamless secret rotation
-
Use separate vaults per environment (dev, staging, prod)
-
Tag items for organization and filtering
Resources
References
-
references/cli-commands.md
-
Complete CLI command reference
-
references/kubernetes-examples.md
-
Kubernetes manifest examples
-
references/python-sdk.md
-
Python SDK reference and integration guide
-
references/environments/README.md
-
Developer Environments guide
-
references/environments/inventory.md
-
Current environments inventory
Tools
Environment management CLI tools in TypeScript and Python:
Operation TypeScript (tools/ ) Python (tools-python/ )
Create bun run create
uv run op-env-create
Update bun run update
uv run op-env-update
Delete bun run delete
uv run op-env-delete
Show bun run show
uv run op-env-show
List bun run list
uv run op-env-list
Export bun run export
uv run op-env-export
TypeScript requirements: Bun runtime Python requirements: Python 3.9+, uv, OP_SERVICE_ACCOUNT_TOKEN
TypeScript tools
cd tools && bun run src/op-env-list.ts --help
Python SDK tools
cd tools-python && uv sync && uv run op-env-list --help
Templates
Environment and integration templates (in templates/ ):
Template Description
env.template
Standard .env file template
env-op-refs.template
Template with op:// references
github-actions-env.yaml
GitHub Actions workflow example
docker-compose-env.yaml
Docker Compose with secrets injection
Scripts
-
scripts/setup-gh-plugin.sh
-
Setup GitHub CLI with 1Password integration
-
scripts/setup-service-account.sh
-
Create and configure a service account
-
scripts/sync-check.sh
-
Verify External Secrets synchronization
External Documentation
-
1Password CLI Documentation
-
Service Accounts Guide
-
Developer Environments
-
Local .env Files
-
Kubernetes Operator
-
External Secrets Provider