This guide covers how to manage API keys, tokens, and other secrets without committing them to version control.
Create a secrets file that fish will source on startup:
touch ~/.config/fish/conf.d/secrets.fish
chmod 600 ~/.config/fish/conf.d/secrets.fishAdd your secrets:
# ~/.config/fish/conf.d/secrets.fish
set -gx API_NINJAS_KEY "your-api-key-here"
set -gx GITHUB_TOKEN "ghp_xxxxxxxxxxxx"
set -gx OPENAI_API_KEY "sk-xxxxxxxxxxxx"Important: This file is in conf.d/ which is symlinked from your dotfiles. To keep secrets out of git, either:
- Add it to
.gitignore - Create it at
~/.secrets.fishinstead (outside the dotfiles repo)
# Create secrets file outside dotfiles
touch ~/.secrets.fish
chmod 600 ~/.secrets.fish
# Edit with your secrets
nvim ~/.secrets.fishThe config.fish already sources this file if it exists.
Add to your .gitignore:
config/.config/fish/conf.d/secrets.fish
Then create the file normally.
pass is a simple, GPG-encrypted password manager.
# Install pass
brew install pass gnupg
# Generate a GPG key if you don't have one
gpg --full-generate-key
# Initialize pass with your GPG key ID
pass init "your-email@example.com"# Store API keys
pass insert api-ninjas/key
pass insert github/token
pass insert openai/api-keyAdd to ~/.config/fish/conf.d/secrets.fish:
# Load secrets from pass (requires GPG agent)
if command -q pass
set -gx API_NINJAS_KEY (pass api-ninjas/key 2>/dev/null)
set -gx GITHUB_TOKEN (pass github/token 2>/dev/null)
set -gx OPENAI_API_KEY (pass openai/api-key 2>/dev/null)
endTo avoid repeated passphrase prompts, configure gpg-agent:
mkdir -p ~/.gnupg
cat > ~/.gnupg/gpg-agent.conf << 'EOF'
default-cache-ttl 3600
max-cache-ttl 86400
pinentry-program /opt/homebrew/bin/pinentry-mac
EOF
# Restart gpg-agent
gpgconf --kill gpg-agentInstall pinentry-mac for a native macOS passphrase dialog:
brew install pinentry-macUse the native macOS Keychain for secrets.
security add-generic-password -a "$USER" -s "api-ninjas-key" -w "your-api-key"set -gx API_NINJAS_KEY (security find-generic-password -s "api-ninjas-key" -w 2>/dev/null)# ~/.config/fish/conf.d/secrets.fish
if test (uname -s) = Darwin
set -gx API_NINJAS_KEY (security find-generic-password -s "api-ninjas-key" -w 2>/dev/null)
set -gx GITHUB_TOKEN (security find-generic-password -s "github-token" -w 2>/dev/null)
endIf you use 1Password, their CLI integrates well with shell environments.
brew install 1password-cli
# Sign in
op signinset -gx API_NINJAS_KEY (op read "op://Private/API Ninjas/credential" 2>/dev/null)| Variable | Used By | Description |
|---|---|---|
API_NINJAS_KEY |
inspiration/quote-fetch.sh |
API key for api-ninjas.com quotes |
- Never commit secrets - Always check
git diffbefore committing - Use restrictive permissions -
chmod 600on secret files - Rotate keys regularly - Especially if you suspect exposure
- Use different keys per environment - Dev vs production
- Audit access - Check which apps/scripts use each secret
# Check if agent is running
gpg-connect-agent /bye
# Restart agent
gpgconf --kill gpg-agent
gpg-agent --daemon# List all stored passwords
pass ls
# Check GPG key
gpg --list-secret-keys# Re-add with explicit access
security delete-generic-password -s "api-ninjas-key"
security add-generic-password -a "$USER" -s "api-ninjas-key" -w "your-key"