Skip to main content

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"
caution

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
  • file defaults to true — the job sees a file path, not the raw value. Read it with cat $VAR_NAME.
  • required defaults to true — a missing env var fails the job with SECRETS_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/mainLOOM_KEEPASS_DB_LOCAL_MAIN_).

VariablePurposeRequired
LOOM_KEEPASS_DB_<ALIAS>_PATHAbsolute path to the .kdbx fileYes
LOOM_KEEPASS_DB_<ALIAS>_PASSWORD_ENVName of env var containing the master passwordOne of password or keyfile
LOOM_KEEPASS_DB_<ALIAS>_KEYFILE_ENVName of env var containing the keyfile pathOne of password or keyfile
tip

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>

SegmentDescriptionExample
<database-alias>Alias from env var configlocal/main
<entry-path>Group/item path inside the KeePass databaseservices/deploy
<field>Field name to readtoken, 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>

SegmentDescriptionExample
<vault>1Password vault name or UUIDEngineering
<item-path>Item title/path in 1Passwordservices/loom/deploy
<field>Field name to resolvetoken, 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

ProviderAuth mechanismBest forDocs
env://Host environment variablesQuick setup, CI runnersWorkflows → Secrets
keepass://Local .kdbx file + master password or keyfileEncrypted local storage, solo devKeePass provider
op://OP_SERVICE_ACCOUNT_TOKEN (1Password Go SDK)Team vaults, shared access control1Password provider

Common pitfalls

SymptomCauseFix
SECRETS_REQUIRED_MISSINGEnv var not exported before running Loomexport VAR_NAME="value" in your shell
SECRETS_PROVIDER_UNAVAILABLEMissing alias mapping, vault auth, or expired tokenVerify provider env vars; for op://, check token with loom secrets op vault list
SECRETS_REF_NOT_FOUNDTypo in ref or missing vault entryCheck ref against loom secrets keepass item list or loom secrets op item list --vault <vault>
SECRETS_REF_INVALIDMalformed URI (wrong scheme, missing segments)Check URI format for the provider
Script fails reading secretfile: true (default) but script expects a direct valueUse cat $VAR_NAME or set file: false
SECRETS_UNSAFE_DEBUG_TRACECI_DEBUG_TRACE=true with file: false secretsDisable debug trace or switch to file: true

Team workflow

When sharing workflows that use secrets:

  1. Workflow YAML goes in version control — it contains only references, not values.
  2. Document required env vars in a README or onboarding doc (e.g., "set DEPLOY_TOKEN and DATABASE_PASSWORD before running").
  3. Each developer provides their own values — from their shell, a local .env file, or their 1Password account.
  4. Use required: false for optional secrets so the workflow runs even if a teammate doesn't have a particular value configured.