This document outlines security best practices for using fern safely.
- API Key Management
- Separate Secrets File Setup
- File Permissions
- Version Control Safety
- Advanced Options
- Security Checklist
- NEVER commit API keys to version control
- NEVER hardcode keys in Lua config files
- ALWAYS use environment variables
- ALWAYS secure your secrets file with proper permissions
Keeping API keys in a separate file offers several advantages:
- Isolation: Keys are isolated from general configuration
- Portability: Share dotfiles publicly without exposing secrets
- Manageability: One place to manage all sensitive credentials
- Gitignore-friendly: Easy to exclude from version control
- Multiple environments: Different keys for dev/prod without config changes
Use the provided setup script:
# Run the interactive setup
./setup-api-key.sh
# Follow the prompts to:
# 1. Create ~/.env.secrets
# 2. Set proper permissions (600)
# 3. Add API key
# 4. Update shell config to source the file# Create the file
touch ~/.env.secrets
# Verify it was created
ls -la ~/.env.secretsCritical: Set restrictive permissions immediately:
# Only you can read/write this file
chmod 600 ~/.env.secrets
# Verify permissions
ls -la ~/.env.secrets
# Should show: -rw------- (600)# Option A: Use echo (be careful with shell history)
echo 'export CURSOR_API_KEY="your_api_key_here"' >> ~/.env.secrets
# Option B: Edit manually (more secure)
vim ~/.env.secrets
# or
nano ~/.env.secrets
# Add this line:
# export CURSOR_API_KEY="your_actual_api_key"For zsh (macOS/Linux default):
# Add to ~/.zshrc
echo '# Source environment secrets' >> ~/.zshrc
echo '[ -f ~/.env.secrets ] && source ~/.env.secrets' >> ~/.zshrc
# Reload
source ~/.zshrcFor bash:
# Add to ~/.bashrc
echo '# Source environment secrets' >> ~/.bashrc
echo '[ -f ~/.env.secrets ] && source ~/.bashrc' >> ~/.bashrc
# Reload
source ~/.bashrc# Check variable is set
echo $CURSOR_API_KEY
# Open a NEW terminal window and check again
echo $CURSOR_API_KEY
# Test in Neovim
nvim -c "checkhealth fern" -c "qa"The 600 permission means:
6(owner): read (4) + write (2) = 60(group): no permissions0(others): no permissions
ls -la ~/.env.secretsExpected output:
-rw------- 1 username staff XX bytes date .env.secrets
If permissions are too open:
# Fix it immediately
chmod 600 ~/.env.secrets
# Verify
ls -la ~/.env.secretsLoose permissions (e.g., 644 or 755) allow other users on your system to read your API keys. Always use 600 for sensitive files.
The project .gitignore already includes:
# Environment secrets (API keys, tokens)
.env.secrets
*.env.local
.env.*.localIf you version control your home directory dotfiles:
# Add to your dotfiles .gitignore
cd ~ # or wherever your dotfiles repo is
echo '.env.secrets' >> .gitignore
echo '*.env.local' >> .gitignore
# Verify secrets file won't be tracked
git status # .env.secrets should not appear
# If it appears in git status:
git rm --cached ~/.env.secrets # Remove from git indexAlways check before committing:
# Search for potential API keys in staged files
git diff --cached | grep -i "api_key"
git diff --cached | grep -i "cursor_api"
# Check what files are staged
git status
# If secrets file appears, remove it
git reset ~/.env.secretsFor maximum security, use a password manager:
# Install 1Password CLI
brew install --cask 1password-cli
# Sign in
eval $(op signin)
# Store your key in 1Password, then in ~/.env.secrets:
echo 'export CURSOR_API_KEY=$(op read "op://Personal/Cursor API/credential")' >> ~/.env.secrets# Install pass
brew install pass # macOS
# or
apt install pass # Linux
# Initialize pass (one-time setup)
pass init your-gpg-id
# Store your API key
pass insert cursor-api-key
# In ~/.env.secrets:
echo 'export CURSOR_API_KEY=$(pass show cursor-api-key)' >> ~/.env.secrets# Install Bitwarden CLI
brew install bitwarden-cli
# Login
bw login
# In ~/.env.secrets:
echo 'export CURSOR_API_KEY=$(bw get password "Cursor API")' >> ~/.env.secretsManage different keys for different environments:
# In ~/.env.secrets
if [ "$ENVIRONMENT" = "production" ]; then
export CURSOR_API_KEY="prod_key_here"
else
export CURSOR_API_KEY="dev_key_here"
fiIf you use multiple AI services:
# In ~/.env.secrets
export CURSOR_API_KEY="your_cursor_key"
export OPENAI_API_KEY="your_openai_key"
export ANTHROPIC_API_KEY="your_anthropic_key"Before using fern, verify:
- API key is in
~/.env.secrets, not in Lua config -
~/.env.secretshas600permissions -
.env.secretsis in.gitignore(both project and dotfiles) - Shell config sources
~/.env.secretson startup - Environment variable is set:
echo $CURSOR_API_KEYreturns value - New terminal sessions have the variable set
-
:checkhealth fernpasses all checks - No API keys appear in git history:
git log -p | grep -i api_key
- Test the plugin with a simple request
- Check logs don't contain sensitive data:
~/.cache/nvim/fern.log - Verify the plugin warns if key is hardcoded (test by temporarily adding to config)
- Rotate API keys periodically
- Review file permissions regularly
- Check
.gitignoreeffectiveness before commits - Audit shell history for exposed keys:
history | grep -i api_key
If you accidentally commit your API key:
- Immediately revoke the key in your Cursor account
- Generate a new API key
- Update
~/.env.secretswith the new key - Remove from git history:
# Use BFG Repo-Cleaner or git-filter-repo # DO NOT use git filter-branch (it's deprecated) # With git-filter-repo: git filter-repo --invert-paths --path .env.secrets # Force push (WARNING: rewrites history) git push --force
- Notify your team if this is a shared repository
- Review access logs in your Cursor account
If you find a security issue, please report it responsibly. Do not open a public issue. Contact the maintainers directly.