From dotsecenv
Interprets .secenv files and resolves dotsecenv vault references. Helps create, edit, and debug .secenv files, troubleshoot secret loading, vault configuration, and shell plugin issues.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dotsecenv:secenvThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill teaches you how to read, write, and debug `.secenv` files and their relationship to dotsecenv vaults and config. For CLI operations (storing, retrieving, sharing secrets), defer to the `/dotsecenv:secrets` skill.
This skill teaches you how to read, write, and debug .secenv files and their relationship to dotsecenv vaults and config. For CLI operations (storing, retrieving, sharing secrets), defer to the /dotsecenv:secrets skill.
A .secenv file is a line-based file with KEY=VALUE pairs. It lives in a project directory and is loaded by the shell plugin when the user cds into that directory.
# Plain environment variables
DATABASE_HOST=localhost
DATABASE_PORT=5432
# Quoted values (quotes are stripped on load)
APP_NAME="My Application"
DESCRIPTION='Has spaces'
# Secret references — fetched from a dotsecenv vault at load time
# Same name: variable name = secret key name
DATABASE_PASSWORD={dotsecenv}
# Explicit name: variable name differs from secret key
MY_API_KEY={dotsecenv/API_KEY}
# Name ommitted: empty string is used after dotsecenv/ reference
MY_API_KEY={dotsecenv/}
# Namespaced secret (:: separator)
DB_PASS={dotsecenv/prod::DB_PASSWORD}
# Comments
# This line is ignored
# Empty lines are ignored
| Pattern | Type | Behavior |
|---|---|---|
KEY=value | Plain | Exported as-is |
KEY="value" or KEY='value' | Plain (quoted) | Quotes stripped, then exported |
KEY={dotsecenv} | Secret (same name) | Fetches secret named KEY from vault |
KEY={dotsecenv/} | Secret (same name) | Fetches secret named KEY from vault |
KEY={dotsecenv/SECRET} | Secret (explicit) | Fetches secret named SECRET from vault |
KEY={dotsecenv/ns::SECRET} | Secret (namespaced) | Fetches secret ns::SECRET from vault |
# comment | Comment | Ignored |
| Empty line | — | Ignored |
^[A-Za-z_][A-Za-z0-9_]*$:: as namespace separator: namespace::KEY_NAME (e.g., prod::DB_PASSWORD)/ allowed in {dotsecenv/...} references; a second / is rejected by the parser{dotsecenv/ can be a plain key (API_KEY) or namespaced (prod::DB_PASSWORD)The shell plugin loads .secenv files in two phases:
KEY=value lines are exported first{dotsecenv} references are resolved via the CLIThis ensures plain variables are available before secret resolution. The plugin also loads ancestor .secenv files — if /project/.secenv and /project/src/.secenv both exist, entering /project/src/ loads both, with child values shadowing parent values for the same key.
When the shell plugin encounters a {dotsecenv} reference, it calls the dotsecenv CLI to fetch the secret. The CLI finds the vault using the dotsecenv config file.
Resolved in this order:
DOTSECENV_CONFIG environment variable$XDG_CONFIG_HOME/dotsecenv/config (default: ~/.config/dotsecenv/config)The config file (YAML) lists vault paths:
vault:
- ~/.local/share/dotsecenv/vault # absolute (tilde-expanded)
- /shared/team/vault # absolute
- .dotsecenv/vault # relative to CWD
Relative vault paths (like .dotsecenv/vault) are resolved relative to the current working directory, NOT relative to the config file.
This is why the shell plugin cds into the directory containing .secenv before calling the CLI. For example:
/project/.secenv → references DATABASE_PASSWORD={dotsecenv}
/project/.dotsecenv/vault → contains the encrypted secret
~/.config/dotsecenv/config → lists ".dotsecenv/vault" as a vault path
When the plugin loads /project/.secenv, it cds to /project/ first, then runs dotsecenv secret get DATABASE_PASSWORD. The CLI reads the config, sees .dotsecenv/vault, and resolves it to /project/.dotsecenv/vault.
The fastest way is dotsecenv init secenv, which builds the file from the user's vaults. In a terminal it opens a picker (one tab per vault, space to select); with --all it adds every reference not already present. It writes references only, never values, and skips keys already in the file.
cd /path/to/project
dotsecenv init secenv # pick interactively
dotsecenv init secenv --all # add every vault secret
To write the file by hand instead:
Ask which variables they need (plain vs. secret)
For secrets, check if they exist in a vault first:
# List secrets in the default vault
dotsecenv secret get --json
# Or check a specific vault
dotsecenv vault describe --json
Write the .secenv file with the correct syntax
Remind them the shell plugin needs to be installed for auto-loading
When a secret referenced in .secenv fails to load:
Read the .secenv file and identify the {dotsecenv} references
Read the config to find vault paths:
cat ~/.config/dotsecenv/config 2>/dev/null || cat "${XDG_CONFIG_HOME:-$HOME/.config}/dotsecenv/config"
Check if any vault paths are relative (like .dotsecenv/vault)
If relative, the vault must exist in the same directory as the .secenv file, not in the current working directory of the Claude session
Check if the vault file exists at the resolved path:
# For a .secenv in /project/, check relative vault path
ls -la /project/.dotsecenv/vault
List secrets in that vault to see if the referenced secret exists:
dotsecenv secret get --json -v /project/.dotsecenv/vault
Check identities — the user's fingerprint must be in the vault's available_to list for that secret:
dotsecenv vault describe --json -v /project/.dotsecenv/vault
.secenv directory)/dotsecenv:secrets — that's an init operationWhen adding or modifying entries:
{dotsecenv} or {dotsecenv/SECRET_NAME}If the user has nested .secenv files:
/project/.secenv → APP_ENV=production, DATABASE_URL={dotsecenv}
/project/services/.secenv → SERVICE_NAME=api, API_KEY={dotsecenv}
When entering /project/services/:
/project/services/ for /other/ unloads bothThe shell plugin performs these checks before loading a .secenv file:
When creating .secenv files, ensure correct ownership and permissions:
chmod 600 .secenv # owner read/write only
npx claudepluginhub dotsecenv/dotsecenv --plugin dotsecenvProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.