# 1Password Secret References Secret references are the safest way to use secrets — they point to 1Password without exposing actual values in code or config files. ## Syntax ``` op://vault/item/field op://vault/item/section/field ``` **Examples:** ```bash op://Dev/Anthropic/api_key op://Personal/AWS/access_key_id op://Dev/Supabase/section/service_key ``` ## Reading a Secret Reference ```bash # Single secret op read "op://Dev/Anthropic/api_key" # Into a variable export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key") # Multiple secrets via op run op run --env-file=.env.tpl -- your-command ``` ## .env Template Files Store references in a `.env.tpl` file (safe to commit to **private** repos): > **Privacy note:** `.env.tpl` contains your vault names, item names, and field names — > e.g. `op://Dev/Anthropic/api_key`. This reveals the structure of your 1Password vault > to anyone who can read the file. For **private repos**, this is fine. For **public repos**, > consider whether your vault/item naming reveals anything sensitive (client names, internal > service names, etc.). Real secret values are never exposed — only the structure. ```bash # .env.tpl — commit this ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key N8N_API_KEY=op://Dev/n8n/api_key SUPABASE_SERVICE_KEY=op://Dev/Supabase/service_key NOTION_TOKEN=op://Dev/Notion/api_token ``` Then inject at runtime: ```bash # ✅ RECOMMENDED — run your command with secrets injected into subprocess only op run --env-file=.env.tpl -- npm start op run --env-file=.env.tpl -- node server.js op run --env-file=.env.tpl -- docker compose up # ✅ OK — read a single secret into a variable for immediate use export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key") # ⚠️ AVOID — sourcing op run output exposes secrets in current shell # and is unsafe if any secret value contains shell metacharacters like $(...): # source <(op run --env-file=.env.tpl -- env) ← DON'T DO THIS # ⚠️ AVOID — writing resolved secrets to disk (don't commit .env) # op run --env-file=.env.tpl -- env > .env ← only if truly necessary ``` ## In Config Files Claude Desktop (`claude_desktop_config.json`): ```json { "mcpServers": { "my-server": { "command": "op", "args": ["run", "--", "node", "server.js"], "env": { "API_KEY": "op://Dev/MyServer/api_key" } } } } ``` Docker Compose: ```yaml services: app: image: myapp environment: - DATABASE_URL=op://Dev/Postgres/connection_string ``` Run with: `op run -- docker compose up` n8n (environment injection): ```bash # In your n8n startup script op run --env-file=n8n.env.tpl -- docker compose up n8n ``` ## Finding Field Names ```bash # List all fields in an item op item get "Item Name" --format=json | jq -r '.fields[] | select(.value) | .label' # Or view interactively op item get "Item Name" ``` ## Common Field Names by Category | Category | Common Fields | |----------|---------------| | API_CREDENTIAL | `api_key`, `credential`, `token` | | LOGIN | `username`, `password` | | DATABASE | `connection_string`, `host`, `port`, `username`, `password` | | SECURE_NOTE | `notesPlain` | | SERVER | `hostname`, `port`, `username`, `password` |