Collect scattered development environment variables into a "platform → account → Key" ledger, clarify each Key's lifecycle, verification status, and current projection target, and sync the Shell or user graphical session environment without echoing secrets.
Triggers
Activate when
- The user says "manage my environment variables," "the same platform has multiple accounts and API Keys," "rotate this Key to zsh," or "open the environment variables Dashboard."
- User asks to “manage API keys”, “rotate an environment variable”, “switch the active account”, or “audit expiring keys”.
- The user needs to maintain a Key's effective time, expiration time, remote verification results, or select one Key from multiple Keys to project to a specified variable.
Do not activate when
- The user only wants to temporarily pass an environment variable for the current single command; directly use the current Shell's invocation-scoped environment.
- The user wants to write a cloud Secret into Vercel, GitHub Actions, Supabase, or Kubernetes; use the target platform's Secret management process, and this Skill may only provide a confirmed list of variable names.
- The user wants to manage login passwords, credit cards, or recovery codes; use a password manager. 1Password serves only as an optional secret source for this Skill.
- The user wants to add a zsh shortcut command or function rather than an environment variable; hand off to
lov-zsh-alias。
Security Invariants
- Never write Key values into chats, Profiles, logs, the Dashboard, URLs, command arguments, or version control.
- Adding a Key only accepts hidden interactive input or standard input; the CLI deliberately does not provide
--value。 - The Registry only stores redacted metadata. By default, macOS uses Keychain, and other systems use a local vault with permissions of
0600; it also supportsop://references and existing environment variable references. ~/.zshenvwrites only onesourceblock managed by sentinel markers, and the actual exports reside in a generated file with permissions of0600.- Only one binding is allowed for the same target and variable name. Switching accounts or Keys replaces the binding, not copying multiple exports.
- The Dashboard only binds
127.0.0.1, does not display secrets, and does not provide a secret input box; all write operations require a temporary token generated by the current process and same-origin requests. - Do not automatically write Keys into
/etc/environment, LaunchAgent plists, or repository.envfiles. System projection only affects the current user session and requires explicit confirmation of the process environment exposure risk.
User Profile (cross-session)
At each run, first read skill.yaml declared by user-profile/v1. The Profile only stores safe working preferences, such as the default secret backend, expiration warning days, Shell rc file, and whether the Dashboard opens automatically; all Key values and secret references remain in dedicated storage and do not enter the Profile.
When the user directly declares a non-secret preference that needs to be saved across sessions, write it via scripts/profile_store.py record --skill-id lov-env-management --confirm into records and report the save path. Credentials, tokens, cookies, and any secret-like fields must not be written into the Profile. See the full contract at references/user-profile.md。
Skill Group Composition
Read references/skill-composition.mdbefore running. External Skills only perform optional handoff through a redacted variable list or secret references, and are not hidden dependencies.
Workflow (MANDATORY)
Step 0: Resolve context and inspect without secrets
- Resolve
SKILL_DIR, then runprofile_store.py readfor safe defaults. - Resolve storage with this precedence: current CLI flag,
LOV_ENV_HOME, Skill Profile, then the platform-safe config directory. - Start with
listoraudit; never search broad home-directory globs for credentials. - Separate requested targets: current command, zsh startup, current user GUI session, or a platform-specific remote Secret store.
python3 "$SKILL_DIR/scripts/env_manager.py" list
python3 "$SKILL_DIR/scripts/env_manager.py" audit
Step 1: Model platform, account, and Key identity
Use stable kebab-case IDs. A Key locator is platform/account/key, for example openai/personal/primary or openai/work/rotation-2026-08.
Add every rotated Key as a new record so history stays attributable. Do not overwrite an existing key ID. Choose a secret backend automatically unless the user named one:
keychainon macOS when available;filevault with mode0600elsewhere;opfor an explicitop://reference;envonly when an existing variable is the intended source.
python3 "$SKILL_DIR/scripts/env_manager.py" add \
--platform openai --account personal --key rotation-2026-08 \
--env-var OPENAI_API_KEY --backend auto \
--status standby --expires-at 2026-12-31
The command prompts without echo. For automation, pipe the value and add --secret-stdin; never place it in a shell argument.
Step 2: Maintain lifecycle and validity evidence
Read references/data-model.md before changing lifecycle fields.
active: eligible for a binding.standby: stored for rotation but not preferred.disabled: temporarily excluded.revoked: permanently excluded; keep metadata for audit history.- Effective health additionally accounts for
not_before,expires_at, and the latest validation result.
Use status for administrative state and probe for remote evidence. probe sends the Key only in an HTTPS header, blocks redirects, never stores a response body, and records only origin, status code, time, and redacted result.
python3 "$SKILL_DIR/scripts/env_manager.py" status \
openai/personal/rotation-2026-08 --status active
python3 "$SKILL_DIR/scripts/env_manager.py" probe \
openai/personal/rotation-2026-08 \
--url https://api.openai.com/v1/models --auth bearer
If a service cannot be probed generically, use mark-validation --result valid|invalid|unknown after a real platform-specific check and record a non-secret note.
Step 3: Bind exactly one Key per target variable
Bindings are independent for shell and system. The binding is the atomic switch point for multiple accounts and multiple keys.
python3 "$SKILL_DIR/scripts/env_manager.py" bind \
--target shell --env-var OPENAI_API_KEY \
openai/personal/rotation-2026-08
Reject expired, invalid, disabled, revoked, or not-yet-valid Keys. Only use --allow-unhealthy when the user explicitly accepts the reason and the resulting risk.
Step 4: Preview, apply, and verify environment projection
Read references/environment-targets.md. Every sync is a preview unless --apply is present.
python3 "$SKILL_DIR/scripts/env_manager.py" sync-shell --rcfile "$HOME/.zshenv"
python3 "$SKILL_DIR/scripts/env_manager.py" sync-shell --rcfile "$HOME/.zshenv" --apply
python3 "$SKILL_DIR/scripts/env_manager.py" audit
After applying zsh projection, verify in a new clean zsh process by checking presence or a fingerprint only; never print the value. sync-system targets the current user login session, not machine-wide state, and requires --acknowledge-process-env-risk --apply.
Step 5: Use the local Dashboard
python3 "$SKILL_DIR/scripts/env_manager.py" dashboard --open
The Dashboard shows accounts, effective health, expiry windows, validation age, and target bindings. It can switch bindings and update administrative or validation status, but adding, reading, exporting, or deleting secret values remains terminal-only. See references/dashboard.md.
Step 6: Report evidence
Report only:
- platform/account/key locators;
- variable names and selected targets;
- effective health, dates, validation age, and fingerprint when requested;
- files changed, their modes, backup path, and audit result;
- copyable
context_idfor errors.
Never report a raw Key, secret reference path, generated export content, or a command containing a secret.
CLI Summary
| Command | Outcome |
|---|---|
init |
Create the registry and secure storage directory |
add |
Add one platform/account/key record and secret source |
list, show |
Return redacted inventory and effective health |
status, mark-validation |
Maintain administrative and validation state |
probe |
Validate one Key through a guarded HTTPS request |
bind, unbind |
Select the only Key used by a target variable |
sync-shell |
Preview or update generated zsh exports and ~/.zshenv source block |
sync-system |
Preview or update current user session environment |
audit |
Detect unsafe permissions, dangling bindings, unhealthy selections, and expiry warnings |
dashboard |
Run the redacted local operations console |
All commands support --json. Mutating output names changed records but never secret values.
Dependencies
- Python 3.9+ standard library.
- Optional macOS
securitycommand for Keychain storage. - Optional 1Password CLI
opforop://secret references. - zsh for
sync-shell; macOSlaunchctlor Linuxsystemctl --userforsync-system.
Validation
python3 "$SKILL_DIR/scripts/validate_skill.py" "$SKILL_DIR"
python3 -m unittest discover -s "$SKILL_DIR/tests" -v
General feedback loop
When the user provides modification feedback during a Skill-driven task, before continuing the current artifact, you must perform:
- First determine whether the feedback is
task-specific(this time only) orreusable(reusable across tasks). task-specificOnly modify the current task, do not modify the Skill.reusableFirst determine the scope: for domain rules, update the corresponding canonical Skill first; for rules that apply to all Skills, update the shared specification first.- After completing the rule update, versioning, lint, and distribution verification, then apply the changes to the current task.
reusableModifications will invalidate previous "confirm," "continue," and "send it" instructions; after completing the current artifact modification and read-back, you must stop and wait for the user's next instruction, and do not automatically proceed to publishing, committing, or other external writes.