Skip to content

Tools

Useful tools.

Go linting

Use ./build.sh lint from the repository root. It checks shell formatting and authored text with Opengrep, then runs golangci-lint v2; a globally installed v1 binary cannot read .golangci.yaml. It validates the Go linter configuration and exits nonzero for findings. It does not apply fixes. The first run needs network access to download dependencies and may take longer while Go compiles the tool.

Apply available automatic fixes before fixing remaining findings by hand. From the repository root, run:

Bash
go tool -modfile=tools/golangci-lint.mod golangci-lint run --fix ./...

This command rewrites source files. Review the diff, fix any remaining findings, then rerun ./build.sh lint to check the result. Not every linter supports autofix. build.sh does not forward flags to the linter, so use the direct command above rather than ./build.sh lint --fix.

The tool version and dependencies are pinned in tools/golangci-lint.mod and tools/golangci-lint.sum, separate from the application module. This follows upstream's dedicated module-file guidance to avoid mixing linter dependencies with application and build-tool dependencies. Upstream recommends release binaries for general installation; the isolated Go tool lets this repository build the linter with its required Go toolchain without relying on a global installation.

To inspect the pinned tool or validate only the configuration:

Bash
go tool -modfile=tools/golangci-lint.mod golangci-lint version
go tool -modfile=tools/golangci-lint.mod golangci-lint config verify

To upgrade, choose a stable release from the upstream release notes that supports the repository's Go version, replace vX.Y.Z below with that version, and run:

Bash
go get -tool -modfile=tools/golangci-lint.mod github.com/golangci/golangci-lint/v2/cmd/golangci-lint@vX.Y.Z
./build.sh lint

Commit both tool module files and any required configuration updates. Do not upgrade the tool's transitive dependencies independently. Review the enabled linters when upgrading: .golangci.yaml enables all linters except its explicit exclusions, so releases can add checks and findings.

JavaScript tooling

Use Node.js 22+ and pnpm. The versions of Tailwind CSS, Prettier, Playwright, and Wrangler are pinned in package.json and resolved in pnpm-lock.yaml. pnpm-workspace.yaml permits only the native build scripts required by these dependencies. Install from the root:

Bash
pnpm install --frozen-lockfile
pnpm css:build

Use pnpm css:watch while changing styles and pnpm exec prettier for formatting. pnpm exec playwright and pnpm exec wrangler run the same versions used in the CI images. The Playwright browser-image tag must match the pinned Playwright package version.

The compiled CSS is tracked. ./build.sh build only regenerates it if it is missing; run pnpm css:build after changing Tailwind classes or source CSS. Go-only builds do not require installing JavaScript dependencies while the compiled CSS exists.

Shell formatting

shfmt is pinned in go.mod as a Go tool. Format tracked .sh and .bash files (excluding Fish scripts), or check them without modifying the working tree:

Bash
./build.sh format
./build.sh lint

./build.sh format formats shell, templ and Go sources without building. ./build.sh build does not format sources. CI runs the shell check on branches and tags.

Opengrep

Opengrep is a non-sucky version of Semgrep that doesn't hide features.

Download it at https://github.com/opengrep/opengrep/releases/.

For Arch Linux users

If you get libcrypt.so.1: cannot open shared object file, install libxcrypt-compat with sudo pacman -S libxcrypt-compat.

Common usage:

Bash
1
2
3
4
# scan
opengrep scan -f opengrep.yaml
# scan with autofix
opengrep scan -f opengrep.yaml --autofix FILES...

The blocking Opengrep rules live in opengrep.lint.yaml and run through ./build.sh lint and GitLab CI. opengrep.yaml contains non-blocking i18n message inventory rules. No separate Opengrep command is needed before committing; ./build.sh lint also runs the Go analyzers.

goimports-reviser

This tool organizes imports into three groups -- std, 3rdparty, ours.

Install with

Bash
go install -v github.com/incu6us/goimports-reviser/v3@latest

Format all code:

Bash
goimports-reviser -rm-unused -format ./...