{"id":19537255,"url":"https://github.com/rnkn/pw","last_synced_at":"2026-06-11T06:31:43.074Z","repository":{"id":76984700,"uuid":"445056523","full_name":"rnkn/pw","owner":"rnkn","description":"POSIX shell password manager","archived":false,"fork":false,"pushed_at":"2022-01-06T05:50:38.000Z","size":49,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-26T04:28:29.991Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rnkn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-06T05:50:14.000Z","updated_at":"2022-01-06T19:01:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"abadeb29-6c89-4ade-98f6-6be6f36d90d3","html_url":"https://github.com/rnkn/pw","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rnkn/pw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rnkn%2Fpw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rnkn%2Fpw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rnkn%2Fpw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rnkn%2Fpw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rnkn","download_url":"https://codeload.github.com/rnkn/pw/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rnkn%2Fpw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34186385,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T02:27:06.732Z","updated_at":"2026-06-11T06:31:43.055Z","avatar_url":"https://github.com/rnkn.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"pw - POSIX shell password manager\n=================================\n\npw is a rewrite of Roman Zolotarev's POSIX shell password manager [pass][1].\n\nI've used a new name to avoid confusion with the more well-known\n[pass][2], it's 50% quicker to type, and also because it's my initials.\n\n\nRequirements\n------------\n\n- [`openssl`][3] handles all encryption processes\n- [`urandom`][4] is required for generating random passwords\n- [`oathtool`][5] is required for generating TOTPs\n\n\nInstallation\n------------\n\nThe first step is to read and understand the source. I encourage you not to\nencrypt your password data using a program you do not understand. (As a\nfail-safe, pw requires its default directories to be manually created.)\n\nAfter that:\n\n\t$ git clone git://git.bydasein.com/pw.git\n\t$ cd pw\n\t# make install\n\nor\n\n\t$ make PREFIX=$HOME install\n\n\nUsage\n-----\n\n\tpw [COMMAND] [ENTRY]\n\tpw [COMMAND] -h\n\nCommands:\n\n\tinit\n\t  initialize RSA key pair\n\tls|list [QUERY]\n\t  list entries matching QUERY or list all\n\tadd \u003cENTRY\u003e\n\t  add ENTRY from STDIN or prompt for multiline text\n\tshow \u003cENTRY\u003e\n\t  decrypt and show ENTRY or ENTRY FIELD or ENTRY TOTP\n\ted|edit \u003cENTRY\u003e\n\t  temporarily decrypt ENTRY and edit in EDITOR\n\tgen|generate [LENGTH]\n\t  generate random password of LENGTH (default 16)\n\tsign \u003cENTRY\u003e\n\t  create signature for ENTRY with private key\n\tverify \u003cENTRY\u003e\n\t  verify ENTRY against signature with public key\n\tgit \u003cARGUMENTS\u003e\n\t  call git and pass ARGUMENTS verbatim\n\tmaster\n\t  change private key password\n\nAll configuration is accomplished via environment variables:\n\n\tPW_PUBLIC_KEY\tlocation of public key\n\tPW_PRIVATE_KEY\tlocation of private key\n\tPW_DIR\t\t\tlocation of password directory\n\tPW_MASTER\t\tprivate key password (see below)\n\tPW_SIGN\t\t\twhen set, sign password tarballs\n\tPW_VERIFY\t\twhen set, verify password tarballs\n\tPW_CLIP\t\t\tclipboard program name\n\nTo avoid needing to enter your private key password with every invocation of\npw, set the `PW_MASTER` environment variable to your private key password.\nFor convenience, add the following aliases to your profile:\n\n\talias pw_unlock=\"stty -echo; read -r PW_MASTER; stty echo; export PW_MASTER\"\n\talias pw_lock=\"unset PW_MASTER\"\n\n\nHow it works\n------------\n\npw uses hybrid encryption, which combines the strengths of RSA asymmetric\nencryption with AES symmetric encryption.\n\nFor example, adding a password for `example.com` generates an encryption key and\nthe password content is then encrypted with this key using AES-256-CBC\nencryption, as `example.com.enc`. The key is then encrypted using your RSA\npublic key as `example.com.key` and the original key discarded. Both\n`example.com.enc` and `example.com.key` are added to a tarball\n`example.com.tar`, and an optional signed hash `example.com.tar.sig` is\ngenerated using your RSA private key.\n\nThis is the resulting hierarchy:\n\n\t.PW_DIR/\n\t├── example.com.tar\n\t│   ├── example.com.enc\n\t│   └── example.com.key\n\t└── example.com.tar.sig\n\n\nBugs\n----\n\nPlease email patches to the address in the source.\n\n\nHints\n-----\n\nTo add a generated password:\n\n\t$ pw generate | pw add example.com\n\nTo generate a new password for an existing entry in-place:\n\n\t$ pw show example.com | sed \"1d; i\\\\\n\t\u003e $(pw generate)\n\t\u003e \" | pw add -f example.com\n\nSet git to perform binary diffs:\n\n\t$ cd .pw\n\t$ cat \u003e .gitattributes\n\t\u003e *.tar diff=\n\t\u003e *.tar.sig diff=\n\nTo import from `password-store`:\n\n\t$ pw_unlock\n\t$ cd $HOME/.password-store\n\t$ for file in *.gpg; do\n\t\u003e\tentry=\"${file%.gpg}\"\n\t\u003e\tpass \"$entry\" | sed -E 's/^otpauth:.*secret=([A-Za-z2-7]+).*/totp: \\1/' | pw add \"$entry\"\n\t\u003e done\n\nTo batch edit all entries, e.g. to change an email:\n\n\t$ pw_unlock\n\t$ pw ls | while read -r entry; do\n\t\u003e\tpw show \"$entry\" | sed 's/@example\\.com/@newaddress.com/' | pw add -f \"$entry\"\n\t\u003e done\n\nTo rotate your private key:\n\n\t$ tar -cvf keybackup.tar $HOME/.keys\n\t$ PW_PRIVATE_KEY=$HOME/.keys/newkey.sec \\\n\t\u003e PW_PUBLIC_KEY=$HOME/.keys/newkey.pub \\\n\t\u003e pw init\n\t$ mkdir $HOME/.pw_new\n\t$ pw_unlock\n\t$ pw ls | while read -r entry; do\n\t\u003e\tpw show \"$entry\" |\n\t\u003e\t\tPW_PUBLIC_KEY=$HOME/.keys/newkey.pub \\\n\t\u003e\t\tPW_DIR=$HOME/.pw_new \\\n\t\u003e\t\tpw add \"$entry\"\n\t\u003e done\n\t$ mv $HOME/.keys/{newkey,pw}.sec\n\t$ mv $HOME/.keys/{newkey,pw}.pub\n\t$ rm -rf $HOME/.pw\n\t$ mv $HOME/.pw_new $HOME/.pw\n\n\n[1]: https://www.romanzolotarev.com/pass.html\n[2]: https://www.passwordstore.org\n[3]: https://man.openbsd.org/openssl\n[4]: https://man.openbsd.org/urandom\n[5]: https://www.nongnu.org/oath-toolkit/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frnkn%2Fpw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frnkn%2Fpw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frnkn%2Fpw/lists"}