Skip to content

Auto-install the coding agent skill during install.sh/install.ps1 - #61

Open
mattpodwysocki wants to merge 1 commit into
mainfrom
agi-1149-auto-install-skills
Open

mattpodwysocki wants to merge 1 commit into
mainfrom
agi-1149-auto-install-skills

Conversation

@mattpodwysocki

Copy link
Copy Markdown
Contributor

What

AGI-1149 (Phase 1 of the coding-agent-setup epic): mapbox generate-skills
and mapbox agent-skills install already auto-detect the caller's coding
agent, but only run if someone remembers to invoke them after installing
the CLI. Both installers now run them right after placing the binary,
so an agent can use the CLI's skill immediately with no extra step.

Rust: a stable error code, not a behavior change

src/skill_dest.rs's resolve() returned a plain anyhow! when no coding
agent was detected and none was explicitly named with --agent/--global/
--dir. That's the common case for most machines running the installer
(no coding agent at all), and the error had no way to be told apart from
an unrelated internal failure, -o json rendered both with the same
generic "code":"error".

Fixed: that path now returns a CliError with a stable no_agent_detected
code. Same message, same non-zero exit, for every existing caller, human
or script. This is not a behavior change, exit codes are a documented
promise in this repo (CONTRIBUTING.md#compatibility), and I checked that
before touching it.

No other Rust changes were needed. generate-skills/agent-skills install/update already return via ? before making any network call
in this case (confirmed by timing a real run: 0.038s against a scratch
$HOME with no agent, versus a real tarball fetch when one is detected),
so the installers never pay for a wasted network call on a plain human
install either.

install.sh / install.ps1

A new best-effort, silent step after the binary is placed and before the
Tilesets CLI section:

  • --global, not the default project-scoped write: the installer runs in
    whatever directory the shell happened to be in, not a project, so the
    skill goes under the agent's own home instead.
  • Tries agent-skills install first; on a reinstall/upgrade this fails
    with already_installed (the skill directory is already there from the
    previous run), and it falls back to agent-skills update --yes rather
    than the command's own suggested --force, which would blindly discard
    anything a user customized in that directory.
  • Fully silent on any other failure. No agent detected is one of these
    (see above); a genuine failure (no network, disk full, etc.) is treated
    the same way, matching this script's own established best-effort
    precedent elsewhere.
  • Opt out entirely with MAPBOX_CLI_NO_AGENT_SETUP, same boolean spellings
    as MAPBOX_CLI_NO_TELEMETRY.
  • install.ps1 additionally wraps both calls in
    $ErrorActionPreference = 'Continue': both commands write their
    failures to stderr on purpose, and a child writing to stderr is a
    terminating NativeCommandError in Windows PowerShell under Stop
    (set globally at the top of the script), the exact problem
    test-install.ps1's own Invoke-Installer helper already had to work
    around for the same reason, so this reuses that fix rather than
    reinventing one.

Tests

test-install.sh/test-install.ps1 each get three new scenarios
(detected agent, none detected, opted out), a HOME-isolated per-case
environment (new: nothing previously touched $HOME, and this needed
to, without leaking into whoever's real coding agent setup happens to be
present on the machine running the suite), and a fake
generate-skills/agent-skills stand-in so these run for real rather
than against a stub that only understood --version.

Every path was also verified by hand against the real compiled binary
and the real network, not just the stub:

  • Fresh install: real tarball fetch, files land under
    ~/.claude/skills/....
  • Reinstall: already_installed correctly triggers the update fallback.
  • A local edit present at reinstall time: restored to the published
    content, with zero prompt, piped (</dev/null) and run locally in a
    real terminal both.
  • The opt-out variable and all of MAPBOX_CLI_NO_TELEMETRY's accepted
    false-spellings (0, off, no, false) behave the same for the new
    variable.

Not verified: real Windows PowerShell 5.1. This machine only runs
cross-platform pwsh, and test-install.ps1's own C# stand-in binary
(built via csc.exe, Windows-only) wasn't extended to understand the new
subcommands, since iterating on that needs a real Windows machine, which I
don't have here. The PowerShell logic itself was verified via pwsh
against the real compiled binary instead, including under an explicit
$ErrorActionPreference = 'Stop' to match what install.ps1 actually runs
under. Worth a manual check on Windows before this ships, or leaning on CI
if it covers this.

Verification

cargo build/fmt/clippy --all-targets -- -D warnings/test all
clean. shellcheck -s sh clean on both modified shell scripts.
test-install.sh and test-install.ps1 both pass in full, including the
six new scenarios. PSScriptAnalyzer run on install.ps1: the two new
warnings it raised (Write-Host, empty catch block) both already exist
dozens of times elsewhere in the same file, not a new class of issue.

🤖 Generated with Claude Code

AGI-1149 (Phase 1 of the coding-agent-setup epic): mapbox generate-skills
and mapbox agent-skills install already auto-detect the caller's coding
agent, but only run if someone remembers to invoke them after installing
the CLI. Both installers now run them right after placing the binary.

- src/skill_dest.rs: "no agent detected, none named with --agent/--global/
  --dir" now carries a stable no_agent_detected CliError code instead of a
  plain anyhow error with the generic `error` code. Same message, same
  non-zero exit for every existing caller — only the code a caller can
  match on is new. This is what lets the installers tell "nothing to do"
  apart from a real failure without parsing JSON, and it comes for free
  from the existing `?` early-return: generate-skills and agent-skills
  install/update already return before making any network call in this
  case, so no other Rust changes were needed.

- install.sh/install.ps1: a new best-effort, silent step after the binary
  is placed. --global (not the project-scoped default), since the
  installer runs in whatever directory the shell happened to be in, not a
  project. Tries `agent-skills install` first and falls back to
  `agent-skills update --yes` on the one error code that means "already
  installed from a previous run of this same script" — never `--force`,
  which would blindly discard anything a user customized. Opt out with
  MAPBOX_CLI_NO_AGENT_SETUP, same boolean spellings as
  MAPBOX_CLI_NO_TELEMETRY. install.ps1 additionally switches
  $ErrorActionPreference to Continue around both calls, the same fix
  test-install.ps1's own Invoke-Installer already needed for the identical
  Windows PowerShell 5.1 native-stderr-is-terminating quirk.

- test-install.sh/test-install.ps1: three new scenarios each (detected
  agent, none detected, opt-out), plus a HOME-isolated per-case
  environment and a fake generate-skills/agent-skills stand-in so the
  scenarios run for real rather than against a stub that doesn't know the
  new subcommands. The already-installed-then-update fallback and every
  other path were also verified by hand against the real compiled binary
  and the real network (fresh install, reinstall, and a local edit
  restored without any prompt, piped and run locally both) — see the PR
  body for specifics; not something the offline harness can exercise on
  its own.

Not verified: install.ps1's actual behavior on real Windows PowerShell
5.1 — this machine can only run cross-platform pwsh, and
test-install.ps1's own C# stand-in binary (built via csc.exe, Windows
only) wasn't extended to understand the new subcommands, since iterating
on it needs a real Windows machine. The PowerShell logic itself was
verified via pwsh against the real binary instead, including under an
explicit $ErrorActionPreference = 'Stop' to match install.ps1's own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@mattpodwysocki
mattpodwysocki requested a review from a team as a code owner September 28, 2026 19:14

@zmofei zmofei left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, the goal makes sense. But the installer must not set up agent skills without the user's explicit, interactive consent.

As written, both installers do this by default whenever ~/.claude, ~/.codex, etc. exist:

  • They write into directories this CLI doesn't own, and download the whole Mapbox Agent Skills library, without asking.
  • agent-skills install/update output is discarded, so the user isn't even told it happened.
  • On reinstall, agent-skills update --yes overwrites files the user edited, with no prompt. That contradicts the changelog's "a customized skill directory is never silently discarded".
  • The only way out is MAPBOX_CLI_NO_AGENT_SETUP, which someone running curl … | sh won't know about beforehand. An opt-out nobody sees in time isn't a choice.

Requested changes:

  1. Ask before installing. In an interactive terminal, prompt via /dev/tty (and the PowerShell equivalent), naming the detected agent and what will be written where. Install only on an explicit yes.
  2. No prompt possible (CI, no TTY): skip the step and print one line telling the user how to run it by hand (mapbox generate-skills --global, mapbox agent-skills install --global).
  3. Drop --yes from update. If the user has modified files, skip and say so rather than overwrite.
  4. When something is installed, print what and where.

The no_agent_detected error code is useful on its own. Consider splitting it into a separate PR, and documenting it in docs/commands.md with a test, since it's a new machine-readable contract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants