Files
Evan Purkhiser d86aedebf5 feat(installer): add CLI to install the Sentry plugin across AI agents (#180)
Add a pnpm workspace with a `packages/installer` package (`@sentry/ai`)
that provides a single CLI for installing the Sentry plugin into any
supported AI coding assistant: Claude Code, Codex, Cursor, and Grok.

The CLI (built on citty) exposes an `install` subcommand. By default it
shows an interactive selector pre-selecting the detected agents;
`--no-interactive`/`--yes` skips the prompt and installs every detected
agent — used for CI and unattended runs.

Each agent is a self-contained harness implementing a common strategy
interface — detect, isInstalled, canInstall, install — so adding a new
agent is just another module. System access (shell, fs, platform,
homedir) is injected through a SystemDeps seam, keeping every harness
unit-testable without side effects.

Behavior:
- Already-installed agents update in place rather than erroring or
  no-opping: Cursor pulls, Grok/Claude use their update commands, Codex
  re-adds (idempotent; it has no update command).
- Claude refreshes its marketplace index before installing, since a fresh
  CLI ships a stale index that cannot resolve the plugin.
- canInstall gates prerequisites (Cursor needs git) and reports a clear
  skip instead of a cryptic failure.
- One agent failing does not abort the rest, and the CLI exits non-zero
  if any selected agent failed or was blocked.
- Cross-platform: binary detection uses where/which per OS, Cursor is
  located via its per-OS install path, and git paths are quoted for
  Windows spaces.

Distribution:
- rolldown bundles the npm package (deps external).
- fossilize builds standalone Node SEA binaries; --hole-punch drops
  non-English ICU data to cut the download ~30%.

CI:
- A smoke-test matrix (Linux, macOS, Windows) installs the real agent
  CLIs and runs the installer non-interactively, asserting the plugin
  lands for every detected agent.

Instrumented with the Sentry Node SDK.
2026-06-17 13:09:44 -04:00

100 lines
3.4 KiB
YAML

# End-to-end smoke test of the installer across Linux, macOS, and Windows.
#
# Installs the real agent CLIs, then runs the installer in non-interactive mode
# (--no-interactive) so it installs the Sentry plugin for every detected agent
# without a prompt, and verifies each plugin actually landed.
#
# Claude Code, Codex, and Grok ship cross-platform npm CLIs, so they get a real
# install against their default marketplaces. Cursor has no headless CLI to
# install in CI, but our Cursor install is only a `git clone` of the public
# plugin repo into ~/.cursor/plugins/local/sentry — so we put a `cursor` stub on
# PATH to satisfy detection and verify the real clone (this is what exercises
# the per-OS path handling, including Windows).
name: Smoke installer
permissions:
contents: read
on:
push:
branches: [main]
paths:
- "packages/installer/**"
- ".github/workflows/smoke-installer.yml"
pull_request:
paths:
- "packages/installer/**"
- ".github/workflows/smoke-installer.yml"
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
smoke:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
env:
SENTRY_DSN: "" # don't report CI smoke runs to Sentry
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build
run: pnpm --filter @sentry/ai build
- name: Install Claude Code, Codex, and Grok CLIs
run: npm install -g @anthropic-ai/claude-code @openai/codex @xai-official/grok
- name: Put a Cursor stub on PATH
run: |
dir="$RUNNER_TEMP/cursor-bin"
mkdir -p "$dir"
if [ "$RUNNER_OS" = "Windows" ]; then
printf '@exit /b 0\r\n' > "$dir/cursor.cmd"
else
printf '#!/bin/sh\nexit 0\n' > "$dir/cursor"
chmod +x "$dir/cursor"
fi
echo "$dir" >> "$GITHUB_PATH"
- name: Run installer (non-interactive)
# No working-directory: on Windows the bash shell mangles the
# backslashes in a `cd` to the workspace path, so run from the root.
run: node packages/installer/dist/index.js install --no-interactive
- name: Verify the Sentry plugin installed for each agent
run: |
set -euo pipefail
echo "== claude =="
claude plugin list
claude plugin list | grep -iq sentry || { echo "claude: sentry plugin missing"; exit 1; }
echo "== codex =="
codex plugin list
codex plugin list | grep -iq sentry || { echo "codex: sentry plugin missing"; exit 1; }
echo "== grok =="
grok plugin list
grok plugin list | grep -iq sentry || { echo "grok: sentry plugin missing"; exit 1; }
echo "== cursor =="
node -e "const p=require('path').join(require('os').homedir(),'.cursor','plugins','local','sentry'); if(!require('fs').existsSync(p)){console.error('cursor: plugin dir missing at '+p);process.exit(1)} console.log(p)"
echo "All agents have the Sentry plugin."