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


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