Scut

Contributing

Architecture

architecture · Kong

How the scut CLI is organized and where new code belongs.

Scut is a Go module at github.com/ajbeck/scut. All packages live under internal/ by default; public packages are exposed only when another tool needs to import typed contracts, such as hook payload definitions.

CLI framework

Scut uses github.com/alecthomas/kong for struct-based CLI parsing. Commands are grouped under the root CLI struct and run through ctx.Run(...) with dependencies bound at parse time.

The entrypoint follows this shape:

parser := kong.Must(&cli)
ctx, err := parser.Parse(os.Args[1:])
if err != nil {
    logging.LogParseError(os.Args, err)
    parser.FatalIfErrorf(err)
}
err = ctx.Run(bindings...)

Package layout

AreaPurpose
cmd/scutMain released binary entrypoint.
cmd/walleRepository-local task runner for development.
internal/cmd/claudeClaude command tree, status line, config, and hooks.
internal/cmd/codexCodex command tree, config, and hooks.
internal/cmd/gotoolsGo documentation and module-cache command tree.
internal/cmd/initcmdUnified setup across supported agents.
internal/cmd/doctorRead-only diagnostics.
internal/cmd/formatDirect formatter CLI and atomic file handling.
internal/cmd/mcpMCP utility commands and proxy launchers.
internal/cmd/updateInstall-method detection and release binary updates.
internal/godocGo source resolution, archives, cache, and rendering.
internal/formatPure byte-oriented Go and Markdown formatters.
internal/formatignoreFormatter ignore-file discovery and matching.
hooks/claudecodePublic Claude Code hook payload types.
hooks/codexPublic Codex hook payload types.

Build rules

Use Walle for all Go operations. The task runner applies required build metadata and verification settings consistently. Scut targets Go 1.27.1 and uses the stable encoding/json/v2 APIs without experiment flags or build constraints.

./walle fmt
./walle vet
./walle test
./walle build

Do not call go test, go build, go vet, or gofmt directly in this repo.

Go documentation resolution

internal/godoc separates source precedence from remote transport policy. The generic resolver checks local/workspace source, the standard library, the read-only Go download cache, and scut-owned archives in order. Its final remote fetcher owns the complete GOPROXY sequence so comma and pipe fallback cannot be changed accidentally by the generic resolver.

Remote mechanisms sit below that state machine: proxy protocol access handles HTTP, HTTPS, and file URLs; direct access performs go-import discovery and in-memory Git cloning. GONOPROXY, GOAUTH, GOINSECURE, and GOVCS are applied at those source, request, transport, and VCS boundaries respectively. Go environment policy is read directly from process, user go/env, and GOROOT/go.env configuration rather than through another Go subprocess.

Archive integrity is a separate boundary shared by cache reads, proxy downloads, and exact-version Git clones. It validates complete canonical ZIPs, checks active module or workspace sums first, and otherwise applies GOSUMDB and GONOSUMDB. The scut-owned cache atomically publishes the ZIP, content hash, and verification provenance as one immutable version entry. Checksum-database latest-tree checkpoints live in separate scut-owned configuration state so cache cleanup cannot erase anti-rollback history.

Source retrieval deliberately retains complete target-independent package contents. Immediately before parsing, the lookup resolver applies a shared go/build.Context derived from Go’s environment precedence, including GOOS, GOARCH, CGO_ENABLED, and GOFLAGS=-tags. Keeping build selection above every backend prevents local, cached, proxy, and direct-Git sources from drifting into different documentation surfaces.