pashage

Yet Another Opinionated Re-engineering of the Unix Password Store
git clone https://git.instinctive.eu/pashage.git
Log | Files | Refs | README | LICENSE

pashage.1 (11936B)


      1 .Dd November 2, 2025
      2 .Dt PASHAGE 1
      3 .Os
      4 .Sh NAME
      5 .Nm pashage
      6 .Nd simple and portable password store for the Unix shell
      7 .Sh SYNOPSIS
      8 .Nm
      9 .Op Ar COMMAND
     10 .Op Ar OPTIONS
     11 .Op Ar ARGS
     12 .Sh DESCRIPTION
     13 .Nm
     14 is a
     15 .Em password manager ,
     16 which means it manages a database of encrypted secrets, including encrypting
     17 externally-provided new secrets, generating and encrypting random strings, and
     18 decrypting and displaying stored secrets.
     19 .Pp
     20 It aims to be simple and composable, but its reliance on Unix philosophy
     21 and customs might make steep learning curve for users outside of this
     22 culture.
     23 .Pp
     24 The
     25 .Nm
     26 utility provides commands for query and management of the password store.
     27 When no command is specified,
     28 .Cm list
     29 or
     30 .Cm show
     31 is implicitly assumed.
     32 .Pp
     33 The database is optionally versioned using
     34 .Xr git 1
     35 to help with history audit and synchronization.
     36 It should be noted that this prevents re-encryption from erasing old
     37 cyphertext, leaving the secret vulnerable to compromised encryption keys.
     38 .Pp
     39 The cryptography is done by
     40 .Xr age 1
     41 external command.
     42 It decrypts using the
     43 .Em identity
     44 file given in the environment, and crypts using a list of
     45 .Em recipients
     46 per subfolder, defaulting to the parent
     47 .Em recipient
     48 list or the
     49 .Em identity .
     50 .Sh COMMANDS
     51 .Ss copy
     52 .Nm
     53 .Cm copy
     54 .Op Fl e,--reencrypt | Fl i,--interactive | Fl k,--keep
     55 .Op Fl f,--force
     56 .Ar old-path ... new-path
     57 .Pp
     58 This subcommand copies secrets and recursively copies subfolders,
     59 using the same positional argument scheme as
     60 .Xr cp 1 .
     61 By default it asks before overwriting an existing secret and it re-encrypts
     62 the secret when the destination has a different
     63 .Em recipient
     64 list.
     65 .Pp
     66 The options are as follows:
     67 .Bl -tag -compact -width \-i,--interactive
     68 .It Fl e,--reencrypt
     69 always re-encrypt secrets
     70 .It Fl f,--force
     71 overwrite existing secrets without asking
     72 .It Fl i,--interactive
     73 asks whether to re-encrypt or not for each secret
     74 .It Fl k,--keep
     75 never re-encrypt secrets
     76 .El
     77 .Ss delete
     78 .Nm
     79 .Cm delete
     80 .Op Fl r,--recursive
     81 .Op Fl f,--force
     82 .Ar pass-name
     83 .Ar ...
     84 .Pp
     85 This subcommand deletes secrets from the database.
     86 By default it skips subfolders and asks for confirmation for each secret.
     87 .Pp
     88 The options are as follows:
     89 .Bl -tag -compact -width \-r,--recursive
     90 .It Fl f,--force
     91 delete without asking for confirmation
     92 .It Fl r,--recursive
     93 recursively delete all secrets in given subfolders
     94 .El
     95 .Ss edit
     96 .Nm
     97 .Cm edit
     98 .Ar pass-name
     99 .Ar ...
    100 .Pp
    101 This subcommand starts an interactive editor to update the secrets.
    102 .Ss find
    103 .Nm
    104 .Cm find
    105 .Op Fl r,--raw
    106 .Op Ar GREP_OPTIONS
    107 .Ar regex
    108 .Pp
    109 This subcommand lists as a tree the secrets whose name match the given
    110 regular expression, using the corresponding
    111 .Xr grep 1
    112 options.
    113 .Pp
    114 The options are as follows:
    115 .Bl -tag -compact -width \-r,--raw
    116 .It Fl r,--raw
    117 display the results as a raw list of secrets, rather than a tree
    118 .El
    119 .Ss generate
    120 .Nm
    121 .Cm generate
    122 .Op Fl n,--no-symbols
    123 .Op Fl c,--clip | Fl q,--qrcode
    124 .Op Fl i,--in-place | Fl f,--force
    125 .Op Fl m,--multiline
    126 .Op Fl t,--try
    127 .Ar pass-name
    128 .Op Ar pass-length Op Ar character-set
    129 .Pp
    130 This subcommand generates a new secret from
    131 .Pa /dev/urandom ,
    132 stores it in the database, and by default displays it on the standard output
    133 and asks
    134 for confirmation before overwriting an existing secret.
    135 .Pp
    136 The options are as follows:
    137 .Bl -tag -compact -width \-n,--no-symbols
    138 .It Fl c,--clip
    139 paste the secret into the clipboard instead of using the standard output
    140 .It Fl f,--force
    141 replace existing secrets without asking
    142 .It Fl i,--in-place
    143 when the secret already exists, replace only its first line and re-use the
    144 following lines
    145 .It Fl m,--multiline
    146 read lines from standard input to append after the generated data into the secret
    147 file
    148 .It Fl n,--no-symbols
    149 generate a secret using only alphanumeric characters
    150 .It Fl q,--qrcode
    151 display the secret as a QR-code instead of using the standard output
    152 .It Fl t,--try
    153 display the secret and ask for confirmation before storing it into the database
    154 .El
    155 .Ss git
    156 .Nm
    157 .Cm git git-command-args ...
    158 .Pp
    159 This subcommand invokes
    160 .Xr git 1
    161 in the database repository.
    162 Only
    163 .Cm git init
    164 and
    165 .Cm git clone
    166 are accepted when there is no underlying repository.
    167 .Ss gitconfig
    168 .Nm
    169 .Cm gitconfig
    170 .Pp
    171 This subcommand configures the underlying repository to automatically
    172 decrypt secrets to display differences.
    173 .Ss grep
    174 .Nm
    175 .Cm grep
    176 .Op Ar GREP_OPTIONS
    177 .Ar search-regex
    178 .Pp
    179 This subcommand successively decrypts all the secrets in the store and
    180 filter them through
    181 .Xr grep 1
    182 using the given options, and outputs all the matching lines and the
    183 corresponding secret.
    184 .Ss help
    185 .Nm
    186 .Cm help
    187 .Op Ar subcommand ...
    188 .Pp
    189 This subcommand displays on the standard output the help text for the
    190 given subcommands.
    191 .Pp
    192 Without arguments, this subcommand displays on the standard output the
    193 version and help text, including all subcommands and flags and a brief
    194 description.
    195 .Ss init
    196 .Nm
    197 .Cm init
    198 .Op Fl i,--interactive | Fl k,--keep
    199 .Op Fl p,--path Ar subfolder
    200 .Ar age-recipient
    201 .Ar ...
    202 .Pp
    203 This subcommand initializes an age
    204 .Em recipient
    205 list, by default of the root of the password store, and re-encrypts all the
    206 affected secrets.
    207 When the
    208 .Ar age-recipient
    209 list is a single empty string, the
    210 .Em recipient
    211 list is instead removed, falling back to a parent
    212 .Em recipient
    213 list or ultimately to the age
    214 .Em identity .
    215 .Pp
    216 The options are as follows:
    217 .Bl -tag -compact -width \-i,--interactive
    218 .It Fl i,--interactive
    219 ask for each secret whether to re-encrypt it or not
    220 .It Fl k,--keep
    221 do not re-encrypt any secret
    222 .It Fl p,--path
    223 operate on the
    224 .Em recipient
    225 list in the given subfolder instead of the root of the password store
    226 .El
    227 .Ss insert
    228 .Nm
    229 .Cm insert
    230 .Op Fl e,--echo | Fl m,--multiline
    231 .Op Fl f,--force
    232 .Ar pass-name
    233 .Ar ...
    234 .Pp
    235 This subcommand adds new secrets in the database, using the provided data
    236 from the standard input.
    237 By default asks before overwriting an existing secret, and it reads a single
    238 secret line after turning off the console echo, and reads it a second time for
    239 confirmation.
    240 .Pp
    241 The options are as follows:
    242 .Bl -tag -compact -width \-m,--multiline
    243 .It Fl e,--echo
    244 read a single line once without manipulating the standard input
    245 .It Fl m,--multiline
    246 read an arbitrary amount of lines from the standard input, without trying to
    247 manipulate the console, until the end of input or a blank line is entered
    248 .It Fl f,--force
    249 overwrite an existing secret without asking
    250 .El
    251 .Ss list
    252 .Nm
    253 .Op Cm list
    254 .Op r,--raw
    255 .Op Ar subfolder ...
    256 .Pp
    257 This subcommand displays the given subfolders as a tree or as a raw list, or
    258 the whole store when no subfolder is specified.
    259 .Pp
    260 Note that when a secret is given instead of a subfolder, the
    261 .Cm show
    262 command will be used instead, without any warning or error.
    263 .Pp
    264 The options are as follows:
    265 .Bl -tag -compact -width \-r,--raw
    266 .It Fl r,--raw
    267 display the results as a raw list of secrets.
    268 .El
    269 .Ss move
    270 .Nm
    271 .Cm move
    272 .Op Fl e,--reencrypt | Fl i,--interactive | Fl k,--keep
    273 .Op Fl f,--force
    274 .Ar old-path ... new-path
    275 .Pp
    276 This subcommand moves or renames secrets and subfolders recursively,
    277 using the same positional argument scheme as
    278 .Xr mv 1 .
    279 By default it asks before overwriting an existing secret and it re-encrypts
    280 the secret when the destination has a different
    281 .Em recipient
    282 list.
    283 .Pp
    284 The options are as follows:
    285 .Bl -tag -compact -width \-i,--interactive
    286 .It Fl e,--reencrypt
    287 always re-encrypt secrets
    288 .It Fl f,--force
    289 overwrite existing secrets without asking
    290 .It Fl i,--interactive
    291 asks whether to re-encrypt or not for each secret
    292 .It Fl k,--keep
    293 never re-encrypt secrets
    294 .El
    295 .Ss random
    296 .Nm
    297 .Cm random
    298 .Op Ar pass-length Op Ar character-set
    299 .Pp
    300 This subcommand generates a new secret, like the
    301 .Cm generate
    302 subcommand, then directly displays on the standard output without storing it.
    303 .Ss reencrypt
    304 .Nm
    305 .Cm reencrypt
    306 .Op Fl d,--deep
    307 .Op Fl i,--interactive
    308 .Ar pass-name|subfolder
    309 .Ar ...
    310 .Pp
    311 This subcommand re-encrypts in place the given secrets, and all the secrets
    312 recursively in the given subfolders.
    313 .Pp
    314 The options are as follows:
    315 .Bl -tag -compact -width \-i,--interactive
    316 .It Fl d,--deep
    317 re-encrypt subfolders with their own recipient list
    318 .It Fl i,--interactive
    319 asks whether to re-encrypt or not for each secret
    320 .El
    321 .Ss show
    322 .Nm
    323 .Op Cm show
    324 .Oo
    325 .Fl c,--clip Op Ar line-number
    326 |
    327 .Fl q,--qrcode Op Ar line-number
    328 .Oc
    329 .Ar pass-name
    330 .Ar ...
    331 .Pp
    332 This subcommand decrypts the given secrets and by default displays the
    333 whole text on the standard output.
    334 .Pp
    335 Note that when a subfolder is given instead of a secret, the
    336 .Cm list
    337 command will be used instead, without any warning or error.
    338 .Pp
    339 The options are as follows:
    340 .Bl -tag -compact -width \-q,--qrcode
    341 .It Fl c,--clip
    342 paste the given line (by default the first line) of the secret into the
    343 clipboard instead of using the standard output
    344 .It Fl q,--qrcode
    345 display the given line (by default the first line) of the secret as a QR-code
    346 instead of using the standard output
    347 .El
    348 .Ss version
    349 .Nm
    350 .Cm version
    351 .Pp
    352 This subcommand displays on the standard output the version and author
    353 list.
    354 .Sh ENVIRONMENT
    355 The following environment variables affect the execution of
    356 .Nm :
    357 .\" The largest symbol is actually PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS
    358 .\" but that compresses the second columns way too much.
    359 .Bl -tag -width XXXXXXXX
    360 .It Ev CLICOLOR_FORCE
    361 when set to a non-empty value, and
    362 .Ev NO_COLOR
    363 is unset or empty, use ANSI escape sequences to color the output even when not
    364 writing to a terminal
    365 .It Ev EDITOR
    366 editor command to use instead of
    367 .Xr vi 1
    368 when
    369 .Ev VISUAL
    370 is not set
    371 .It Ev LC_CTYPE
    372 when it contains
    373 .Qq UTF ,
    374 the tree is displayed using Unicode graphic characters instead of ASCII
    375 .It NO_COLOR
    376 when set to a non-empty value, no ANSI escape sequence is output
    377 .It Ev PASHAGE_AGE
    378 external command to use instead of
    379 .Xr age 1
    380 .It Ev PASHAGE_DIR
    381 database directory to use instead of
    382 .Pa ~/.passage/store
    383 .It Ev PASHAGE_IDENTITIES_FILE
    384 .Em identity
    385 file to use instead of
    386 .Pa ~/.passage/identities
    387 .It Ev PASSAGE_AGE
    388 external command to use instead of
    389 .Xr age 1
    390 when
    391 .Ev PASHAGE_AGE
    392 is unset
    393 .It Ev PASSAGE_DIR
    394 database directory to use instead of
    395 .Pa ~/.passage/store
    396 when
    397 .Ev PASHAGE_DIR
    398 is unset
    399 .It Ev PASSAGE_IDENTITIES_FILE
    400 .Em identity
    401 file to use instead of
    402 .Pa ~/.passage/identities
    403 when
    404 .Ev PASHAGE_IDENTITIES_FILE
    405 is unset
    406 .It Ev PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS
    407 default character set to use with
    408 .Xr tr 1
    409 when
    410 .Fl n
    411 is specified, instead of
    412 .Qq [:alnum:]
    413 .It Ev PASSWORD_STORE_CHARACTER_SET
    414 character set to use with
    415 .Xr tr 1
    416 when no character set requirement is specified for the
    417 .Cm generate
    418 or
    419 .Cm random
    420 commands, instead of
    421 .Qq [:punct:][:alnum:]
    422 .It Ev PASSWORD_STORE_CLIP_TIME
    423 number of second before clearing the clipboard when
    424 .Fl c
    425 is used, instead of 45
    426 .It Ev PASSWORD_STORE_DIR
    427 database directory to use instead of
    428 .Pa ~/.passage/store
    429 when both
    430 .Ev PASHAGE_DIR
    431 and
    432 .Ev PASSAGE_DIR
    433 are unset
    434 .It Ev PASSWORD_STORE_GENERATED_LENGTH
    435 number of characters in the generated secret when not explicitly given,
    436 instead of 25
    437 .It Ev PASSWORD_STORE_X_SELECTION
    438 selection to use when
    439 .Fl c
    440 and
    441 .Xr xclip 1
    442 are used, instead of
    443 .Qq clipboard
    444 .It Ev TMPDIR
    445 temporary directory for the decrypted file to use instead of
    446 .Pa /tmp
    447 when
    448 .Pa /dev/shm
    449 is not available
    450 .It Ev VISUAL
    451 editor command to use instead of
    452 .Xr vi 1
    453 .El
    454 .Sh FILES
    455 Most paths used by
    456 .Nm
    457 can be configured through environment variables.
    458 Here are the defaults:
    459 .Bl -tag -width XXXXXXXX
    460 .It Pa ~/.passage/identities
    461 .Xr age 1
    462 .Em identities
    463 to use for decryption
    464 .It Pa ~/.passage/store/
    465 Root directory of the password store
    466 .It Pa /dev/shm/
    467 Temporary directory
    468 .Pq when available
    469 .It Pa /dev/urandom
    470 Source of entropy
    471 .It Pa /tmp
    472 Temporary directory
    473 .Po
    474 when
    475 .Pa /dev/sdm
    476 is not available
    477 .Pc
    478 .El
    479 .Sh SEE ALSO
    480 .Xr age 1 ,
    481 .Xr git 1 ,
    482 .Xr tr 1 ,
    483 .Xr vi 1 ,
    484 .Xr xclip 1 .
    485 .Sh AUTHORS
    486 .Nm
    487 was written by
    488 .An Natasha Kerensikova ,
    489 based on earlier work by:
    490 .An Jason A. Donenfeld
    491 .Pq password-store
    492 .An Filippo Valsorda
    493 .Pq passage
    494 .An Dylan Araps
    495 .Pq pash