Summary
Define and implement a single, durable strategy for sharing Claude Code (and other agentic-tool) configuration — .claude/agents, .claude/rules/*, .claude/skills/*, .github/skills/*, and arguably AGENTS.md / CLAUDE.md / GEMINI.md — across all sibling repositories under C:\DevNet\my\mrploch\. The current ad-hoc setup has caused real damage in ploch-data and a near-miss in ploch-common, and will keep doing so until normalised.
Background — the problem
Claude Code reads configuration from .claude/ inside each repository. The lookup is not hierarchical: a .claude/ at C:\DevNet\my\mrploch\ is ignored by Claude Code working inside C:\DevNet\my\mrploch\ploch-common\. So the canonical set of skills/rules/agents must physically appear in every repo where you want them to take effect.
The repos themselves are already federated: Directory.Build.props files in each library import shared MSBuild fragments via relative paths (<Import Project="../mrploch-development/dependencies/..."/>). mrploch-development is the established home for shared org-level dev config. Claude config is a natural extension of the same problem, but no convention has been set yet.
Current state — evidence of the gap
A snapshot taken on 2026-04-26 across ploch-common and ploch-data:
ploch-common
.claude/rules/*.md and .claude/skills/* and .claude/agents were all symlinks (mode 120000) into the user's local environment.
- All of them were staged for commit by accident as part of an unrelated branch (
codex/fix-not-out-of-range-flag-support). They were unstaged before commit.
- 2 real
.md files in .claude/rules/ are intentionally tracked: change-log.md, todo-tasks-execution.md.
AGENTS.md was also staged (real file, 330 lines). Currently kept untracked pending the strategy decision.
- A
.gitignore block has been added in this PR/commit to prevent re-staging of the symlinks (Claude config + agentic tooling paths). See linked PR.
ploch-data
- 30 symlinks under
.claude/ are already committed and pushed to origin. This is the future-cross-machine breakage we worried about — already in production. git ls-files --stage shows mode 120000 for all of them.
- 2 real
.md files in .claude/rules/ are intentionally tracked: integration-testing.md, sample-app.md.
- A
.gitignore block has been added (linked PR/commit) to stop further pollution. It does not remove the already-committed symlinks — gitignore doesn't affect tracked files. Those need a separate git rm --cached cleanup once the canonical strategy is in place.
Other repos
Probably similar — needs a sweep once the strategy is decided. At minimum: ploch-commandline, ploch-lists, ploch-groupmatters, ploch-ini-parser, ploch-tools-editorconfig, ploch-endpoints, ploch-tiny-tools, ploch-ai-tools, ploch-dotnet-templates, ploch-templates-dotnet-repository, ploch-templates-dotnet-with-common, ploch-generic-repository, ploch-github-actions, ploch-scripts.
Existing assets in mrploch-development
The repo already hosts (root level): AGENTS.md, CLAUDE.md, GEMINI.md. Folders include dependencies/, editor-config/, repository-config/, scripts/, solution-templates/, repositories/, computer-config/. There is no .claude/ directory yet but the repo is the natural home.
Why this matters
- Public-repo correctness.
ploch-common, ploch-data, and the rest are public open-source repos. Committing personal-machine symlinks pollutes history with paths that mean nothing on any other machine — broken links on Linux/Mac, plain text files containing the link target on Windows without dev mode.
- Drift. Any "copy the rules/skills around" approach inevitably drifts. A rule update in one repo doesn't propagate. Different repos make different decisions silently.
- Onboarding for contributors. External contributors to the OSS libs shouldn't need any of this config — the agentic tooling is personal. But right now
ploch-data ships with 30 broken-on-clone files, which looks unprofessional and confusing.
- Symmetry with existing patterns.
Directory.Build.props already federates MSBuild config from mrploch-development. Solving Claude config the same way reduces cognitive load.
Strategy options
|
A. Symlinks/junctions + gitignore |
B. Sync script + committed copies |
C. Hybrid (junctions in dev, gitignored, bootstrap script) |
| Canonical source |
mrploch-development/.claude/ |
mrploch-development/.claude/ |
mrploch-development/.claude/ |
| In each repo |
symlink (Unix) / junction (Windows) into canonical |
real file copies, regenerated |
junction into canonical |
| Tracked in repo? |
No (gitignored) |
Yes |
No (gitignored) |
| Edit experience |
Edit canonical, all repos see it instantly |
Edit canonical, run claude-sync.ps1, commit copies |
Edit canonical, all repos see it instantly |
| Other contributors |
❌ broken (or missing config) |
✅ they get the real files |
❌ they don't have it (but probably don't need it) |
| CI |
❌ doesn't see config |
✅ sees real files; can verify drift |
❌ doesn't see config (but probably doesn't need it) |
| Windows perms |
Symlinks: dev mode required. Junctions: directory-only, no special perms. |
None — plain files |
Junctions: directory-only, no special perms |
| Drift risk |
None — single source of truth |
Real (someone edits the copy) |
None |
| Setup friction (per fresh clone) |
Run a one-time symlink/junction creation step |
None (files are committed) |
Run bootstrap-claude.ps1 once |
| One-line update flow |
Edit and save in canonical |
Edit, sync, commit N repos, push N repos |
Edit and save in canonical |
Option D — git submodule
Add mrploch-development/.claude as a submodule under each repo. Rejected: submodules pin per-repo SHAs (each repo can drift), require contributors to know git submodule update --init, and a one-line rule edit becomes a multi-step process across multiple repos. Bad fit for "shared dotfiles".
Option E — dotnet tool
Build a Ploch.ClaudeConfig.Tool that, when run in a repo directory, materialises the canonical config. Could be hosted as a dotnet tool. Overkill for personal use but the most "real product" approach. Worth keeping in mind if the user base ever grows.
Recommendation
Option C (hybrid: junctions + gitignore + bootstrap script). Best fit because:
- You're the sole maintainer of these libraries. External contributors don't need your personal Claude tooling.
- Junctions (Windows) and symlinks (Unix) work without special permissions for directories — easier than file-level symlinks.
- Zero drift: edit once in
mrploch-development, every repo sees it.
.gitignore keeps the public repos clean.
- A small
bootstrap-claude.ps1 is the only friction at fresh-clone time.
Exception: AGENTS.md. This file is public-facing documentation that non-Claude agentic tools (Codex, etc.) read from the repo root. Treat it differently:
- Canonical template lives at
mrploch-development/AGENTS.template.md.
bootstrap-claude.ps1 copies (not links) it into each repo's root as AGENTS.md.
- The copy IS committed (it's public docs).
- Drift is your responsibility to manage by re-running the sync.
Same logic applies to CLAUDE.md and GEMINI.md if you want consistent versions across repos — they're public docs, not personal tooling.
Decisions needed
Please decide before implementation:
- Strategy choice: A, B, C, or something else.
- Scope of "shared": Which directories are canonical-from-
mrploch-development and which are repo-specific? Current real-file exceptions in the gitignore are:
ploch-common: .claude/rules/change-log.md, .claude/rules/todo-tasks-execution.md
ploch-data: .claude/rules/integration-testing.md, .claude/rules/sample-app.md
- Should these be promoted to canonical (live in
mrploch-development) or stay repo-specific?
AGENTS.md policy: Single canonical template copied into every repo, or per-repo authored?
- Scope of cleanup: Just
ploch-common + ploch-data for now, or sweep all 16 sibling repos?
- Cleanup of already-committed symlinks in
ploch-data: Single bulk git rm --cached commit, or repo-by-repo as we touch them for other work?
- Settings files:
.claude/settings.json and .claude/settings.local.json are personal — already gitignored. Confirm they stay that way and never become canonical.
Implementation plan (once strategy is chosen)
Assuming Option C is chosen:
-
Move canonical content into mrploch-development/.claude/.
- Create
mrploch-development/.claude/{agents,rules,skills}/.
- Copy the current canonical versions from wherever they live now (likely
~/.claude/ or already-committed copies in ploch-data).
- Decide and document the structure.
-
Author mrploch-development/scripts/bootstrap-claude.ps1.
- Args:
-RepoPath (default: current dir), -DryRun.
- For each canonical directory in
../mrploch-development/.claude/<X>, create a junction at <RepoPath>/.claude/<X>.
- For each canonical file (
AGENTS.template.md, CLAUDE.template.md, etc.), copy into <RepoPath>/<filename>.
- Idempotent: re-running replaces junctions/copies cleanly.
- Cross-platform aside: supply a
bootstrap-claude.sh equivalent if you ever want to run on Linux/Mac.
-
Per-repo .gitignore template in mrploch-development/repository-config/gitignore-claude-block.txt so all repos use the same pattern. Wire it into your repo template (ploch-templates-dotnet-repository).
-
Cleanup pass. For each sibling repo:
- If symlinks are committed:
git rm --cached <paths> and commit.
- Append the gitignore block (or reference it).
- Run
bootstrap-claude.ps1 to materialise junctions.
- Verify
git status is clean.
-
Document. Add a section to mrploch-development/README.md describing the strategy and the bootstrap command. Optional: add a one-liner to each repo's CONTRIBUTING.md saying "Claude Code config is personal tooling sourced from mrploch-development — see bootstrap-claude.ps1. External contributors can ignore this."
Acceptance criteria
Stop-gap already in place (2026-04-26)
To prevent further pollution while the strategy is decided:
ploch-common/.gitignore: appended a Claude/agentic-tooling block ignoring .claude/agents, .claude/skills/, .claude/rules/* (with !-exceptions for the 2 real tracked files), .github/skills/. Also some local IDE artefacts.
ploch-data/.gitignore: same block with the appropriate !-exceptions for that repo. Note: gitignore does not remove the 30 already-committed symlinks; that remains TODO under acceptance criteria.
References
- Workspace
CLAUDE.md describing the multi-repo layout: C:\DevNet\my\mrploch\CLAUDE.md
- Existing federation precedent:
Directory.Build.props files importing mrploch-development/dependencies/*
- Polluted state in
ploch-data: 30 mode-120000 entries under .claude/ (see git ls-files --stage filtered to that path)
- The conversation that surfaced this (
mrploch/ploch-common, branch codex/fix-not-out-of-range-flag-support): symlinks were staged accidentally as part of a Guard.cs refactor and unstaged before commit
Summary
Define and implement a single, durable strategy for sharing Claude Code (and other agentic-tool) configuration —
.claude/agents,.claude/rules/*,.claude/skills/*,.github/skills/*, and arguablyAGENTS.md/CLAUDE.md/GEMINI.md— across all sibling repositories underC:\DevNet\my\mrploch\. The current ad-hoc setup has caused real damage inploch-dataand a near-miss inploch-common, and will keep doing so until normalised.Background — the problem
Claude Code reads configuration from
.claude/inside each repository. The lookup is not hierarchical: a.claude/atC:\DevNet\my\mrploch\is ignored by Claude Code working insideC:\DevNet\my\mrploch\ploch-common\. So the canonical set of skills/rules/agents must physically appear in every repo where you want them to take effect.The repos themselves are already federated:
Directory.Build.propsfiles in each library import shared MSBuild fragments via relative paths (<Import Project="../mrploch-development/dependencies/..."/>).mrploch-developmentis the established home for shared org-level dev config. Claude config is a natural extension of the same problem, but no convention has been set yet.Current state — evidence of the gap
A snapshot taken on
2026-04-26acrossploch-commonandploch-data:ploch-common.claude/rules/*.mdand.claude/skills/*and.claude/agentswere all symlinks (mode120000) into the user's local environment.codex/fix-not-out-of-range-flag-support). They were unstaged before commit..mdfiles in.claude/rules/are intentionally tracked:change-log.md,todo-tasks-execution.md.AGENTS.mdwas also staged (real file, 330 lines). Currently kept untracked pending the strategy decision..gitignoreblock has been added in this PR/commit to prevent re-staging of the symlinks (Claude config + agentic tooling paths). See linked PR.ploch-data.claude/are already committed and pushed to origin. This is the future-cross-machine breakage we worried about — already in production.git ls-files --stageshows mode120000for all of them..mdfiles in.claude/rules/are intentionally tracked:integration-testing.md,sample-app.md..gitignoreblock has been added (linked PR/commit) to stop further pollution. It does not remove the already-committed symlinks — gitignore doesn't affect tracked files. Those need a separategit rm --cachedcleanup once the canonical strategy is in place.Other repos
Probably similar — needs a sweep once the strategy is decided. At minimum:
ploch-commandline,ploch-lists,ploch-groupmatters,ploch-ini-parser,ploch-tools-editorconfig,ploch-endpoints,ploch-tiny-tools,ploch-ai-tools,ploch-dotnet-templates,ploch-templates-dotnet-repository,ploch-templates-dotnet-with-common,ploch-generic-repository,ploch-github-actions,ploch-scripts.Existing assets in
mrploch-developmentThe repo already hosts (root level):
AGENTS.md,CLAUDE.md,GEMINI.md. Folders includedependencies/,editor-config/,repository-config/,scripts/,solution-templates/,repositories/,computer-config/. There is no.claude/directory yet but the repo is the natural home.Why this matters
ploch-common,ploch-data, and the rest are public open-source repos. Committing personal-machine symlinks pollutes history with paths that mean nothing on any other machine — broken links on Linux/Mac, plain text files containing the link target on Windows without dev mode.ploch-dataships with 30 broken-on-clone files, which looks unprofessional and confusing.Directory.Build.propsalready federates MSBuild config frommrploch-development. Solving Claude config the same way reduces cognitive load.Strategy options
mrploch-development/.claude/mrploch-development/.claude/mrploch-development/.claude/claude-sync.ps1, commit copiesbootstrap-claude.ps1onceOption D — git submodule
Add
mrploch-development/.claudeas a submodule under each repo. Rejected: submodules pin per-repo SHAs (each repo can drift), require contributors to knowgit submodule update --init, and a one-line rule edit becomes a multi-step process across multiple repos. Bad fit for "shared dotfiles".Option E — dotnet tool
Build a
Ploch.ClaudeConfig.Toolthat, when run in a repo directory, materialises the canonical config. Could be hosted as adotnet tool. Overkill for personal use but the most "real product" approach. Worth keeping in mind if the user base ever grows.Recommendation
Option C (hybrid: junctions + gitignore + bootstrap script). Best fit because:
mrploch-development, every repo sees it..gitignorekeeps the public repos clean.bootstrap-claude.ps1is the only friction at fresh-clone time.Exception:
AGENTS.md. This file is public-facing documentation that non-Claude agentic tools (Codex, etc.) read from the repo root. Treat it differently:mrploch-development/AGENTS.template.md.bootstrap-claude.ps1copies (not links) it into each repo's root asAGENTS.md.Same logic applies to
CLAUDE.mdandGEMINI.mdif you want consistent versions across repos — they're public docs, not personal tooling.Decisions needed
Please decide before implementation:
mrploch-developmentand which are repo-specific? Current real-file exceptions in the gitignore are:ploch-common:.claude/rules/change-log.md,.claude/rules/todo-tasks-execution.mdploch-data:.claude/rules/integration-testing.md,.claude/rules/sample-app.mdmrploch-development) or stay repo-specific?AGENTS.mdpolicy: Single canonical template copied into every repo, or per-repo authored?ploch-common+ploch-datafor now, or sweep all 16 sibling repos?ploch-data: Single bulkgit rm --cachedcommit, or repo-by-repo as we touch them for other work?.claude/settings.jsonand.claude/settings.local.jsonare personal — already gitignored. Confirm they stay that way and never become canonical.Implementation plan (once strategy is chosen)
Assuming Option C is chosen:
Move canonical content into
mrploch-development/.claude/.mrploch-development/.claude/{agents,rules,skills}/.~/.claude/or already-committed copies inploch-data).Author
mrploch-development/scripts/bootstrap-claude.ps1.-RepoPath(default: current dir),-DryRun.../mrploch-development/.claude/<X>, create a junction at<RepoPath>/.claude/<X>.AGENTS.template.md,CLAUDE.template.md, etc.), copy into<RepoPath>/<filename>.bootstrap-claude.shequivalent if you ever want to run on Linux/Mac.Per-repo
.gitignoretemplate inmrploch-development/repository-config/gitignore-claude-block.txtso all repos use the same pattern. Wire it into your repo template (ploch-templates-dotnet-repository).Cleanup pass. For each sibling repo:
git rm --cached <paths>and commit.bootstrap-claude.ps1to materialise junctions.git statusis clean.Document. Add a section to
mrploch-development/README.mddescribing the strategy and the bootstrap command. Optional: add a one-liner to each repo'sCONTRIBUTING.mdsaying "Claude Code config is personal tooling sourced frommrploch-development— seebootstrap-claude.ps1. External contributors can ignore this."Acceptance criteria
mrploch-development/README.md.bootstrap-claude.ps1(or the chosen sync mechanism) lives inmrploch-development/scripts/and is idempotent.C:\DevNet\my\mrploch\either use the new strategy or are explicitly opted out.ploch-datano longer ships committed symlinks under.claude/.git statusin every sibling repo is clean of stray Claude/.github/skills/entries.ploch-templates-dotnet-repository) ships the gitignore block and a pointer tobootstrap-claude.ps1.AGENTS.mdpolicy documented; copies (or per-repo originals) consistent.Stop-gap already in place (2026-04-26)
To prevent further pollution while the strategy is decided:
ploch-common/.gitignore: appended a Claude/agentic-tooling block ignoring.claude/agents,.claude/skills/,.claude/rules/*(with!-exceptions for the 2 real tracked files),.github/skills/. Also some local IDE artefacts.ploch-data/.gitignore: same block with the appropriate!-exceptions for that repo. Note: gitignore does not remove the 30 already-committed symlinks; that remains TODO under acceptance criteria.References
CLAUDE.mddescribing the multi-repo layout:C:\DevNet\my\mrploch\CLAUDE.mdDirectory.Build.propsfiles importingmrploch-development/dependencies/*ploch-data: 30 mode-120000entries under.claude/(seegit ls-files --stagefiltered to that path)mrploch/ploch-common, branchcodex/fix-not-out-of-range-flag-support): symlinks were staged accidentally as part of aGuard.csrefactor and unstaged before commit