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 (22494B)


      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 - completion for various shells
    107 - better logic for recursivity in re-encryption
    108 - rewriting of git history to purge old cyphertexts
    109 - partial display of secrets on standard output
    110 - successive clipboard copy of several lines from a single decryption
    111 (e.g. username then password)
    112 - OTP support
    113 - maybe extension support?
    114 
    115 ## Manual
    116 
    117 **pashage** is a _password manager_, which means it manages a database of
    118 encrypted secrets, including encrypting externally-provided new secrets,
    119 generating and encrypting random strings, and decrypting and displaying
    120 stored secrets.
    121 
    122 It aims to be simple and composable, but its reliance on Unix philosophy
    123 and customs might make steep learning curve for users outside of this
    124 culture.
    125 
    126 It is used through a shell command, denoted as `pashage` in this document,
    127 immediately followed by a subcommand and its arguments. When no subcommand
    128 is specified, _list_ or _show_ is implicitly assumed.
    129 
    130 The database is optionally versioned using [git](https://git-scm.com/)
    131 to help with history audit and synchronization. It should be noted that
    132 this prevents re-encryption from erasing old cyphertext, leaving the secret
    133 vulnerable to compromised encryption keys.
    134 
    135 The cryptography is done by [age](https://age-encryption.org/) external
    136 command. It decrypts using the _identity_ file given in the environment,
    137 and crypts using a list of _recipients_ per subfolder, defaulting to the
    138 parent _recipient_ list or the _identity_.
    139 
    140 ## Command Reference
    141 
    142 Here is an alphabetical list of all subcommands and aliases:
    143 
    144 - `--help`: alias for _help_
    145 - `--version`: alias for _version_
    146 - `-h`: alias for _help_
    147 - `copy`
    148 - `cp`: alias for _copy_
    149 - `delete`
    150 - `edit`
    151 - `find`
    152 - `gen`: alias for _generate_
    153 - `generate`
    154 - `git`
    155 - `gitconfig`
    156 - `grep`
    157 - `help`
    158 - `init`
    159 - `insert`
    160 - `list`
    161 - `ls`: alias for _list_
    162 - `move`
    163 - `mv`: alias for _move_
    164 - `random`
    165 - `re-encrypt`: alias for _reencrypt_
    166 - `reencrypt`
    167 - `remove`: alias for _delete_
    168 - `rm`: alias for _delete_
    169 - `show`
    170 - `version`
    171 
    172 ### copy
    173 
    174 Syntax:
    175 
    176 ```
    177 pashage copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
    178              [--force,-f] old-path ... new-path
    179 ```
    180 
    181 This subcommand copies secrets and recursively copies subfolders,
    182 using the same positional argument scheme as `cp(1)`.
    183 By default it asks before overwriting an existing secret and it re-encrypts
    184 the secret when the destination has a different _recipient_ list.
    185 
    186 Flags:
    187 - `-e` or `--reencrypt`: always re-encrypt secrets
    188 - `-f` or `--force`: overwrite existing secrets without asking
    189 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    190 - `-k` or `--keep`: never re-encrypt secrets
    191 
    192 Environment:
    193 - `PASHAGE_AGE`: external command to use instead of `age`
    194 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    195 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    196   `~/.passage/identities`
    197 - `PASSAGE_AGE`: external command to use instead of `age` when
    198   `PASHAGE_AGE` is unset
    199 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    200   when `PASHAGE_DIR` is unset
    201 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    202   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    203 - `PASSWORD_STORE_DIR`: database directory to use instead of
    204   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    205 
    206 ### delete
    207 
    208 Syntax:
    209 
    210 ```
    211 pashage delete [--recursive,-r] [--force,-f] pass-name ...
    212 ```
    213 
    214 This subcommand deletes secrets from the database. By default it skips
    215 subfolders and asks for confirmation for each secret.
    216 
    217 Flags:
    218 - `-f` or `--force`: delete without asking for confirmation
    219 - `-r` or `--recursive`: recursively delete all secrets in given subfolders
    220 
    221 Environment:
    222 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    223 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    224   when `PASHAGE_DIR` is unset
    225 - `PASSWORD_STORE_DIR`: database directory to use instead of
    226   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    227 
    228 ### edit
    229 
    230 Syntax:
    231 
    232 ```
    233 pashage edit pass-name ...
    234 ```
    235 
    236 This subcommand starts an interactive editor to update the secrets.
    237 
    238 Environment:
    239 - `EDITOR`: editor command to use instead of `vi` when `VISUAL` is not set
    240 - `PASHAGE_AGE`: external command to use instead of `age`
    241 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    242 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    243   `~/.passage/identities`
    244 - `PASSAGE_AGE`: external command to use instead of `age` when
    245   `PASHAGE_AGE` is unset
    246 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    247   when `PASHAGE_DIR` is unset
    248 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    249   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    250 - `PASSWORD_STORE_DIR`: database directory to use instead of
    251   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    252 - `TMPDIR`: temporary directory for the decrypted file to use instead of
    253   `/tmp` when `/dev/shm` is not available
    254 - `VISUAL`: editor command to use instead of `vi`
    255 
    256 ### find
    257 
    258 Syntax:
    259 
    260 ```
    261 pashage find [GREP_OPTIONS] regex
    262 ```
    263 
    264 This subcommand lists as a tree the secrets whose name match the given
    265 regular expression, using the corresponding `grep(1)` options.
    266 
    267 Environment:
    268 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    269   color the output
    270 - `LC_CTYPE`: when it contains `UTF`, the tree is displayed using Unicode
    271   graphic characters instead of ASCII
    272 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    273 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    274   when `PASHAGE_DIR` is unset
    275 - `PASSWORD_STORE_DIR`: database directory to use instead of
    276   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    277 
    278 ### generate
    279 
    280 ```
    281 pashage generate [--no-symbols,-n] [--clip,-c | --qrcode,-q]
    282                  [--in-place,-i | --force,-f] [--multiline,-m]
    283                  [--try,-t] pass-name [pass-length [character-set]]
    284 ```
    285 
    286 This subcommand generates a new secret from `/dev/urandom`, stores it in
    287 the database, and by default displays it on the standard output and asks
    288 for confirmation before overwriting an existing secret.
    289 
    290 Flags:
    291 - `-c` or `--clip`: paste the secret into the clipboard instead of using
    292   the standard output
    293 - `-f` or `--force`: replace existing secrets without asking
    294 - `-i` or `--in-place`: when the secret already exists, replace only its
    295   first line and re-use the following lines
    296 - `-m` or `--multiline`: read lines from standard input append after the
    297   generated data into the secret file
    298 - `-n` or `--no-symbols`: generate a secret using only alphanumeric
    299   characters
    300 - `-q` or `--qrcode`: display the secret as a QR-code instead of using the
    301   standard output
    302 - `-t` or `--try`: display the secret and ask for confirmation before
    303   storing it into the database
    304 
    305 Environment:
    306 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    307   color the output
    308 - `PASHAGE_AGE`: external command to use instead of `age`
    309 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    310 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    311   `~/.passage/identities`
    312 - `PASSAGE_AGE`: external command to use instead of `age` when
    313   `PASHAGE_AGE` is unset
    314 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    315   when `PASHAGE_DIR` is unset
    316 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    317   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    318 - `PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS`: default character set to use
    319   with `tr(1)` when `-n` is specified, instead of `[:alnum:]`
    320 - `PASSWORD_STORE_CHARACTER_SET`: default character set to use with `tr(1)`
    321   when `-n` is not specified, instead of `[:punct:][:alnum:]`
    322 - `PASSWORD_STORE_CLIP_TIME`: number of second before clearing the
    323   clipboard when `-c` is used, instead of 45
    324 - `PASSWORD_STORE_DIR`: database directory to use instead of
    325   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    326 - `PASSWORD_STORE_GENERATED_LENGTH`: number of characters in the generated
    327   secret when not explicitly given, instead of 25
    328 - `PASSWORD_STORE_X_SELECTION`: selection to use when `-c` and `xclip` are
    329   used, instead of `clipboard`
    330 
    331 ### git
    332 
    333 Syntax:
    334 
    335 ```
    336 pashage git git-command-args ...
    337 ```
    338 
    339 This subcommand invokes `git` in the database repository.
    340 Only `git init` and `git clone` are accepted when there is no underlying
    341 repository.
    342 
    343 Environment:
    344 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    345 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    346   when `PASHAGE_DIR` is unset
    347 - `PASSWORD_STORE_DIR`: database directory to use instead of
    348   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    349 
    350 ### gitconfig
    351 
    352 Syntax:
    353 
    354 ```
    355 pashage gitconfig
    356 ```
    357 
    358 This subcommand configures the underlying repository to automatically
    359 decrypt secrets to display differences.
    360 
    361 Environment:
    362 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    363 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    364   when `PASHAGE_DIR` is unset
    365 - `PASSWORD_STORE_DIR`: database directory to use instead of
    366   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    367 
    368 ### grep
    369 
    370 Syntax:
    371 
    372 ```
    373 pashage grep [GREP_OPTIONS] search-regex
    374 ```
    375 
    376 This subcommand successively decrypts all the secrets in the store and
    377 filter them through `grep(1)` using the given options, and outputs all the
    378 matching lines and the corresponding secret.
    379 
    380 Environment:
    381 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    382   color the output
    383 - `PASHAGE_AGE`: external command to use instead of `age`
    384 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    385 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    386   `~/.passage/identities`
    387 - `PASSAGE_AGE`: external command to use instead of `age` when
    388   `PASHAGE_AGE` is unset
    389 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    390   when `PASHAGE_DIR` is unset
    391 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    392   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    393 - `PASSWORD_STORE_DIR`: database directory to use instead of
    394   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    395 
    396 ### help
    397 
    398 Syntax:
    399 
    400 ```
    401 pashage help
    402 ```
    403 
    404 This subcommand displays on the standard output the version and help text,
    405 including all subcommands and flags and a brief description.
    406 
    407 This subcommand is not affected by the environment.
    408 
    409 ### init
    410 
    411 Syntax:
    412 
    413 ```
    414 pashage init [--interactive,-i | --keep,-k ]
    415              [--path=subfolder,-p subfolder] age-recipient ...
    416 ```
    417 
    418 This subcommand initializes an age _recipient_ list, by default of the root
    419 of the password store, and re-encrypts all the affected secrets.
    420 When the _recipient_ list is a single empty string, the _recipient_ list is
    421 instead removed, falling back to a parent _recipient_ list or ultimately to
    422 the age _identity_.
    423 
    424 Flags:
    425 - `-i` or `--interactive`: ask for each secret whether to re-encrypt it
    426   or not
    427 - `-k` or `--keep`: do not re-encrypt any secret
    428 - `-p` or `--path`: operate on the _recipient_ list in the given subfolder
    429   instead of the root of the password store
    430 
    431 Environment:
    432 - `PASHAGE_AGE`: external command to use instead of `age`
    433 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    434 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    435   `~/.passage/identities`
    436 - `PASSAGE_AGE`: external command to use instead of `age` when
    437   `PASHAGE_AGE` is unset
    438 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    439   when `PASHAGE_DIR` is unset
    440 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    441   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    442 - `PASSWORD_STORE_DIR`: database directory to use instead of
    443   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    444 
    445 ### insert
    446 
    447 Syntax:
    448 
    449 ```
    450 pashage insert [--echo,-e | --multiline,-m] [--force,-f] pass-name ...
    451 ```
    452 
    453 This subcommand adds new secrets in the database, using the provided data
    454 from the standard input. By default asks before overwriting an existing
    455 secret, and it reads a single secret line after turning off the console
    456 echo, and reads it a second time for confirmation.
    457 
    458 Flags:
    459 - `-e` or `--echo`: read a single line once without manipulating the
    460   standard input
    461 - `-m` or `--multiline`: an arbitrary amount of lines from the standard
    462   input, without trying to manipulate the console, until the end of input
    463   or a blank line is entered
    464 - `-f` or `--force`: overwrite an existing secret without asking
    465 
    466 Environment:
    467 - `PASHAGE_AGE`: external command to use instead of `age`
    468 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    469 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    470   `~/.passage/identities`
    471 - `PASSAGE_AGE`: external command to use instead of `age` when
    472   `PASHAGE_AGE` is unset
    473 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    474   when `PASHAGE_DIR` is unset
    475 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    476   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    477 - `PASSWORD_STORE_DIR`: database directory to use instead of
    478   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    479 
    480 ### list
    481 
    482 Syntax:
    483 
    484 ```
    485 pashage [list] [subfolder ...]
    486 ```
    487 
    488 This subcommand displays the given subfolders as a tree, or the whole store
    489 when no subfolder is specified.
    490 
    491 Note that when a secret is given instead of a subfolder, the _show_ command
    492 will be used instead, without any warning or error.
    493 
    494 Environment:
    495 - `CLICOLOR`: when set to a non-empty value, use ANSI escape sequences to
    496   color the output
    497 - `LC_CTYPE`: when it contains `UTF`, the tree is displayed using Unicode
    498   graphic characters instead of ASCII
    499 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    500 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    501   when `PASHAGE_DIR` is unset
    502 - `PASSWORD_STORE_DIR`: database directory to use instead of
    503   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    504 
    505 ### move
    506 
    507 Syntax:
    508 
    509 ```
    510 pashage move [--reencrypt,-e | --interactive,-i | --keep,-k ]
    511              [--force,-f] old-path ... new-path
    512 ```
    513 
    514 This subcommand moves or renames secrets and subfolders recursively,
    515 using the same positional argument scheme as `mv(1)`.
    516 By default it asks before overwriting an existing secret and it re-encrypts
    517 the secret when the destination has a different _recipient_ list.
    518 
    519 Flags:
    520 - `-e` or `--reencrypt`: always re-encrypt secrets
    521 - `-f` or `--force`: overwrite existing secrets without asking
    522 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    523 - `-k` or `--keep`: never re-encrypt secrets
    524 
    525 Environment:
    526 - `PASHAGE_AGE`: external command to use instead of `age`
    527 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    528 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    529   `~/.passage/identities`
    530 - `PASSAGE_AGE`: external command to use instead of `age` when
    531   `PASHAGE_AGE` is unset
    532 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    533   when `PASHAGE_DIR` is unset
    534 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    535   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    536 - `PASSWORD_STORE_DIR`: database directory to use instead of
    537   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    538 
    539 ### random
    540 
    541 Syntax:
    542 
    543 ```
    544 pashage random [pass-length [character-set]]
    545 ```
    546 
    547 This subcommand generates a new secret, like the _generate_ subcommand,
    548 then directly displays on the standard output without storing it.
    549 
    550 Environment:
    551 - `PASSWORD_STORE_CHARACTER_SET`: character set to use with `tr(1)` when
    552   `character-set` is not specified, instead of `[:punct:][:alnum:]`
    553 - `PASSWORD_STORE_GENERATED_LENGTH`: number of characters in the generated
    554   secret when not explicitly given, instead of 25
    555 
    556 ### reencrypt
    557 
    558 Syntax:
    559 
    560 ```
    561 pashage reencrypt [--interactive,-i] pass-name|subfolder ...
    562 ```
    563 
    564 This subcommand re-encrypts in place the given secrets, and all the secrets
    565 recursively in the given subfolders.
    566 
    567 Flags:
    568 - `-i` or `--interactive`: asks whether to re-encrypt or not for each secret
    569 
    570 Environment:
    571 - `PASHAGE_AGE`: external command to use instead of `age`
    572 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    573 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    574   `~/.passage/identities`
    575 - `PASSAGE_AGE`: external command to use instead of `age` when
    576   `PASHAGE_AGE` is unset
    577 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    578   when `PASHAGE_DIR` is unset
    579 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    580   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    581 - `PASSWORD_STORE_DIR`: database directory to use instead of
    582   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    583 
    584 ### show
    585 
    586 Syntax:
    587 
    588 ```
    589 pashage [show] [--clip[=line-number],-c[line-number] |
    590                 --qrcode[=line-number],-q[line-number]] pass-name ...
    591 ```
    592 
    593 This subcommand decrypts the given secrets and by default displays the
    594 whole text on the standard output.
    595 
    596 Note that when a subfolder is given instead of a secret, the _list_ command
    597 will be used instead, without any warning or error.
    598 
    599 Flags:
    600 - `-c` or `--clip`: paste the given line (by default the first line) of the
    601   secret into the clipboard instead of using the standard output
    602 - `-q` or `--qrcode`: display the given line (by default the first line) of
    603   the secret as a QR-code instead of using the standard output
    604 
    605 Environment:
    606 - `PASHAGE_AGE`: external command to use instead of `age`
    607 - `PASHAGE_DIR`: database directory to use instead of `~/.passage/store`
    608 - `PASHAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    609   `~/.passage/identities`
    610 - `PASSAGE_AGE`: external command to use instead of `age` when
    611   `PASHAGE_AGE` is unset
    612 - `PASSAGE_DIR`: database directory to use instead of `~/.passage/store`
    613   when `PASHAGE_DIR` is unset
    614 - `PASSAGE_IDENTITIES_FILE`: _identity_ file to use instead of
    615   `~/.passage/identities` when `PASHAGE_IDENTITIES_FILE` is unset
    616 - `PASSWORD_STORE_DIR`: database directory to use instead of
    617   `~/.passage/store` when both `PASHAGE_DIR` and `PASSAGE_DIR` are unset
    618 
    619 ### version
    620 
    621 Syntax:
    622 
    623 ```
    624 pashage version
    625 ```
    626 
    627 This subcommand displays on the standard output the version and author
    628 list.
    629 
    630 This subcommand is not affected by the environment.