pashage

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

README.md (22559B)


      1 [![Casual Maintenance Intended](https://casuallymaintained.tech/badge.svg)](https://casuallymaintained.tech/)
      2 
      3 # pashage
      4 
      5 Yet Another Opinionated Re-engineering of the Unix Password Store
      6 
      7 Core objectives:
      8 
      9 - same interface and similar feature set
     10   as [pass](https://www.passwordstore.org/)
     11 - simplicity, understandability, and hackability, from using POSIX shell,
     12   like [pash](https://github.com/dylanaraps/pash)
     13 - [age](https://age-encryption.org) as encryption backend,
     14   like [passage](https://github.com/FiloSottile/passage)
     15 - validation using [shellcheck](https://www.shellcheck.net/)
     16   and [shellspec tests](https://shellspec.info/)
     17 
     18 Portability is not a core objective, but a nice side-effect of using
     19 basic POSIX shell, and it is embraced when possible.
     20 
     21 Security is not branded as a core objective, because the author does not
     22 have the clout to declare anything secure, and you should probably not
     23 trust random READMEs anyway.
     24 However the simplicity should help you assess whether this password store
     25 is a worthwhile trade-off for _your_ threat model.
     26 
     27 For the reference, the author has views [similar to those of Filippo
     28 Valsorda](https://words.filippo.io/dispatches/passage/) and considers
     29 the password store shell script to be about as critical as the rest
     30 of her computer, and relies mostly on age to provide secure encryption
     31 at rest and on a [YubiKey](https://www.yubico.com/) to gatekeep decryption.
     32 
     33 ## Licencing
     34 
     35 This project was written from scratch, and every character of the script
     36 was typed with my fingers.
     37 However I looked deeply into pass, passage, and pash code bases.
     38 I don't know whether that's enough to make it a derivative work covered
     39 by the GPL, so to be on the safe side I'm using GPL v2+ too.
     40 
     41 ## Differences with `pass`
     42 
     43 ### Behavior Differences
     44 
     45 - Not using a terminal does not imply `--force`, instead `pashage` asks for
     46 a confirming `y` on a standard input line.
     47 
     48 - When copying a secret to the clipboard, the script keeps running while
     49 waiting for the automatic clearing. This provides a user-facing cue that
     50 the secret may still be the clipboard and allows to clear the clipboard
     51 earlier.
     52 
     53 - The commands `copy`, `edit`, `insert`, `list`, `move`, and `show`
     54 accept multiple arguments to operate on many secrets at once.
     55 
     56 - The commands `copy` and `move` also operate on unencrypted files in the
     57 password store.
     58 
     59 - The `edit` command does not warn a about using `/tmp` rather than
     60 `/dev/shm`, because the warning does not seem actionable and quickly
     61 becomes ignored noise.
     62 
     63 - The `edit` command uses `$VISUAL` rather than `$EDITOR` when it set and
     64 the terminal is not dumb.
     65 
     66 - The `find` command search-pattern is a regular expression rather than
     67 a glob.
     68 
     69 - The `init` command is redesigned to accommodate `age` backend.
     70 I didn't really understand the original `init` command, so I'm not sure
     71 how different it is; but now it installs `.age-recipients` and re-encrypts.
     72 
     73 - The `insert` command makes the user try again when entering mismatching
     74 passwords.
     75 
     76 ### New Features and Extensions
     77 
     78 - The commands `copy` and `move` have new flags to control re-encryption
     79 (always, never, ask for each file).
     80 
     81 - The `generate` command has a new command-line argument to specify
     82 explicitly the character set.
     83 
     84 - The `generate` command optionally asks for confirmation before storing
     85 the generated secret (e.g. for iterative attempts against stupid password
     86 rules).
     87 
     88 - The `generate` command optionally asks for extra lines to append after
     89 the generated secret (e.g. for username, login page, or others comments).
     90 
     91 - The `init` command has new flags to control re-encryption (never or
     92 ask for each file).
     93 
     94 - The new `gitconfig` command configures an existing store repository to
     95 decrypt before `diff`.
     96 
     97 - The new `random` command leverages password generation without touching
     98 the password store.
     99 
    100 - The new `reencrypt` command re-encrypts secrets in-place.
    101 
    102 ## Roadmap
    103 
    104 The following features are currently under consideration:
    105 
    106 - v1.0.0:
    107     + completion for various shells
    108     + better logic for recursivity in re-encryption
    109 - v1.1.0:
    110     + partial display of secrets on standard output
    111     + successive clipboard copy of several lines from a single decryption
    112 (e.g. username then password)
    113 - maybe/later:
    114     + rewriting of git history to purge old cyphertexts
    115     + OTP support
    116     + extension support
    117 
    118 ## Manual
    119 
    120 **pashage** is a _password manager_, which means it manages a database of
    121 encrypted secrets, including encrypting externally-provided new secrets,
    122 generating and encrypting random strings, and decrypting and displaying
    123 stored secrets.
    124 
    125 It aims to be simple and composable, but its reliance on Unix philosophy
    126 and customs might make steep learning curve for users outside of this
    127 culture.
    128 
    129 It is used through a shell command, denoted as `pashage` in this document,
    130 immediately followed by a subcommand and its arguments. When no subcommand
    131 is specified, _list_ or _show_ is implicitly assumed.
    132 
    133 The database is optionally versioned using [git](https://git-scm.com/)
    134 to help with history audit and synchronization. It should be noted that
    135 this prevents re-encryption from erasing old cyphertext, leaving the secret
    136 vulnerable to compromised encryption keys.
    137 
    138 The cryptography is done by [age](https://age-encryption.org/) external
    139 command. It decrypts using the _identity_ file given in the environment,
    140 and crypts using a list of _recipients_ per subfolder, defaulting to the
    141 parent _recipient_ list or the _identity_.
    142 
    143 ## Command Reference
    144 
    145 Here is an alphabetical list of all subcommands and aliases:
    146 
    147 - `--help`: alias for _help_
    148 - `--version`: alias for _version_
    149 - `-h`: alias for _help_
    150 - `copy`
    151 - `cp`: alias for _copy_
    152 - `delete`
    153 - `edit`
    154 - `find`
    155 - `gen`: alias for _generate_
    156 - `generate`
    157 - `git`
    158 - `gitconfig`
    159 - `grep`
    160 - `help`
    161 - `init`
    162 - `insert`
    163 - `list`
    164 - `ls`: alias for _list_
    165 - `move`
    166 - `mv`: alias for _move_
    167 - `random`
    168 - `re-encrypt`: alias for _reencrypt_
    169 - `reencrypt`
    170 - `remove`: alias for _delete_
    171 - `rm`: alias for _delete_
    172 - `show`
    173 - `version`
    174 
    175 ### copy
    176 
    177 Syntax:
    178 
    179 ```
    180 pashage copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
    181              [--force,-f] old-path ... new-path
    182 ```
    183 
    184 This subcommand copies secrets and recursively copies subfolders,
    185 using the same positional argument scheme as `cp(1)`.
    186 By default it asks before overwriting an existing secret and it re-encrypts
    187 the secret when the destination has a different _recipient_ list.
    188 
    189 Flags:
    190 - `-e` or `--reencrypt`: always re-encrypt secrets
    191 - `-f` or `--force`: overwrite existing secrets without asking
    192 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    193 - `-k` or `--keep`: never re-encrypt secrets
    194 
    195 Environment:
    196 - `PASHAGE_AGE`: external command to use instead of `age`
    197 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    198 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    199   `~/.passage/identities`
    200 - `PASSAGE_AGE`: external command to use instead of `age` when
    201   `PASHAGE_AGE` is unset
    202 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    203   when `PASHAGE_DIR` is unset
    204 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    205   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    206 - `PASSWORD_STORE_DIR`: database directory to use instead of
    207   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    208 
    209 ### delete
    210 
    211 Syntax:
    212 
    213 ```
    214 pashage delete [--recursive,-r] [--force,-f] pass-name ...
    215 ```
    216 
    217 This subcommand deletes secrets from the database. By default it skips
    218 subfolders and asks for confirmation for each secret.
    219 
    220 Flags:
    221 - `-f` or `--force`: delete without asking for confirmation
    222 - `-r` or `--recursive`: recursively delete all secrets in given subfolders
    223 
    224 Environment:
    225 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    226 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    227   when `PASHAGE_DIR` is unset
    228 - `PASSWORD_STORE_DIR`: database directory to use instead of
    229   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    230 
    231 ### edit
    232 
    233 Syntax:
    234 
    235 ```
    236 pashage edit pass-name ...
    237 ```
    238 
    239 This subcommand starts an interactive editor to update the secrets.
    240 
    241 Environment:
    242 - `EDITOR`: editor command to use instead of `vi` when `VISUAL` is not set
    243 - `PASHAGE_AGE`: external command to use instead of `age`
    244 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    245 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    246   `~/.passage/identities`
    247 - `PASSAGE_AGE`: external command to use instead of `age` when
    248   `PASHAGE_AGE` is unset
    249 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    250   when `PASHAGE_DIR` is unset
    251 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    252   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    253 - `PASSWORD_STORE_DIR`: database directory to use instead of
    254   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    255 - `TMPDIR`: temporary directory for the decrypted file to use instead of
    256   `/tmp` when `/dev/shm` is not available
    257 - `VISUAL`: editor command to use instead of `vi`
    258 
    259 ### find
    260 
    261 Syntax:
    262 
    263 ```
    264 pashage find [GREP_OPTIONS] regex
    265 ```
    266 
    267 This subcommand lists as a tree the secrets whose name match the given
    268 regular expression, using the corresponding `grep(1)` options.
    269 
    270 Environment:
    271 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    272   color the output
    273 - `LC_CTYPE`: when it contains `UTF`, the tree is displayed using Unicode
    274   graphic characters instead of ASCII
    275 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    276 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    277   when `PASHAGE_DIR` is unset
    278 - `PASSWORD_STORE_DIR`: database directory to use instead of
    279   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    280 
    281 ### generate
    282 
    283 Syntax:
    284 
    285 ```
    286 pashage generate [--no-symbols,-n] [--clip,-c | --qrcode,-q]
    287                  [--in-place,-i | --force,-f] [--multiline,-m]
    288                  [--try,-t] pass-name [pass-length [character-set]]
    289 ```
    290 
    291 This subcommand generates a new secret from `/dev/urandom`, stores it in
    292 the database, and by default displays it on the standard output and asks
    293 for confirmation before overwriting an existing secret.
    294 
    295 Flags:
    296 - `-c` or `--clip`: paste the secret into the clipboard instead of using
    297   the standard output
    298 - `-f` or `--force`: replace existing secrets without asking
    299 - `-i` or `--in-place`: when the secret already exists, replace only its
    300   first line and re-use the following lines
    301 - `-m` or `--multiline`: read lines from standard input append after the
    302   generated data into the secret file
    303 - `-n` or `--no-symbols`: generate a secret using only alphanumeric
    304   characters
    305 - `-q` or `--qrcode`: display the secret as a QR-code instead of using the
    306   standard output
    307 - `-t` or `--try`: display the secret and ask for confirmation before
    308   storing it into the database
    309 
    310 Environment:
    311 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    312   color the output
    313 - `PASHAGE_AGE`: external command to use instead of `age`
    314 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    315 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    316   `~/.passage/identities`
    317 - `PASSAGE_AGE`: external command to use instead of `age` when
    318   `PASHAGE_AGE` is unset
    319 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    320   when `PASHAGE_DIR` is unset
    321 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    322   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    323 - `PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS`: default character set to use
    324   with `tr(1)` when `-n` is specified, instead of `[:alnum:]`
    325 - `PASSWORD_STORE_CHARACTER_SET`: default character set to use with `tr(1)`
    326   when `-n` is not specified, instead of `[:punct:][:alnum:]`
    327 - `PASSWORD_STORE_CLIP_TIME`: number of second before clearing the
    328   clipboard when `-c` is used, instead of 45
    329 - `PASSWORD_STORE_DIR`: database directory to use instead of
    330   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    331 - `PASSWORD_STORE_GENERATED_LENGTH`: number of characters in the generated
    332   secret when not explicitly given, instead of 25
    333 - `PASSWORD_STORE_X_SELECTION`: selection to use when `-c` and `xclip` are
    334   used, instead of `clipboard`
    335 
    336 ### git
    337 
    338 Syntax:
    339 
    340 ```
    341 pashage git git-command-args ...
    342 ```
    343 
    344 This subcommand invokes `git` in the database repository.
    345 Only `git init` and `git clone` are accepted when there is no underlying
    346 repository.
    347 
    348 Environment:
    349 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    350 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    351   when `PASHAGE_DIR` is unset
    352 - `PASSWORD_STORE_DIR`: database directory to use instead of
    353   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    354 
    355 ### gitconfig
    356 
    357 Syntax:
    358 
    359 ```
    360 pashage gitconfig
    361 ```
    362 
    363 This subcommand configures the underlying repository to automatically
    364 decrypt secrets to display differences.
    365 
    366 Environment:
    367 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    368 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    369   when `PASHAGE_DIR` is unset
    370 - `PASSWORD_STORE_DIR`: database directory to use instead of
    371   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    372 
    373 ### grep
    374 
    375 Syntax:
    376 
    377 ```
    378 pashage grep [GREP_OPTIONS] search-regex
    379 ```
    380 
    381 This subcommand successively decrypts all the secrets in the store and
    382 filter them through `grep(1)` using the given options, and outputs all the
    383 matching lines and the corresponding secret.
    384 
    385 Environment:
    386 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    387   color the output
    388 - `PASHAGE_AGE`: external command to use instead of `age`
    389 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    390 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    391   `~/.passage/identities`
    392 - `PASSAGE_AGE`: external command to use instead of `age` when
    393   `PASHAGE_AGE` is unset
    394 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    395   when `PASHAGE_DIR` is unset
    396 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    397   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    398 - `PASSWORD_STORE_DIR`: database directory to use instead of
    399   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    400 
    401 ### help
    402 
    403 Syntax:
    404 
    405 ```
    406 pashage help
    407 ```
    408 
    409 This subcommand displays on the standard output the version and help text,
    410 including all subcommands and flags and a brief description.
    411 
    412 This subcommand is not affected by the environment.
    413 
    414 ### init
    415 
    416 Syntax:
    417 
    418 ```
    419 pashage init [--interactive,-i | --keep,-k ]
    420              [--path=subfolder,-p subfolder] age-recipient ...
    421 ```
    422 
    423 This subcommand initializes an age _recipient_ list, by default of the root
    424 of the password store, and re-encrypts all the affected secrets.
    425 When the _recipient_ list is a single empty string, the _recipient_ list is
    426 instead removed, falling back to a parent _recipient_ list or ultimately to
    427 the age _identity_.
    428 
    429 Flags:
    430 - `-i` or `--interactive`: ask for each secret whether to re-encrypt it
    431   or not
    432 - `-k` or `--keep`: do not re-encrypt any secret
    433 - `-p` or `--path`: operate on the _recipient_ list in the given subfolder
    434   instead of the root of the password store
    435 
    436 Environment:
    437 - `PASHAGE_AGE`: external command to use instead of `age`
    438 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    439 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    440   `~/.passage/identities`
    441 - `PASSAGE_AGE`: external command to use instead of `age` when
    442   `PASHAGE_AGE` is unset
    443 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    444   when `PASHAGE_DIR` is unset
    445 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    446   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    447 - `PASSWORD_STORE_DIR`: database directory to use instead of
    448   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    449 
    450 ### insert
    451 
    452 Syntax:
    453 
    454 ```
    455 pashage insert [--echo,-e | --multiline,-m] [--force,-f] pass-name ...
    456 ```
    457 
    458 This subcommand adds new secrets in the database, using the provided data
    459 from the standard input. By default asks before overwriting an existing
    460 secret, and it reads a single secret line after turning off the console
    461 echo, and reads it a second time for confirmation.
    462 
    463 Flags:
    464 - `-e` or `--echo`: read a single line once without manipulating the
    465   standard input
    466 - `-m` or `--multiline`: an arbitrary amount of lines from the standard
    467   input, without trying to manipulate the console, until the end of input
    468   or a blank line is entered
    469 - `-f` or `--force`: overwrite an existing secret without asking
    470 
    471 Environment:
    472 - `PASHAGE_AGE`: external command to use instead of `age`
    473 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    474 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    475   `~/.passage/identities`
    476 - `PASSAGE_AGE`: external command to use instead of `age` when
    477   `PASHAGE_AGE` is unset
    478 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    479   when `PASHAGE_DIR` is unset
    480 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    481   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    482 - `PASSWORD_STORE_DIR`: database directory to use instead of
    483   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    484 
    485 ### list
    486 
    487 Syntax:
    488 
    489 ```
    490 pashage [list] [subfolder ...]
    491 ```
    492 
    493 This subcommand displays the given subfolders as a tree, or the whole store
    494 when no subfolder is specified.
    495 
    496 Note that when a secret is given instead of a subfolder, the _show_ command
    497 will be used instead, without any warning or error.
    498 
    499 Environment:
    500 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    501   color the output
    502 - `LC_CTYPE`: when it contains `UTF`, the tree is displayed using Unicode
    503   graphic characters instead of ASCII
    504 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    505 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    506   when `PASHAGE_DIR` is unset
    507 - `PASSWORD_STORE_DIR`: database directory to use instead of
    508   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    509 
    510 ### move
    511 
    512 Syntax:
    513 
    514 ```
    515 pashage move [--reencrypt,-e | --interactive,-i | --keep,-k ]
    516              [--force,-f] old-path ... new-path
    517 ```
    518 
    519 This subcommand moves or renames secrets and subfolders recursively,
    520 using the same positional argument scheme as `mv(1)`.
    521 By default it asks before overwriting an existing secret and it re-encrypts
    522 the secret when the destination has a different _recipient_ list.
    523 
    524 Flags:
    525 - `-e` or `--reencrypt`: always re-encrypt secrets
    526 - `-f` or `--force`: overwrite existing secrets without asking
    527 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    528 - `-k` or `--keep`: never re-encrypt secrets
    529 
    530 Environment:
    531 - `PASHAGE_AGE`: external command to use instead of `age`
    532 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    533 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    534   `~/.passage/identities`
    535 - `PASSAGE_AGE`: external command to use instead of `age` when
    536   `PASHAGE_AGE` is unset
    537 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    538   when `PASHAGE_DIR` is unset
    539 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    540   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    541 - `PASSWORD_STORE_DIR`: database directory to use instead of
    542   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    543 
    544 ### random
    545 
    546 Syntax:
    547 
    548 ```
    549 pashage random [pass-length [character-set]]
    550 ```
    551 
    552 This subcommand generates a new secret, like the _generate_ subcommand,
    553 then directly displays on the standard output without storing it.
    554 
    555 Environment:
    556 - `PASSWORD_STORE_CHARACTER_SET`: character set to use with `tr(1)` when
    557   `character-set` is not specified, instead of `[:punct:][:alnum:]`
    558 - `PASSWORD_STORE_GENERATED_LENGTH`: number of characters in the generated
    559   secret when not explicitly given, instead of 25
    560 
    561 ### reencrypt
    562 
    563 Syntax:
    564 
    565 ```
    566 pashage reencrypt [--interactive,-i] pass-name|subfolder ...
    567 ```
    568 
    569 This subcommand re-encrypts in place the given secrets, and all the secrets
    570 recursively in the given subfolders.
    571 
    572 Flags:
    573 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    574 
    575 Environment:
    576 - `PASHAGE_AGE`: external command to use instead of `age`
    577 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    578 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    579   `~/.passage/identities`
    580 - `PASSAGE_AGE`: external command to use instead of `age` when
    581   `PASHAGE_AGE` is unset
    582 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    583   when `PASHAGE_DIR` is unset
    584 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    585   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    586 - `PASSWORD_STORE_DIR`: database directory to use instead of
    587   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    588 
    589 ### show
    590 
    591 Syntax:
    592 
    593 ```
    594 pashage [show] [--clip[=line-number],-c[line-number] |
    595                 --qrcode[=line-number],-q[line-number]] pass-name ...
    596 ```
    597 
    598 This subcommand decrypts the given secrets and by default displays the
    599 whole text on the standard output.
    600 
    601 Note that when a subfolder is given instead of a secret, the _list_ command
    602 will be used instead, without any warning or error.
    603 
    604 Flags:
    605 - `-c` or `--clip`: paste the given line (by default the first line) of the
    606   secret into the clipboard instead of using the standard output
    607 - `-q` or `--qrcode`: display the given line (by default the first line) of
    608   the secret as a QR-code instead of using the standard output
    609 
    610 Environment:
    611 - `PASHAGE_AGE`: external command to use instead of `age`
    612 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    613 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    614   `~/.passage/identities`
    615 - `PASSAGE_AGE`: external command to use instead of `age` when
    616   `PASHAGE_AGE` is unset
    617 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    618   when `PASHAGE_DIR` is unset
    619 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    620   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    621 - `PASSWORD_STORE_DIR`: database directory to use instead of
    622   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    623 
    624 ### version
    625 
    626 Syntax:
    627 
    628 ```
    629 pashage version
    630 ```
    631 
    632 This subcommand displays on the standard output the version and author
    633 list.
    634 
    635 This subcommand is not affected by the environment.