From dev-tools
Store a secret (API key, token, password) in the macOS Keychain and wire it up as an environment variable in .zshrc. Use this skill whenever the user wants to store a secret, API key, or token securely, add a keychain secret, store credentials for a project, or asks how to keep a key out of dotfiles/code. Trigger phrases: 'store this key', 'add to keychain', 'save this secret', 'store API key', 'add secret'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dev-tools:store-secretThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Store secrets in the macOS Keychain so they never appear in dotfiles, shell history, or chat logs. The secret itself must always be entered by the user directly in their terminal — never typed in chat, never passed through a Claude tool call.
Store secrets in the macOS Keychain so they never appear in dotfiles, shell history, or chat logs. The secret itself must always be entered by the user directly in their terminal — never typed in chat, never passed through a Claude tool call.
read -s pattern is preferred — it suppresses echo and clears the variable after use.Use AskUserQuestion to gather:
ANTHROPIC_API_KEY, GITHUB_TOKEN). Convention: uppercase, matches the env var name.$USER (their macOS username). Confirm if there's a reason to use something else..zshrc on every new shell? (Usually yes.)Output this block for the user to run in their terminal. Replace SERVICE_NAME with the actual name:
read -s -p "Paste key (input hidden): " K \
&& security add-generic-password -s "SERVICE_NAME" -a "$USER" -w "$K" -U \
&& unset K \
&& echo "Stored."
Explain the flags:
read -s — suppresses echo, key never appears on screen-U — updates the entry if it already exists (safe to re-run)unset K — clears the variable from shell memory immediately after storingsecurity find-generic-password -s "SERVICE_NAME" -a "$USER" -w
This should print the key. If it returns nothing or errors, the store failed.
Secrets are loaded from ~/.config/dotfiles/zsh/secrets.zsh, which is sourced by .zshrc. This file has two parts
to update:
# ENV_VAR_NAME ENV_VAR_NAME Short description of purpose
_keychain_export line inside the if [[ "$OSTYPE" == darwin* ]] block, before
unfunction _keychain_export: _keychain_export SERVICE_NAME
The _keychain_export helper only sets the env var if the Keychain entry exists — no empty-string exports on
machines where the secret hasn't been created yet.
Then tell the user to reload their shell:
source ~/.zshrc
echo ${SERVICE_NAME:0:10}...
Prints only the first 10 characters — enough to confirm it loaded, not enough to expose it.
If the project uses a devcontainer, the env var will be available in the container automatically as long as docker-compose.yml passes it through:
environment:
- SERVICE_NAME
The var is set on the host shell before dev up, so it flows in without ever being hardcoded.
npx claudepluginhub noah-goodrich/claude-plugins --plugin dev-toolsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.