air-verse/air ⭐ 22,998
github.com/air-verse/air Last updated: 2026-02-20 04:13:11
AGENTS.md
# AGENTS
Guidelines for contributors and AI coding agents working in this repository.
## Goals
- Keep changes minimal, focused, and idiomatic to Go.
- When adding changes, do NOT break existing behavior.
- Make changes small and easy to review.
- Code and comments must be written in English.
- Prefer root-cause fixes over band-aids; do not refactor unrelated code.
- Maintain user-facing behavior and CLI flags unless explicitly changing them.
## Project Snapshot
- Language: Go (modules enabled; `go 1.25` in `go.mod`).
- Module path: `github.com/air-verse/air`.
- Entry: `main.go`.
- Core package: `runner/` (watcher, engine, flags, config, proxy).
- Docs: `README*.md`, `air_example.toml`, `docs/`.
- Tooling: `Makefile`, `hack/check.sh`, `hooks/pre-commit`, `.golangci.yml`.
- Default config file: `.air.toml` (generated by `air init`).
## Repository Layout
- `main.go`: CLI entrypoint and flag parsing.
- `runner/engine.go`: build/run loop and watcher orchestration.
- `runner/config.go`: config schema, defaults, parsing, validation.
- `runner/flag.go`: CLI flag wiring.
- `runner/watcher.go`: fsnotify vs polling watcher selection.
- `runner/proxy*.go`: live-reload proxy, SSE stream, embedded JS.
- `runner/util*.go`: platform helpers, process control, misc utilities.
- `runner/*_test.go`: unit tests and platform-specific tests.
- `hack/check.sh`: goimports + golangci-lint driver.
- `hooks/pre-commit`: runs `hack/check.sh` on staged files.
## Build / Lint / Test
- Install tools + hook: `make init` (goimports + golangci-lint v2.6.1).
- Format + lint staged Go files: `make check`.
- Format + lint all Go files: `make check scope=all`.
- Build binary: `make build` (runs `make check` first).
- Install locally: `make install` (runs `make check` first).
- CI prep (module tidy): `make ci`.
- Full test suite: `go test ./...` or `make test` (race + timeout).
- CI tests: `make test-ci` (CI=true, longer timeout).
- Pre-commit hook: runs `./hack/check.sh` on staged files.
### Single Test Recipes
- Single package: `go test ./runner -v`.
- Single test: `go test ./runner -run '^TestName$' -count=1 -v`.
- Subtest: `go test ./runner -run '^TestName$/Subcase$' -count=1`.
- All packages, one test: `go test ./... -run '^TestName$' -count=1`.
- Add `-race` or `-timeout=3m` when debugging flakiness.
## Code Style (Go)
- Formatting: run `goimports` (it also applies `gofmt`).
- Imports: let `goimports` group stdlib, third-party, local imports.
- Naming: `CamelCase` for exported, `lowerCamel` for unexported.
- Initialisms: use standard forms (ID, URL, HTTP, JSON).
- Receivers: keep receiver names short and consistent (`cfg`, `e`, `p`).
- Types: prefer concrete types over `any`; avoid needless interfaces.
- Constants: use `const` for defaults; use `0o755` style perms.
- Zero values: design structs so zero values are valid when possible.
- Early returns: avoid deeply nested `else` blocks.
- Paths: use `filepath` for OS-safe path handling.
- Shelling out: prefer `exec.Command` with args; use `/bin/sh -c` only when needed.
- Platform code: maintain `*_linux.go`, `*_windows.go`, build tags parity.
- Comments: keep short, English, and explain "why" more than "what".
- Use `time.Duration` for timeouts and backoffs.
- Prefer value receivers unless mutation or large copies require pointers.
- Avoid globals except for constants and small immutable vars.
- Treat nil slices as empty; do not rely on non-nil defaults.
- Keep TOML/JSON tags aligned with field names and usage strings.
## Error Handling & Logging
- Wrap errors with context: `fmt.Errorf("read config: %w", err)`.
- Use `errors.Is/As` for comparisons, `errors.Join` for aggregates.
- Avoid panics in packages; `log.Fatal` only at CLI entrypoints.
- Log via `mainLog`, `buildLog`, `runnerLog`, `watcherLog` in `runner`.
- Keep log output concise and consistent with existing prefixes.
## Concurrency & State
- Guard shared state with `sync.Mutex` or `sync/atomic`.
- Avoid data races; keep goroutines bounded and cancellable.
- Use channels for signaling (see `buildRunCh` in `runner/engine.go`).
- Use `context` and timeouts for operations that may block on I/O.
## Tests
- Location: alongside code as `*_test.go`.
- Style: table-driven tests with `t.Run` where it improves clarity.
- Parallelism: use `t.Parallel()` only for isolated tests.
- Helpers: use `t.Helper`, `t.TempDir`, `t.Setenv`, `t.Cleanup`.
- Assertions: use `testify/require` for fatal checks, `testify/assert` for soft checks.
- Fixtures: prefer `_testdata` and temp dirs; avoid network dependencies.
- OS coverage: use `*_windows_test.go`, `*_linux_test.go` for platform behavior.
## Config / CLI Discipline
- Config fields: edit `runner/config.go`, update parsing/defaults/tests.
- CLI flags: update `runner/flag.go`, sync help text, update README usage.
- Keep `air_example.toml` aligned with any config changes.
- Behavior changes must include README updates and tests.
## Documentation
- Update `README.md` for user-visible changes (flags, config, examples).
- Keep `docs/` content accurate when behavior changes.
- Add concise migration notes for breaking or behavioral changes.
- Mention new environment variables or defaults in docs.
## Tooling and Linters
- `make check` runs `hack/check.sh` -> `goimports` + `golangci-lint`.
- Enabled linters include: `errcheck`, `revive`, `staticcheck`, `testifylint`, `unused`.
- Fix lint warnings rather than suppressing unless clearly justified.
- Keep changes compatible with the current Go version in `go.mod`.
## Scope and Safety
- Avoid touching `vendor/`, `third_party/`, or generated files.
- Do not change CLI output or flags unless explicitly requested.
- Avoid broad refactors; keep changes localized to the feature/bug.
- Prefer root-cause fixes over temporary workarounds.
- Do not add dependencies unless there is a clear, reviewed need.
- Assume offline mode; no external network usage.
## Cursor / Copilot Rules
- No `.cursor/rules/`, `.cursorrules`, or `.github/copilot-instructions.md` found.
- If any are added later, follow them and copy key points here.
## For AI Coding Agents (Codex CLI)
- For multi-step tasks, maintain an explicit plan and mark progress.
- Keep edits in a single focused patch per logical change.
- Briefly state what you are about to do before running commands.
- Prefer `rg` for searches and keep file reads to small chunks.
- Validate with `make check` and `go test ./...` when changes touch Go code.
- Avoid touching unrelated files; do not reformat the repo wholesale.
## Release Notes (maintainers)
- Follow the README "Release" section for tagging; CI performs builds.
---
Questions or uncertain scope? Open an issue or ask for clarification before implementing.