Split the agentics repo into a develop branch for day-to-day work and a clean main branch (kept as the GitHub default) that carries only the plugin distribution — so every /plugin install pulls stripped plugin files directly from the default branch while docs, scripts, and development live on develop, automatically republished to main on every push.
Read and implement all steps in the plan at docs/plans/publish-clean-main-from-develop-branch.html — Split repo into a develop dev branch and a clean main distribution branch
Run as workflow — launch parallel subagents
Run a workflow to implement the plan at docs/plans/publish-clean-main-from-develop-branch.html — Split repo into a develop dev branch and a clean main distribution branch
publish-clean-main-from-develop-branch.html
docs/plans/publish-clean-main-from-develop-branch.html
Context
The agentics repo is both the development workspace and the install source. .claude-plugin/marketplace.json registers 12 active plugins via git-subdir sources whose url points at https://github.com/shawn-sandy/agentics.git. When a user installs, Claude Code sparsely clones the plugin's path subtree from the repo's default branch — but that branch carries a lot that has no business in an install: a 35 KB root README.md, docs/, examples/, scripts/, tests/, .playwright-mcp/, a session .png, CLAUDE.local.md, .DS_Store files, and top-level markdown (ROADMAP.md, SECURITY.md, SOCIAL.md).
The sibling plan build-clean-plugin-dist.html solves this by mirroring the marketplace into a separate clean repo (shawn-sandy/agentics-kit) and rewriting each source.url. This plan takes a branch-based approach in the same repo instead: main stays as the GitHub default but is replaced with a clean, stripped plugin distribution, while a new develop branch holds the full workspace where all dev work and PRs happen. Because main remains the default branch, git-subdir sources need no ref field at all — installs naturally resolve from the default branch and get clean files. No second repo, no source.url rewrite, and no ref pins needed.
Decisions locked in clarification: branch model = developers push to develop first (all feature branches and PRs target develop), and only develop can be merged/pushed to main — no direct pushes, no PRs from feature branches to main. A GitHub Action rebuilds and republishes main on every push to develop, orphan-replacing main's tree with the freshly built clean output (main carries distribution snapshots, not dev history). main stays as the GitHub default so installs resolve from it automatically. A key advantage over the separate-repo plan: publishing stays in-repo, so the default GITHUB_TOKEN can push to main — no cross-repo PAT required. An additional advantage over flipping the default: no user migration needed — existing installs keep resolving from main seamlessly.
Files to Modify
- .github/workflows/
publish-dist.ymlnew rebuild + publish main on push to developversion-guard.ymlmodified retarget PR branch filter main → developupdate-readme.ymlmodified ensure it writes to develop, not main.claude-plugin/marketplace.jsonmodified strip removed[] for clean dist; no ref pins neededscripts/build-dist.mjsnew manifest-driven clean builder + check/publish.claude/rules/marketplace.mdmodified main is generated; never hand-editREADME.mdmodified branch model & distribution sectionCLAUDE.mdmodified develop-default; never commit to mainmain (branch)generated clean plugin distribution snapshot
Diagram
develop.github/workflows/publish-dist.ymlscripts/build-dist.mjsmain/plugin install <name>@agentics-kit- docs/ · examples/
- scripts/ · tests/
- *.local.md · ROADMAP/SECURITY/SOCIAL.md
- full kit/plugins/* (with scratch)
- all dev CI workflows
- .claude-plugin/marketplace.json
- no ref needed (default branch)
- kit/plugins/<name>/ stripped
- slim README.md · LICENSE
- docs/ · examples/ · tests/
- *.local.md · .DS_Store · *.png
- .playwright-mcp/
- ROADMAP/SECURITY/SOCIAL.md
- removed[] plugins (×6)
Steps
develop branch from main and configure PR targeting
git tag pre-dist-split) as a safety net so the full history stays reachable. Main stays as the GitHub default so that /plugin install resolves from it without any ref pin — but PRs and dev work must target develop going forward.Verify
git checkout main && git pull && git checkout -b develop && git push -u origin develop succeeds; gh repo view --json defaultBranchRef -q .defaultBranchRef.name still returns main; git diff main develop --stat is empty (identical trees at split time); git tag pre-dist-split exists.develop first — all feature branches and PRs must target develop, never main. Only the CI publish workflow writes to main. Retarget any open PRs from main to develop and communicate the new branching model to contributors.Verify
gh pr list --base main --state open returns no results (all retargeted to develop); commit lands on develop.scripts/build-dist.mjs — a manifest-driven clean builder
merge-marketplace.mjs convention (bare ESM, run via node, no package.json). Enumerate plugins by reading marketplace.json plugins[] (never by globbing); copy only a KEEP allowlist (.claude-plugin, commands, skills, agents, hooks, hooks.json, templates, README.md, CHANGELOG.md, LICENSE) per plugin into an OUT_DIR; drop a DROP denylist (docs, *.local.md, .DS_Store, *.png, .playwright-mcp); emit a clean root (marketplace.json with removed[] stripped, a slim README.md, copied LICENSE).Verify
node scripts/build-dist.mjs --list prints exactly the 12 active plugin names and omits the 6 in removed[]; after node scripts/build-dist.mjs, find <OUT_DIR> -name '*.local.md' -o -name '.DS_Store' -o -path '*/docs/*' returns nothing.--check and orphan-replace --publish modes to the build script
--check walks the built output and exits non-zero if any DROP pattern leaked (a CI tripwire against bloat). --publish implements the chosen "orphan / replace each publish" model: it builds the clean tree, replaces main's working tree wholesale with that output as a single fresh commit referencing the source develop SHA, and updates main (via git worktree + a clean checkout, or an orphan commit) so deleted plugins disappear downstream. Support --dry-run so the commit can be previewed without pushing.Verify
node scripts/build-dist.mjs --check; echo $? prints 0; temporarily adding docs to KEEP, rebuilding, and rerunning --check exits non-zero naming the offending path (then revert). node scripts/build-dist.mjs --publish --dry-run reports the single clean commit it would write to main without pushing..github/workflows/publish-dist.yml triggered on push to develop
on: push: branches: [develop] plus workflow_dispatch; checkout develop, actions/setup-node, node scripts/build-dist.mjs --check (fail fast on leakage), then --publish to replace main's tree. Because the dist target is the same repo, set permissions: contents: write and use the default GITHUB_TOKEN — no cross-repo PAT. Add a concurrency group (publish-dist, cancel-in-progress) so rapid pushes don't race on main.Verify
actionlint .github/workflows/publish-dist.yml); a workflow_dispatch run (or a test push to develop) completes green and writes a new clean commit to main; git ls-tree -r origin/main --name-only | grep -E 'docs/|\.local\.md|\.DS_Store' returns nothing.develop and protect main as generated-only
version-guard.yml filters pull_request: branches: [main] — change to [develop]. Update update-readme.yml to commit to develop instead of main. claude-code-review.yml / claude.yml need PR base branch filter updated to develop. Add branch protection on main to block direct pushes and PRs — only the publish-dist Action (via GITHUB_TOKEN) can write to main.Verify
grep -n 'branches:' .github/workflows/version-guard.yml shows [develop]; opening a test PR against develop triggers the version-guard and Claude review workflows; no workflow other than publish-dist.yml pushes to main.develop first, all PRs target develop, and only develop is published to main via CI. Main is a generated artifact (clean dist + default branch) — never commit to main directly. Add a "Branch model & distribution" section to README.md explaining the develop-first workflow. Include an "Existing Users" migration note: installed plugins are safe (local copies in ~/.claude/plugins/cache/), the marketplace self-heals on next /plugin marketplace update (one-time re-clone after the orphan-replace), and no action is required — but if users hit issues, they can remove and re-add the marketplace. Update CLAUDE.md's Git & Branches section to branch off develop and never commit to main. Note in .claude/rules/marketplace.md that main is generated — not hand-edited.Verify
grep -ri 'develop' README.md CLAUDE.md .claude/rules/marketplace.md shows the new branch-model guidance in all three; CLAUDE.md's branch-creation command branches off develop; marketplace.md states main is generated and not hand-edited; README.md contains an "Existing Users" section with migration guidance.publish-dist.yml (or run --publish once) to rebuild main clean, then in a fresh session register the marketplace and install a plugin — confirming the catalog and plugin files both resolve from main (the default branch) and contain only clean distribution files.Verify
/plugin marketplace add shawn-sandy/agentics then /plugin install plan-agent@agentics-kit installs successfully; the installed tree contains no docs/, *.local.md, .DS_Store, or session PNGs; git ls-tree origin/main --name-only shows only the clean root set.Acceptance Criteria
Verification
End-to-end: confirm gh repo view --json defaultBranchRef still reports main and that the pre-split tag exists. Run node scripts/build-dist.mjs --check locally (exit 0), then verify the tripwire by temporarily allowlisting docs and confirming a non-zero exit. Trigger publish-dist.yml via workflow_dispatch (or push a no-op commit to develop) and confirm it writes a fresh clean commit to main; then git ls-tree -r origin/main --name-only must show 12 plugin directories carrying only allowlisted files plus a root marketplace.json, slim README.md, and LICENSE — and zero cruft. Finally, in a clean session register shawn-sandy/agentics and install plan-agent (both resolve from main, the default branch), then list the installed files to confirm no docs/, *.local.md, or PNGs. develop must still hold the complete workspace, unchanged except for the new script, workflow, and docs.
Completion Checklist
Completion Report
No items to report — all requirements met.
Unresolved Questions
-
Should main be a true orphan branch or a rolling single-commit branch?
For the agentics publish-dist pipeline, decide between two implementations of "orphan / replace each publish" for the main branch: (a) a true orphan branch with no parent (git checkout --orphan) force-pushed each publish, versus (b) a normal branch where each publish commits the fully-replaced clean tree on top of the previous main commit (no force-push, history grows but stays diffable). Weigh force-push safety for downstream consumers, diffability of releases, and CI simplicity, and recommend one. Then specify the exact git commands build-dist.mjs --publish should run.