pw is a command-line password manager unifying trusted password managers
like macOS Keychain,
KeePassXC and GnuPG in a single terminal interface.
It combines the security of your favourite password managers with the speed and
simplicity of the fzf fuzzy finder and allows
you to interact with multiple keychains effortlessly.
- Built on Proven Tools: Combines reliable and established password managers into one interface.
- Efficiency: Rapid interaction via fzf.
- Simplicity: Pure bash β easy to understand, modify, and extend.
- Extensibility: Add plugins for your preferred password managers in minutes (see plugins).
- Clipboard Management: Auto-clears passwords after a configurable time.
See requirements for dependencies.
curl -fsSL https://raw.githubusercontent.com/sschmid/pw/main/install | bashRun the install script again to update pw to the latest version.
Latest release
extract and add src to your $PATH, or run directly:
~/Downloads/pw/src/pw~/.local/share/pw/install --uninstall| Platform | Containerfile | |
|---|---|---|
| macOS | ||
| Alpine Linux | Containerfile | |
| Arch Linux | Containerfile | |
| Debian | Containerfile | |
| Fedora | Containerfile | |
| openSUSE Tumbleweed | Containerfile | |
| Ubuntu | Containerfile |
pw init ~/secrets.keychain-db # macOS Keychain
# pw init ~/secrets.kdbx # KeePassXC
# pw init ~/secrets/ # GnuPG (trailing `/`)
# pw auto-discovers keychains in the current folder.
# Add to ~/.config/pw/pw.conf to access them from anywhere:
echo 'keychain = ~/secrets.keychain-db' >> ~/.config/pw/pw.conf
pw add GitHub # add entry with name
pw add # add entry interactively
pw GitHub # copy password
pw -p # fzf select, print instead of copyFor GnuPG, make sure you have a valid GPG key (not expired, with encryption capability [E]).
# List keys
gpg --list-secret-keys --keyid-format long
# If you don't have one yet, create it with
gpg --full-generate-keypw init ~/secrets/ # trailing `/` for GnuPG
pw -k ~/secrets add GitHub # specify keychain for the first item
pw add GitHub.gpg # binary format (default)
pw add GitHub.asc # ASCII-armored format
pw GitHub # copy passwordpw forwards commands to plugins that implement these functions:
init, add, edit, mv, get, show, rm, ls, open, lock, unlock (see plugins).
| Feature | macOS Keychain | KeePassXC | GnuPG |
|---|---|---|---|
| Create keychain | β | β | β (dir) |
| Add entry (name + password) | β | β | β |
| Add entry (name, account, url, notes + password) | β | β | π |
| Multiple entries with same name (different account) | β | β | β |
| Add entry in groups (e.g. Coding/Work) | β | π | β |
| Edit entry | β | β | β |
| Move (rename) entry | β | π | β |
| Remove entry | β | β | β |
| List entries | β | β | β |
| Open keychain | β | β | β |
| Lock keychain | β | βΉοΈ keychain is never left unlocked | β |
| Unlock keychain | β | β starts interactive session | β |
| Key file support | β | β | β |
| YubiKey support | β | β | β |
| Auto keychain discovery | β | β | β |
π: workaround implemented by pw
β: not supported by the password manager
The following are notes on the underlying security command and gpg that pw integrates with.
These risks arise from the behavior of these tools, not from pw itself.
When accessing keychain items added by other applications, the user is typically prompted to allow or always allow access.
However, entries added via the security command itself are auto-granted access without future prompts β other apps can exploit this.
pw avoids this by not adding the security command to the keychain's ACL by default, giving you full control over access per item.
See macOS Keychain to change the default ACL behaviour.
Tip
- Set the keychain to require a password after a certain time and lock on sleep.
- Lock after use:
pw lock
Metadata (name, account, URL, comments) can be listed even when locked β a macOS Keychain limitation. Workarounds include encrypting the keychain and only temporarily decrypting it.
GPG caches passphrases after use, allowing access to the private key without re-entering it.
Tip
- Shorten the cache time via
gpg-agentsettings - Clear the passphrase cache:
pw lock
While GPG encrypts file contents, file names can still be listed without a passphrase β a GPG limitation.
Workarounds include using a separate encrypted container or tar to encrypt files into a single archive.
KeePassXC, unlike the security command and GPG, remains locked when not in use and does not have these risks.
In examples below, [<args>] = name, account, url, notes (in order).
fzf tips: Press ? to toggle entry preview (name, account, url, notes). Press CTRL-Y to copy/print details.
pw init secrets.keychain-db # macOS Keychain (defaults to ~/Library/Keychains)
pw init ~/secrets.keychain-db # macOS Keychain (absolute path)
pw init ~/secrets.kdbx # KeePassXC
pw init ~/secrets/ # GnuPG (trailing `/`)pw add [<args>] add entry (interactive if no args)
pw edit [<args>] edit entry (fzf if no args)
pw mv [<args>] move/rename entry (fzf if no args)
pw [-p] [<args>] copy/print password (fzf if no args)
pw [-p] show [<args>] copy/print details (fzf if no args)
pw rm [<args>] remove entry (fzf if no args)
pw [-p] gen [<len>] [<class>] generate password (default: 24 [:graph:])
Examples:
pw add GitHub # add entry with name
pw add Google work@example.com # add entry with name + account
pw add Coveralls "" https://coveralls.io "login via GitHub" # name, url, notes
pw add Coding/GitHub # add entry with name in group Coding
pw gen 16 # generate 16-char password
pw gen 24 '[:alnum:]' # generate alphanumeric onlypw -k secrets.keychain-db # per-command flag
PW_KEYCHAIN=secrets.keychain-db pw # per-command env var
export PW_KEYCHAIN=secrets.keychain-db # shell-wideAdd keychains to ~/.config/pw/pw.conf:
[keychains]
keychain = secrets.keychain-db
keychain = ~/path/to/myproject.keychain-db
keychain = ~/path/to/keepassxc.kdbx
keychain = ~/path/to/gpg/secretsWithout -k or PW_KEYCHAIN, pw uses fzf to let you pick one.
pw searches the current directory for keychains, so you can keep them alongside your project.
Use pw to avoid leaking secrets in scripts that you share or commit.
curl -s -H "Authorization: token $(pw -p GITHUB_TOKEN)" https://api.github.com/userCaution
Avoid plain-text passwords β they can leak in process listings, history, logs, and network traffic. Use environment variables instead.
echo "${MY_PASSWORD}" | pw init ~/secrets.kdbx
pw add GitHub <<< "${MY_PASSWORD}"Config file: ~/.config/pw/pw.conf (auto-created with defaults, or use -c /path/to/config).
See examples/pw.conf for a full reference.
[general]
password_length = 24
password_character_class = [:graph:]
clipboard_clear_time = 45
# pbcopy/pbpaste, xclip, xsel, and wl-copy/wl-paste are supported by default.
# If you're using a different clipboard manager, you can specify it here:
# copy = my-copy-command
# paste = my-paste-command
[plugins]
plugin = $PW_HOME/plugins/gpg
plugin = $PW_HOME/plugins/keepassxc
plugin = $PW_HOME/plugins/macos_keychain
[keychains]
keychain = secrets.keychain-db
keychain = ~/path/to/your/gpg/vault
keychain = ~/path/to/your/keychain.kdbx
keychain = ~/path/to/your/keychain.keychain-dbEnvironment variables override config file settings:
export PW_KEYCHAIN=secrets.keychain-db
export PW_GEN_LENGTH=24
export PW_GEN_CLASS='[:graph:]'
export PW_CLIP_TIME=45Append :key=value to any keychain path (in -k, env vars, or config):
pw -k ~/secrets.kdbx:key1=value1,key2=value2To auto-allow the security command in the ACL:
[macos_keychain]
keychain_access_control = always-allowOr: export PW_MACOS_KEYCHAIN_ACCESS_CONTROL="always-allow"
- Key file:
~/secrets.kdbx:keyfile=/path/to/keyfile - YubiKey:
~/secrets.kdbx:yubikey=1:23456789
- Default encryption key:
~/path/to/gpg/secrets:key=634419040D678764 - Output binary:
pw add GitHub.gpg - Output ASCII-armored:
pw add GitHub.asc
Ignore false-positive keychain dirs:
[gpg]
ignore_path = ~
ignore_path = ~/ignored_folderOr: export PW_GPG_IGNORE_PATHS="${HOME};${HOME}/ignored_folder;"
bashfzfgnupg(optional, GnuPG plugin)keepassxc(optional, KeePassXC plugin)
Supported clipboard managers:
pbcopy/pbpaste(macOS)xclip,xsel(X11)wl-copy/wl-paste(Wayland)
If you're using a different clipboard manager, you can specify it in ~/.config/pw/pw.conf:
[general]
copy = my-copy-command
paste = my-paste-command
