Installing the Sentry plugin was a one-way door — there was no built-in
way to take it back out. Add a `remove` subcommand that mirrors install:
it reuses the detect and select steps, then uninstalls the plugin from
each chosen agent (claude plugin uninstall, codex plugin remove, grok
plugin uninstall, and deleting the Cursor checkout).
Removal only takes out our own plugin. Any marketplace we registered is
left in place — Claude's is Anthropic's shared official one, so
deregistering it could pull it out from under other plugins — and the
install-time cleanup of conflicting plugins does not run.
The UI is factored into a shared runFlow driven by a FlowMode descriptor
so install and remove share detection, selection, concurrency, and
output streaming while differing only in their tagline, prompt copy,
per-agent action, and closing line. The remove flow leads with a static
"Neuralyzing your agents of Sentry." header (no shimmer).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships the updated installer README (install command + demo) to the npm
package page. craft's "simple" changelog policy requires the entry to exist
before prepare.
Add a tagline under the banner and rework the closing line so the run
opens and closes on the same beat ("teaching your agents to speak
Sentry" -> "your agents now speak Sentry") instead of a flat restart
hint.
On a color terminal the tagline animates: a bright band shimmers across
"speak Sentry" while the install runs, then settles to a static line.
It is painted as a header by a custom listr renderer (ShimmerRenderer)
so the step list renders normally beneath it; off a TTY (CI, pipes,
NO_COLOR) it stays a plain static line. The shimmer effect lives in its
own module, text-shimmer.ts.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When an install streams through an output sink, runStreaming piped the
command's stderr to the live view but never captured it, so a failure
fell through to runInstallCommand's generic "exit code N" message. The
interactive UI always passes a sink, so Listr failure text was almost
always that generic message instead of the agent's actual error.
Tee stderr: keep piping it to the sink for the live view, and also
buffer it into the result so the thrown error carries the real text.
Show what each agent is actually doing instead of a static spinner. An
optional output sink threads from the install task down through
install/update/cleanup to the shell runner; the real system spawns the
command and pipes its stdout/stderr into the task's stream, so progress
appears live under each agent's row. Detection probes still buffer and
parse as before — only the mutating commands stream.
Theme the renderer to match the Sentry banner: diamond task icons with a
small-to-large pulsing diamond spinner, streamed output grayed (per line,
so blank lines stay empty and removeEmptyLines can drop them) and kept on
screen via persistentOutput, an arrow prompt cursor with the gap moved
onto the checkbox icons to preserve alignment, and a blue hollow-diamond
prompt prefix. Also drop the Cursor restart note now that the closing
line covers it.
The install subtasks run under a parent "Installing plugins" task, which
collapses its children once it completes — folding away each agent's
resolved command and cleanup note. Set collapseSubtasks: false so the
per-agent rows and their output stay visible after the group finishes.
The closing line said "Restart your AI tools to load the Sentry plugin",
which is vague when only some of the detected agents were installed.
List the agents that actually received the plugin instead, e.g. "Restart
Claude Code and Codex to use Sentry with AI". Blocked or failed agents
are excluded since there is nothing to restart for them.
Switch every harness's installed-probe from substring-grepping plain
`plugin list` output to parsing the `--json` variant and matching on the
plugin's real identity. Claude and Codex match a marketplace-qualified
id; Grok matches our repo source with no marketplace, since the source
alone cannot tell a direct repo install from one made through the "xAI
Official" marketplace.
Add an optional `cleanup` step that runs before install to remove a
conflicting or legacy Sentry plugin that would otherwise shadow ours:
Codex removes the curated `sentry@openai-curated`, and Grok uninstalls a
marketplace-installed sentry so our direct-repo install resolves.
`cleanup` returns a short description of what it removed, which the
installer surfaces as persistent task output so the removal is visible
rather than silent.
Split the single `install` method into explicit `install` and `update`
so the orchestrator picks based on what detection already found, instead
of each harness re-probing its own listing.
Add the Craft release pipeline so packages/installer can be published to
npm as @sentry/ai.
- .craft.yml configures a single npm target (public scoped access) with a
tarball-name guard. There is deliberately no github target, so a release
creates no git tags and no GitHub releases -- nothing repo-wide implying
the skills/plugins are versioned by it.
- The release branch is scoped to `release-installer/<version>` via
releaseBranchPrefix, so it reads as a package release. craft creates it
during prepare and deletes it after publish, so it is transient.
- changelogPolicy is `simple` (matching sentry-javascript) and the
changelog lives with the package at packages/installer/CHANGELOG.md. The
entry is written by hand before releasing; `auto` would sweep this repo's
skill-drift and plugin churn into the installer changelog.
- release.yml runs `craft prepare` via the Sentry release bot App token.
It must be an App token rather than GITHUB_TOKEN so the pushed release
branch triggers release-build.yml, which packs the tarball and uploads
it as the SHA-named artifact Craft's GitHub provider expects.
- The package gains `files: ["dist", "CHANGELOG.md"]`, publishConfig.access
public, and an explicit LICENSE so the published tarball is complete
without relying on pnpm copying the root LICENSE.
Publishing runs from getsentry/publish after a team lead approves the
release issue; this repo only prepares the release and builds the artifact.
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.