Air — Dependencies#

Module info#

  • Module: github.com/air-verse/air
  • Go version: 1.25
  • Direct dependencies: 9
  • Indirect dependencies: 17 (listed in go.mod) + ~79 further transitives (go.sum has ~105 total module entries across 210 lines)

Dependency categories#

Core infrastructure#

  • github.com/pelletier/go-toml v1.9.5 — TOML parsing for .air.toml config files. Air uses v1 (not v2) directly; hugo pulls in v2 as an indirect dep.
  • dario.cat/mergo v1.0.2 — Struct deep-merge. Used in runner/config.go to merge user-supplied config over default config values, respecting zero values via a custom transformer.
  • github.com/joho/godotenv v1.5.1 — Loads .env files into the process environment. Supports Air’s env_files config option for injecting environment variables before the watched binary runs.
  • github.com/fatih/color v1.18.0 — Terminal color output for Air’s logger (colored prefixes for different log levels/statuses). Pulls in mattn/go-colorable and mattn/go-isatty as indirect deps for Windows compatibility.
  • golang.org/x/sys v0.35.0 — Low-level OS syscalls. Used in platform-specific files (util_linux.go, util_unix.go, util_windows.go) for process signaling and filesystem operations.

File watching#

  • github.com/fsnotify/fsnotify v1.9.0 — Cross-platform filesystem event watching (inotify on Linux, FSEvents on macOS, ReadDirectoryChanges on Windows). The primary mechanism for detecting file changes.
  • github.com/gohugoio/hugo v0.149.1 — Used exclusively for github.com/gohugoio/hugo/watcher/filenotify, a package that provides poll-based file watching as a fallback when native fsnotify is unavailable or when poll mode is configured. This is the most controversial dependency: importing all of Hugo (a full CMS framework) just to get a single sub-package’s polling abstraction.

Networking/HTTP#

  • github.com/andybalholm/brotli v1.2.0 — Brotli decompression/recompression used in Air’s embedded HTTP proxy (runner/proxy.go) to handle Brotli-encoded upstream responses when injecting the live-reload WebSocket script.

Testing#

  • github.com/stretchr/testify v1.11.1 — Test assertions (assert, require sub-packages) used across runner/*_test.go files. Pulls in go-spew, go-difflib, and yaml.v3 as indirect deps.

Other#

No CLI framework, no gRPC, no database drivers.

Stdlib reliance#

Air relies heavily on stdlib — arguably more than on third-party packages for its core logic:

PackageUsage
os / os/execLaunching and managing the watched binary process
net/httpEntire embedded reverse-proxy implementation
contextCancellation propagation through engine, watcher, proxy
sync / sync/atomicMutex guards on internal state; atomic flags for shutdown
path/filepathInclude/exclude path matching throughout watcher
reflectReflection-based CLI flag generation in runner/flag.go
compress/gzipGzip body decoding in the proxy (alongside brotli)
encoding/jsonProxy response body inspection
regexpExclude regex matching for file paths
timeRebuild delay, kill delay, timeout handling
htmlHTML entity escaping in proxy script injection
embedEmbedding the live-reload JS snippet into the binary
crypto/sha256 / encoding/hexFile checksum caching for unchanged-file detection

The stdlib handles process management, HTTP proxying, and most I/O. Third-party deps fill specific gaps: TOML parsing, file watching, terminal colors, struct merging, and Brotli support.

Shared dependencies#

Dependencies that appear frequently across the 50-project research set:

  • github.com/fsnotify/fsnotify — Used by many Go tools and servers for file watching (e.g., Viper, Hugo, many test frameworks)
  • github.com/fatih/color — Common in CLI tools for terminal output styling
  • github.com/stretchr/testify — Near-universal in Go projects as a test assertion library
  • golang.org/x/sys — Used by any project doing low-level OS operations
  • github.com/pelletier/go-toml — Less common but appears in projects with TOML config (Hugo, etc.)
  • dario.cat/mergo — Occasionally seen in config-heavy tools
  • github.com/joho/godotenv — Common in dev-tooling and twelve-factor app helpers

Vendoring#

No vendor directory. Air relies on the Go module cache. This is standard for a developer tool rather than a deployable service. The Docker image (cosmtrek/air) presumably uses go install or a pre-built binary, not vendored source.

Notable dependency decisions#

The Hugo problem: Air imports github.com/gohugoio/hugo — a full static site generator — solely for hugo/watcher/filenotify. This one sub-package provides a polling-based file notification abstraction. The consequence: Air’s go.sum balloons to ~105 module entries, pulling in Dart Sass bindings (bep/godartsass), WebP support (bep/gowebp), libsass (bep/golibsass), spf13/afero, spf13/cast, tdewolff/parse, google.golang.org/protobuf, and more — none of which are used by Air at all. This is a known anti-pattern in Go: importing a large module for one package. A better approach would be to vendor just the filenotify package directly or extract it to a standalone library.

TOML v1 vs v2: Air uses pelletier/go-toml v1 directly while Hugo (pulled in as a dep) uses v2, resulting in both versions appearing in the module graph. This suggests Air has not yet migrated to the v2 API.

No CLI framework: Air uses flag from stdlib plus its own reflection-based flag generation (runner/flag.go) instead of cobra or urfave/cli. This keeps the dependency count low but creates non-standard CLI behavior (no --help auto-generation, no subcommands).

Minimal data layer: Zero database, cache, or serialization dependencies beyond TOML and JSON (stdlib). The tool is purely computational — file watching, process management, and HTTP proxying — which justifies the lean dependency profile in everything except the Hugo import.