Skip to content

Investigate distributing PAI as a Claude Code plugin #102

@virtualian

Description

@virtualian

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

  1. 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?
  2. Skills: plugins ship skills/ per the marketplace examples already on disk under ~/.claude/plugins/marketplaces/. How does plugin-shipped skills/ interact with ~/.pai/skills/?
  3. 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?
  4. Custom commands under ~/.claude/commands/: same question.
  5. 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?
  6. Local development install path: how does a contributor install a plugin from a local clone (vs. from a marketplace)?
  7. CC version compatibility: minimum CC version that supports the plugin model PAI would need.

Suggested investigation steps

  1. Read Anthropic's plugin development docs (root: code.claude.com/docs/en/)
  2. 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
  3. 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
  4. Document the gap (if any) between what plugins support and what PAI needs
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions