Skip to main content

Precedence and merge rules

When the same setting appears in multiple places, later layers win, but only for the fields they actually set.

Effective order for loom config show​

This is the precedence order for the effective config that loom config show prints:

PrioritySource
1Built-in defaults
2~/.config/loom/config.yml
3.loom/config.yml
4Supported runtime env overlays

The built-in default is:

KeyBuilt-in default
runtime.docker.workspaceMountephemeral_volume
defaults.*unset

Supported env overlays​

Loom reads these environment overrides:

  • LOOM_WORKFLOW, LOOM_FORMAT, LOOM_CONTEXT (stand-ins for the --workflow, --format, --context flags of loom check, compile, run)
  • LOOM_DOCKER_WORKSPACE_MOUNT
  • LOOM_KEEPASS_DB_<ALIAS>_PATH
  • LOOM_KEEPASS_DB_<ALIAS>_PASSWORD_ENV
  • LOOM_KEEPASS_DB_<ALIAS>_KEYFILE_ENV

There is no matching env overlay for providers.op.serviceAccountTokenEnv. That field comes from config files and stores the env var name Loom should read later.

How merge works​

Loom merges the supported fields instead of replacing the whole tree:

  • runtime.docker.workspaceMount and each defaults.* key are simple last-writer-wins values
  • KeePass aliases merge by alias name
  • later layers replace only the KeePass alias fields they set
  • empty env values are ignored instead of treated as overrides

For example, this user config:

providers:
keepass:
aliases:
team/app:
path: vaults/team-app.kdbx
passwordEnv: TEAM_APP_PASSWORD

combined with this repo config:

providers:
keepass:
aliases:
team/app:
keyfileEnv: TEAM_APP_KEYFILE

produces one effective team/app alias with all three fields merged.

Path resolution rules​

KeePass path values from config files are resolved relative to the file that declared them:

  • ~/.config/loom/config.yml values resolve relative to ~/.config/loom
  • .loom/config.yml values resolve relative to .loom

Environment overlay paths are used as provided. Loom does not re-base them relative to the repo.

What changes during loom run --local​

loom run --local uses the same layered config, but Docker mount mode has one extra override above the layered result:

PrioritySource
1Built-in default ephemeral_volume
2~/.config/loom/config.yml
3.loom/config.yml
4LOOM_DOCKER_WORKSPACE_MOUNT
5loom run --local --docker-workspace-mount ...

That CLI flag affects the current run only. It does not change what loom config show prints.

loom check, loom compile, and loom run apply the same shape to the workflow selection flags: --workflow, --format, and --context sit above LOOM_WORKFLOW, LOOM_FORMAT, and LOOM_CONTEXT, which sit above the defaults block of .loom/config.yml and then ~/.config/loom/config.yml.

Quick examples​

Repository config overrides user config​

If .loom/config.yml sets:

runtime:
docker:
workspaceMount: bind_mount

and ~/.config/loom/config.yml sets:

runtime:
docker:
workspaceMount: ephemeral_volume

Because the repository layer is merged after the user layer, loom config show prints bind_mount.

Env override wins over files​

If both config files exist but you run:

LOOM_DOCKER_WORKSPACE_MOUNT=bind_mount loom config show

the effective value becomes bind_mount for that process.

Execution-time detail that matters​

During loom run --local, Loom fills in missing runtime env vars from the effective config. If you already exported a concrete env var such as LOOM_KEEPASS_DB_TEAM_APP_PATH or OP_SERVICE_ACCOUNT_TOKEN, Loom keeps that existing value instead of replacing it with a default.