feat(dist): build and publish per-agent plugin distributions#158
Conversation
68ee821 to
f487ae7
Compare
14232f6 to
6a23314
Compare
| PLUGIN_ROOT="$TARGET_DIR/plugins/sentry" | ||
|
|
||
| # Pinned to openai/codex; bump the SHA to track upstream contract changes. | ||
| VALIDATOR_SHA="cdc1d592df7f066c141025cc8ae80bb3202580b6" |
There was a problem hiding this comment.
tbh no idea when we would want to bump this. I guess when we absolutely need to?
2a82462 to
9139500
Compare
|
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. |
9eb4962 to
4ed210f
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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") |
There was a problem hiding this comment.
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.
Reviewed by Cursor Bugbot for commit f8e1403. Configure here.
| `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: |
There was a problem hiding this comment.
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.
bb48cc4 to
69fd368
Compare
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.


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-facingREADME.md(shipped into the dist), and abuild.shthat 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.ymlruns all four builds on every push and commits each result onto themainbranch 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.README.md(with a do-not-edit notice) and aLICENSE.Per-agent shapes
.claude-plugin/), MCP declared inline inplugin.json..cursor-plugin/), MCP as a rootmcp.json.plugins/sentry/with a catalog at.agents/plugins/marketplace.json; Codex rejectsdisable-model-invocation, so the build strips it and emits a per-skillagents/openai.yaml. MCP as a root.mcp.json.plugin.jsonand a self-install catalog at.grok-plugin/marketplace.json. MCP as a root.mcp.json.MCP config is built from the repo's
mcp.jsonsource 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.jsonare 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_TOKENis 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 tocontents: writeon theplugin-*repos, viaactions/create-github-app-token. The App ID lives in thePLUGIN_DEPLOY_APP_IDrepo variable and its private key in thePLUGIN_DEPLOY_KEYsecret.Setup status
plugin-claude,plugin-cursor,plugin-codex,plugin-grok), public, default branchmain.PLUGIN_DEPLOY_APP_IDvariable andPLUGIN_DEPLOY_KEYsecret provisioned.contents: writeon the claude/cursor/codex repos.plugin-grokto the GitHub App's repo access (needed for its CI deploy job).Follow-ups (not in this PR)