@voyageurworks/launch-guard

中文文档
0.1.3发布于 2026/11/03MITES Module零依赖构建来源已验证

Scan a private git repo before it goes public and report secrets, personal details, restricted terms and reachable old commits without printing private data.

原始使用文档
文档目录15 节
  1. What it looks like
  2. Why
  3. Next to gitleaks and TruffleHog
  4. Use it as a Claude Code or Codex skill
  5. First run, no setup
  6. In scripts, before a push, and in CI
  7. Your private list
  8. The four checks
  9. Reading the report
  10. Levels and exit codes
  11. Network and files
  12. Stop your assistant reading the list
  13. Honest limits
  14. Contributing and security
  15. Licence

launch-guard

npm CI License: MIT

Check a private git repository before you make it public, and never print what it finds.

npx -y @voyageurworks/launch-guard path/to/your/repo

You need Node 22 or newer and nothing else. It never edits the repository, and the only network step (a read-only git ls-remote) can be switched off with --offline. The exit code is 0 when nothing blocks publishing, 1 when something does.

What it looks like

Real output on a throwaway repository whose app.js holds a fake AWS-style key:

BLOCK (2)
  app.js:1 secret format
  4e4cc92:app.js:1 secret in history

WARN (4)
  list private list has no entries
  LICENSE missing LICENSE
  SECURITY missing SECURITY
  CI missing CI

INFO (1)
  remote no remote
RESULT: FAIL

It says which file and line, what kind of problem, and that an old commit holds the same thing (deleting the line is not enough once a repository is public). It does not print the key, any part of it, or the commit message.

Try the same thing in 30 seconds, with no real secret (bash, macOS, Linux or Git Bash; your commit id will differ):

mkdir launch-guard-demo && cd launch-guard-demo && git init -q
printf "const k = 'AKIA%s';\n" ABCDEFGHIJKLMNOP > app.js
git add . && git -c user.name=demo -c user.email=demo commit -qm demo
npx -y @voyageurworks/launch-guard . --offline

By Voyageur Works. MIT licence.

Why

More and more repositories are written with an AI assistant, and the assistant is also the one you ask "is this safe to publish?" The trouble is that a normal scanner prints what it finds. If an AI runs it, your secret key or your home address is now in the chat.

launch-guard is built so that cannot happen. It only reports where something is (file and line), what kind of problem it is, and which entry of your private list matched. It does not print the secret, any part of it, a value from your list, an author name or a commit message. It never changes your files, rewrites history or pushes. The only network use is a read-only git ls-remote against your configured remotes (skip it with --offline), and the only file it writes is the template from --init-list.

Next to gitleaks and TruffleHog

launch-guard does not replace a general secret scanner; run those too. They are built for other jobs. Everything in the right-hand column comes from their own READMEs (checked 2026-11-02).

launch-guardgitleaks, TruffleHog
Main question"Is this repository safe to make public?""Where are the secrets in this code, history or data source?"
What a finding showsFile and line, kind of problem, which list entry matched. Never the value, an author or a commit message.gitleaks' documented git -v output shows the matched secret, the author, the email and the commit.
Your own private words (names, address, school, codewords)Checked from a private list that stays outside the repositoryNot their purpose (gitleaks can be given custom rules)
Where it looksOne git repository: files, history, tags, reflog, leftover refsgitleaks: git repositories, directories and stdin. TruffleHog also scans chats, wikis, object stores and more
Secret formatsA focused set of known formats plus assignments next to words like key or tokenTruffleHog classifies 800+ secret types and can check whether a credential is still live
Built to be run by an AI assistantYes: the output is safe to appear in a chatNot what they are designed around

Use gitleaks or TruffleHog for continuous scanning and to check live credentials. Use launch-guard as the last check before you press "make public", and whenever an AI assistant is the one running it.

Use it as a Claude Code or Codex skill

First run, no setup

npx -y @voyageurworks/launch-guard <repo>

(From a clone, node skill/launch-guard.mjs <repo> does the same.) Replace <repo> with the path of the repository (leave it out to scan the current folder). Add --offline to skip the one network step (see "Network and files" below). Point it at the top folder of a repository: for a plain folder or a subfolder of a repository it skips the history and old-commit checks and says so. With no private list yet, it still checks for secrets, old commits that stay reachable, and the basics, and says plainly that the personal and restricted checks were skipped.

In scripts, before a push, and in CI

  • --json prints the same report as one JSON document (version, result, counts, findings), with the same six fixed fields per finding and the same promise: no secret, no list value, no commit message. The exit code is the same, so node skill/launch-guard.mjs . --json --offline > report.json works in any script.
  • --print-hook prints a git pre-push hook to the screen. It writes nothing; you save it yourself as .git/hooks/pre-push (the tool never edits a repository) and put the path of launch-guard.mjs into it. Any blocking finding then stops the push.
  • docs/ci.md has a ready GitHub Actions job. A runner has no private list, so CI covers secrets, history, old commits and basics; the personal and restricted checks stay on your own machine.

Your private list

To catch your own names, address, school, family or codewords, the tool needs a list of them. The list lives outside the repo so it can never be published by accident.

node skill/launch-guard.mjs --init-list

This creates a template at ~/.config/launch-guard/private-list.txt. It will not overwrite a file and will not write inside a git repository. Open it in your own editor and add one entry per line, in the format kind|regex:

personal|zq-example-name
restricted|zq-example-codeword

kind is personal or restricted. The part after | is a regular expression, matched without regard to upper or lower case. Lines starting with # and blank lines are ignored. To use a list in another place, add --list <file>.

Never paste the list into a chat, and never ask an assistant to open it. The assistant does not need the values. The report will say "list entry 3", and you can look up line 3 yourself.

The four checks

  1. Secrets. Known key formats and long random-looking strings next to words like key, token or password, in your current files. It follows a value that sits on a later line than its key (a YAML block, a continuation, or a string split with + or a backslash, over up to four lines), reads quoted values that contain symbols, and knows the formats of common providers (cloud, payment, chat and developer tokens) as well as Authorization: Bearer headers.
  2. Personal details and restricted terms. Everything in your private list, matched against file contents and against file and folder names.
  3. History. Every branch, tag and the reflog, checked for the same secrets and list entries in old versions of files, in commit messages, in annotated tag messages and taggers, in author names and emails, and in what a merge commit changed beyond an automatic merge (such as a secret typed in while resolving a conflict). The merge check needs git 2.36 or newer; on an older git it says "history incomplete".
  4. Old commits still reachable. Leftover rewrite refs, extra refs and hidden pull-request refs on your remotes that would still be downloadable after a history rewrite, plus local unreachable objects (a prompt to check, not proof of a leak).

It also runs a few basics: the presence of a LICENSE, a SECURITY file and CI, a funding file that is switched on, and absolute paths to a user profile folder (such as C:\Users\<name>) in assistant files like CLAUDE.md.

Reading the report

Each line looks like path:line label (list entry N), grouped by level. The last line is RESULT: PASS or RESULT: FAIL (with --json, the result field says pass or fail instead).

LabelWhat it meansWhat to do
secret formatA string shaped like a known key or tokenRemove it from the file, then treat the key as exposed and replace it at its provider
secret near keywordA long random-looking value next to a word like key, token or passwordCheck the line yourself; remove it, or mark it allowed if it is harmless (see below)
tracked env fileA .env file is tracked by git (its contents are never read)Stop tracking it and keep it out of the repo; replace any secrets in it
personal detailA personal entry from your list matches in a fileEdit the line yourself
restricted termA restricted entry from your list matches in a fileEdit the line yourself
path matches listA file or folder name matches your list (shown as [redacted])Rename it
list inside repoYour private list is inside the folder being scannedMove it out of the repo
secret in historyA secret appears in an old version of a fileSee the note on history below
term in historyA list entry appears in an old commit, message, author or ref nameSee the note on history below
recommend a fresh repositoryA rewrite leftover (refs/original) or a hidden pull-request ref on a remote would stay reachablePublish from a brand-new repository with no old history
unreachable objectGit still holds an object that no branch reaches. Staging, amending, rebasing and git stash drop all leave these until git cleans up. They are local and a push does not publish themA warn, not proof of a leak: check that nothing sensitive was in the file you changed. To clear them, run git reflog expire --expire-unreachable=now --all, then git gc --prune=now (git gc --prune=now alone only clears re-staged blobs and dropped stash entries, because the reflog still holds commits left by an amend or rebase)
extra refA branch, tag or stash beyond the current branchCheck whether it should be public
not a repository rootThe folder is not the top level of a git repository (a plain folder, or a subfolder of another repository), so the history and old-commit checks did not runRun the tool on the repository's top folder
user profile pathA file holds an absolute path into a user profile folderReplace it with a relative path or a placeholder
missing LICENSE, missing SECURITY, missing CIA basics file is absentAdd one
funding file activeA funding file is switched onMake sure that is what you want before going public
file skipped, more files skippedA file was too large, binary, a symlink or unreadable, so it was not readLook at it yourself if it matters
history incomplete, no commits, no remoteThe tool could not look at part of the historyInformational; the check for that part did not run
nested repository not scannedAn untracked folder inside the repository is itself a git repository. Its files and history are not part of this scan, and a plain git add would not publish themScan it on its own, or keep it out of the folder you publish
submodule not scannedThe repository has submodules (another repository each). Their files and history are not part of this scanRun the tool inside each submodule before you publish
remote not checkedThe hidden pull-request ref check did not run: --offline was given, or git could not reach the remote without a prompt. The tool never asks for a password, so a private HTTPS remote that needs credentials will often land hereRun the tool from a shell where git already has credentials for that remote (without --offline). If the repository was ever pushed with sensitive content, treat it as needing a fresh repository
checks skipped: no private list, private list has no entriesThe personal and restricted checks had nothing to useCreate and fill in your list

For a harmless match (a test file, a documented example) put launch-guard-allow: <reason> in a comment on that line or the line above, with a real reason. Only secret findings and the user-profile-path finding are lowered from block to warn, and only in test files (*.test.*, *.spec.*, *_test.*, test_*) and under test, tests, spec, specs, fixtures, __tests__, __fixtures__, __mocks__, testdata and docs/examples folders. Findings from your private list (personal, restricted, matching paths, history) always stay block there: those are things you said must not be public, so use launch-guard-allow: <reason> for a real exception. Files with a key or credential extension (pem key p12 pfx env crt cer jks keystore asc gpg ppk kdbx) and names starting .env are never lowered, whatever their folder or name.

Levels and exit codes

  • block: must be fixed. Any block makes the result FAIL.
  • warn: look at it.
  • info: a note, such as a skipped file or a missing list.

Exit code 0 means no blocking findings, 1 means at least one blocking finding, and 2 means the tool could not run (a bad path, a bad list, or an internal error, which prints one fixed message and nothing else).

PASS is not a promise that the repository is safe. It means these checks found nothing that blocks.

Network and files

  • The only network use is a read-only git ls-remote --refs against each remote you have configured, to look for hidden pull-request refs. It never prompts for credentials, and it uses your own ssh setting (GIT_SSH_COMMAND, core.sshCommand or GIT_SSH) the way git would; for a plain ssh it only adds batch mode so nothing waits for a password. Skip it with --offline, which adds an info note that the remote was not checked (or, when no remote is configured, a "no remote" note instead).
  • The only file the tool writes is the template from --init-list, and only if nothing is there yet and the location is outside any git repository.
  • It sends nothing anywhere else and has no telemetry.

Stop your assistant reading the list

The skill tells the assistant never to open your list, but a skill is only advice. To enforce it in Claude Code, add a deny rule for the list's path to your user settings (~/.claude/settings.json). It has this shape:

{
  "permissions": {
    "deny": ["Read(~/.config/launch-guard/private-list.txt)"]
  }
}

This follows Claude Code's documented permission rule form Read(path), where ~/ means your home folder. Settings change over time, so check the current permissions documentation before relying on it.

Tested 2026-10-31 on Claude Code 2.1.316: with the permission mode set to bypassPermissions, a headless session was still refused when it asked the Read tool for a file named in such a rule, while a control file in the same folder read fine. So the rule holds in that mode too; re-check it after Claude Code updates.

What this does and does not do: it blocks the assistant's built-in file-reading tool, and Claude Code also applies Read rules to common shell commands that name the file. It does not reliably stop every command the assistant could run in a shell (for example one that searches a whole folder without naming the file). For stronger protection, also cover the path with Claude Code's sandbox read restrictions, or keep the list somewhere the assistant's session cannot reach. See the same documentation.

Codex has its own permission and sandbox settings, and they should be set so that the assistant cannot read the list's location. Use Codex's own documentation for the exact settings; they are not repeated here.

Honest limits

  • A chat already holds everything typed or read in it. If you paste a secret or your list into a conversation, no tool can take it back out.
  • Fixing a leak means someone sees the line. The report tells you where. You or your assistant still has to open that spot to change it.
  • The existence of a category is disclosed. "A personal detail was found in this file" is itself information, even though the detail is not shown.
  • A scanner that matches patterns cannot see everything. A secret with no key word beside it and no known provider format (for example a bare random string in a variable named x), one split over more than four lines or inside a Python parenthesised string, a triple-quoted block, a heredoc or a template literal, one that is encoded or encrypted, or one inside a binary or very large file is not found. PASS means these rules found nothing, not that nothing is there. Rotate any key that was ever committed.
  • GitHub's own caches cannot be seen. If the repository was ever pushed with something sensitive, copies may live in places this tool cannot check (forks, pull-request refs, cached views). The safe answer is a fresh repository with no history, and the tool says so rather than claiming a rewrite is enough.
  • Amending, rebasing, staging and stashing leave old objects behind. They are no longer on any branch but stay in the repository until git cleans up (first git reflog expire --expire-unreachable=now --all, then git gc --prune=now; the reflog keeps amended and rebased commits alive). They are local and a push does not publish them, so they only warn.
  • Example env files are read. .env.example, .env.sample and .env.template are scanned for secrets like any other file; other .env files are flagged by name and never opened.
  • It is not a replacement for a general secret scanner, and it gives no legal or licence advice.

Contributing and security

Issues and pull requests are welcome; please read the code of conduct. Keep test data obviously fake (words like zq-example), and never include anything real. Run pnpm check, pnpm test and pnpm build before sending a change, and commit the rebuilt skill/launch-guard.mjs with it.

To report a vulnerability, including any case where the tool prints something private, see SECURITY.md.

Licence

MIT. See LICENSE.

版本与发布记录

@voyageurworks/launch-guard 共发布 4 个版本,首次发布于 2026/11/02;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.3latest2026/11/03今天
0.1.22026/11/03今天
0.1.02026/11/021 天前
0.0.0-stage2026/11/021 天前

关于 @voyageurworks/launch-guard 的常见问题

@voyageurworks/launch-guard 是什么?

在私有git仓库公开之前扫描它,报告秘密、个人详细信息、限制条款和可访问的旧提交,而不打印私有数据。

如何安装 @voyageurworks/launch-guard?

在项目目录运行 npm install @voyageurworks/launch-guard,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 launch-guard,可以用 npx launch-guard 直接运行。

@voyageurworks/launch-guard 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/voyageurworks__launch-guard 是否存在。

@voyageurworks/launch-guard 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@voyageurworks/launch-guard 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@voyageurworks/launch-guard 可以商用吗?

@voyageurworks/launch-guard 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@voyageurworks/launch-guard 还在维护吗?

最新版本 0.1.3 发布于 2026/11/03(今天);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/11/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。