> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Auto-Update

> ChatCLI detects how it was installed and updates itself through that same channel — Homebrew, go install, or verified binary self-replace

ChatCLI keeps itself current. It detects **which channel the running binary was installed through** and applies updates **through that exact channel** — it never crosses channels, never fights your package manager, and never touches a build it didn't produce.

```bash theme={"system"}
/update          # check + apply through the detected channel
/update check    # only check — never applies
```

***

## Install-Channel Detection

Detection runs locally (no network) by combining the binary's real path, the Go build metadata and the version stamp injected by the release CI:

| Channel            | How it is recognized                                                                          | Update strategy                                                   |
| ------------------ | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| **Homebrew**       | Real path lives under `Cellar/chatcli` (any prefix: `/opt/homebrew`, `/usr/local`, Linuxbrew) | Runs `brew upgrade diillson/chatcli/chatcli` with streamed output |
| **go install**     | No CI version stamp, but the Go module version is embedded in the binary                      | Runs `go install github.com/diillson/chatcli@latest`              |
| **Release binary** | Version stamped via ldflags by the release workflow                                           | Verified in-place **self-replace**                                |
| **Docker**         | Container markers (`/.dockerenv`, `/run/.containerenv`)                                       | Instructions only — pull the new image                            |
| **Source build**   | Build metadata reports a local `go build`                                                     | **Never touched** — instructions only                             |

<Note>
  The Homebrew check runs first on purpose: the bottle installed by the tap is the *same* stamped asset published on the GitHub release, so only the `Cellar` path distinguishes the two channels.
</Note>

### Why source builds are never auto-updated

A locally compiled binary may carry uncommitted patches. Replacing it with a release artifact would silently destroy that work, so ChatCLI only prints the way forward:

```text theme={"system"}
This is a local source build, so it won't be touched.
Update your checkout: git pull && go build ./...
```

***

## The /update Command

Bare `/update` is an explicit request: when a newer release exists on an automatable channel, it applies immediately — the same semantics as `brew upgrade`.

```text theme={"system"}
> /update

── ChatCLI · Update ──────────────────────────────────────────────

  Checking for updates...
  Install method: official release binary
  Current: v1.169.0 · Latest: v1.186.1

── What's new in v1.186.1 ────────────────────────────────────────

  Features
    • update: new-release notice inside the running session (#1300)
  Bug Fixes
    • welcome banner no longer lags a day behind a new release

  https://github.com/diillson/chatcli/releases/tag/v1.186.1

  Downloading v1.186.1 (chatcli-darwin-arm64)...
  ✓ Updated to v1.186.1 — restart chatcli to use the new version.
```

Before applying anything — and on `/update check` — ChatCLI shows the **What's new** section: the highlights parsed straight from the GitHub release notes, which arrive in the same API response as the version check (no extra network call).

`/update check` reports the same status but never applies anything.

The same card backs `/version` and the `-v`/`--version` flag: installed build, detected install channel, latest release, the invitation to `/update` (plus the channel-native command when there is one) and the what's-new section whenever an update exists.

The command is also available from the interactive command palette and the tab completer, and `/config update` shows the resolved policy at any time.

***

## Verified Self-Replace

When the binary came straight from a GitHub release, ChatCLI updates it in place with a hardened pipeline:

1. Downloads `checksums.txt` from the target release.
2. Streams the platform asset to a staging file **in the same directory** as the binary (guaranteeing an atomic rename on the same filesystem) while computing its SHA-256.
3. Refuses the install on any checksum mismatch — the download is discarded and the current binary is never touched.
4. Swaps atomically: a plain rename on macOS/Linux (the running process keeps its old inode), or the rename-to-`.old` dance on Windows with automatic rollback if activation fails. Leftover artifacts are cleaned on the next boot.

<Warning>
  Releases published before `checksums.txt` existed cannot be verified, and ChatCLI **refuses unverified installs** — you'll get a manual-download instruction instead. This only affects updating *to* very old releases.
</Warning>

If the install directory isn't writable (say, `/usr/local/bin` owned by root), the updater degrades to a copy-paste command:

```text theme={"system"}
❌ No write permission on /usr/local/bin. Update manually:
sudo curl -fsSL -o /usr/local/bin/chatcli https://github.com/diillson/chatcli/releases/download/v1.186.1/chatcli-darwin-arm64 && sudo chmod +x /usr/local/bin/chatcli
```

***

## Background Auto-Update (Staging)

Set `CHATCLI_AUTO_UPDATE` to control the boot-time behavior:

| Value                | Behavior                                                                                                            |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `notify` *(default)* | Checks at boot and shows the update invite on the welcome screen; updating stays a manual `/update`                 |
| `auto`               | Additionally applies the update **silently in the background** on eligible channels (go install and release binary) |
| `off`                | No checks, no notifications                                                                                         |

Auto mode uses **staging**, the same model as Claude Code: the running process is never restarted or interrupted. The new binary lands on disk while you work, and the *next* start opens on the new version — announced once on the welcome screen:

```text theme={"system"}
  Version: 1.186.1 (commit: 52441581)
  ✓ Auto-updated to v1.186.1
```

In `notify` mode (the default) the welcome screen shows the invitation instead — the same one the `/version` card renders, including the native command of your detected install channel:

```text theme={"system"}
  ⬆ v1.186.1 available — run /update to upgrade
    or via your install channel: brew upgrade diillson/chatcli/chatcli
```

The banner is both instant and current: it trusts the last known release data even past the daily re-check window, and when that cache is stale the boot gives the refresh a short synchronous budget (about 1.5 s) before printing — so a release published overnight shows up on the very first banner, not one boot later. A fresh cache (at most one query per day) costs nothing, and `off` mode skips the network entirely. Only when the check can't finish inside the budget (slow or absent network) does the announcement fall back to the running session, at the next prompt turn — you still don't have to restart (or run `/version`) to find out:

```text theme={"system"}
  ⬆ ChatCLI v1.186.1 is available — run /update to upgrade.
```

The same in-session notice fires in `auto` mode when the silent staging fails (for example, the module proxy is unreachable), so a broken background update never hides a new release from you.

<Note>
  **Homebrew is deliberately excluded from silent background updates.** `brew upgrade` takes Homebrew's global lock and can trigger a full `brew update`; ChatCLI only drives it when you explicitly run `/update`. Concurrent ChatCLI processes coordinate through a lock file, so only one performs the background update.
</Note>

***

## Configuration

```bash theme={"system"}
/config update
```

```text theme={"system"}
🔄 Auto-update
   Mode                            notify
   Install method                  Homebrew
   Current version                 1.186.1
   Latest release                  1.186.1

   Environment
   CHATCLI_AUTO_UPDATE             (default) notify
   CHATCLI_DISABLE_VERSION_CHECK   disabled (default)
   CHATCLI_LATEST_VERSION_URL      (not set)
```

| Variable                        | Description                                                | Default    |
| ------------------------------- | ---------------------------------------------------------- | ---------- |
| `CHATCLI_AUTO_UPDATE`           | Update policy: `auto`, `notify` or `off`                   | `notify`   |
| `CHATCLI_DISABLE_VERSION_CHECK` | Disables the release check entirely (implies `off`)        | `false`    |
| `CHATCLI_LATEST_VERSION_URL`    | Custom endpoint for the release check (air-gapped mirrors) | GitHub API |

***

## Troubleshooting

| Symptom                                   | Cause                                                           | Fix                                                               |
| ----------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------- |
| `brew not found in PATH`                  | Homebrew install being updated from a shell without brew        | Run `brew upgrade diillson/chatcli/chatcli` from a normal shell   |
| `go not found in PATH`                    | go install channel without a Go toolchain available             | Install Go, or download the release binary directly               |
| `No prebuilt binary for <os>/<arch>`      | Platform without a published release asset                      | Update through the channel you installed with (e.g. `go install`) |
| Update applied but old version still runs | The staged binary lands on disk; the live process keeps running | Restart chatcli — the next start opens on the new version         |
| `release does not publish checksums.txt`  | Target release predates checksum publishing                     | Download manually from the releases page                          |
