air

air-verseGPL-3.0活跃维护

Go 应用的实时热重载工具,改完代码自动重新编译并重启服务,省去手动构建的麻烦,适合本地开发调试。

☁️ Live reload for Go apps

v1.67.4发布于 2026-08-01 14:40 UTC24,117star +6 / 7 天929fork同步于 2026-11-10 23:24 UTC

怎么上手

由 README 提炼,执行前请确认
go install github.com/air-verse/air@latest
硬件要求按 README 说明

README 未说明,纯命令行工具,无 GPU 或显存要求

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

Go 开发时的热重载命令行工具,改完代码自动重新编译并重启,省去手动构建

Go 应用的实时热重载工具,改完代码自动重新编译并重启服务,省去手动构建的麻烦,适合本地开发调试。

核心能力

  • 监听文件变化自动重新构建并重启 Go 程序
  • 支持自定义构建命令与运行命令
  • 可排除子目录并监听启动后新增的目录
  • 支持加载 .env 环境文件
  • 内置代理可在静态文件变更时自动刷新浏览器

容易踩的坑

go install 方式要求 Go 1.25 或更高版本;需把 $(go env GOPATH)/bin 加入 PATH,否则会报 command not found: air;该工具仅用于开发,不适用于生产环境热部署

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.67.4
  1. v1.67.4最新正式版2026-08-01 · 2026-08-01 14:40 UTC

    v1.67.4 (2026-08-01)

    Bug Fixes

    • strip hop-by-hop headers in the proxy (#934) (9f19e52)

    Others

    • restructure all four READMEs and document the sync rule (#931) (b487a2c)
  2. v1.67.32026-07-26 · 2026-07-26 07:35 UTC
    查看更新说明

    v1.67.3 (2026-07-26)

    Bug Fixes

    • stamp a real version into the docker latest image (#930) (900deca)

    Others

    • cover proxy handlers, entrypoint parsing, logger and checksum paths (#929) (208af6c)
    • add release, go version, downloads and docker pulls badges (#928) (61a601c)
    • stop config warning tests from racing on os.Stderr (#927) (61b7a57)
  3. v1.67.22026-07-22 · 2026-07-22 13:59 UTC
    查看更新说明

    v1.67.2 (2026-07-22)

    Others

    • update hugo to v0.164.0 (#926) (ced170e)
  4. v1.67.12026-07-20 · 2026-07-20 13:56 UTC
    查看更新说明

    v1.67.1 (2026-07-20)

    Bug Fixes

    • don't let a transient empty read defeat exclude_unchanged (#924) (6fbfb5d)
  5. v1.67.02026-07-20 · 2026-07-20 11:54 UTC
    查看更新说明

    v1.67.0 (2026-07-20)

    Features

    • allow slice flags to be repeated on the command line (#922) (f1b47a1)

    Others

    • document repeatable list arguments (#923) (e9fc14d)

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    :cloud: Air - Live reload for Go apps

    Release Go Version Downloads Docker Pulls Go Codacy Badge codecov

    English | 简体中文 | 繁體中文 | 日本語

    Air is a live-reloading command line utility for developing Go applications. Run air in your project root directory, leave it alone, and focus on your code. Note that this tool has nothing to do with hot-deploy for production.

    air

    Contents

    Installation

    Via go install (recommended)

    With go 1.25 or higher:

    go install github.com/air-verse/air@latest
    

    Make sure your Go bin directory is in your PATH:

    export PATH="$PATH:$(go env GOPATH)/bin"
    

    Via go get -tool (project install)

    With go 1.25 or higher:

    go get -tool github.com/air-verse/air@latest
    
    # then use it like so:
    go tool air -v
    

    Via install.sh

    # binary will be $(go env GOPATH)/bin/air
    curl -sSfL https://raw.githubusercontent.com/air-verse/air/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
    
    # or install it into ./bin/
    curl -sSfL https://raw.githubusercontent.com/air-verse/air/master/install.sh | sh -s
    
    air -v
    

    Via goblin.run

    See goblin.run.

    # binary will be /usr/local/bin/air
    curl -sSfL https://goblin.run/github.com/air-verse/air | sh
    
    # to put to a custom path
    curl -sSfL https://goblin.run/github.com/air-verse/air | PREFIX=/tmp sh
    

    Via Homebrew

    brew install go-air
    

    Via Scoop

    scoop install air
    

    Via mise

    mise use -g air
    

    Via Docker/Podman

    Pull the cosmtrek/air image and see Docker for usage.

    Quick start

    # enter your project
    cd /path/to/your_project
    
    # first tries `.air.toml` in the current directory; if not found, uses defaults
    air
    

    To generate a config file you can edit, run air init once and then air from then on:

    # writes .air.toml with the default settings
    air init
    
    # picks up .air.toml automatically
    air
    

    To use a specific config file explicitly, pass -c:

    air -c .air.toml
    

    For every available option refer to the air_example.toml file.

    Features

    • Colorful log output
    • Customize build or any command
    • Support excluding subdirectories
    • Allow watching new directories after Air started
    • Better building process
    • Configurable .env file loading

    Usage

    Runtime arguments

    You can pass arguments for running the built binary by adding them after the air command.

    # Will run ./tmp/main bench
    air bench
    
    # Will run ./tmp/main server --port 8080
    air server --port 8080
    

    You can separate the arguments passed for the air command and the built binary with the -- argument.

    # Will run ./tmp/main -h
    air -- -h
    
    # Will run air with custom config and pass -h argument to the built binary
    air -c .air.toml -- -h
    

    Debug

    air -d prints all logs.

    Configuration

    Overwrite specific configuration from arguments

    Air config fields are supported as command-line arguments. You can view the available arguments by running:

    air -h
    # or
    air --help
    

    If you want to configure the build command and run command, you can use the following command without a config file:

    air --build.cmd "go build -o bin/api cmd/run.go" --build.entrypoint "./bin/api"
    

    Use a comma to separate items for arguments that take a list as input:

    air --build.cmd "go build -o bin/api cmd/run.go" --build.entrypoint "./bin/api" --build.exclude_dir "templates,build"
    

    List arguments can also be repeated, and the values are appended in the order they appear. This is handy when the command line is generated by a script or Makefile:

    # equivalent to --env_files ".env,.env.local,.env.secret"
    air --env_files ".env,.env.local" --env_files ".env.secret"
    

    Startup banner

    Use misc.startup_banner to control what Air prints at startup.

    [misc]
    # Not set (default): show built-in ASCII banner with version.
    
    # Set to empty string: print nothing.
    startup_banner = ""
    
    # Set to custom text: print this text instead of the built-in banner.
    # startup_banner = "API watcher"
    

    Entrypoint

    Use build.entrypoint to point at the binary generated by build.cmd and describe how it should be executed. The value can be either a string (just the executable) or an array of strings. When using an array, the first element is the executable (resolved relative to root unless it lacks a path separator, in which case $PATH is consulted) and every subsequent element is treated as a default argument. Values from build.args_bin and the command line are appended after the inline arguments. The legacy build.bin field is deprecated and will be removed in a future release, so prefer the entrypoint form going forward.

    [build]
    entrypoint = ["./tmp/main"]
    args_bin = ["server", ":8080"]
    
    # Inline the default arguments directly after the binary.
    entrypoint = ["./tmp/main", "server", ":8080"]
    
    # Use PATH-resolved tools like dlv by omitting path separators.
    entrypoint = [
      "dlv", "exec", "--accept-multiclient", "--log", "--headless", "--continue",
      "--listen=:8999", "--api-version", "2", "./tmp/main",
    ]
    

    Environment files

    Air can automatically load environment variables from .env files before both building and running when env_files is configured.

    # Loads .env.development and then .env files.
    # Values in the lattermost file overwrite any preceding ones.
    # Does not overwrite variables that were present before running air.
    env_files = [".env.development", ".env"]
    

    Platform-specific build overrides

    You can override build settings per OS with [build.windows], [build.darwin], and [build.linux]. These blocks override the base [build] values when running on the matching platform. Only the following fields are supported in platform blocks: pre_cmd, cmd, post_cmd, bin, entrypoint, full_bin, args_bin.

    [build]
    cmd = "go build -o ./tmp/main ."
    bin = "./tmp/main"
    
    [build.windows]
    cmd = "go build -o ./tmp/main.exe ."
    bin = "tmp\\main.exe"
    entrypoint = ["tmp\\main.exe"]
    

    Running air init adds a platform block for the current OS when its defaults differ from the base configuration.

    Watch rules: run a command instead of rebuilding

    Sometimes a change should run a command rather than rebuild your app — frontend assets served from disk, templ/sqlc/go generate pipelines, and so on. Declare a [[build.rules]] block for each of them:

    [build]
    cmd = "go build -o ./tmp/main ."
    # the main build ignores the frontend...
    exclude_dir = ["web"]
    
    # ...but this rule watches it and rebuilds the assets on change
    [[build.rules]]
    name = "assets"
    include_dir = ["web"]
    include_ext = ["js", "ts", "css"]
    cmd = "npm run build"
    
    [[build.rules]]
    name = "templ"
    include_ext = ["templ"]
    cmd = "templ generate"
    

    A file matched by a rule runs the rule's cmd and never triggers a rebuild, even if it would also match the main build's watch settings. Rule directories are watched even when listed in exclude_dir. If a rule's command generates files the main build watches (for example, templ generate writing .go files), the rebuild follows naturally.

    Each rule supports include_dir, include_ext, include_file, exclude_regex, and a delay (debounce in milliseconds, default 1000). At least one of the include_* matchers is required. Rules run their commands to completion; changes arriving meanwhile queue a follow-up run.

    Proxy: reload the browser automatically

    Air can put a small proxy in front of your web app that refreshes the browser after every successful rebuild, so you no longer have to hit reload yourself.

    [proxy]
    enabled = true
    # the port you open in the browser
    proxy_port = 8090
    # the port your app listens on
    app_port = 8080
    

    Start air as usual and open http://localhost:8090 instead of your app's own port. Requests are forwarded to app_port, and Air injects a tiny script before the </body> tag of every HTML response; when a rebuild finishes, the script reloads the page.

    Two things are required for this to work:

    • your HTML must contain a </body> tag — there is nowhere to inject the script otherwise, and the page is served unchanged;
    • the files you edit must be watched, so static assets need to be covered by include_dir, include_ext, or include_file.

    If your app is slow to boot (database connections, config loading) and you see "unable to reach app" errors, give it more time:

    [proxy]
    # how long to keep retrying the app after a rebuild, in milliseconds (default 5000)
    app_start_timeout = 10000
    

    Docker

    Using the official image

    Pull this Docker image: cosmtrek/air.

    docker/podman run -it --rm \
        -w "<PROJECT>" \
        -e "air_wd=<PROJECT>" \
        -v $(pwd):<PROJECT> \
        -p <PORT>:<APP SERVER PORT> \
        cosmtrek/air \
        -c <CONF>
    

    <PROJECT> is your project path in the container, e.g. /go/example. If you want to enter the container, add --entrypoint=bash.

    One of my projects runs in Docker:

    docker run -it --rm \
      -w "/go/src/github.com/cosmtrek/hub" \
      -v $(pwd):/go/src/github.com/cosmtrek/hub \
      -p 9090:9090 \
      cosmtrek/air
    

    Shell function

    If you want to use air continuously like a normal app, create a function in your ${SHELL}rc (Bash, Zsh, etc…):

    air() {
      podman/docker run -it --rm \
        -w "$PWD" -v "$PWD":"$PWD" \
        -p "$AIR_PORT":"$AIR_PORT" \
        docker.io/cosmtrek/air "$@"
    }
    

    $PWD is replaced with the current directory, $AIR_PORT is the port to publish, and $@ accepts arguments of the application itself, for example -c:

    cd /go/src/github.com/cosmtrek/hub
    AIR_PORT=8080 air -c "config.toml"
    

    Docker Compose

    services:
      my-project-with-air:
        image: cosmtrek/air
        # working_dir value has to be the same of mapped volume
        working_dir: /project-package
        ports:
          - <any>:<any>
        environment:
          - ENV_A=${ENV_A}
          - ENV_B=${ENV_B}
          - ENV_C=${ENV_C}
        volumes:
          - ./project-relative-path/:/project-package/
    

    Without the air image

    Dockerfile

    # Choose whatever you want, version >= 1.25
    FROM golang:1.25-alpine
    
    WORKDIR /app
    
    RUN go install github.com/air-verse/air@latest
    
    COPY go.mod go.sum ./
    RUN go mod download
    
    CMD ["air", "-c", ".air.toml"]
    

    docker-compose.yaml

    version: "3.8"
    services:
      web:
        build:
          context: .
          # Correct the path to your Dockerfile
          dockerfile: Dockerfile
        ports:
          - 8080:3000
        # Important to bind/mount your codebase dir to /app dir for live reload
        volumes:
          - ./:/app
    

    Q&A

    command not found: air

    Also reported as "No such file or directory". Make sure the Go bin directory is on your PATH:

    export GOPATH=$HOME/xxxxx
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
    export PATH=$PATH:$(go env GOPATH)/bin #Confirm this line in your .profile and make sure to source the .profile if you add it!!!
    

    Error under WSL when the bin path contains a single quote

    Use \ to escape the ' in the bin. Related issue: #305

    How to do hot compile only and not run anything?

    See #365.

    [build]
      cmd = "/usr/bin/true"
    

    How to reload the browser automatically on static file changes?

    Enable the proxy — see Proxy: reload the browser automatically. Make sure your static files are covered by include_dir, include_ext, or include_file, otherwise editing them never triggers a reload. Refer to issue #512 for additional details.

    Development

    Please note that it requires Go 1.25+ (see go.mod).

    # Fork this project
    
    # Clone it
    mkdir -p $GOPATH/src/github.com/cosmtrek
    cd $GOPATH/src/github.com/cosmtrek
    git clone [email protected]:<YOUR USERNAME>/air.git
    
    # Install dependencies
    cd air
    make ci
    
    # Explore it and happy hacking!
    make install
    

    Pull requests are welcome.

    Release

    # Checkout to master
    git checkout master
    
    # Add the version that needs to be released
    git tag v1.xx.x
    
    # Push to remote
    git push origin v1.xx.x
    
    # The CI will process and release a new version. Wait about 5 min, and you can fetch the latest version
    

    Motivation

    When I started developing websites in Go and using the gin framework, it was a pity that gin lacked a live-reloading function. So I searched around and tried fresh; it seemed not much flexible, so I intended to rewrite it better. Finally, Air's born.

    In addition, great thanks to pilu, no fresh, no air :)

    Star History

    Sponsor

    Buy Me A Coffee

    Give huge thanks to lots of supporters. I've always been remembering your kindness.

    License

    GNU General Public License v3.0