Skip to content

feat(dist): build and publish per-agent plugin distributions#158

Merged
evanpurkhiser merged 1 commit into
getsentry:mainfrom
evanpurkhiser:main
Jun 12, 2026
Merged

feat(dist): build and publish per-agent plugin distributions#158
evanpurkhiser merged 1 commit into
getsentry:mainfrom
evanpurkhiser:main

Conversation

@evanpurkhiser

@evanpurkhiser evanpurkhiser commented Jun 4, 2026

Copy link
Copy Markdown
Member

What

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 different shape, so this adds a build that produces a per-agent plugin from this repo and deploys each one to its own repository.

  • plugin-src/<agent>/ holds each agent's source: its manifest(s), a user-facing README.md (shipped into the dist), and a build.sh that assembles that agent's output layout. Shared content (skills/, commands/, assets/, MCP config, SKILL_TREE.md) stays at the repo root.
  • .github/workflows/deploy-plugins.yml runs all four builds on every push and commits each result onto the main branch of a dedicated repo whose root is exactly that agent's plugin: plugin-claude, plugin-cursor, plugin-codex, plugin-grok. The four jobs target four different repos, so they run in parallel.
  • Each target repo's root carries the built plugin plus a generated README.md (with a do-not-edit notice) and a LICENSE.

Per-agent shapes

  • Claude — plugin at the repo root (.claude-plugin/), MCP declared inline in plugin.json.
  • Cursor — same root layout (.cursor-plugin/), MCP as a root mcp.json.
  • Codex — plugin under plugins/sentry/ with a catalog at .agents/plugins/marketplace.json; Codex rejects disable-model-invocation, so the build strips it and emits a per-skill agents/openai.yaml. MCP as a root .mcp.json.
  • Grok — native Grok layout: components at the repo root with a root plugin.json and a self-install catalog at .grok-plugin/marketplace.json. MCP as a root .mcp.json.

MCP config is built from the repo's mcp.json source of truth.

Why

No plugin ecosystem can consume a zip or release asset; all install from a git ref. Deploying each built plugin to its own repository lets a marketplace point at getsentry/plugin-<agent>, and keeps each agent's published surface clean: just that agent's plugin, with no source, build scripts, or sibling agents' files alongside it.

Backwards compatibility

The plugin used to be installed directly from this repo's root. To avoid breaking those installs on a pull, the root .claude-plugin/, .cursor-plugin/, and .mcp.json are retained; their READMEs announce the directories will be removed on or after 2026-07-11 and point at the new repos.

Cross-repo auth

The default GITHUB_TOKEN is scoped to only the repo a workflow runs in, so it cannot push to the sibling plugin repos. Each job mints a short-lived installation token from a dedicated GitHub App (sentry-for-ai distributor) scoped to contents: write on the plugin-* repos, via actions/create-github-app-token. The App ID lives in the PLUGIN_DEPLOY_APP_ID repo variable and its private key in the PLUGIN_DEPLOY_KEY secret.

Setup status

  • Target repos created (plugin-claude, plugin-cursor, plugin-codex, plugin-grok), public, default branch main.
  • PLUGIN_DEPLOY_APP_ID variable and PLUGIN_DEPLOY_KEY secret provisioned.
  • GitHub App installed with contents: write on the claude/cursor/codex repos.
  • Add plugin-grok to the GitHub App's repo access (needed for its CI deploy job).
  • Repoint the agent marketplaces to the new repos (Claude: anthropics/claude-plugins-official #2582; Codex: openai/plugins; Grok: xai-org/plugin-marketplace).

Follow-ups (not in this PR)

  • The Codex router skill bodies still fetch leaves from skills.sentry.dev; they can be rewritten to reference the bundled skills for a fully self-contained Codex plugin.
  • Optional release tags on the plugin repos for pinned installs.

Comment thread .github/workflows/build-dist.yml Outdated
Comment thread .github/workflows/build-dist.yml Outdated
Comment thread .github/workflows/build-dist.yml Outdated
Comment thread plugin-src/codex/build.sh
@evanpurkhiser evanpurkhiser force-pushed the main branch 3 times, most recently from 68ee821 to f487ae7 Compare June 5, 2026 15:28
Comment thread README.md Outdated
Comment thread .github/workflows/build-dist.yml Outdated
Comment thread plugin-src/codex/build.sh Outdated
@evanpurkhiser evanpurkhiser force-pushed the main branch 2 times, most recently from 14232f6 to 6a23314 Compare June 9, 2026 14:57
Comment thread .github/workflows/deploy-plugins.yml
Comment thread .github/workflows/deploy-plugins.yml
PLUGIN_ROOT="$TARGET_DIR/plugins/sentry"

# Pinned to openai/codex; bump the SHA to track upstream contract changes.
VALIDATOR_SHA="cdc1d592df7f066c141025cc8ae80bb3202580b6"

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.

How do we bump this and when?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

tbh no idea when we would want to bump this. I guess when we absolutely need to?

Comment thread plugin-src/codex/hide-skills.py
@evanpurkhiser evanpurkhiser force-pushed the main branch 4 times, most recently from 2a82462 to 9139500 Compare June 10, 2026 16:04
@evanpurkhiser

Copy link
Copy Markdown
Member Author

Not merging this yet. I want to hold until the new per-agent plugin repos (getsentry/plugin-claude, getsentry/plugin-cursor, getsentry/plugin-codex) are established as the source of truth for every published plugin, i.e. the Claude and Codex marketplaces/directories repointed at them. Once all the downstream directories are pointing at the new repos, I'll merge this.

Comment thread .github/workflows/deploy-plugins.yml

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f8e1403. Configure here.


kept = [ln for ln in text.splitlines(keepends=True)
if not ln.lstrip().startswith("disable-model-invocation:")]
skill_md.write_text("".join(kept), encoding="utf-8")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Strips YAML key outside frontmatter

Low Severity

When hiding Codex leaf skills, hide-skills.py drops every line whose trimmed content starts with disable-model-invocation:, not only the frontmatter line. Any later documentation or template in SKILL.md that mentions that key is removed from the built plugin.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f8e1403. Configure here.

Comment thread README.md Outdated
Comment on lines +62 to +67
`main` 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 `main` by the build scripts
under `plugin-src/<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:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let's not mention main so much in our diff, it used to be that there was a multi-branch setup on this repo, but not anymore. in this case we would just say This repository is the single source of truth for all skills etc etc.

@evanpurkhiser evanpurkhiser force-pushed the main branch 3 times, most recently from bb48cc4 to 69fd368 Compare June 12, 2026 17:32
This repository is the single source of truth for skills and routing metadata,
but it is not itself an installable plugin, and each assistant (Claude Code,
Cursor, Codex, Grok) expects the plugin in a different on-disk shape. No plugin
ecosystem can consume a zip or release asset; all install from a git ref. So a
GitHub Actions workflow builds each agent's distribution from this repository
and deploys it to a dedicated repository whose root is exactly that agent's
plugin, which a marketplace points at as getsentry/plugin-<agent>.

Each agent has a `plugin-src/<agent>/` dir with its manifests, README, and a
`build.sh` that assembles the dist tree from shared repo content. Claude, Cursor,
and Grok consume the plugin at the repo root; Codex requires it under
`plugins/sentry/` and rejects the `disable-model-invocation` field the skill
tree relies on, so its build strips that field and emits a per-skill
`agents/openai.yaml` (see `hide-skills.py`). MCP config is built from the repo's
`mcp.json` source of truth: inline in Claude's manifest, and a file for the
others.

Cross-repo writes use a short-lived token from a dedicated GitHub App scoped to
contents:write on the plugin repos; the default GITHUB_TOKEN cannot push to
other repositories.

The root `.claude-plugin/`, `.cursor-plugin/`, and `.mcp.json` are retained so
existing installs that consumed the plugin from this repo's root keep working;
their READMEs announce removal on or after 2026-07-11.
@evanpurkhiser evanpurkhiser merged commit d65bd23 into getsentry:main Jun 12, 2026
6 of 8 checks passed
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