{"id":21881119,"url":"https://github.com/wtsi-hgi/secrets","last_synced_at":"2026-05-15T13:31:26.285Z","repository":{"id":146402616,"uuid":"99107292","full_name":"wtsi-hgi/secrets","owner":"wtsi-hgi","description":"A command line based secrets manager","archived":false,"fork":false,"pushed_at":"2017-10-24T22:25:39.000Z","size":102,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-16T04:54:27.126Z","etag":null,"topics":["bash","blockchain","gnupg","gpg","password-manager"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wtsi-hgi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-02T11:07:02.000Z","updated_at":"2018-02-27T10:24:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"40469fe7-0964-4c13-b5a6-60bd6de467cf","html_url":"https://github.com/wtsi-hgi/secrets","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/wtsi-hgi/secrets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wtsi-hgi%2Fsecrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wtsi-hgi%2Fsecrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wtsi-hgi%2Fsecrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wtsi-hgi%2Fsecrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wtsi-hgi","download_url":"https://codeload.github.com/wtsi-hgi/secrets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wtsi-hgi%2Fsecrets/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33068347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","blockchain","gnupg","gpg","password-manager"],"created_at":"2024-11-28T09:17:53.358Z","updated_at":"2026-05-15T13:31:26.264Z","avatar_url":"https://github.com/wtsi-hgi.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Secrets\n\n[![Build Status](https://travis-ci.org/wtsi-hgi/secrets.svg?branch=master)](https://travis-ci.org/wtsi-hgi/secrets)\n\nA command line based secrets manager.\n\n## Usage\n\n    secrets SUBCOMMAND [OPTIONS]\n    secrets (-V | --version)\n    secrets (-h | --help)\n\nThe `-h` or `--help` option can be used against any subcommand for\ndetails.\n\n## Common Options\n\nThe following options are common to all subcommands and can be placed\nanywhere within the command line arguments:\n\n    --secrets FILE        Secrets file [~/.secrets]\n    --gpg FILE            Alternative GnuPG binary [auto-detected]\n\nBy default, the latest version of GnuPG within your path (i.e., binaries\nnamed `gpg` and `gpg2`) is used.\n\n## Subcommands\n\n### `keep`\n\n    secrets keep [OPTIONS] SECRET_ID [SECRET]\n\nKeep a secret with the identifier of `SECRET_ID`. The secret can be\nspecified with the plaintext given in `SECRET`, read through `stdin`, or\ngenerated following the rule policy provided by the options.\n\nOptions:\n\n    --force               Overwrite the secret if it already exists\n    --length LENGTH       Length [16]\n    --allowed CLASS       Class of allowed characters [a-zA-Z0-9!?$%\u0026=+_-]\n    --must-include CLASS  Class of characters that must be included (this\n                          option can be provided multiple times)\n    --expire SECONDS      Delete the secret from the clipboard, if used,\n                          after a time limit [30]\n    --reveal              Write the secret to stdout, rather than to the\n                          clipboard\n\nThe default policy will generate a secret with over 98 bits of entropy.\n\nIf the secrets file has not yet been created, you will be prompted for\nyour GnuPG encryption and signing key IDs.\n\nYou mustn't supply more `--must-include` arguments than the `--length`,\notherwise an error will be raised. Also note that the `--allowed` and\n`--must-include` classes may be mutually exclusive.\n\n**Warning** Specifying the secret in the command line is dangerous, as\nit will be preserved in your shell history. If you must do this, rather\nthan generating a random password or reading from `stdin`, then you're\nadvised to add a layer of indirection. For example, in Bash:\n\n    secrets keep [OPTIONS] SECRET_ID \"$(read -rsp \"Secret: \" X \u0026\u0026 echo -n \"$X\")\"\n\n**Warning** You should not recycle secrets, even those that are no\nlonger in use. You will be warned and advised to keep a different secret\nif any duplication is detected.\n\n### `tell`\n\n    secrets tell [OPTIONS] SECRET_ID\n\nTell the secret with the identifier of `SECRET_ID`.\n\nOptions:\n\n    --expire SECONDS      Delete the secret from the clipboard, if used,\n                          after a time limit [30]\n    --reveal              Write the secret to stdout, rather than to the\n                          clipboard\n\n### `expose`\n\n    secrets expose [OPTIONS]\n\nExpose the list of all the available secret IDs.\n\nOptions:\n\n    --with-date           Include the date the secret was kept\n\n### `forget`\n\n    secrets forget [OPTIONS] SECRET_ID\n\nForget the secret with the identifier of `SECRET_ID`.\n\n## Installation\n\nJust copy or symlink `secrets` to somewhere in your `PATH`.\n\n### Dependencies\n\nThe following dependencies are required:\n\n* Bash 4.2, or newer\n* [GnuPG](https://gnupg.org/) (tested with 1.4, 2.0, 2.1 and 2.2)\n* A means of calculating SHA256 digests (either `sha256sum` or OpenSSL)\n\nYou will need at least one valid encryption and signing key. Note that,\nwith GnuPG 2 (and later), your `pinentry` program will be invoked to\nacquire the key passphrase; this may not work correctly with a\nterminal-based `pinentry`.\n\nFor clipboard support, the following dependencies are needed:\n\n* macOS: `pbcopy` and `pbpaste`\n* Linux: `xclip`\n\n## Blockchain Maintenance\n\nEvery time a secret is kept, told or forgotten, it is logged in the\nsecrets blockchain. In time, this can cause the database to become large\nand unwieldy. Moreover, if you have a need to revoke the GnuPG keys with\nwhich you signed or encrypted your database, you'll face similar\nproblems. To this end, you can transfer just the kept secrets from one\nblockchain to another with the following command:\n\n\u003c!-- FIXME This command may not work if the secret IDs contain whitespace --\u003e\n\n    secrets expose --secrets OLD_BLOCKCHAIN | \\\n    tee \u003e(wc -l | xargs -I{} echo \"Transferring {} secrets...\" \u003e\u00262) | \\\n    xargs -n1 -I{} bash -c \"secrets keep --secrets NEW_BLOCKCHAIN\n                                         '{}' \\\"\\$(secrets tell --secrets OLD_BLOCKCHAIN --reveal '{}' 2\u003e/dev/null)\\\"\n                                         \u003e/dev/null\"\n\nNote that this process will take some time to complete (O(n) on the\nnumber of secrets you have) and GnuPG may prompt you for various key\npassphrases, throughout. The status of the new blockchain calculation\nwill be written to `stderr`; it is important that this is *not*\nredirected to `/dev/null`, in case `secrets` asks you to choose new\nencryption or signing keys.\n\n*n.b., The term \"blockchain\" is used somewhat liberally!*\n\n## Why Not Just Use `pass`?\n\n\u003cp align=\"center\"\u003e\u003cimg alt=\"xkcd Standards\" src=\"https://imgs.xkcd.com/comics/standards.png\"\u003e\u003c/p\u003e\n\n`secrets` was inspired by Jason A. Donenfeld's [`pass`](https://www.passwordstore.org/),\nbut with several key differences:\n\n* Secrets are stored in a single database, so no metadata (from the\n  secret IDs, for instance) is leaked. [`pass-tomb`](https://github.com/roddhjav/pass-tomb)\n  provides a similar function for `pass`, but at the expense of\n  complexity.\n\n* `secrets` has a much simpler interface, yet it provides all the useful\n  functionality of `pass`, plus a few neat tricks of its own.\n\n* The secrets database is structured as a self-validating blockchain\n  audit log, for additional security.\n\n* No automatic Git integration, so you can use a VCS of your choice\n  and/or manage the version control of your database how you prefer (if\n  you wish).\n\nThink of `secrets` as `pass-lite`!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwtsi-hgi%2Fsecrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwtsi-hgi%2Fsecrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwtsi-hgi%2Fsecrets/lists"}