# Dependency notes for Go

`go.mod` records which modules a build requires and at which version. It does not record why a module was chosen, which of its APIs the code is built around, or what to run before moving it — and `go get -u ./...` moves everything at once.

Depos keeps a note for each module in `.depos/go/DEPENDENCY-NOTES.md`, beside `go.mod`, and shows it on the module's `require` line.

## What Depos reads

- **Manifest:** `go.mod`
- **Notes file:** `.depos/go/DEPENDENCY-NOTES.md`
- **Section heading:** the module path: `## github.com/spf13/cobra`, `## github.com/jackc/pgx/v5`

Depos reads module paths in `require` directives of `go.mod`, including `// indirect` ones, shown with their own scope. A `tool` directive points at the required module that provides it. `replace`, `exclude`, `retract`, `go.work` and `vendor/` are not read as dependencies.

Depos never runs the `go` command, so it needs no Go toolchain.

## Example

```go
module example.com/billing

go 1.24

require (
	github.com/jackc/pgx/v5 v5.7.1
	github.com/spf13/cobra v1.8.1
	golang.org/x/sync v0.10.0 // indirect
)
```

`.depos/go/DEPENDENCY-NOTES.md`:

```md
## github.com/jackc/pgx/v5

Postgres driver. Use it through internal/db only.

### Agent notes

- purpose: PostgreSQL driver and connection pool for the billing service
- usage: only through internal/db, which wraps the pool and the transaction helpers
- verify: `go test ./internal/db/...` against the Postgres in docker-compose.yml
- verified: v5.7.1
```

The heading is the module path as `require` spells it, major-version suffix included. A new major version of a Go module is a new module path, so moving from `/v5` to `/v6` starts a new section, and the old one stays with `- status: removed <YYYY-MM> — <reason>`.

## Comments in go.mod

```go
require (
	// pgx: use it through internal/db only
	github.com/jackc/pgx/v5 v5.7.1
	github.com/spf13/cobra v1.8.1 // CLI for the admin tools
)
```

A comment in `go.mod` starts with `//` and runs to the end of the line. `/* */` is not allowed: the go command stops with `mod files must use // comments`.

The go command writes a comment of its own. `// indirect` marks a requirement that no package in the main module imports directly, and when `go mod tidy` marks a line that already has a comment, it puts `indirect;` in front of it: `// indirect; CLI for the admin tools`. When `go mod tidy` drops a requirement, the comments on its line and above it go with it.

## Pinning a version

A `require` line is not a pin. It sets the lowest version the build accepts: when another module in the build requires a higher one, the build uses that, and in a module that says `go 1.17` or later, `go mod tidy` rewrites the line to it. A comment beside the line stays, and may now describe a version that is no longer there.

`go get github.com/spf13/cobra@v1.8.1` moves a requirement up or down. `exclude` keeps one version out, and the build takes the next higher one instead; `replace` swaps a module for another version or a local directory. Both apply only in the main module's `go.mod`.

No directive sets an upper bound, and a comment such as `// keep below v1.9.0` does not stop `go get` either. Write the limit in the module's note as `constraint:`: agents read it before they move the module.

## For AI coding agents

An agent reads a module's section before it adds, upgrades or removes the module, runs what `verify:` says, and records the version it checked in `verified:`. See [the rules agents follow](https://depos.dev/agents/).
