Skip to main content

Getting started with secrets

Add your first secret to a Loom workflow in under ten minutes. This guide walks through end-to-end setup using 1Password (recommended for teams), then covers KeePass and environment passthrough as alternatives.

What you will do

  1. Configure a 1Password service account token.
  2. Create or verify a secret in your 1Password vault.
  3. Reference the secret in a workflow.
  4. Run the workflow and confirm the secret is resolved and redacted.

Prerequisites

  • Loom CLI available (run loom --version to confirm).
  • A working Loom workspace (loom check succeeds).
  • A shell session where you can export environment variables.

1Password is the recommended secrets provider for team workflows. It provides centralized vault management, access control, and audit logging out of the box. Loom resolves op:// references through the 1Password Go SDK — no op CLI installation is needed.

A1. Export your service account token

Create a 1Password service account if you do not have one. The token starts with ops_....

export OP_SERVICE_ACCOUNT_TOKEN="ops_..."

Verify connectivity by listing accessible vaults:

loom secrets op vault list

You should see output like:

name=Engineering id=vlt_abc123
name=Platform id=vlt_def456

A2. Create a secret (or use an existing one)

If you already have an item in your vault, skip to A3.

Store a deploy token using the Loom CLI:

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

Expected output:

item field created: vault=Engineering item=services/loom/deploy field=token

Verify the item exists (no secret values are printed):

loom secrets op item list --vault Engineering
services/loom/deploy  token

A3. Reference the secret in a workflow

Add a secrets block to a job. The ref URI tells Loom which vault entry to resolve:

version: v1
stages: [ci]

deploy:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: op://Engineering/services/loom/deploy/token
script:
- echo "Token file path is $DEPLOY_TOKEN"
- curl -H "Authorization: Bearer $(cat $DEPLOY_TOKEN)" https://api.example.com/deploy

Key points:

  • ref format: op://<vault>/<item-path>/<field>.
  • file defaults to true: $DEPLOY_TOKEN contains a path to a temp file. Read the value with cat "$DEPLOY_TOKEN".
  • required defaults to true: if the secret cannot be resolved, the job fails before script execution.
  • No credentials in YAML: the token value never appears in workflow files.

A4. Validate and run

loom check
loom run --local --workflow .loom/workflow.yml

What to expect:

  • The job starts and the secret is resolved from 1Password.
  • Console output shows $DEPLOY_TOKEN as a file path (e.g. /tmp/loom-secret-DEPLOY_TOKEN-0).
  • Any output that contains the actual token value is redacted to [REDACTED:SECRET_DEPLOY_TOKEN].
  • Runtime logs under .loom/.runtime/logs/<run_id>/ contain only redacted output.

Option B: KeePass (local encrypted vaults)

KeePass is ideal when you need offline, encrypted secret storage without external services. Loom manages .kdbx databases through alias-driven configuration.

B1. Create a KeePass vault

export KEEPASS_PASSWORD="pick-a-strong-master-password"

loom secrets keepass vault create \
--password-from-env KEEPASS_PASSWORD

Expected output:

vault created: alias=<your-repo-path> path=.loom/keepass/<ALIAS>.kdbx

The vault alias defaults to your Git remote origin path (e.g. group/project/repo). Override with --vault-path <alias>.

B2. Configure runtime access

The CLI creates the .kdbx file, but runtime resolution requires environment variables. Before running loom check or loom run, export:

export LOOM_KEEPASS_DB_GROUP_PROJECT_REPO_PATH="$PWD/.loom/keepass/GROUP_PROJECT_REPO.kdbx"
export LOOM_KEEPASS_DB_GROUP_PROJECT_REPO_PASSWORD_ENV="KEEPASS_PASSWORD"
export KEEPASS_PASSWORD="pick-a-strong-master-password"

Replace GROUP_PROJECT_REPO with the uppercase, underscore-delimited version of your vault alias.

tip

Store these exports in a local .env file (excluded from version control) and source it at the start of each session.

B3. Add a secret and reference it

export DEPLOY_TOKEN_VALUE="ghp_abc123_your_real_token"

loom secrets keepass item create \
--item-path services/deploy \
--field token \
--value-from-env DEPLOY_TOKEN_VALUE

Reference it in your workflow:

deploy:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: keepass://<alias>#services/deploy:token
script:
- curl -H "Authorization: Bearer $(cat $DEPLOY_TOKEN)" https://api.example.com/deploy

B4. Validate and run

loom check
loom run --local --workflow .loom/workflow.yml

Option C: Environment passthrough (env://)

The simplest option — reads a value directly from the host environment. No vault setup required.

deploy:
stage: ci
target: linux
secrets:
DEPLOY_TOKEN:
ref: env://DEPLOY_TOKEN
script:
- curl -H "Authorization: Bearer $(cat $DEPLOY_TOKEN)" https://api.example.com/deploy

Before running:

export DEPLOY_TOKEN="ghp_abc123"
loom run --local --workflow .loom/workflow.yml

Use env:// for quick prototyping or when secrets are already managed by your CI runner.


Injection modes

By default, $SECRET_NAME holds a path to a temp file containing the value. Some tools expect the raw value in the env var instead.

Modefile settingJob seesWhen to use
File injection (default)truePath to a 0600 temp fileMost cases — lower leakage risk
Direct injectionfalseRaw secret valueOnly when a tool cannot read from a file

Example: direct injection for npm publish

secrets:
NPM_TOKEN:
ref: env://NPM_TOKEN
file: false

Tradeoff: direct injection is more exposed to shell tracing (set -x). If CI_DEBUG_TRACE=true is set and any secret uses file: false, Loom hard-fails with SECRETS_UNSAFE_DEBUG_TRACE to prevent accidental exposure.

Optional secrets

Mark a secret required: false when the job should succeed even if the secret is unavailable:

secrets:
SLACK_WEBHOOK:
ref: op://Engineering/notifications/webhook
required: false

Your script should handle the missing-variable case:

if [ -n "$SLACK_WEBHOOK" ]; then
curl -X POST "$(cat $SLACK_WEBHOOK)" -d '{"text":"Deploy complete"}'
fi

Validation rules

RuleWhat happens on violation
A key cannot be in both variables and secrets for the same jobSchema validation error (fail-fast)
default.secrets is not allowedSchema validation error
Secret names must match ^[A-Z_][A-Z0-9_]*$Schema validation error
ref must use a supported URI schemeSECRETS_REF_INVALID
Missing required secretSECRETS_REQUIRED_MISSING — job fails
CI_DEBUG_TRACE=true with file: false secretsSECRETS_UNSAFE_DEBUG_TRACE

Troubleshooting

SymptomLikely causeFix
SECRETS_PROVIDER_UNAVAILABLEAuth config missing or invalid for the providerCheck OP_SERVICE_ACCOUNT_TOKEN or LOOM_KEEPASS_DB_* env vars
SECRETS_REQUIRED_MISSINGEnv var not exported (env://), or vault entry missingExport the variable or verify the vault item exists
SECRETS_REF_NOT_FOUNDEntry path or field does not match vault contentsVerify ref against loom secrets op item list or keepass item list
SECRETS_REF_INVALIDTypo in URI scheme or malformed refVerify scheme is env://, keepass://, or op://
Script fails reading secret valuefile: true (default) but script expects a direct valueUse cat "$VAR_NAME" in scripts, or set file: false
Schema error: key in both variables and secretsSame name in both blocks for one jobRemove the key from variables
SECRETS_UNSAFE_DEBUG_TRACECI_DEBUG_TRACE=true with file: false secretsDisable debug trace or switch to file: true