{"id":17994043,"url":"https://github.com/pepa65/twofat","last_synced_at":"2026-03-14T18:58:07.766Z","repository":{"id":57504815,"uuid":"231291180","full_name":"pepa65/twofat","owner":"pepa65","description":"Manage a TOTP database by CLI","archived":false,"fork":false,"pushed_at":"2026-01-11T07:00:00.000Z","size":51696,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-11T13:41:41.111Z","etag":null,"topics":["2fa","2fa-client","2factor","totp","totp-authenticator","totp-cli"],"latest_commit_sha":null,"homepage":"","language":"Go","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/pepa65.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-01-02T02:13:32.000Z","updated_at":"2026-01-11T07:00:03.000Z","dependencies_parsed_at":"2024-03-19T11:52:42.644Z","dependency_job_id":"02177cf8-9d6d-44ac-9fe6-700c8913392d","html_url":"https://github.com/pepa65/twofat","commit_stats":null,"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/pepa65/twofat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepa65%2Ftwofat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepa65%2Ftwofat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepa65%2Ftwofat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepa65%2Ftwofat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pepa65","download_url":"https://codeload.github.com/pepa65/twofat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepa65%2Ftwofat/sbom","scorecard":{"id":727443,"data":{"date":"2025-08-11","repo":{"name":"github.com/pepa65/twofat","commit":"01cac73a9b98bba3586b8aede2389641ed52b6fe"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":3,"reason":"4 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.2.5 not signed: https://api.github.com/repos/pepa65/twofat/releases/239898303","Warn: release artifact v2.2.4 not signed: https://api.github.com/repos/pepa65/twofat/releases/231702866","Warn: release artifact v2.2.3 not signed: https://api.github.com/repos/pepa65/twofat/releases/225887763","Warn: release artifact v2.2.2 not signed: https://api.github.com/repos/pepa65/twofat/releases/220272488","Warn: release artifact v2.2.1 not signed: https://api.github.com/repos/pepa65/twofat/releases/216179964","Warn: release artifact v2.2.5 does not have provenance: https://api.github.com/repos/pepa65/twofat/releases/239898303","Warn: release artifact v2.2.4 does not have provenance: https://api.github.com/repos/pepa65/twofat/releases/231702866","Warn: release artifact v2.2.3 does not have provenance: https://api.github.com/repos/pepa65/twofat/releases/225887763","Warn: release artifact v2.2.2 does not have provenance: https://api.github.com/repos/pepa65/twofat/releases/220272488","Warn: release artifact v2.2.1 does not have provenance: https://api.github.com/repos/pepa65/twofat/releases/216179964"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}}]},"last_synced_at":"2025-08-22T13:16:37.337Z","repository_id":57504815,"created_at":"2025-08-22T13:16:37.337Z","updated_at":"2025-08-22T13:16:37.337Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28491737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T00:50:05.742Z","status":"ssl_error","status_checked_at":"2026-01-17T00:43:11.982Z","response_time":107,"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":["2fa","2fa-client","2factor","totp","totp-authenticator","totp-cli"],"created_at":"2024-10-29T20:13:50.804Z","updated_at":"2026-01-17T01:53:44.298Z","avatar_url":"https://github.com/pepa65.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# twofat\n\u003cimg src=\"https://raw.githubusercontent.com/pepa65/twofat/master/twofat.png\" width=\"96\" alt=\"twofat icon\" align=\"right\"\u003e\n\n## Manage TOTPs from CLI\n* **v2.2.3**\n* Repo: [github.com/pepa65/twofat](https://github.com/pepa65/twofat)\n* After: [github.com/slandx/tfat](https://github.com/slandx/tfat)\n* Contact: github.com/pepa65\n* Install: `wget -qO- gobinaries.com/pepa65/twofat |sh`\n* Migration from pre v1.0.0 versions of twofat:\n  **Export the data with twofat v0 and import that with twofat v1.**\n* Migration from pre v2.0.0 versions of twofat:\n  **Export the data with twofat v1 (or v0) and import that with twofat v2.**\n\n### Features\n* Data saved with AES-GCM encrypt in ~/.twofat.enc (by default).\n* Memory is wiped of SECRETs, garbage collected. Best not to give SECRET on the commandline!\n  For even more security, run like: `GODEBUG=clobberfree=1 twofat`\n* Datafile password can be changed.\n* Display TOTPs of names matching regex, which auto-refresh.\n* Option to display the next TOTP as well.\n* Add, rename, delete entry, reveal secret, copy TOTP to clipboard.\n* Import \u0026 export entries from \u0026 to standardized OTPAUTH_URI file.\n* Adjusts to terminal width for display. NAME truncated to 20 on display\n  (shown in full on `export` and `ls`/`list`).\n* Implementing RFC 4226/6238:\n  - Defaults to HMAC-SHA-1 hashing, but allows HMAC-SHA-256 and HMAC-SHA-512.\n  - Defaults to a TOTP length of 6, but allows 5 (for Steam), 7 (Twitch) and 8 (no other lengths seem to be in use).\n  - The minimum SECRET length (128 bit, or 26 base32-chars) is not enforced (1 char is the minimum).\n    Most OTP servers seem to use less than the minimum (security is not significantly reduced).\n    There is no maximum length for a SECRET in twofat.\n  - A 30 second timeout seems to be more or less universal, and twofat only supports 30 for period LENGTH.\n    (Making this shorter does little to prevent the success of brute-force attacks.)\n\n## Build\n```shell\n# While in the repo root directory:\ngo build\n\n# Or anywhere:\ngo get -u github.com/pepa65/twofat\n\n# Smaller binary:\ngo build -ldflags=\"-s -w\"\n\n# More extreme shrinking:\nupx twofat*\n\n# Build for various architectures:\nCGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags=\"-s -w\" -o twofat\nCGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags=\"-s -w\" -o twofat_pi\nCGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags=\"-s -w\" -o twofat_bsd\nCGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags=\"-s -w\" -o twofat_osx\nCGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags=\"-s -w\" -o twofat.exe\n```\n\n## Usage\n```\ntwofat v2.2.3 - Manage TOTPs from CLI\nThe CLI is interactive \u0026 colorful, output to Stderr. Password can be piped in.\nWhen output is redirected, only pertinent plain text is sent to Stdout.\n* Repo:       github.com/pepa65/twofat \u003cpepa65@passchier.net\u003e\n* Datafile:   ~/.twofat.enc  (default, depends on the binary's name)\n* Usage:      twofat  [COMMAND]  [ -d | --datafile  DATAFILE ]\n  == COMMAND:\n[ show | view ]  [REGEX [ -c | --case ]]  [ -n | --next ]\n    Display all TOTPs with NAMEs [matching REGEX] (-n/--next: show next TOTP).\nlist | ls  [REGEX [ -c | --case ]]\n    List all NAMEs [matching REGEX].\nadd | insert | entry  NAME  [TOTP-OPTIONS]  [ -f | --force ]  [SECRET]\n    Add a new entry NAME with SECRET (queried when not given).\n    If -f/--force: existing NAME overwritten, no NAME max.length check.\ntotp | temp  [TOTP-OPTIONS]  [SECRET]\n    Show the TOTP for SECRET (queried when not given), no datafile access.\ndelete | remove | rm  NAME  [ -f | --force ]\n    Delete entry NAME. If -f/--force: no confirmation asked.\nrename | move | mv  NAME  NEWNAME  [ -f | --force ]\n    Rename entry NAME to NEWNAME, if -f/--force: no max.length checks.\nimport  FILE  [ -f | --force ]\n    Import lines with OTPAUTH_URI from file FILE.\n    If -f/--force: existing NAME overwritten, no NAME max.length check.\nexport  [FILE]              Export OTPAUTH_URI-format entries [to file FILE].\nreveal | secret  NAME       Show Secret of entry NAME.\nclip | copy | cp  NAME      Put TOTP of entry NAME onto the clipboard.\npassword | passwd | pw      Change datafile encryption password.\nversion | --version | -V    Show version.\nhelp | --help | -h          Show this help text.\n  == REGEX:  Optional, case-insensitive matching (unless -c/--case is given).\n  == TOTP-OPTIONS:\n-s | --size  LENGTH       TOTP length: 5-8 (default: 6).\n-a | --algorithm  HASH    Hash algorithm: SHA1/SHA256/SHA512 (default: SHA1).\n```\n\n### Import/Export data\n`twofat` abides by the backup standard from:\nhttps://www.ietf.org/archive/id/draft-linuxgemini-otpauth-uri-01.html\n\nEach exported line has a otpauth URI of the form:\n`otpauth://totp/NAME?secret=SECRET\u0026algorithm=HASH\u0026digits=LENGTH\u0026period=PERIOD\u0026issuer=NAME`\n(the capitalized parts are variable parameters: `NAME`, `SECRET`, `HASH`, `LENGTH`, `PERIOD`).\n\n* The `NAME` should not have a colon `:` or `%` (messes with URI conversion).\n  (`NAME` could be `ISSUER:ACCOUNTNAME`, but `twofat` uses the full `NAME` for the `issuer` parameter.)\n* The `SECRET` is the base32 RFC3548 seed (without the `=` padding!) for the OTPs.\n* `NAME` and `SECRET` are mandatory.\n* The `HASH` for `algorithm` is `SHA1` (the default), `SHA256` or `SHA512`.\n* The `LENGTH` for `digits` is most often `6`, but can be set to `5` (for Steam), `7` (Twitch) or `8` (Microsoft).\n* The `PERIOD` for `period` is fixed to `30` (the default) in (almost?) all apps.\n* On import, `digits`, `period` and `algorithm` will be set to the defaults when not specified.\n* The `issuer` is set to `NAME` on export from `twofat`, and is ignored on import.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpepa65%2Ftwofat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpepa65%2Ftwofat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpepa65%2Ftwofat/lists"}