Make the "update available" nudge install-aware and agent-aware
<!-- AI-Sessions dir: ~/.claude/projects/-Users-samwiskow-projects-glab/ 785476a3-9a21-475b-9a1d-914560433da3.jsonl (2026-05-22) --> ## Problem glab already prints an update-available nudge after every command (24h throttled, see `internal/commands/update/check_update.go`). Two gaps make it less useful than it could be: 1. **Coding agents don't relay it to users.** Coding-agent detection only landed in glab v1.98.0 (`internal/api/coding_agent.go`), and agents do not independently check whether glab is up to date. They simply pass through (or drop) whatever the binary prints. The current message — `A new version of glab has been released: v1.60.0 -> v1.62.1` plus a URL, colored on stderr — reads as decorative noise, and agents frequently swallow it. A user can run an outdated glab through an agent for months and never find out. 2. **It isn't actionable.** The message points at the release page but doesn't tell the user how to upgrade on their system. There's also a small secondary benefit: branching the output on `BuildInfo.CodingAgent` reinforces the existing agent-detection signal and helps us understand how glab is used inside coding agents. ## Proposal Keep the existing trigger, 24h throttle, and config wiring exactly as they are. Improve only the *message* in two ways. ### 1. Install-method-aware upgrade command Add a helper that inspects `os.Executable()` (with `filepath.EvalSymlinks`) and returns an install method + suggested command: | Resolved path contains | Method | Suggested command | | --------------------------------------------------------------------- | ------------ | -------------------------------------------------------------- | | `/opt/homebrew/`, `/usr/local/Cellar/`, `/home/linuxbrew/.linuxbrew/` | `homebrew` | `brew upgrade glab` | | `$GOPATH/bin/` (or `$HOME/go/bin/` if `GOPATH` unset) | `go-install` | `go install gitlab.com/gitlab-org/cli/cmd/glab@latest` | | anything else | `unknown` | *(omit command, link release notes only)* | Out of scope for this issue: snap, apt, dnf, scoop, winget. Happy to add in follow-ups if there's demand — comment if you'd find any of these useful. ### 2. Two output formats, chosen by `BuildInfo.CodingAgent` **Human format (no agent detected)** — multi-line, colored, prominent diff: A new version of glab is available v1.60.0 → v1.62.1 Run: brew upgrade glab Release notes: https://gitlab.com/gitlab-org/cli/-/releases/v1.62.1 **Agent format (`CodingAgent != ""`)** — single distinctive line, no ANSI: [glab] Update available: v1.60.0 → v1.62.1 (installed via homebrew). Suggested upgrade command: `brew upgrade glab`. Release notes: https://gitlab.com/gitlab-org/cli/-/releases/v1.62.1 The bracketed `[glab]` prefix and the word "suggested" (advisory, not imperative) are deliberate: it should read as a hint the agent passes along, not an instruction. When the install method is `unknown`, the agent variant drops the "installed via" and "Suggested upgrade command" segments and keeps the release-notes link. The human variant drops the "Run:" line similarly. Both formats continue to write to stderr so structured/JSON output on stdout stays clean. ## Non-goals - No change to *when* the check fires (still post-command, still 24h throttled). - No new config keys. - No structured status file, no JSON marker, no new telemetry payload. - No detection for snap / apt / dnf / scoop / winget at this stage. ## Files to change - **add** `internal/commands/update/install_method.go` - **add** `internal/commands/update/install_method_test.go` - **modify** `internal/commands/update/check_update.go` — message rendering block only (the throttle / HTTP / config code stays untouched) - **modify** `internal/commands/update/check_update_test.go` — table cases covering both formats and both install-method states ## Acceptance criteria - [ ] `DetectInstallMethod()` returns `homebrew` for paths under the three Homebrew prefixes; `go-install` for paths under `$GOPATH/bin` or `$HOME/go/bin`; `unknown` otherwise. Errors from `os.Executable()` or `EvalSymlinks` return `unknown` without panicking. - [ ] When no coding agent is detected and an upgrade is available, the user sees the four-line human format on stderr with `Run:` and `Release notes:` lines. - [ ] When `CLAUDECODE=1` (or any other agent env var detected by `api.DetectCodingAgent()`) is set, the user sees the single `[glab] Update available: …` line on stderr, with no ANSI color codes. - [ ] When install method is `unknown`, neither variant prints an upgrade command — only the release-notes URL. - [ ] No change to the 24h throttle, the explicit `glab check-update` command, `ShouldSkipUpdate`, or the `silentSuccess` behaviour on automatic checks. - [ ] Unit tests cover all four combinations (human × known/unknown, agent × known/unknown). ## Open questions for reviewers - Are there install methods you'd want detected beyond Homebrew and `go install`? snap and apt are the obvious next candidates. - Should the agent-format prefix be `[glab]` or something more distinctive (e.g. `<glab:update>`)? Open to either.
issue