Skip to content

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

Open
evanpurkhiser wants to merge 1 commit into
getsentry:mainfrom
evanpurkhiser:main
Open

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

Conversation

@evanpurkhiser
Copy link
Copy Markdown
Member

@evanpurkhiser evanpurkhiser commented Jun 4, 2026

What

main is the single source of truth for 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 main and publishes each to its own branch.

  • plugin-src/<agent>/ holds each agent's source: a flat plugin.json and marketplace.json, 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/build-dist.yml runs all three builds on every push to main and commits each to an orphan branch whose root is that agent's plugin: dist-claude, dist-cursor, dist-codex. The three jobs touch three different branches, so they run in parallel.
  • Each dist branch root carries the built plugin plus a generated README.md (with a do-not-edit notice) and a LICENSE.
  • The agent adapter dirs (.claude-plugin, .cursor-plugin) are no longer at the repo root, so main's root is no longer itself a plugin; every agent is produced only through its build. Note: Anthropic's official marketplace currently points at the repo root, so it would need repointing to @dist-claude.

Why

No plugin ecosystem (Claude, Cursor, Codex) can consume a zip or release asset; all of them install from a git ref. Publishing each built plugin to a branch lets a marketplace point at getsentry/sentry-for-ai@dist-<agent>.

Claude and Cursor consume a plugin at the dist branch root, but Codex requires the plugin in a subdirectory and rejects the disable-model-invocation field the skill tree relies on. The Codex build moves the plugin under plugins/sentry/, strips that field, and emits a per-skill agents/openai.yaml with policy.allow_implicit_invocation: false, which is Codex's native equivalent. The router skills stay visible and the leaf skills stay hidden, fully bundled, with no skills.sentry.dev dependency.

Live preview (built on my fork)

Verified installs from those branches:

claude plugin marketplace add evanpurkhiser/sentry-for-ai@dist-claude
claude plugin install sentry@sentry-plugin-marketplace

codex plugin marketplace add evanpurkhiser/sentry-for-ai --ref dist-codex
codex plugin add sentry@sentry-plugin-marketplace

Setup needed before this works in this repo

The workflow appends commits to existing orphan branches. Bootstrap them once, then the workflow maintains them:

for a in claude cursor codex; do
  c=$(git commit-tree $(git hash-object -t tree /dev/null) -m "init dist-$a")
  git push origin $c:refs/heads/dist-$a
done

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 dist branches for pinned installs.

Comment thread .github/workflows/build-dist.yml
Comment thread .github/workflows/build-dist.yml
Comment thread .github/workflows/build-dist.yml
Comment thread plugin-src/codex/build.sh
@evanpurkhiser evanpurkhiser force-pushed the main branch 2 times, most recently from b5ce219 to 68ee821 Compare June 4, 2026 19:00
`main` is the single source of truth for skills and routing metadata, but
it is not itself an installable plugin, and Claude Code, Cursor, and Codex each
expect 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 `main` and publishes it to an orphan
`dist-<agent>` branch whose root is exactly that agent's plugin, which a
marketplace points at as `getsentry/sentry-for-ai@dist-<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 and
Cursor consume the plugin at the branch 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` with `policy.allow_implicit_invocation: false` (see
`hide-skills.py`).

Before publishing, each build runs a `validate.sh` gate: Claude and Cursor
manifests are checked against their published JSON Schemas via
`check-jsonschema`, and Codex runs OpenAI's `validate_plugin.py`. Claude
manifests embed `$schema` for editor autocomplete; Cursor and Codex forbid
unknown keys, so theirs supply the schema only at validation time.
Comment thread README.md
Comment on lines +107 to +110
plugin-src/codex/build.sh /tmp/sentry-codex # or plugin-src/claude / plugin-src/cursor
```

Then install from the built directory:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The README's build example only shows how to build the codex plugin, but subsequent installation steps reference directories for claude and cursor which would not exist.
Severity: LOW

Suggested Fix

Expand the build example to explicitly show the build commands for all three agents (claude, codex, and cursor). Alternatively, move the general instruction To build any target locally, run 'plugin-src/<agent>/build.sh <output-dir>' to before the specific code block to provide necessary context upfront.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: README.md#L107-L110

Potential issue: The "Build it yourself" section in the README.md provides an incomplete
example. It shows the build command `plugin-src/codex/build.sh /tmp/sentry-codex` but
then lists installation steps for Claude, Codex, and Cursor, which expect directories
`/tmp/sentry-claude`, `/tmp/sentry-codex`, and `/tmp/sentry-cursor` to exist. A user
following these instructions literally would encounter 'path does not exist' errors for
the Claude and Cursor plugins, as only the `codex` directory would have been created. A
later note clarifies the general build pattern, but it appears after the misleading
example.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

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 f487ae7. Configure here.


# Validate the built tree against the agent's schema/validator before
# it can be published.
"plugin-src/${AGENT}/validate.sh" "$WORKTREE"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dist publish skips skill tree

Medium Severity

The dist publish job copies SKILL_TREE.md from main without running scripts/build-skill-tree.sh --check. Skill-tree validation runs only on pull requests, so a stale or inconsistent index on main can still be built and pushed to install branches.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f487ae7. Configure here.

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.

1 participant