Title: feat: separate plugin and skills · Issue #311 · EntityProcess/allagents · GitHub
Open Graph Title: feat: separate plugin and skills · Issue #311 · EntityProcess/allagents
X Title: feat: separate plugin and skills · Issue #311 · EntityProcess/allagents
Description: Problem Currently skills, hooks, and other artifacts need to be uniquely named otherwise links break — when conflicts are detected, a plugin-name or hash prefix is appended to the artifact folder name. This only works for specific market...
Open Graph Description: Problem Currently skills, hooks, and other artifacts need to be uniquely named otherwise links break — when conflicts are detected, a plugin-name or hash prefix is appended to the artifact folder n...
X Description: Problem Currently skills, hooks, and other artifacts need to be uniquely named otherwise links break — when conflicts are detected, a plugin-name or hash prefix is appended to the artifact folder n...
Opengraph URL: https://github.com/EntityProcess/allagents/issues/311
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"feat: separate plugin and skills","articleBody":"## Problem\n\nCurrently skills, hooks, and other artifacts need to be uniquely named otherwise links break — when conflicts are detected, a plugin-name or hash prefix is appended to the artifact folder name. This only works for specific marketplaces where they follow unique naming standards.\n\nThis is fine for internal plugins since we control the naming. But doesn't work for public plugins like superpowers which have names conflicting with other plugins.\n\n## Current Behavior\n\nWhen plugins are synced, skills are copied to client skill directories (e.g., `.claude/skills/`, `.agents/skills/`). The **folder name** on disk becomes the skill's identity — it's how clients discover and reference skills.\n\n**Current dedup logic** (`src/utils/skill-name-resolver.ts`):\n- No conflict → folder name as-is (e.g., `coding-standards/`)\n- Folder name conflicts across plugins → `{plugin}_{skill}` (e.g., `plugin-a_coding-standards/`)\n- Folder AND plugin name conflict → `{org}_{plugin}_{skill}` (e.g., `acme_plugin-a_coding-standards/`)\n\n### Why this breaks\n\nDedup only kicks in **when there's a conflict**. This means the same skill gets **different names depending on what other plugins are installed**:\n\n1. User installs `superpowers` plugin → skill lands as `brainstorming/`\n2. User installs another plugin that also has `brainstorming/` → both get renamed to `superpowers_brainstorming/` and `other_brainstorming/`\n\nAny hardcoded references to `brainstorming` (in AGENTS.md, other skills, etc.) **break silently** when step 2 happens.\n\n## Proposed Solution: Always-Namespaced Mode\n\nAdd a config option to **always prefix skill names** with the plugin namespace, regardless of conflicts:\n\n```yaml\n# workspace.yaml\nskillNamespace: always # default: \"auto\" (current behavior)\n```\n\n| Mode | Behavior |\n|------|----------|\n| `auto` (default) | Current behavior — only prefix on conflict |\n| `always` | Every skill gets `{plugin}_{skill}` naming |\n\n## Implementation Guide\n\n### Key files\n\n| File | Change |\n|------|--------|\n| `src/models/workspace-config.ts` | Add `skillNamespace` field to schema |\n| `src/utils/skill-name-resolver.ts` | Add `mode` param to `resolveSkillNames()`, always-qualify path |\n| `src/core/sync.ts` | Thread config through `buildPluginSkillNameMaps()` calls (~lines 1841 and 2220) |\n| `tests/unit/utils/skill-name-resolver.test.ts` | Add `always` mode tests (existing tests cover current tiers) |\n| `docs/src/content/docs/reference/configuration.mdx` | Document new option |\n| `docs/src/content/docs/guides/plugins.mdx` | Update dedup section |\n\n### Implementation detail\n\nIn `src/utils/skill-name-resolver.ts`, add a `mode` parameter to `resolveSkillNames()`. When `always`, skip the \"no conflict\" fast path (line 90-101) and always qualify with plugin name.\n\n### Scope boundaries\n\n- Skills that reference other skills by name in their content (e.g., \"run the `brainstorming` skill first\") would still need to use the namespaced name. This is a documentation/convention problem, not a code problem.\n- The `{org}_{plugin}_{skill}` tier 3 disambiguator is still needed even in `always` mode if two plugins from different orgs have the same plugin name.\n\n## Related\n\n- PR #339 fixed a separate issue: **repository skills** (discovered from workspace repos, embedded as an index in AGENTS.md) had duplicates. Those now deduplicate by picking a winner (`.agents/` priority, then largest file). That is a different mechanism from plugin skill dedup — repo skills are pointers in an index, not copied files.","author":{"url":"https://github.com/christso","@type":"Person","name":"christso"},"datePublished":"2026-03-22T11:41:40.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/311/allagents/issues/311"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:1f29af08-aebd-42ef-e1b3-34ea046816e6 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D6DA:38C5EF:EAC681:13FA6E9:6A4D60D5 |
| html-safe-nonce | ed69dd3aeebc34d20329dce989a47526c5060e8749d19cc8e10c0e72a2ac5663 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENkRBOjM4QzVFRjpFQUM2ODE6MTNGQTZFOTo2QTRENjBENSIsInZpc2l0b3JfaWQiOiI0NTMyNzU0NzQyMjAzNzYyNzciLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | f0c65626f1cd6c8c141b36eb5f8617a3e933361df4739a8c37e0975bfbe32eef |
| hovercard-subject-tag | issue:4115771420 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/EntityProcess/allagents/311/issue_layout |
| twitter:image | https://opengraph.githubassets.com/b7a16c04e63719248639b68cdcd0700713db9e09e7ed92f258f944a544b8d32a/EntityProcess/allagents/issues/311 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/b7a16c04e63719248639b68cdcd0700713db9e09e7ed92f258f944a544b8d32a/EntityProcess/allagents/issues/311 |
| og:image:alt | Problem Currently skills, hooks, and other artifacts need to be uniquely named otherwise links break — when conflicts are detected, a plugin-name or hash prefix is appended to the artifact folder n... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | christso |
| hostname | github.com |
| expected-hostname | github.com |
| None | e6658d7c7808aeed776f841e0839b885fce343c9b96244be612c779298e7661e |
| turbo-cache-control | no-preview |
| go-import | github.com/EntityProcess/allagents git https://github.com/EntityProcess/allagents.git |
| octolytics-dimension-user_id | 8837957 |
| octolytics-dimension-user_login | EntityProcess |
| octolytics-dimension-repository_id | 1139437609 |
| octolytics-dimension-repository_nwo | EntityProcess/allagents |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1139437609 |
| octolytics-dimension-repository_network_root_nwo | EntityProcess/allagents |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | a438513d3a22ffcd713795ed948c3e5525007665 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width