A Fish shell plugin for seamless 1Password secrets management with automatic loading and intelligent caching.
opah.fish is a Fish shell plugin that automatically loads secrets from 1Password into your shell environment variables. It features intelligent caching to minimize 1Password CLI calls and includes opah (a playful nod to the opah fish and the 1Password CLI op), a comprehensive CLI for managing your secrets.
Commit your dotfiles without committing your secrets.
When you manage your Fish shell configuration in git, you typically face a dilemma: either hardcode secrets directly (and risk committing them), use templating systems (adding complexity), or exclude configuration files from version control (losing the benefits of dotfile management).
opah.fish solves this by:
- Separating secrets from configuration - Your dotfiles contain only references to secrets, not the secrets themselves
- Enabling safe version control - Commit your entire Fish configuration to git without worrying about exposed credentials
- Eliminating templating complexity - No need for dotfile preprocessors or template systems
- Maintaining portability - The same configuration works across all your machines, with secrets fetched securely from 1Password
- π Automatic secret loading on shell startup
- πΎ Intelligent caching to avoid repeated 1Password authentication
- π¨ Beautiful CLI with modern UI and helpful diagnostics
- β‘ Selective refresh - update individual secrets without reloading everything
- π Comprehensive diagnostics with
opah doctor - π‘οΈ Secure - secrets are fetched directly from 1Password and cached locally
- Fish shell 3.0+
- 1Password CLI (
op)
fisher install tbcrawford/opah.fishomf install https://github.com/tbcrawford/opah.fishClone the repository to your Fish functions directory:
git clone https://github.com/tbcrawford/opah.fish.git ~/.config/fish/conf.d/opahCreate a configuration file at one of these locations (checked in order):
~/.config/fish/secrets.yaml(recommended)~/.config/fish/secrets.yml~/.config/fish/.secrets.yaml~/.config/fish/.secrets.yml~/.config/opah/secrets.yaml~/.config/opah/secrets.yml
secrets:
API_KEY: "op://vault/MyVault/API Keys/api_key"
DATABASE_URL: "op://vault/MyVault/Database/connection_string"
AWS_ACCESS_KEY_ID: "op://vault/AWS/Access Key"
AWS_SECRET_ACCESS_KEY: "op://vault/AWS/Secret Key"
GITHUB_TOKEN: "op://vault/GitHub/Personal Access Token"Each secret should use the 1Password secret reference URI format:
op://[vault]/[item]/[section]/[field]
The plugin includes opah, a comprehensive CLI for managing your 1Password secrets. The name is a playful reference to the opah fish and the 1Password CLI op.
opah <SUBCOMMAND> [OPTIONS]Show the status of cached secrets and configuration.
# Show all secrets status
opah status
# Show specific secret status
opah status API_KEYExample output:
π Cache file: ~/.cache/fish/opah/secrets.fish
βΉ Last updated: Sep 30 12:34:56 2025
βΉ Cached secrets: 5
Cached secrets:
API_KEY: β Cached & Loaded
DATABASE_URL: β Cached & Loaded
AWS_ACCESS_KEY_ID: β Cached & Loaded
Refresh secrets from 1Password, forcing a new fetch from the 1Password CLI.
# Refresh all secrets
opah refresh
# Refresh specific secret only
opah refresh DATABASE_URLThis command will:
- Re-authenticate with 1Password if needed
- Fetch the latest secret values
- Update the cache
- Load secrets into your current shell session
Clear all cached secrets and unset environment variables.
opah clearThis is useful when:
- You want to remove secrets from memory
- You're switching 1Password accounts
- You need to clean up before re-initialization
Show configuration file information and validate the format.
opah configExample output:
Checking configuration file locations:
β ~/.config/fish/secrets.yaml (FOUND)
β ~/.config/fish/secrets.yml
...
π Active configuration file: ~/.config/fish/secrets.yaml
βΉ Last modified: Sep 30 12:00:00 2025
Configuration validation:
β API_KEY: op://vault/MyVault/API Keys/api_key
β DATABASE_URL: op://vault/MyVault/Database/connection_string
β SOME_VAR: not_a_1password_ref (not a 1Password reference)
β Success! Configuration valid
βΉ Found 3 secret(s) defined
Run comprehensive diagnostics to validate your complete setup.
opah doctorThis command checks:
- β 1Password CLI installation and version
- β 1Password authentication status
- β Configuration file existence and validity
- β Cache system status
- β Fish shell integration
- β Core functions availability
Example output:
π Checking 1Password CLI...
β 1Password CLI (op) is installed
Version: 2.23.0
π Checking 1Password authentication...
β Signed in to 1Password
Accounts: user@example.com
π Checking configuration file...
β Configuration file found: ~/.config/fish/secrets.yaml
Format: Valid YAML with secrets section
1Password references: 5
π Checking cache system...
β Cache directory exists: ~/.cache/fish/opah
β Cache file exists: ~/.cache/fish/opah/secrets.fish
Last updated: Sep 30 12:34:56 2025
Cached secrets: 5
π Checking Fish shell integration...
β Running from functions directory
β Core functions are available
π Summary
ββββββββββββββββββββββββββββββ
β All systems operational!
Next steps:
Run 'opah refresh' to load secrets from 1Password
Run 'opah status' to verify loaded secrets
Re-initialize the plugin after authentication changes (e.g., switching 1Password accounts).
opah reinitThis command will:
- Clear existing cache and environment variables
- Check 1Password authentication (prompting if needed)
- Reload all secrets from configuration
Display help information.
opah helpAll subcommands also support the -h/--help flag:
opah status --help
opah refresh --help
opah clear --helpWhen you start a new Fish shell session, the plugin automatically:
- Checks for cached secrets in
~/.cache/fish/opah/secrets.fish - If cache exists and is valid, loads secrets from cache (fast!)
- If cache is missing, fetches secrets from 1Password using the CLI
- Stores fetched secrets in cache for future sessions
- Exports secrets as environment variables
- Cache location:
~/.cache/fish/opah/secrets.fish - Cache format: Fish shell script with
set -gxcommands - Cache invalidation: Manual (use
opah refreshoropah clear) - Selective updates: Refresh individual secrets with
opah refresh SECRET_NAME
This approach minimizes authentication prompts while keeping your secrets secure and up-to-date.
The plugin includes intelligent tab completion for the opah command:
- Subcommand completion
- Secret name completion for
statusandrefresh - Help flag completion for all subcommands
Try typing opah <TAB> or opah refresh <TAB> to see it in action!
Update a single secret without refreshing everything:
opah refresh DATABASE_URLThis is perfect when:
- You've rotated a single credential
- You want to test a specific secret reference
- You don't want to re-fetch all secrets
Since secrets are loaded as environment variables, they're available to all commands:
# Use in scripts
echo $DATABASE_URL
# Pass to commands
psql $DATABASE_URL
# Use in config files
export DATABASE_URL # Already exported by opah!Want to skip automatic loading in certain scenarios? You can disable the auto-load by removing or commenting out the conf.d/opah.fish file.
-
Cache storage: Cached secrets are stored in plain text in
~/.cache/fish/opah/secrets.fish- Ensure your home directory has appropriate permissions
- Consider encrypting your home directory
- Use
opah clearwhen done with a session on shared machines
-
Environment variables: Secrets are stored as global environment variables
- They're available to all processes started from your shell
- They may appear in process listings
- Clear them with
opah clearwhen working with untrusted code
-
1Password CLI: The plugin relies on 1Password CLI's authentication
- Use biometric unlock when available
- Set appropriate session timeouts in 1Password settings
Run diagnostics:
opah doctorSign in manually:
op signinOr let opah handle it:
opah refresh # Will prompt for authentication if neededCheck your configuration file location:
opah configCreate a configuration file if needed:
mkdir -p ~/.config/fish
touch ~/.config/fish/secrets.yamlValidate your configuration:
opah configMake sure your secret references follow the format:
op://[vault]/[item]/[section]/[field]
Clear and rebuild the cache:
opah reinitHere's a typical workflow for using opah.fish:
# 1. Initial setup
opah doctor # Check your setup
# 2. First-time load
opah refresh # Fetch secrets from 1Password
opah status # Verify secrets are loaded
# 3. Daily usage
# Secrets automatically load on shell startup!
# 4. When a secret changes
opah refresh DATABASE_URL # Update just one secret
# 5. When switching contexts
opah clear # Clear secrets
opah reinit # Re-initialize with new contextContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- Named after the opah fish, continuing the aquatic theme of Fish shell
- Built on top of the excellent 1Password CLI
- Inspired by the Fish shell community's focus on user-friendly tooling
Made with π by @tbcrawford
