crumb is a command line tool designed to securely store, manage, and export API keys and secrets for developers. It uses an encrypted plain text file as the backend, leveraging the age encryption library with SSH public/private key pairs for encryption and decryption.
but, designed for the non-enterprise developer without access to a cloud Secrets Manager, raft storage, etc. Crumb was born out of the need to be able to switch secrets between different projects, without leaving project secrets unencrypted on disk.
$ crumb setup
Enter path to SSH public key (e.g., ~/.ssh/id_ed25519.pub): ~/.ssh/id_ed25519.pub
Enter path to SSH private key (e.g., ~/.ssh/id_ed25519): ~/.ssh/id_ed25519
Setup completed successfully for profile 'default'!
Config file: /Users/username/.config/crumb/config.yaml
Storage file: /Users/username/.config/crumb/secrets
Work profile setup:
$ crumb --profile work setup
Enter path to SSH public key (e.g., ~/.ssh/work.pub): ~/.ssh/work.pub
Enter path to SSH private key (e.g., ~/.ssh/work): ~/.ssh/work
Enter storage file path (e.g., ~/.config/crumb/secrets-work): ~/.config/crumb/work-secrets
Setup completed successfully for profile 'work'!
Config file: /Users/username/.config/crumb/config.yaml
Storage file: /Users/username/.config/crumb/work-secrets
The ls command lists all stored secret keys, optionally filtered by path.
This command:
Decrypts the secrets file using the private key
Displays all secret keys (not values) in sorted order
Supports optional path filtering with partial matching
Treats trailing slashes as equivalent (e.g., /any/ vs /any)
# List all secrets
$ crumb ls
/any/other/mykey
/any/path/mykey
/prod/api_key
/prod/auth-svc/secret
/prod/billing-svc/api_key
/test/mykey
# Filter by path prefix
$ crumb ls /prod
/prod/api_key
/prod/auth-svc/secret
/prod/billing-svc/api_key
# Filter with partial matching
$ crumb ls /any
/any/other/mykey
/any/path/mykey
# No secrets found
$ crumb ls /nonexistent
No secrets found matching path: /nonexistent
# Empty secrets file
$ crumb ls
No secrets found
The set command adds or updates a secret key-value pair.
crumb set<key-path><value>
This command:
Validates the key path (must start with /, no spaces or special characters)
Decrypts the secrets file using the private key
Checks if the key already exists and prompts for confirmation if it does
Adds or updates the key-value pair
Re-encrypts and saves the secrets file
# Add a new secret
$ crumb set /prod/api_key secret123
Successfully set key: /prod/api_key
# Update an existing secret (with confirmation)
$ crumb set /prod/api_key newsecret456
Key '/prod/api_key' already exists with value: secret123
key already exists. Overwrite? (y/n): y
Successfully set key: /prod/api_key
# Invalid key path examples
$ crumb set invalid_key value
Error: key path must start with '/'
$ crumb set"/test/key with spaces" value
Error: key path cannot contain spaces
The get command retrieves a secret by its key path.
crumb get <key-path> [--show] [--export] [--shell=bash|fish]
This command:
Validates the key path (must start with /, no spaces or special characters)
Decrypts the secrets file using the private key
By default, displays **** to mask the value
Supports --show flag to display the actual secret value
Supports --export flag to output in shell-compatible format for sourcing
Supports --shell flag to select output format when using --export (bash or fish, defaulting to bash)
When --export is used, --show is ignored and the secret value is always displayed
Requires a full key path (partial paths are not supported)
# Get a secret (masked value)
$ crumb get /prod/api_key
****# Get a secret with actual value
$ crumb get /prod/api_key --show
secret123
# Export a secret for bash sourcing
$ crumb get /prod/api_key --export
export PROD_API_KEY=secret123
# Export a secret for fish shell
$ crumb get /prod/api_key --export --shell fish
set -x PROD_API_KEY secret123
# Export with complex key path
$ crumb get /api/my-service/auth-token --export
export API_MY_SERVICE_AUTH_TOKEN=token123
# Source the export directly in bash
$ eval"$(crumb get /prod/api_key --export)"
$ echo$PROD_API_KEY
secret123
# Key not found
$ crumb get /nonexistent/key
Key not found.
# Invalid key path
$ crumb get invalid_key
Error: key path must start with '/'
$ crumb get "/test/key with spaces"
Error: key path cannot contain spaces
#### Variable Name Conversion
When using the `--export` flag, the key path is automatically converted to a valid environment variable name:
- Leading slash (`/`) is removed
- Remaining slashes (`/`) are converted to underscores (`_`)
- Hyphens (`-`) are converted to underscores (`_`)
- The result is converted to uppercase
Examples:
- `/api/key` → `API_KEY`
- `/prod/my-service/auth-token` → `PROD_MY_SERVICE_AUTH_TOKEN`
- `/billing-svc/vars/mg` → `BILLING_SVC_VARS_MG`#### Shell Integration
The `--export` flag makes it easy to integrate secrets into shell scripts and workflows:
**Bash:**```bash# Source a single secreteval"$(crumb get /api/key --export)"echo"API Key: $API_KEY"# Source multiple secrets in a script#!/bin/basheval"$(crumb get /prod/database-url --export)"eval"$(crumb get /prod/api-key --export)"eval"$(crumb get /prod/stripe-secret --export)"# Now use the environment variablespsql "$PROD_DATABASE_URL" -c "SELECT COUNT(*) FROM users;"curl -H "Authorization: Bearer $PROD_API_KEY" https://api.example.com/
Fish:
# Source a single secreteval (crumb get /api/key --export--shell fish)
echo"API Key: $API_KEY"# Source multiple secretseval (crumb get /prod/database-url --export--shell fish)
eval (crumb get /prod/api-key --export--shell fish)
The init command creates a YAML configuration file in the current directory.
This command:
Creates a .crumb.yaml file in the current directory
Uses a default structure with empty configuration
Prompts for confirmation if the file already exists
Validates the YAML structure before writing
# Create a new .crumb.yaml file
$ crumb init
Successfully created .crumb.yaml
# File already exists (with confirmation)
$ crumb init
Config file .crumb.yaml already exists. Overwrite? (y/n): y
Successfully created .crumb.yaml
# Reject overwrite
$ crumb init
Config file .crumb.yaml already exists. Overwrite? (y/n): n
Operation cancelled.
Default Configuration Structure
The created .crumb.yaml file contains:
version: "1.0"path_sync:
path: ""remap: {}env: {}
This structure allows you to configure:
path_sync.path: A path to sync secrets from (e.g., /prod/billing-svc)
path_sync.remap: Key remapping for environment variables
# Set storage path for work profile
$ crumb --profile work storage set~/.config/crumb/work-secrets
Storage path set to: /Users/username/.config/crumb/work-secrets (profile: work)
# Set storage path for default profile
$ crumb storage set~/personal-secrets
Storage path set to: /Users/username/personal-secrets (profile: default)
Show the current storage file path for the current profile:
crumb storage get [--profile <profile-name>]
Example:
# Check storage path for work profile
$ crumb --profile work storage get
Storage: /Users/username/.config/crumb/work-secrets (profile: work)
# Check storage path for default profile
$ crumb storage get
Storage: /Users/username/.config/crumb/secrets (profile: default)
Clear the storage file path for the current profile (reverts to default):
crumb storage clear [--profile <profile-name>]
Example:
# Clear custom storage path for work profile
$ crumb --profile work storage clear
Storage path cleared for profile: work (using default)
# Verify it's using default path
$ crumb --profile work storage get
Storage: /Users/username/.config/crumb/secrets (profile: work)
You can maintain separate secret stores for different contexts (work, personal, projects):
# Set up different profiles
crumb --profile work setup
crumb --profile personal setup
crumb --profile project-x setup
# Add secrets to different profiles
crumb --profile work set /api/key "work-secret"
crumb --profile personal set /github/token "personal-token"
crumb --profile project-x set /db/password "project-password"# List secrets by profile
crumb --profile work ls
crumb --profile personal ls
crumb --profile project-x ls
Using Environment Variables
# Set default profile via environment variableexport CRUMB_PROFILE=work
crumb ls # Lists work profile secrets# Override storage path temporarilyexport CRUMB_STORAGE=~/temp-secrets
crumb set /temp/key "temporary value"
# Use a specific profile for one command
crumb --profile work get /api/key
# Override storage path for one command
crumb --storage ~/backup-secrets ls
# Combine profile and storage overrides
crumb --profile work --storage ~/work-backup get /api/key
Work and Personal Separation
# Set up work profile with company SSH keys
crumb --profile work setup
# Enter work SSH key paths when prompted# Set up personal profile with personal SSH keys
crumb --profile personal setup
# Enter personal SSH key paths when prompted# Add work secrets
crumb --profile work set /company/api-key "work-secret-123"
crumb --profile work set /company/db-password "work-db-pass"# Add personal secrets
crumb --profile personal set /github/token "ghp_personal123"
crumb --profile personal set /aws/access-key "personal-aws-key"# List work secrets only
crumb --profile work ls
# List personal secrets only
crumb --profile personal ls
# Use environment variable for default profileexport CRUMB_PROFILE=work
crumb get /company/api-key # Uses work profile# Export individual secrets for sourcingeval"$(crumb --profile work get --export /company/api-key)"eval"$(crumb --profile work get --export /company/db-password)"echo$COMPANY_API_KEYecho$COMPANY_DB_PASSWORD
# Create a backup of work secrets to a different location
crumb --profile work --storage ~/backups/work-secrets-backup ls
# This will show empty since backup doesn't exist yet# Copy secrets by exporting and re-importing (manual process)
crumb --profile work ls # Note the keys you want to backup# Temporarily use backup storage to set up new secrets
crumb --profile work --storage ~/backups/work-secrets-backup set /api/key "$(crumb --profile work get --show /api/key)"# Switch work profile to use backup storage permanently
crumb --profile work storage set~/backups/work-secrets-backup
The export command exports secrets as shell-compatible environment variable assignments based on the .crumb.yaml config file.
You need to migrate it to the new profile-based format. Run crumb setup to create a new profile-based configuration, or manually update your ~/.config/crumb/config.yaml to: