Use this skill to keep the AI toolchain declarative and simple: package updates land in the package repo, consumption happens through locked inputs in the system repo, and live installs happen through the normal Nix/Darwin switch path.
Prefer deleting or reusing existing surfaces over adding commands. Codex is usually the caller; the point is not a polished human interface, it is one small workflow with no duplicate wrappers, aliases, or imperative package-manager side paths.
-
Inspect current state.
cd ~/code/nix/nix-ai-tools && git status --short --branch
cd ~/code/nix/nixos-config && git status --short --branch
-
Check whether the package repo is healthy and current before changing the consumer lock.
cd ~/code/nix/nix-ai-tools
gh run list --branch main --limit 5
./scripts/auto-bump.sh
If auto-bump.sh changes files, inspect the diff, build the changed packages or rerun with AUTO_BUMP_BUILD=1, then commit and push nix-ai-tools first.
-
Check upstream current versions for Homebrew-managed fast tools before trusting local state.
brew livecheck --cask codex claude claude-code || true
python3 - <<'PY'
import json, urllib.request
for cask in ["codex", "claude", "claude-code"]:
with urllib.request.urlopen(f"https://formulae.brew.sh/api/cask/{cask}.json", timeout=20) as response:
data = json.load(response)
print(cask, data.get("version"), data.get("tap_git_head"))
PY
If Homebrew is unavailable, immutable, or stale locally, query the remote tap or upstream release source directly. For example, inspect homebrew/homebrew-cask at the target remote commit and compare the cask version against the local flake-locked tap commit and installed app. brew cat, brew list, and app receipts are local state; they are not enough to prove latest.
-
Update the consumer from the published inputs.
cd ~/code/nix/nixos-config
./stacks/ai/config/scripts/update-ai-tools.sh
This updates the fast inputs, runs nix run .#build, and reports local fast-tool state. Review flake.lock before committing.
-
Compare local installed versions against declared and upstream state.
codex --version || true
claude --version || true
pi --version || true
brew list --cask --versions claude claude-code codex || true
brew outdated --cask --greedy claude claude-code codex || true
/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' /Applications/Claude.app/Contents/Info.plist 2>/dev/null || true
/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' /Applications/Codex.app/Contents/Info.plist 2>/dev/null || true
For each important tool, report upstream latest, locked/declarative version, and installed/live version. Call out uncertainty explicitly when a vendor hides the latest version behind an auto-updater or non-public feed.
-
Install by applying the committed declarative state.
cd ~/code/nix/nixos-config
nix run .#build-switch
This may require interactive sudo with Apple Watch approval. Run it in a real TTY. A normal switch should need one Watch approval up front: keep sudo alive with non-interactive validation, make later wrapper sudo calls non-interactive, and do not leave Homebrew cleanup in prompt mode. If the Watch prompt does not appear or sudo falls through to Password:, do not assume PAM is broken; common causes are Sleep Focus / "Computer and other devices" focus state, a locked or long-idle Mac, the user typing as the prompt appears and dismissing it, or a stale prompt context. Retry once with a fresh foreground TTY prompt. If it still does not trigger, stop and return to the user rather than inventing a non-declarative apply path.
Report four things: package repo health, consumer lock changes, local installed versions, and whether the committed state was built and switched. Call out any package that could not be verified or installed.