A simple password manager using GPG written in POSIX sh
.
- Written in safe and shellcheck compliant POSIX
sh
. - Only
120~
LOC (minus blank lines and comments). - Compatible with
pass
's password store. - Clears the clipboard after a timeout.
- Configurable password generation using
/dev/urandom
. - Guards against
set -x
,ps
and/proc
leakage. - Easily extendible through the shell.
- Dependencies
- Usage
- FAQ
- How does this differ from
pass
or etc? - Where are passwords stored?
- How can I use a public key?
- How do I change the password length?
- How do I change the password generation pattern?
- How do I change the password store location?
- How do I change the clipboard tool?
- How do I change the clipboard timeout?
- How do I rename an entry?
- How can I migrate from
pass
topash
? - How can I extend
pash
?
- How does this differ from
gpg
orgpg2
Clipboard Support:
xclip
(can be customized throughPASH_CLIP
).
Examples: pash add web/gmail
, pash list
, pash del google
, pash show github
, pash copy github
.
SYNOPSIS
pash [ add|del|show|list|copy ] [name]
COMMANDS
[a]dd [name] - Create a new password entry.
[c]opy [name] - Copy entry to the clipboard.
[d]el [name] - Delete a password entry.
[l]ist - List all entries.
[s]how [name] - Show password for an entry.
[t]ree - List all entries in a tree.
OPTIONS
Using a key pair: export PASH_KEYID=XXXXXXXX
Password length: export PASH_LENGTH=50
Password pattern: export PASH_PATTERN=_A-Z-a-z-0-9
Store location: export PASH_DIR=~/.local/share/pash
Clipboard tool: export PASH_CLIP='xclip -sel c'
Clipboard timeout: export PASH_TIMEOUT=15 ('off' to disable)
I was looking for a CLI password manager (written in shell) and wasn't happy with the options I had found. They either had multiple instances of eval
(on user inputted data), lots of unsafe shell (nowhere near being shellcheck
compliant.) or they were overly complex. The opposites for what I'd want in a password manager.
I decided to write my own. pash
is written in POSIX sh
and the codebase is minimal (120~ LOC minus blank lines and comments).
The passwords are stored in GPG encrypted files located at ${XDG_DATA_HOME:=$HOME/.local/share}/pash}
.
Set the environment variable PASH_KEYID
to the ID of the key you'd like to encrypt and decrypt passwords with.
Example:
# Default: 'unset'.
export PASH_KEYID=XXXXXXXX
# This can also be an email.
export PASH_KEYID=dylan.araps@gmail.com
# This can also be used as a one-off.
PASH_KEYID=XXXXXXXX pash add github
Set the environment variable PASH_LENGTH
to a valid integer.
Example:
# Default: '50'.
export PASH_LENGTH=50
# This can also be used as a one-off.
PASH_LENGTH=10 pash add github
Set the environment variable PASH_PATTERN
to a valid tr
string.
# Default: '_A-Z-a-z-0-9'.
export PASH_PATTERN=_A-Z-a-z-0-9
# This can also be used as a one-off.
PASH_PATTERN=_A-Z-a-z-0-9 pash add hackernews
Set the environment variable PASH_DIR
to a directory.
# Default: '~/.local/share/pash'.
export PASH_DIR=~/.local/share/pash
# This can also be used as a one-off.
PASH_DIR=/mnt/drive/pash pash list
Set the environment variable PASH_CLIP
to a command.
NOTE: I advise that you disable clipboard history in managers like KDE's klipper
before copying passwords through pash
. Your Desktop Environment's clipboard manager may read entries from the X clipboard when xclip
is used.
NOTE: pash
will correctly clear all clipboards which have history disabled.
# Default: 'xclip -sel c'.
export PASH_CLIP='xclip -sel c'
# This can also be used as a one-off.
PASH_CLIP='xclip -sel c' pash copy github
Set the environment variable PASH_TIMEOUT
to a valid sleep
interval or off
to disable the feature.
# Default: '15'
export PASH_TIMEOUT=15
# Disable timeout.
export PASH_TIMEOUT=off
# This can also be used as a one-off.
PASH_TIMEOUT=5 pash copy github
It's a file! Standard UNIX utilities can be used here.
I cannot guarantee 100% compatibility with the stores from pass
as pash
wasn't written as a 1:1 replacement, however users have reported that pash
does in fact work fine with pass
' store.
Add the following to your .shellrc
or .profile
.
read -r PASH_KEYID < "$PASH_DIR/.gpg-id"
export PASH_DIR=${PASSWORD_STORE_DIR:-$HOME/.password-store}
export PASH_KEYID
A shell function can be used to add new commands and functionality to pash
. The following example adds pash git
to execute git
commands on the password store.
pash() {
case $1 in
g*)
cd "${PASH_DIR:=${XDG_DATA_HOME:=$HOME/.local/share}/pash}"
shift
git "$@"
;;
*)
command pash "$@"
;;
esac
}