After trying to develop my own password manager on top of KeePassX APIs, I decided instead to give a try to pass, "the standard unix password manager".

Mainly is just a simple shell script that manages the password like any other password manager does, but with more simplicity and following some of the standard unix philosophy principles (everything is a file, use text streams, ans so on). It extensively uses pwgen to generate the actual passwors, xclip to copy them into the clipboard, gpg for encryption, git for backend and other tools listed into the README file.

Instead of having a single, monolithic XML file like KeePassX, each password (or entry) is stored in a single file within the ~/.password-store directory. Each file is encrypted with the user’s GPG public key; it can also use multiple keys to allow collaboration in a team (I actually need to test this more because is a requirement I ever like to implement). You can then manipulate these files like every other file (cp, mv, etc.) or use the pass command facility.

Quick setup

So, to initialize a new "database" (assuming you have pass and all other requirements installed) you can use:

pass init 19061099
pass git init

The first tells to create the password manager directory into the standard location using the GPG key ID specified as argument, the latter (optional if you don’t want to manage it with GIT) to initialize the git repository.

The first time I run that an error (gpg: [stdin]: encryption failed: Unusable public key) told me that I need to fully trust my own public key, or it can’t be used by pass. A simple way to do that is to run:

$ gpg --edit-key 19061099
gpg> trust
gpg> 4
gpg> quit

Then re-run the init commands and you should have your empty pass repository into ~/.password-store with the .gpg-id file and the .git/ folder.

Add an entry is quite straightforward: just pass insert test/sampleentry and insert and confirm the password; it also have a nice completion features (if installed with apt-get the completion files for your shell shoult already be into the appropriate directories)). The password can be also generated with pass generate aaa/bbb 10 meaning that it will generate and update a 10 characters password into the aaa/bbb entry.

While these entries are thought for single line (just password), you can insert as many lines as you want using the -m (--multiline) switch like pass insert --m aaa/bbb. It will overwrite existing entries but gives you the ability to insert additional fields like username, email, secret questions and so on.

Here the issue is that if you use now pass generate aaa/bbb 20 to generate a 20 chars password for an existing, multiline entry, it will completely overwrite all fields and just replace it with the generated password.

To avoid this just use the -i (--in-place) switch to update just the first line. pass always assumes that the first line is the password; Some ways to organize entries are well-described in the official website.


If you clone the GIT project you can find the contrib/importers folder (or into /usr/share/pass if you installed it using apt-get) that contains some scripts to import other password manager format into pass. For example if you want to import a KeePassX XML file into pass you have to:

  1. Open the DB into KeePassX
  2. Export it as plain XML (unencrypted)
  3. Run the using the path of the exported XML as argument
  4. Obviously securely delete the exported XML file

It will then create the full structure into the ~/.password-store folder creating a folder for each KeePassX group. You can then inspect it with pass ls or simply pass.

Some thoughts

  • The default action for pass show is to display all entry’s data, including the password in clear text. If you want to just copy it into the clipboard (the most common workflow, at least for me) you need to use the -c switch. I would have inverted this behaviour or at least hide the displayed password; then a explicit switch should be used to show the password in clear text.
  • There is no option to set/find/alert about password expiracy. This would be very handful.
  • To search a string pattern into the whole entries you can use the pass grep command, but options for grep cannot be passed on command line. Instead you have to use the GREP_OPTIONS environment variable. Quite awkward.
  • It should understand if an entry is a multiline entry and, in this case, the default action should be to replace just the first line (the password) instead of overwrite the whole file. This can be done with the -i switch (see above) but if omitted the entry will be lost (but can be reverted with git).
  • The generate function uses pwgen as backend but supports just the -n option to avoid use of symbols into the generated string. It would also be nice to allow control on capital letters, numbers and other pwgen features.


Is a very very nice piece of bash. I really like the ability to manage my passwords on cli, and have them encrypted with gpg and backed up with git.

In the future I hope to have some spare time to do some patches to fix some behavior and also post a quick tutorial on how to use it to manage passwords in a shared (eg. IT/Sysadmin team) environment.

The importer scripts, man pages and other resources are well-done.