Architecture
How one Go binary ships to Go, npm, and PyPI without native builds in each.
secretcheck is a single Go binary. Everything else — the npm package, the PyPI package — is a thin wrapper that locates and execs that same binary. Nothing is recompiled per ecosystem.
Project layout
cmd/secretcheck/ CLI entry point
internal/
rules/ built-in detection patterns + placeholder/redaction helpers
gitutil/ git plumbing (staged files, index content, hooks dir)
ignore/ .secretcheckignore + default excludes (custom glob matcher, no deps)
config/ .secretcheckrc.json loading + rule resolution
scanner/ runs rules against staged/working-tree files
hook/ installs/removes the pre-commit hook (native + Husky)
prompt/ interactive y/N confirmation, TTY/CI detection
colors/ minimal ANSI helper
report/ findings output formatting
packaging/
npm/ main npm shim package + 5 per-platform binary packages
pypi/ pyproject.toml/setup.py + per-platform wheel build script
.goreleaser.yaml cross-platform build configThe core Go module has zero third-party dependencies — smaller attack surface for a
security tool, no go.sum to audit, and no network access needed to build.
Cross-compiling once
GoReleaser cross-compiles the binary for
{linux,darwin,windows} × {amd64,arm64} (windows/arm64 excluded) from a single build step,
with the version injected via -X main.version=....
npm: optionalDependencies
The npm side follows the pattern used by esbuild, swc, and turbo: a main secretcheck
package with no binary of its own, plus five tiny platform packages
(secretcheck-darwin-arm64, secretcheck-darwin-x64, secretcheck-linux-arm64,
secretcheck-linux-x64, secretcheck-win32-x64), each scoped to one OS/CPU pair via the
os/cpu fields in package.json. They're listed as optionalDependencies of the main
package — npm installs only the one matching the current machine and silently skips the
rest. The main package's bin/secretcheck.js resolves the installed platform package at
runtime and execs its binary, forwarding stdio and the exit code.
PyPI: platform-tagged wheels
PyPI doesn't have an optionalDependencies-style mechanism — instead, one wheel is built
per platform, each tagged so pip's platform-compatibility check only offers the right
one (macosx_11_0_arm64, manylinux_2_17_x86_64, win_amd64, etc.). Since the binary is
already compiled by GoReleaser, the build step doesn't compile anything — it just copies
the right binary in and forces the wheel's platform tag via a SECRETCHECK_WHEEL_PLATFORM
environment variable read by a custom bdist_wheel override. pip install secretcheck
resolves to whichever wheel matches the installing machine automatically.
Go: no separate publish step
The Go module needs nothing beyond the pushed git tag — go install github.com/anukool23/secretcheck/cmd/secretcheck@v1.0.3 resolves directly from the tag via
the Go module proxy.
Three independent release pipelines
Pushing a tag (git tag v1.0.3 && git push origin v1.0.3) triggers three separate GitHub
Actions workflows in parallel, not one combined job:
release-go.yml— runs GoReleaser's realrelease, cross-compiling and publishing the GitHub Release (this alone is what makesgo installwork).release-npm.yml— builds its own copy of the binaries (goreleaser build, which has no GitHub Release side effects) and publishes the npm packages.release-pypi.yml— same build-only step, then builds and uploads the wheels.
Each workflow is fully self-contained. A failure in one — say, npm's automated anti-spam
scanner flagging a package containing a raw .exe — can't block the other two, and
re-running a failed workflow is safe even after a partial success: the npm publish script
checks npm view <name>@<version> before publishing each package, so it skips anything
already live and only retries what actually failed.