Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 30 additions & 14 deletions .github/workflows/deploy-plugins.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Deploy per-agent plugin distributions to their own repositories.
# Deploy per-agent distributions to their own repositories.
#
# This repository is the single source of truth (skills + routing metadata,
# feeding skills.sentry.dev). Each AI assistant needs the plugin in a different
# shape, so this workflow builds each one and deploys it to a dedicated
# repository whose ROOT is exactly that agent's plugin:
# feeding skills.sentry.dev). Each AI assistant needs the integration in a
# different shape, so this workflow builds each one and deploys it to a
# dedicated repository whose root is exactly that agent's distribution:
#
# claude -> getsentry/plugin-claude
# cursor -> getsentry/plugin-cursor
# codex -> getsentry/plugin-codex
# grok -> getsentry/plugin-grok
# claude -> getsentry/plugin-claude
# cursor -> getsentry/plugin-cursor
# codex -> getsentry/plugin-codex
# grok -> getsentry/plugin-grok
# opencode -> getsentry/plugin-opencode
# opencode2 -> getsentry/plugin-opencode2
#
# Each plugin repository carries two rolling branches, and which one a run writes
# is the whole difference between a deploy and a release:
Expand All @@ -25,14 +27,14 @@
# A release also tags the plugin repository (`v<version>`), giving each shipped
# version an addressable ref for pinning and rollback.
#
# Marketplaces consume `getsentry/plugin-<agent>` by git ref. Each job builds its
# agent's tree from this repo, then commits it onto the target branch of the
# target repo, replacing the previous contents. The four jobs target four
# different repos, so they run in parallel without contention.
# Marketplaces and installers consume `getsentry/plugin-<agent>` by git ref. Each
# job builds its agent's tree from this repo, then commits it onto the target
# branch of the target repo, replacing the previous contents. The six jobs target
# six different repos, so they run in parallel without contention.
#
# Cross-repo writes use a GitHub App token scoped per-job to a single plugin
# repo; the default GITHUB_TOKEN cannot push to other repositories. The app must
# be installed on the org with contents:write on the four plugin repos, its ID
# be installed on the org with contents:write on the six plugin repos, its ID
# stored as the PLUGIN_DEPLOY_APP_ID variable and its private key as the
# PLUGIN_DEPLOY_KEY secret. Each target repo must already exist with `main` as
# its default branch; `develop` is branched off it on the first deploy.
Expand Down Expand Up @@ -83,7 +85,7 @@ jobs:
strategy:
fail-fast: false
matrix:
agent: [claude, cursor, codex, grok]
agent: [claude, cursor, codex, grok, opencode, opencode2]
concurrency:
group: deploy-plugin-${{ matrix.agent }}-${{ inputs.target_branch || 'develop' }}
cancel-in-progress: false
Expand All @@ -108,6 +110,20 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0

- name: Set up Node for OpenCode validation
if: matrix.agent == 'opencode' || matrix.agent == 'opencode2'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24

- name: Install OpenCode V1 CLI
if: matrix.agent == 'opencode'
run: npm install -g opencode-ai@1.18.0

- name: Install OpenCode V2 CLI
if: matrix.agent == 'opencode2'
run: npm install -g @opencode-ai/cli@0.0.0-next-16420

- name: Build and deploy plugin-${{ matrix.agent }}
env:
AGENT: ${{ matrix.agent }}
Expand Down
104 changes: 98 additions & 6 deletions .github/workflows/smoke-installer.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# 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.
# (--no-interactive) so it installs the Sentry integration for every detected
# agent without a prompt, and verifies each distribution 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
# Claude Code, Codex, Grok, and OpenCode V1 ship cross-platform npm CLIs, so
# they get real CLI installs. 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).
#
# The OpenCode target repositories are replaced with temporary local git
# repositories in both jobs; this tests the real clone flow before those
# generated repositories are first deployed.

name: Smoke installer

Expand All @@ -21,10 +25,12 @@ on:
branches: [main]
paths:
- "packages/installer/**"
- "mcp.json"
- ".github/workflows/smoke-installer.yml"
pull_request:
paths:
- "packages/installer/**"
- "mcp.json"
- ".github/workflows/smoke-installer.yml"
workflow_dispatch:

Expand Down Expand Up @@ -57,8 +63,24 @@ jobs:
- 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: Install Claude Code, Codex, Grok, and OpenCode V1 CLIs
run: npm install -g @anthropic-ai/claude-code @openai/codex @xai-official/grok opencode-ai@1.18.0

- name: Prepare local OpenCode V1 distribution
run: |
set -euo pipefail
repo="$RUNNER_TEMP/plugin-opencode"
mkdir -p "$repo/skills/sentry-installer-smoke"
printf '1\n' > "$repo/.sentry-opencode-v1"
printf '%s\n' '---' 'name: sentry-installer-smoke' 'description: Verify the Sentry OpenCode installer' '---' '' '# Sentry installer smoke' > "$repo/skills/sentry-installer-smoke/SKILL.md"
git -C "$repo" init -q
git -C "$repo" config user.name smoke-test
git -C "$repo" config user.email smoke@example.com
git -C "$repo" add .
git -C "$repo" commit -qm 'test: seed OpenCode bundle'
repo_url="$(node -e 'console.log(require("node:url").pathToFileURL(process.argv[1]).href)' "$repo")"
git config --global protocol.file.allow always
git config --global "url.${repo_url}.insteadOf" https://github.com/getsentry/plugin-opencode.git

- name: Put a Cursor stub on PATH
run: |
Expand Down Expand Up @@ -96,4 +118,74 @@ jobs:
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 "== opencode =="
opencode debug skill > "$RUNNER_TEMP/opencode-skills.json"
grep -q 'sentry-installer-smoke' "$RUNNER_TEMP/opencode-skills.json" || { echo "opencode: sentry skill missing"; exit 1; }
node - <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const os = require("node:os");
const root = path.join(os.homedir(), ".config", "opencode");
const file = ["opencode.json", "opencode.jsonc"].map((name) => path.join(root, name)).find(fs.existsSync);
if (!file) throw new Error("opencode: global config missing");
const config = JSON.parse(fs.readFileSync(file, "utf8"));
if (!config.mcp?.sentry?.url?.includes("mcp.sentry.dev")) throw new Error("opencode: Sentry MCP missing");
NODE

echo "All agents have the Sentry plugin."

# OpenCode V2 currently recommends WSL on Windows and cannot share V1's MCP
# config shape, so exercise it separately from the cross-platform V1 matrix.
smoke-opencode2:
Comment thread
sergical marked this conversation as resolved.
name: OpenCode V2 beta
runs-on: ubuntu-latest
env:
SENTRY_DSN: ""
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
- run: pnpm --filter @sentry/ai build
- run: npm install -g @opencode-ai/cli@0.0.0-next-16420

- name: Prepare local OpenCode V2 distribution
run: |
set -euo pipefail
repo="$RUNNER_TEMP/plugin-opencode2"
mkdir -p "$repo/skills/sentry-installer-smoke"
printf '2\n' > "$repo/.sentry-opencode-v2"
printf '%s\n' '---' 'name: sentry-installer-smoke' 'description: Verify the Sentry OpenCode V2 installer' 'metadata:' ' opencode/autoinvoke: "false"' '---' '' '# Sentry installer smoke' > "$repo/skills/sentry-installer-smoke/SKILL.md"
git -C "$repo" init -q
git -C "$repo" config user.name smoke-test
git -C "$repo" config user.email smoke@example.com
git -C "$repo" add .
git -C "$repo" commit -qm 'test: seed OpenCode V2 bundle'
repo_url="$(node -e 'console.log(require("node:url").pathToFileURL(process.argv[1]).href)' "$repo")"
git config --global protocol.file.allow always
git config --global "url.${repo_url}.insteadOf" https://github.com/getsentry/plugin-opencode2.git

- name: Run installer (non-interactive)
run: node packages/installer/dist/index.js install --no-interactive

- name: Verify OpenCode V2 installation
run: |
set -euo pipefail
node - <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const os = require("node:os");
const bundle = path.join(os.homedir(), ".config", "opencode", "skills", "sentry", "skills", "sentry-installer-smoke", "SKILL.md");
if (!fs.existsSync(bundle)) throw new Error(`opencode2: Sentry skill missing at ${bundle}`);
const root = path.join(os.homedir(), ".config", "opencode");
const file = ["opencode.json", "opencode.jsonc"].map((name) => path.join(root, name)).find(fs.existsSync);
if (!file) throw new Error("opencode2: global config missing");
const config = JSON.parse(fs.readFileSync(file, "utf8"));
if (!config.mcp?.servers?.sentry?.url?.includes("mcp.sentry.dev")) throw new Error("opencode2: Sentry MCP missing");
NODE
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.claude/*
!.claude/settings.json
.DS_Store
node_modules/
13 changes: 9 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

## Project Overview

Sentry plugin for AI coding assistants (Claude Code, Cursor, Codex, and Grok).
Provides MCP server integration and skills.
Sentry plugin for AI coding assistants (Claude Code, Cursor, Codex, Grok, and OpenCode
V1/V2). Provides MCP server integration and skills.

## Commit Attribution

Expand All @@ -24,8 +24,8 @@ src/plugins/version.json # The one release version, stamped into every manifest
src/SKILL_TREE.md # Generated skill index (see Skill Tree Navigation below)
```

Per-agent plugin metadata is generated by the `src/plugins/<agent>/build.sh` scripts and
published to each agent’s distribution repository; it is not committed here.
Per-agent distribution metadata is generated by the `src/plugins/<agent>/build.sh`
scripts and published to each agent’s distribution repository; it is not committed here.

Skill frontmatter is `name`, `description`, and `license`. Nothing else is required, and
the retired router fields (`category`, `parent`, `role`, `disable-model-invocation`) are
Expand Down Expand Up @@ -53,6 +53,11 @@ it).
Claude declares the server inline in its `plugin.json` (`mcpServers`), so the Claude
build ships no MCP file.

OpenCode V1 and V2 generate native `opencode.json` files from `mcp.json`. V1 places
`sentry` directly under `mcp`; V2 places it under `mcp.servers`. Their installer
harnesses use the corresponding CLI command to merge that entry into the user’s global
config.

## Releasing the Plugins

The four agent plugins version in lockstep from `src/plugins/version.json`. Each agent
Expand Down
33 changes: 20 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

> [!IMPORTANT]
> **This is a skill *source* repository — not something you install directly.** The
> skills here are built from this source into installable plugins for
> skills here are built from this source into installable distributions for
> [Claude Code](https://github.com/getsentry/plugin-claude),
> [Cursor](https://github.com/getsentry/plugin-cursor),
> [Codex](https://github.com/getsentry/plugin-codex), and
> [Grok](https://github.com/getsentry/plugin-grok) — install one of those, not this
> repo. They’re also served over HTTP at [skills.sentry.dev](https://skills.sentry.dev)
> for agents to fetch directly.
> [Codex](https://github.com/getsentry/plugin-codex),
> [Grok](https://github.com/getsentry/plugin-grok),
> [OpenCode V1](https://github.com/getsentry/plugin-opencode), and
> [OpenCode V2](https://github.com/getsentry/plugin-opencode2) — install one of those,
> not this repo. They’re also served over HTTP at
> [skills.sentry.dev](https://skills.sentry.dev) for agents to fetch directly.
> In the future we may also publish the skills as a generic, standalone skills
> repository.

Expand All @@ -22,8 +24,10 @@ The plugin gives your assistant the context it needs to do it right.

Supports [**Claude Code**](https://github.com/getsentry/plugin-claude),
[**Cursor**](https://github.com/getsentry/plugin-cursor),
[**Codex**](https://github.com/getsentry/plugin-codex), and
[**Grok**](https://github.com/getsentry/plugin-grok).
[**Codex**](https://github.com/getsentry/plugin-codex),
[**Grok**](https://github.com/getsentry/plugin-grok),
[**OpenCode V1**](https://github.com/getsentry/plugin-opencode), and
[**OpenCode V2**](https://github.com/getsentry/plugin-opencode2).

## What You Can Do

Expand Down Expand Up @@ -65,18 +69,21 @@ Set up OTel Collector with Sentry exporter
## Distribution

This repository is the single source of truth for all skills, but it is not itself an
installable plugin.
Each assistant needs the plugin in a slightly different shape, so the
per-agent plugins are **built** from it by the build scripts under
installable distribution.
Each assistant needs the integration in a slightly different shape, so the per-agent
distributions are **built** from it by the build scripts under
`src/plugins/<agent>/build.sh`. CI runs these on every push and deploys each result to
its own **distribution repository**, whose root is exactly that agent’s plugin:
its own **distribution repository**, whose root is exactly that agent’s installable
bundle or native plugin:

| Agent | Distribution repository |
| --- | --- |
| Claude Code | [`getsentry/plugin-claude`](https://github.com/getsentry/plugin-claude) |
| Cursor | [`getsentry/plugin-cursor`](https://github.com/getsentry/plugin-cursor) |
| Codex | [`getsentry/plugin-codex`](https://github.com/getsentry/plugin-codex) |
| Grok | [`getsentry/plugin-grok`](https://github.com/getsentry/plugin-grok) |
| OpenCode V1 | [`getsentry/plugin-opencode`](https://github.com/getsentry/plugin-opencode) |
| OpenCode V2 | [`getsentry/plugin-opencode2`](https://github.com/getsentry/plugin-opencode2) |

These repositories are generated; do not edit them.
Each one’s README has the install instructions for that agent.
Expand All @@ -94,11 +101,11 @@ skill tree’s `disable-model-invocation` flags for Codex’s `agents/openai.yam
```bash
git clone https://github.com/getsentry/sentry-for-ai.git
cd sentry-for-ai
src/plugins/codex/build.sh /tmp/sentry-codex # or src/plugins/{claude,cursor,grok}
src/plugins/codex/build.sh /tmp/sentry-codex # or src/plugins/{claude,cursor,grok,opencode,opencode2}
```

To build any target locally, run `src/plugins/<agent>/build.sh <output-dir>` (`claude`,
`cursor`, `codex`, or `grok`).
`cursor`, `codex`, `grok`, `opencode`, or `opencode2`).

## Skills

Expand Down
20 changes: 15 additions & 5 deletions packages/installer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ and fix production issues, and how to configure alerts, AI monitoring, and more.
This package detects which assistants you have installed and wires the plugin into each
one for you.

Supports **Claude Code**, **Codex**, **Cursor**, and **Grok**.
Supports **Claude Code**, **Codex**, **Cursor**, **Grok**, **OpenCode V1**, and
**OpenCode V2**.

```bash
npx @sentry/ai install
Expand Down Expand Up @@ -40,16 +41,19 @@ The non-interactive mode is intended for CI and unattended runs and skips this p

## What it installs

For each detected assistant, the installer runs that tool’s native plugin command:
For each detected assistant, the installer uses its native package command or installs
the generated skill bundle:

| Assistant | How it’s installed |
| --- | --- |
| Claude Code | `claude plugin install sentry` from the official plugin marketplace |
| Codex | `codex plugin add sentry` from the Sentry plugin marketplace |
| Cursor | Clones [`getsentry/plugin-cursor`](https://github.com/getsentry/plugin-cursor) into `~/.cursor/plugins/local/sentry` |
| Grok | `grok plugin install getsentry/plugin-grok` |
| OpenCode V1 | Clones [`getsentry/plugin-opencode`](https://github.com/getsentry/plugin-opencode) into OpenCode’s global skills and adds the V1 Sentry MCP entry |
| OpenCode V2 | Clones [`getsentry/plugin-opencode2`](https://github.com/getsentry/plugin-opencode2) into OpenCode’s global skills and adds the V2 Sentry MCP entry |

Each per-agent plugin is built and published from the
Each per-agent distribution is built and published from the
[`sentry-for-ai`](https://github.com/getsentry/sentry-for-ai) repository, which is the
source of truth for all skills.

Expand All @@ -62,13 +66,19 @@ npx @sentry/ai remove --no-interactive # remove from every agent that has it

`uninstall` is an alias for `remove`. This only offers agents that currently have the
plugin, and removes the Sentry plugin itself — each tool’s plugin marketplace is left
registered. Restart your AI tools afterward to drop the plugin.
registered. OpenCode’s CLIs do not provide an MCP remove command, so the installer
identifies the config entry to delete manually.
Restart your AI tools afterward to drop the plugin.

## Requirements

- Node.js 18 or newer
- The assistant CLI you want to set up must already be installed and on your `PATH`
- `git` is required for the Cursor install
- `git` is required for the Cursor and OpenCode installs

OpenCode V1 and the OpenCode V2 beta use the same global config path but incompatible
MCP shapes. When both `opencode` and `opencode2` are installed, the installer configures
V2 only.

## License

Expand Down
1 change: 1 addition & 0 deletions packages/installer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@listr2/prompt-adapter-inquirer": "^4.2.4",
"@sentry/node": "^10.57.0",
"citty": "^0.1.6",
"jsonc-parser": "^3.3.1",
"listr2": "^10.2.1"
},
"devDependencies": {
Expand Down
Loading
Loading