Repository navigation
fix: Claude Code agent frontmatter and the failing upstream sync - #59
Merged
Merged
Conversation
Upstream cursor/plugins now ships its own .claude-plugin/marketplace.json (origin-apps), which add/add-conflicts with this fork's generated one. The conflict handler rebuilt README.md before that conflict was resolved, so rebuild-readme.mjs crashed parsing conflict markers and every daily sync has failed since 2026-10-06. Resolve marketplace.json and README.md with --ours; the existing "Sync manifests" and "Rebuild README" steps regenerate both from the merged tree. Taking upstream's marketplace.json would also have renamed the marketplace from cursor-plugins-claude to cursor-plugins. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Upstream agents use readonly, is_background and model: fast, which Claude Code ignores, so the agent-compatibility reviewers and plugin-architect ran with Edit and Write. sync-manifests now writes adapted copies under <plugin>/agents/claude-code/ and lists every agent in the plugin manifest; upstream files stay untouched, so the sync workflow's upstream-wins conflict rule cannot undo it. CI runs the converter tests and fails when the generated files are stale, and skips draft PRs.
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one): 1
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Move generated copies out of agents/ so upstream's pstack harness walk never sees them, mark the folder as generated, deny Agent too, parse quoted, cased, commented, CRLF and BOM frontmatter, merge an existing disallowedTools, and throw on anything the converter cannot read. Restore validate-plugins.yml to upstream and run the fork's checks from fork-checks.yml and a gate step in sync-upstream.yml.
Throw on Cursor keys hidden in other YAML shapes, in nested agents and on duplicate keys; read only YAML 1.2 booleans; refuse to delete or replace files and agents fields the generator did not write. The sync workflow keeps tokens away from upstream scripts, pushes with an optional SYNC_TOKEN (GITHUB_TOKEN cannot push workflow changes), validates the merged tree, and opens an issue when a run fails.
SmailG
force-pushed
the
fix/claude-agent-frontmatter
branch
from
October 19, 2026 14:29
ff73c2f to
9b02a5a
Compare
Guard pushes with git log --full-history so a touch-then-revert range still needs SYNC_TOKEN, disable hooks for the push, and close the failure issue after a successful sync. Deny writes for a quoted false, throw on escaped or mixed-shape Cursor keys and block-scalar disallowedTools, and test the cleanup loop in sync-manifests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Upstream agents use Cursor-only frontmatter that Claude Code ignores. Claude Code 2.1.296's debug log flags them:
has a frontmatter key Claude Code does not recognize or apply: "readonly"/"is_background".The practical effect: the four
agent-compatibilityreviewers,create-plugin:plugin-architectandadvisor:advisor-subagentare meant to be read-only, but in Claude Code they run with every tool.ci-watcher,poteto-agentanddyl-agentare meant to run in the background and don't.Separately, the daily upstream sync has failed since Oct 6. This PR folds in #58 (by @back1ply), which fixes that, because the agent change needs a working sync to stay current. It will be merged with a merge commit so #58's commit keeps its author.
Fix
Editing the upstream agent files would be undone:
sync-upstream.ymlresolves every merge conflict in upstream's favour. Instead,scripts/sync-manifests.mjsnow:<plugin>/.claude-plugin/agents/, a fork-owned folder. The copies sit outsideagents/, so upstream's pstack harness generator, which walkspstack/agentsrecursively, never sees them. Each copy carries a "generated, do not edit" comment. The folder's marker file lists what the script wrote, and the script refuses to delete a folder without the marker or with any file the marker does not list.readonly: true→disallowedTools: Edit, Write, NotebookEdit, Agent, merged into any existing scalardisallowedTools. Bash is not restricted, so a read-only agent can still write files through it.is_background: true→background: true, unless the agent already setsbackground.model: fast→haiku; an[effort=…]suffix →effort:; a non-Claude model (grok-4.6[...]) is dropped, so the default model order applies..claude-plugin/plugin.jsonagentsfield. A manifestagentsfield replaces the defaultagents/scan, so the originals don't load twice (manifest reference).It fails closed. Only an unquoted YAML 1.2
false(any case, optionally commented) turnsreadonlyoff. Every other value denies writes, including a quoted"false", which a YAML parser reads as a truthy string. Each of these throws and fails the sync rather than shipping a writable agent:? keycomplex key, or outside a recognisable frontmatter block. This includes a plain key repeated in another shape (readonly: falseplus"readonly": true).readonly,is_background,disallowedTools,model,effortorbackground;is_backgroundvalue other thantrueorfalse;disallowedTools;agents/subfolder that needs adapting, or any subfolder when a top-level agent needs adapting;agentsfield the script did not write.The cleanup of
.claude-plugin/for plugins deleted upstream now only runs when that folder is all that is left, so a Claude-native plugin upstream ships is not deleted.CRLF, a byte-order mark, trailing space on the closing fence and frontmatter at end of file are handled, and line endings are kept.
Upstream files are untouched. The README template and the
sync-forkskill describe the new location.CI
validate-plugins.ymlis restored to upstream byte-for-byte. Any fork edit there is lost on the next upstream-wins conflict.fork-checks.ymlruns the converter tests and fails if regenerated files differ from the committed ones. It skips drafts and triggers onscripts/**,*/agents/**,*/.claude-plugin/**and itself.GITHUB_TOKENtrigger no workflows. Before it pushes,sync-upstream.ymltherefore runs these checks on the merged tree:validate-plugins.mjs;generate-pstack-harness-trees.mjs --check, when that script exists.GITHUB_TOKENcannot push commits that change.github/workflows, andworkflowsis not a permission it can be granted. Upstream's182f2ce(Oct 16) changesvalidate-plugins.yml, so the sync now:persist-credentials: false, so the steps that run upstream's scripts hold no token;SYNC_TOKENsecret: a fine-grained token for this repo with Contents, Pull requests and Workflows set to read and write. Without that secret it falls back toGITHUB_TOKEN.SYNC_TOKEN, if any commit inorigin/main..HEADtouches.github/workflows, the run fails with an error naming the secret to add.git log --full-history, because default history simplification hides an upstream touch-then-revert.GITHUB_ENV,PATH). That grants nothing upstream lacks, since its content reachesmainthrough this unattended sync anyway. A separate push job was judged not worth the complexity. Give the token an expiry.sync-failedissue, or comments on the open one; the next successful sync closes it. The sync was red for 14 days without anyone seeing it.Verification
node --test scripts/claude-agents.test.mjs: 112/112 pass. All 87 mutants ofclaude-agents.mjsare killed:node scripts/sync-manifests.mjsis idempotent. Drift-check control: it exits 0 on a clean tree and 1 with a hand-edited generated file committed.d457567).marketplace.json,README.md,validate-plugins.ymlandvalidate-plugins.mjs.All plugins validated successfully.andharness/pstack is up to date.claude plugin validatepasses on the merged tree. Its only warnings are the existing README install-line and version advisories.sync-manifests.mjson a temporary root: a plugin dir holding only.claude-plugin/is cleaned, and one with other content is kept. Removing the guard turns the test red.git logreports 0 files and--full-historyreports 2. With a file-only range it reports 0.actionlintpasses on both workflows, apart from one SC2129 style note that already exists on main.claude -p --plugin-dir …):agent-compatibilityreviewers list(Tools: All tools except Edit, Write, NotebookEdit, Agent);pstackshowspoteto-agentandComment Sickoonce each;Not covered
advisor-subagentasks for a Grok model; in Claude Code it now runs on the default model.background: trueis checked only for ordinary subagents. Agent-team teammates were not exercised.SYNC_TOKENis set yet. Until it is, a sync whose range touches workflows fails loudly and opens an issue./plugin. This is cosmetic and is checked after install.readonly:oris_background:fails the sync. No current upstream agent does this; it is the cost of failing closed.agentslist in the generated shape is replaced by the full list. That is a superset, so no agent is lost.authorfield formatting churn is left as is.