Skip to content

Comments

feat: Support Hooks as an Agent Primitive#97

Open
Copilot wants to merge 6 commits intomainfrom
copilot/add-support-for-hooks
Open

feat: Support Hooks as an Agent Primitive#97
Copilot wants to merge 6 commits intomainfrom
copilot/add-support-for-hooks

Conversation

Copy link
Contributor

Copilot AI commented Feb 23, 2026

🚀 New Feature

Description

Adds Hooks as a first-class APM primitive. Hooks are lifecycle event handlers (PreToolUse, PostToolUse, Stop, etc.) shared by both VSCode Copilot (.github/hooks/*.json) and Claude Code (.claude/settings.json). This is APM's first non-markdown, composite primitive — hook JSON files reference scripts that must travel together.

Target-aware placement:

Source VSCode Claude
.apm/hooks/*.json or hooks/*.json .github/hooks/<pkg>-<name>-apm.json Merged into .claude/settings.json hooks key
Referenced scripts .github/hooks/scripts/<pkg>/ .claude/hooks/<pkg>/

Script path rewriting handles ${CLAUDE_PLUGIN_ROOT}/path, ./relative/path, and system commands (passthrough).

Changes Made

  • Feature implementation
    • HookIntegrator in src/apm_cli/integration/hook_integrator.py — discovery, VSCode integration, Claude merge, sync/cleanup, gitignore
    • CLI install flow: hook integration in both cached and fresh package blocks
    • CLI uninstall flow: nuke-and-regenerate with re-integration from remaining packages
    • PackageInfo.has_primitives() and PackageValidator now recognize .apm/hooks/
  • Tests added
    • 42 tests covering discovery, parsing, VSCode/Claude integration, path rewriting, sync/cleanup, gitignore, end-to-end lifecycle, deep copy safety
    • Tests use fixtures mirroring real plugin structures from anthropics/claude-plugins-official (hookify, learning-output-style, ralph-loop)
  • Documentation updated
    • docs/primitives.md — hooks listed as primitive type with directory structure
    • docs/integrations.md — hook integration flow for VSCode and Claude targets

Testing

  • Manual testing completed
  • All existing tests pass (838 total)
  • New tests added and passing (42 hook integrator tests)

Checklist

  • LABEL: Apply enhancement or feature label to this PR
  • Code follows project style guidelines
  • Documentation updated (if needed)
  • CHANGELOG.md updated (for significant features)
Original prompt

This section details on the original issue you should resolve

<issue_title>[FEATURE] Support Hooks as an Agent Primitive</issue_title>
<issue_description>Hooks are supported both by GitHub Copilot (e.g. in VSCode) and Claude Code.

VSCode specifically reads hook configuration from .github/hooks/*.json files among others.

Hook json files can point to scripts in any location with relative paths, and those files make integral part of a hook - they must also be portable if we make hooks installable via apm.

APM could help distribute Hooks as primitives in a portable and composable way across projects.
</issue_description>

<agent_instructions>Ensure you implement tests for installing hooks in different ways from official sources like this plugin https://github.com/anthropics/claude-plugins-official/tree/main/plugins/hookify/hooks or this one https://github.com/anthropics/claude-plugins-official/blob/main/plugins/learning-output-style/hooks/hooks.json or this https://github.com/anthropics/claude-plugins-official/blob/main/plugins/ralph-loop/hooks/hooks.json</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@danielmeppiel ### Implementation analysis

After researching the VS Code hooks spec and Claude Code hooks spec, here's how this maps to APM's architecture.

Why this fits: Both platforms use the same JSON schema ({ "hooks": { "PreToolUse": [...] } }) with identical event names, matchers, and exit code semantics. A hook definition works across VS Code Copilot and Claude Code without modification — genuinely portable.

Package format:

.apm/
└── hooks/
    ├── security-policy.json
    └── scripts/
        └── block-destructive.sh

Installation placement (target-aware):

Source --target vscode --target claude
.apm/hooks/*.json .github/hooks/*.json Merged into .claude/settings.json hooks key
.apm/hooks/scripts/* .github/hooks/scripts/* .claude/hooks/scripts/*

Implementation path — follows existing integrator pattern (AgentIntegrator, PromptIntegrator, SkillIntegrator, CommandIntegrator):

  1. New HookIntegrator — copies hook JSON + scripts to target locations
  2. Discovery — teach discover_primitives() to find .apm/hooks/*.json
  3. Merge — when multiple packages define hooks for the same event, append to the matcher array (hooks are additive; most restrictive decision wins at runtime per both specs)
  4. Script path rewriting — update command paths in JSON to reflect installed location, using platform vars like $CLAUDE_PROJECT_DIR for Claude

Script portability rules:

  • Relative paths (e.g., ./scripts/validate-tool.sh) — bundled with the package, path rewritten at compile time
  • System commands (e.g., npx prettier ...) — passed through untouched
  • Absolute paths (e.g., /home/user/scripts/foo.py) — rejected at validation time; not portable

No virtual single-file install for hooks. Unlike .prompt.md or .agent.md, a hook JSON typically references scripts — installing just the JSON would leave it broken. Hooks should be distributed as full packages or subdirectory packages (apm install owner/repo/hooks) so JSON + scripts travel together. Subdirectory virtual packages already support this.

Scope: No hook-specific validation beyond valid JSON, no script language detection, no cross-platform command translation. APM does faithful packaging and placement — the runtimes handle the rest. First non-markdown, first composite primitive, but the pattern is straightforward.</comment_new>


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI and others added 4 commits February 23, 2026 23:13
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Implements hook integration following the existing integrator pattern:
- HookIntegrator discovers hooks in .apm/hooks/ and hooks/ directories
- VSCode: copies hook JSON to .github/hooks/ with script path rewriting
- Claude: merges hooks into .claude/settings.json with script copying
- Sync/cleanup for uninstall (nuke-and-regenerate pattern)
- Script path rewriting for ${CLAUDE_PLUGIN_ROOT} and relative paths
- Gitignore updates for APM-managed hook files
- CLI integration in both install blocks (cached + fresh) and uninstall
- 42 comprehensive tests including official plugin format coverage

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
…rations docs

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
…omment

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for hooks as an agent primitive feat: Support Hooks as an Agent Primitive Feb 23, 2026
@danielmeppiel danielmeppiel added the enhancement New feature or request label Feb 23, 2026
@danielmeppiel danielmeppiel added this to the 0.7.4 milestone Feb 23, 2026
@danielmeppiel danielmeppiel marked this pull request as ready for review February 23, 2026 23:29
Copilot AI review requested due to automatic review settings February 23, 2026 23:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Hooks as a first-class APM primitive, enabling lifecycle event handlers (PreToolUse, PostToolUse, Stop, etc.) to be packaged and distributed via APM. This is APM's first non-markdown, composite primitive where hook JSON files reference scripts that must travel together.

Changes:

  • Adds HookIntegrator for discovering, integrating, and managing hook files with target-aware placement (VSCode vs Claude)
  • Implements dual-path integration: VSCode uses file-based .github/hooks/*.json, Claude merges into .claude/settings.json with _apm_source tracking
  • Updates install/uninstall flows to handle hooks alongside existing primitives
  • Includes comprehensive test suite (42 tests) covering real-world plugin structures from anthropics/claude-plugins-official

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/apm_cli/integration/hook_integrator.py Core hook integration logic with discovery, VSCode/Claude integration, path rewriting, sync/cleanup, and gitignore updates
src/apm_cli/integration/__init__.py Exports HookIntegrator for use in CLI
src/apm_cli/cli.py Integrates hooks into install/uninstall flows with target-aware handling for both cached and freshly downloaded packages
src/apm_cli/models/apm_package.py Adds 'hooks' to primitive types in has_primitives() check
src/apm_cli/deps/package_validator.py Adds hook validation and counting in package structure validation
tests/unit/integration/test_hook_integrator.py Comprehensive test coverage (42 tests) for hook discovery, integration, path rewriting, and cleanup
docs/primitives.md Documents hooks as a primitive type with directory structure
docs/integrations.md Documents hook integration flow for both VSCode and Claude targets
uv.lock Version bump to 0.7.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Support Hooks as an Agent Primitive

2 participants