Found during the #154 consumer round on mokuzai, sideshow 0.1.0-alpha.20260801.205946.503e725, testing two repos using one user-wide bmad 6.10.0 install concurrently.
Summary
_<pack>-custom/skills/ is documented and reasoned about as per-repo customization, but every registered repo's custom skills are synced into the single user-wide ~/.claude/skills/ surface. Two consequences:
- Repo A's custom skills are live in sessions running in repo B.
- When two repos define the same skill name, one silently shadows the other permanently — and the winner is registry order, not the repo you are working in.
Store integrity is clean throughout (verified by hash), and _<pack>-output/ isolation is genuinely per-repo. This is specifically about the custom-skills bridge.
Reproduction
Two fresh repos, each sideshow project init bmad, each with a distinct custom skill:
$ cat repos/alpha/_bmad-custom/skills/party-alpha/SKILL.md
---
name: party-alpha
description: ALPHA-ONLY custom skill. Must never appear in repo beta.
---
alpha marker: ALPHA-SENTINEL-7f3a
$ cat repos/beta/_bmad-custom/skills/party-beta/SKILL.md # ... BETA-SENTINEL-9c1b
Sync once from each repo, then look at the user-wide surface:
$ ls -d ~/.claude/skills/party-*
/Users/skippy/.claude/skills/party-alpha
/Users/skippy/.claude/skills/party-beta
Both are present and active simultaneously. In an agent session with cwd = repos/beta, party-alpha is offered in the skill list — I watched the harness list both. Nothing about party-alpha is scoped to alpha.
The registry that drives this is user-wide by construction:
$ cat ~/.local/share/sideshow/custom-sources.yaml
schema_version: 0.1.0
sources:
- project: /tmp/round154/repos/alpha
pack: bmad
- project: /tmp/round154/repos/beta
pack: bmad
internal/bindings/custom_sources.go:31 places it beside packs/, and sync walks all registered sources regardless of cwd (internal/bindings/bindings.go:76).
The collision case — silent, and order-dependent
Same skill name in both repos, different bodies:
$ printf -- '...name: shared-name\ndescription: from ALPHA\n---\nALPHA-BODY\n' > repos/alpha/_bmad-custom/skills/shared-name/SKILL.md
$ printf -- '...name: shared-name\ndescription: from BETA\n---\nBETA-BODY\n' > repos/beta/_bmad-custom/skills/shared-name/SKILL.md
$ cd repos/beta && rm -f ~/.claude/skills/shared-name/SKILL.md && sideshow commands sync
Synced 3 artifacts across all bindings
$ grep -o 'ALPHA-BODY\|BETA-BODY' ~/.claude/skills/shared-name/SKILL.md
ALPHA-BODY
Syncing from beta yields alpha's content, because alpha is earlier in the registry. No warning is printed at any point. A user in beta editing _bmad-custom/skills/shared-name/SKILL.md and re-syncing will never see their own edit take effect and gets no signal why.
Contrast with the repo-bindings channel, which refuses on content-collision rather than picking a winner (verified in the .23 pilot). The custom-skills bridge silently resolves instead.
What is NOT broken
Worth recording, since these were the two things I most expected to fail:
- Store is uncontaminated. Full-tree hash of
packs/bmad/6.10.0 identical before and after all repo activity, customization, and output generation: bc4187434fd4c547b24fb4124cac4799b7615f0561610a372b485ebdc215ab39.
_bmad-output/ is properly isolated. Each repo's report.md kept its own content; nothing crossed, nothing landed in the store.
Suggested direction
I do not think this is one bug with one fix — it is an unstated scope decision, so flagging the fork rather than prescribing:
- If user-wide really is the intended scope (it is a single Claude Code skills directory, so there is a real constraint here), then the docs should say so plainly, and collisions should warn with both source paths instead of resolving silently. Prefixing per repo would also be consistent with how the repo-bindings channel avoids shadowing.
- If per-repo is intended, the bridge needs a repo-scoped destination like the
--scope project materialization the bindings channel already has.
For the community post specifically: "parallel instances under one user-wide install" works for pack content and output, but the honest statement today is that custom skills are shared across all registered repos. That should be stated rather than implied away, or the post should stay off this leg.
Environment
- macOS 26.5.2, arm64
- sideshow
0.1.0-alpha.20260801.205946.503e725 (Homebrew arcavenae/tap)
- bmad 6.10.0 from the signed release, cosign
Verified OK
- Two fresh
git init repos under /tmp
Note: several syncs in this session also emitted the Removed 119 stale artifact(s) / permission-denied failure reported as #108; the transcripts above are from runs where that did not corrupt the measurement, and I removed the target by hand where needed to isolate collision precedence from #108's read-only-target failure.
Found during the #154 consumer round on mokuzai, sideshow
0.1.0-alpha.20260801.205946.503e725, testing two repos using one user-wide bmad 6.10.0 install concurrently.Summary
_<pack>-custom/skills/is documented and reasoned about as per-repo customization, but every registered repo's custom skills are synced into the single user-wide~/.claude/skills/surface. Two consequences:Store integrity is clean throughout (verified by hash), and
_<pack>-output/isolation is genuinely per-repo. This is specifically about the custom-skills bridge.Reproduction
Two fresh repos, each
sideshow project init bmad, each with a distinct custom skill:Sync once from each repo, then look at the user-wide surface:
Both are present and active simultaneously. In an agent session with cwd =
repos/beta,party-alphais offered in the skill list — I watched the harness list both. Nothing aboutparty-alphais scoped to alpha.The registry that drives this is user-wide by construction:
internal/bindings/custom_sources.go:31places it besidepacks/, and sync walks all registered sources regardless of cwd (internal/bindings/bindings.go:76).The collision case — silent, and order-dependent
Same skill name in both repos, different bodies:
Syncing from beta yields alpha's content, because alpha is earlier in the registry. No warning is printed at any point. A user in beta editing
_bmad-custom/skills/shared-name/SKILL.mdand re-syncing will never see their own edit take effect and gets no signal why.Contrast with the repo-bindings channel, which refuses on
content-collisionrather than picking a winner (verified in the .23 pilot). The custom-skills bridge silently resolves instead.What is NOT broken
Worth recording, since these were the two things I most expected to fail:
packs/bmad/6.10.0identical before and after all repo activity, customization, and output generation:bc4187434fd4c547b24fb4124cac4799b7615f0561610a372b485ebdc215ab39._bmad-output/is properly isolated. Each repo'sreport.mdkept its own content; nothing crossed, nothing landed in the store.Suggested direction
I do not think this is one bug with one fix — it is an unstated scope decision, so flagging the fork rather than prescribing:
--scope projectmaterialization the bindings channel already has.For the community post specifically: "parallel instances under one user-wide install" works for pack content and output, but the honest statement today is that custom skills are shared across all registered repos. That should be stated rather than implied away, or the post should stay off this leg.
Environment
0.1.0-alpha.20260801.205946.503e725(Homebrewarcavenae/tap)Verified OKgit initrepos under/tmpNote: several syncs in this session also emitted the
Removed 119 stale artifact(s)/ permission-denied failure reported as #108; the transcripts above are from runs where that did not corrupt the measurement, and I removed the target by hand where needed to isolate collision precedence from #108's read-only-target failure.