Context
PAI currently installs hooks and agents into ~/.claude/{hooks,agents} because:
- Hooks:
settings.json references them via ${CLAUDE_CONFIG_DIR}/hooks/... paths. CC imposes no constraint here — hooks can live anywhere; the path is just a shell command.
- Agents: Claude Code's user-scope agent discovery is hardcoded to
~/.claude/agents/. Verified empirically against CC v2.1.104 using claude agents --setting-sources user against a sandboxed CLAUDE_CONFIG_DIR. There is no agentsDir/agentsPath setting.
This places PAI's agent files inside an Anthropic-defined shared namespace. The in-flight CONFIG_DIR/PAI_DIR separation work addresses the immediate symptom with a per-file symlink scheme:
- Source of truth:
~/.pai/agents/*.md (real, version-controlled)
~/.claude/agents/<name>.md → symlink → ~/.pai/agents/<name>.md
~/.claude/agents/ itself remains a real directory shared with any other tool
This unblocks today's drift hazard but has a structural limitation: PAI must coexist with whatever else lives in ~/.claude/agents, and uninstall logic has to distinguish PAI's symlinks from foreign files via target-path matching.
Proposal
Investigate distributing PAI as a Claude Code plugin. Per the subagents docs (code.claude.com/docs/en/sub-agents.md), plugin agents are discovered from a third hardcoded path: <plugin-dir>/agents/. Plugins also have well-defined install / update / uninstall semantics through CC's own plugin manager.
Benefits
- PAI agents live entirely under a PAI-owned filesystem location — no shared namespace
- Officially supported by Anthropic, not a workaround
- Clean install/uninstall via plugin manager (no per-file symlink bookkeeping)
- Discoverable via plugin marketplace if/when relevant
- Eliminates the entire class of bugs the symlink approach is mitigating
Open questions
- Does the plugin model support hooks? Hooks currently register via top-level
settings.json hooks blocks — can a plugin manifest declare hooks the same way, or does this require staying in ~/.claude/settings.json?
- Skills: plugins ship
skills/ per the marketplace examples already on disk under ~/.claude/plugins/marketplaces/. How does plugin-shipped skills/ interact with ~/.pai/skills/?
- MCP servers: PAI registers several MCP servers in
settings.json. Does the plugin manifest support mcpServers declarations, or do those still need to live in user settings?
- Custom commands under
~/.claude/commands/: same question.
- Loader/auto-context files (
PAI/CONTEXT_ROUTING.md, Algorithm/v3.7.0.md, etc.) loaded via loadAtStartup and LoadContext.hook.ts: can a plugin contribute to that, or only the user-level settings.json?
- Local development install path: how does a contributor install a plugin from a local clone (vs. from a marketplace)?
- CC version compatibility: minimum CC version that supports the plugin model PAI would need.
Suggested investigation steps
- Read Anthropic's plugin development docs (root:
code.claude.com/docs/en/)
- Inventory which PAI components (hooks, agents, skills, MCP servers, commands, context files, settings entries) the plugin model can host vs. which still require user-scope residency
- Build a minimal prototype: one agent + one hook + one skill packaged as a plugin, install locally, verify discovery via
claude agents, hook firing, and skill resolution
- Document the gap (if any) between what plugins support and what PAI needs
- If the gap is small: design migration path from per-file symlinks to plugin distribution
Relationship to current work
The per-file symlink migration is the interim answer that fixes today's drift hazard and ownership leak. PAI-as-plugin is the long-term answer that eliminates the namespace problem entirely. Both can coexist — symlink migration ships now, plugin investigation runs in parallel as research-grade work.
Priority: low. Interim fix unblocks the immediate problem.
Context
PAI currently installs hooks and agents into
~/.claude/{hooks,agents}because:settings.jsonreferences them via${CLAUDE_CONFIG_DIR}/hooks/...paths. CC imposes no constraint here — hooks can live anywhere; the path is just a shell command.~/.claude/agents/. Verified empirically against CC v2.1.104 usingclaude agents --setting-sources useragainst a sandboxedCLAUDE_CONFIG_DIR. There is noagentsDir/agentsPathsetting.This places PAI's agent files inside an Anthropic-defined shared namespace. The in-flight CONFIG_DIR/PAI_DIR separation work addresses the immediate symptom with a per-file symlink scheme:
~/.pai/agents/*.md(real, version-controlled)~/.claude/agents/<name>.md→ symlink →~/.pai/agents/<name>.md~/.claude/agents/itself remains a real directory shared with any other toolThis unblocks today's drift hazard but has a structural limitation: PAI must coexist with whatever else lives in
~/.claude/agents, and uninstall logic has to distinguish PAI's symlinks from foreign files via target-path matching.Proposal
Investigate distributing PAI as a Claude Code plugin. Per the subagents docs (
code.claude.com/docs/en/sub-agents.md), plugin agents are discovered from a third hardcoded path:<plugin-dir>/agents/. Plugins also have well-defined install / update / uninstall semantics through CC's own plugin manager.Benefits
Open questions
settings.jsonhooksblocks — can a plugin manifest declare hooks the same way, or does this require staying in~/.claude/settings.json?skills/per the marketplace examples already on disk under~/.claude/plugins/marketplaces/. How does plugin-shippedskills/interact with~/.pai/skills/?settings.json. Does the plugin manifest supportmcpServersdeclarations, or do those still need to live in user settings?~/.claude/commands/: same question.PAI/CONTEXT_ROUTING.md,Algorithm/v3.7.0.md, etc.) loaded vialoadAtStartupandLoadContext.hook.ts: can a plugin contribute to that, or only the user-levelsettings.json?Suggested investigation steps
code.claude.com/docs/en/)claude agents, hook firing, and skill resolutionRelationship to current work
The per-file symlink migration is the interim answer that fixes today's drift hazard and ownership leak. PAI-as-plugin is the long-term answer that eliminates the namespace problem entirely. Both can coexist — symlink migration ships now, plugin investigation runs in parallel as research-grade work.
Priority: low. Interim fix unblocks the immediate problem.