crumb is a command line tool designed to securely store, manage, and export API keys and secrets for developers. It uses age encryption with SSH public/private key pairs, and supports both local file storage and S3-compatible backends (AWS S3, MinIO, LocalStack).
crumb is inspired by tools such as:
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 load secrets without leaving ecrets unencrypted on disk.
crumb keeps all your secrets inside a single file encryped with an ssh key.
When getting on your secrets, crumb loads the file into memory, decrypts the payload, creates, retrieves or updates secrets, and, if necessary, encrypts the changes back to the store. Each secret is referenced by a path.
# 1. Install crumb
kelp add crhuber/crumb --install
# 2. Initialize your secret store (uses your existing SSH keys)
crumb setup
# 3. Store a secret
crumb set /myapp/api_key
# Enter secret value: [hidden]
# 4. Retrieve it
crumb get /myapp/api_key
# 5. Export secrets as environment variables
eval "$(crumb export --path /myapp)"- SSH Key Encryption/Decryption: Securely encrypt your password storage file using SSH Keys
- S3 Storage Backend: Store encrypted secrets in AWS S3 or S3-compatible services (MinIO, LocalStack)
- Bulk Export: Exports multiple secrets from an entire path like
/myapp/dev/ - Multi-Profile Support: Manage separate secret stores for work, personal, or different projects
- .env Import: Import multiple secrets from
.envfiles - Shell Integration: Automatic secret loading with shell hooks (bash, zsh, fish)
- Download and add binary to $PATH from https://github.com/crhuber/crumb/releases
OR
- Use kelp
kelp add crhuber/crumb --installThe setup command initializes the secure storage backend for a specific profile.
crumb setup [--profile <profile-name>]Before running setup, you need to have SSH keys generated. If you don't have them, create them with:
# For Ed25519 keys (recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"Default setup:
$ crumb setupSetup with S3 storage:
$ crumb setup --storage s3 --s3-bucket my-secrets-bucket --s3-key /crumb/secretsSetup with non default profile
$ crumb --profile work setupThe set command adds or updates a secret key-value pair. The value is entered securely on a new line and is not echoed to the terminal or stored in shell history.
crumb set <key-path># Add a new secret
$ crumb set /myapp/api_key
Enter secret value: [secret not shown]
Successfully set key: /myapp/api_key
# Update an existing secret (with confirmation)
$ crumb set /myapp/api_key
Key '/myapp/api_key' already exists.
key already exists. Overwrite? (y/n): y
Enter secret value: [secret not shown]
Successfully set key: /myapp/api_keyThe ls command lists all stored secret keys, optionally filtered by path.
crumb ls [path]# List all secrets
$ crumb ls
/myapp/dev/api_key
# Filter by path prefix
$ crumb ls /myapp
/myapp/api_key
/myapp/secretThe get command retrieves a secret by its key path.
crumb get <key-path> [--mask] [--export] [--shell=bash|fish]# Get a secret
$ crumb get /myapp/api_key
secret123
# Get a secret masked
$ crumb get /myapp/api_key --mask
****
# Export a secret for bash sourcing
$ crumb get /myapp/api_key --export
export API_KEY=secret123
# Export a secret for fish shell
$ crumb get /myapp/api_key --export --shell fish
set -x API_KEY secret123
# Source the export directly in bash
$ eval "$(crumb get /myapp/api_key --export)"
$ echo $API_KEY
secret123When 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:
/myapp/my-service/auth-token→AUTH_TOKEN
The --export flag makes it easy to integrate secrets into shell scripts and workflows:
Bash:
# Source a single secret
eval "$(crumb get /myapp/key --export)"
echo "Key: $KEY"
# Source multiple secrets in a script
#!/bin/bash
eval "$(crumb get /myapp/ --export)"Fish:
# Source a single secret
eval (crumb get /myapp/key --export --shell fish)
# Source multiple secrets
eval (crumb get /myapp/ --export --shell fish)The init command creates a YAML configuration file in the current project directory.
crumb init# Create a new .crumb.yaml file
$ crumb init
Successfully created .crumb.yaml
#### Default Configuration Structure
The created `.crumb.yaml` file contains:
```yaml
version: "1.0"
environments:
default:
path: ""
remap: {}
env: {}This structure allows you to configure multiple environments, each with:
path: A path to sync secrets from (e.g.,/myapp/api-key)remap: Key remapping for environment variablesenv: Individual environment variable configurations
You can add additional environments for different deployment contexts:
version: "1.0"
environments:
default:
path: "/myapp/dev/"
remap: {}
env: {}
production:
path: "/myapp/prod/"
remap: {}
env: {}export MY_KEY=******The delete command deletes a secret key-value pair from the encrypted file.
crumb delete <key-path># Delete a secret (with confirmation)
$ crumb delete /myapp/dev/api_key
Type the key path to confirm deletion: /myapp/dev/api_key
Successfully deleted key: /myapp/dev/api_keyThe move (or mv) command renames a secret key to a new path, preserving its value. This is useful for reorganizing or refactoring your secret key structure without losing data.
crumb move <old-key-path> <new-key-path>
# or using the alias
crumb mv <old-key-path> <new-key-path>The import command allows you to import multiple secrets from a .env file into your encrypted storage. This is particularly useful when migrating from .env files to Crumb or when setting up a new project with existing environment variables.
crumb import --file <path-to-env-file> --path <destination-path>The import command supports standard .env file formats:
# Comments are ignored
API_KEY=secret123
DATABASE_URL="postgresql://localhost:5432/mydb"
DEBUG=trueBasic import:
# Import to /myapp/dev path
$ crumb import --file .env --path /myapp/dev/
# Verify the imported secrets
$ crumb ls /myapp/dev/Using with different profiles:
# Import to work profile
$ crumb --profile work import --file work.env --path /work/secrets/The storage command provides subcommands to manage storage file paths for profiles.
Set the storage file path for the current profile:
crumb storage set <path> [--profile <profile-name>]Example:
# Set storage path for work profile
$ crumb --profile work storage set ~/.config/crumb/work-secrets
# Set storage path for default profile
$ crumb storage set ~/personal-secretsShow 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)You can maintain separate secret stores for different contexts (work, personal, projects):
# Set up different profiles
crumb --profile work setup
# Add secrets to different profiles
crumb --profile work set /myapp/key
# Enter "work-secret" when prompted
# List secrets by profile
crumb --profile work ls
# Set default profile via environment variable
export CRUMB_PROFILE=work
crumb ls # Lists work profile secretsThe export command exports secrets as shell-compatible environment variable assignments. It supports two modes:
- Config-based export: Uses a
.crumb.yamlconfiguration file (traditional mode) - Direct path export: Exports all secrets from a specific path without requiring a config file (new!)
# Config-based export
crumb export [-f config-file] [--env environment] [--shell=bash|fish] [--profile <profile-name>]
# Direct path export
crumb export --path <secret-path> [--shell=bash|fish] [--profile <profile-name>]First, create a .crumb.yaml configuration file:
version: "1.0"
environments:
default:
path: "/myapp/dev/"
remap: {}
env: {}Then export the secrets:
# Export default environment
$ crumb export
# Export staging environment
$ crumb export --env staging
# Export for fish shell
$ crumb export --shell fish
# Use a custom config file
$ crumb export -f my-project.yaml
# Use custom config file
$ crumb export --file my-project.yaml --shell fish
# Export from work profile
$ crumb export --profile work
# Use environment variable for profile
$ CRUMB_PROFILE=work crumb export --shell=fish
# Source the output directly
$ eval "$(crumb export)"
#### Direct Path Export Examples
The `--path` flag allows you to export secrets directly without a `.crumb.yaml` file:
```bash
# Export all secrets from /api path
$ crumb export --path /myapp/dev/
# Export with fish shell format
$ crumb export --path /myapp/dev/ --shell fish
# Use with different profile
$ crumb export --path /myapp/dev/ --profile work
# Source directly into shell
$ eval "$(crumb export --path /myapp/)"Path to Variable Name Conversion:
- Only the final segment (actual secret name) is used, intermediate path segments are ignored
- Hyphens in the secret name are converted to underscores, and the result is uppercase mgsecret
You can change what finally gets exported to shell by using the remap section within an environment:
version: "1.0"
environments:
default:
path: "/myapp/dev/"
remap:
"FROM": "TO"For example:
version: "1.0"
environments:
default:
path: "/myapp/dev/"
remap:
"SOME_SECRET_KEY": "MY_KEY"will result in SOME_SECRET_KEY being exported as MY_KEY
Say you want to also export a variable that isnt in your secrets file you can do so by adding it in the env key.
environments:
default:
...
env:
MESSAGE: "Hello staging"If you want to load a single secret from a key you can do it like this:
environments:
default:
...
env:
API_KEY: "/myapp/staging/api_key"The hook command generates shell integration scripts that automatically load secrets when you enter a directory containing a .crumb.yaml file. This provides seamless, automatic environment variable management similar to direnv.
crumb hook <shell>Supported shells:
bashzshfish
Add the following to your shell's configuration file:
Bash (~/.bashrc or ~/.bash_profile):
eval "$(crumb hook --shell bash)"Zsh (~/.zshrc):
eval "$(crumb hook --shell zsh)"Fish (~/.config/fish/config.fish):
crumb hook --shell fish | sourceOnce the hook is installed:
- When you enter a directory containing a
.crumb.yamlfile, the hook automatically runscrumb export - The secrets defined in
.crumb.yamlare loaded as environment variables - When you leave the directory, the environment variables remain (they are not automatically unloaded)
# 1. Create a project with secrets
$ mkdir myapp && cd myapp
$ crumb init
# 2. Edit .crumb.yaml to configure your secrets
$ cat > .crumb.yaml << EOF
version: "1.0"
environments:
default:
path: "/myapp/dev"
env: {}
remap: {}
EOF
# 3. Add some secrets to crumb
$ crumb set /myapp/dev/API_KEY
Enter secret value: ********
$ crumb set /myapp/dev/DATABASE_URL
Enter secret value: ********
# 4. With the hook installed, cd into the directory
$ cd myapp
# Secrets are automatically loaded!
$ echo $API_KEY
your-api-key-value
$ echo $DATABASE_URL
your-database-url- The hook checks for
.crumb.yamlin the current directory only (not parent directories) - Errors from
crumb exportare silently suppressed (redirected to/dev/null) - The hook preserves the exit status of the previous command (important for bash prompt functions)
- For bash/zsh, the hook runs on each prompt display and directory change
- For fish, the hook runs on PWD changes and prompt events
~/.config/crumb/config.yaml - Stores profile configurations with SSH key paths and storage locations.
Multi-profile structure:
profiles:
default:
public_key_path: ~/.ssh/id_ed25519.pub
private_key_path: ~/.ssh/id_ed25519
storage:
local:
path: ~/.config/crumb/secrets
work:
public_key_path: ~/.ssh/work.pub
private_key_path: ~/.ssh/work
storage:
local:
path: ~/.config/crumb/work-secretsEach profile has its own encrypted storage file:
- Default profile:
~/.config/crumb/secrets(unless customized) - Named profiles: Configurable per profile (e.g.,
~/.config/crumb/work-secrets)
~/.config/crumb/crumb.toml - Optional TOML configuration file for user preferences.
Shell configuration:
shell = "bash". # Supported values: "bash", "fish", "zsh". Default: "bash"
mask_values = truePriority order for shell configuration:
- Command-line flag (e.g.,
crumb hook --shell fish) - TOML config file (
~/.config/crumb/crumb.toml) - Default value (
bash)
This project uses Task for build automation. Common tasks:
task test- Run all teststask test-coverage- Run tests with coverage reporttask bench- Run benchmark teststask build- Build the applicationtask ci- Run CI pipelinetask clean- Clean build artifactstask --list- Show all available tasks
If you find bugs, please open an issue first.