Pattern: secrets for local development
Set up secrets for local Loom workflows. Three providers are available today — env:// for quick prototyping, keepass:// for encrypted local vaults, and op:// for 1Password team vaults.
For the full walkthrough, see Getting started with secrets.
When to use this pattern
You have a workflow that needs passwords, tokens, or private keys at runtime and you want to:
- Keep secrets out of workflow YAML — store references, not values.
- Get automatic redaction in runtime logs and receipts.
- Set up once on your dev machine and share the workflow safely with teammates.
Option A: env:// (quickest path)
env:// reads values from the host process environment. No vault, no CLI tools, no network — just exported variables.
1) Export secrets in your shell
Add exports to your shell profile (.bashrc, .zshrc) or a local .env file that you source before runs:
export DEPLOY_TOKEN="ghp_abc123..."
export DATABASE_PASSWORD="s3cret"
Never commit .env files or shell profile excerpts containing real secret values. Add .env to your .gitignore.
2) Reference secrets in your workflow
version: v1
stages: [ci]
deploy:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: env://DEPLOY_TOKEN
DATABASE_PASSWORD:
ref: env://DATABASE_PASSWORD
script:
- curl -H "Authorization: Bearer $(cat $DEPLOY_TOKEN)" https://api.example.com/deploy
- ./scripts/migrate.sh
filedefaults totrue— the job sees a file path, not the raw value. Read it withcat $VAR_NAME.requireddefaults totrue— a missing env var fails the job withSECRETS_REQUIRED_MISSING.
3) Run and verify
loom run --local --workflow .loom/workflow.yml
Check the runtime logs — secret values appear as [REDACTED:SECRET_DEPLOY_TOKEN], not the raw string.
Option B: keepass:// (encrypted local vault)
KeePass provides encrypted local storage so secrets don't depend on exported shell variables. The vault file (.kdbx) stays on your machine; Loom unlocks it at runtime using environment variables.
1) Create a vault
export KEEPASS_PASSWORD="pick-a-strong-master-password"
loom secrets keepass vault create \
--password-from-env KEEPASS_PASSWORD
2) Add secrets to the vault
export DEPLOY_TOKEN_VALUE="ghp_abc123..."
loom secrets keepass item create \
--item-path services/deploy \
--field token \
--value-from-env DEPLOY_TOKEN_VALUE
3) Configure runtime access
Loom maps each database alias to environment variables. For an alias like local/main:
export LOOM_KEEPASS_DB_LOCAL_MAIN_PATH="$PWD/.loom/keepass/LOCAL_MAIN.kdbx"
export LOOM_KEEPASS_DB_LOCAL_MAIN_PASSWORD_ENV="KEEPASS_PASSWORD"
export KEEPASS_PASSWORD="pick-a-strong-master-password"
The alias is uppercased with / replaced by _ to form the variable prefix (local/main → LOOM_KEEPASS_DB_LOCAL_MAIN_).
| Variable | Purpose | Required |
|---|---|---|
LOOM_KEEPASS_DB_<ALIAS>_PATH | Absolute path to the .kdbx file | Yes |
LOOM_KEEPASS_DB_<ALIAS>_PASSWORD_ENV | Name of env var containing the master password | One of password or keyfile |
LOOM_KEEPASS_DB_<ALIAS>_KEYFILE_ENV | Name of env var containing the keyfile path | One of password or keyfile |
Store these exports in a local .env file excluded from version control and source it at the start of each session.
4) Reference secrets with keepass://
secrets:
DEPLOY_TOKEN:
ref: keepass://local/main#services/deploy:token
URI structure: keepass://<database-alias>#<entry-path>:<field>
| Segment | Description | Example |
|---|---|---|
<database-alias> | Alias from env var config | local/main |
<entry-path> | Group/item path inside the KeePass database | services/deploy |
<field> | Field name to read | token, password |
5) Validate and run
loom check
loom run --local --workflow .loom/workflow.yml
Full provider reference: Workflows secrets: KeePass.
Option C: op:// (1Password team vaults)
1Password provides shared team vaults with access control. Loom resolves op:// references through the 1Password Go SDK at execution time — no op CLI installation required. You need a service account token.
1) Set up a service account
Create a service account at 1Password service accounts and grant it access to the vault(s) your workflows need.
2) Export the token
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
3) Verify vault access
loom secrets op vault list
Expected output:
name=Engineering id=vlt_abc123
4) Store a secret (or use an existing item)
export DEPLOY_TOKEN_VALUE="tok_example_abc123"
loom secrets op item create \
--vault Engineering \
--item-path services/loom/deploy \
--field token \
--value-from-env DEPLOY_TOKEN_VALUE
5) Reference secrets with op://
secrets:
DEPLOY_TOKEN:
ref: op://Engineering/services/loom/deploy/token
URI structure: op://<vault>/<item-path>/<field>
| Segment | Description | Example |
|---|---|---|
<vault> | 1Password vault name or UUID | Engineering |
<item-path> | Item title/path in 1Password | services/loom/deploy |
<field> | Field name to resolve | token, password |
6) Validate and run
loom check
loom run --local --workflow .loom/workflow.yml
Full provider reference: Workflows secrets: 1Password.
Direct injection for tools that require env values
Some tools (e.g., npm publish reading $NPM_TOKEN) expect the secret value directly in the environment, not a file path. Use file: false:
secrets:
NPM_TOKEN:
ref: env://NPM_TOKEN
file: false
Tradeoff: direct injection is more exposed to shell tracing (set -x). Loom hard-fails with SECRETS_UNSAFE_DEBUG_TRACE if CI_DEBUG_TRACE=true and any secret uses file: false.
Prefer file: true (the default) unless your tooling specifically requires a direct environment value.
Provider comparison
| Provider | Auth mechanism | Best for | Docs |
|---|---|---|---|
env:// | Host environment variables | Quick setup, CI runners | Workflows → Secrets |
keepass:// | Local .kdbx file + master password or keyfile | Encrypted local storage, solo dev | KeePass provider |
op:// | OP_SERVICE_ACCOUNT_TOKEN (1Password Go SDK) | Team vaults, shared access control | 1Password provider |
Common pitfalls
| Symptom | Cause | Fix |
|---|---|---|
SECRETS_REQUIRED_MISSING | Env var not exported before running Loom | export VAR_NAME="value" in your shell |
SECRETS_PROVIDER_UNAVAILABLE | Missing alias mapping, vault auth, or expired token | Verify provider env vars; for op://, check token with loom secrets op vault list |
SECRETS_REF_NOT_FOUND | Typo in ref or missing vault entry | Check ref against loom secrets keepass item list or loom secrets op item list --vault <vault> |
SECRETS_REF_INVALID | Malformed URI (wrong scheme, missing segments) | Check URI format for the provider |
| Script fails reading secret | file: true (default) but script expects a direct value | Use cat $VAR_NAME or set file: false |
SECRETS_UNSAFE_DEBUG_TRACE | CI_DEBUG_TRACE=true with file: false secrets | Disable debug trace or switch to file: true |
Team workflow
When sharing workflows that use secrets:
- Workflow YAML goes in version control — it contains only references, not values.
- Document required env vars in a
READMEor onboarding doc (e.g., "setDEPLOY_TOKENandDATABASE_PASSWORDbefore running"). - Each developer provides their own values — from their shell, a local
.envfile, or their 1Password account. - Use
required: falsefor optional secrets so the workflow runs even if a teammate doesn't have a particular value configured.
Related docs
- Getting started with secrets — end-to-end walkthrough
- Concepts → Secrets — mental model, redaction, injection modes
- Workflows → Secrets — YAML syntax, provider URIs, validation rules
- Secrets with
env://example — runnable example workflow - Secrets error codes — all
SECRETS_*error codes with fixes