Skip to content

feat(pi): add hooks support via generated TypeScript extension#2324

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-issue-2319-pi-hooks
Jul 20, 2026
Merged

feat(pi): add hooks support via generated TypeScript extension#2324
dyoshikawa merged 2 commits into
mainfrom
resolve-issue-2319-pi-hooks

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Adds pi as a hooks target. Pi Coding Agent has no static hooks config file; instead it exposes an extension API with lifecycle events, so rulesync bridges canonical hooks by generating a rulesync-owned TypeScript extension — following the existing OpenCode/Kilo generated-plugin precedent:

  • .pi/extensions/rulesync-hooks.ts (project scope)
  • ~/.pi/agent/extensions/rulesync-hooks.ts (global scope)

Both paths are Pi's documented extension discovery locations (extensions.md).

Event mapping

Only canonical events with a semantically faithful Pi extension event are mapped (CANONICAL_TO_PI_EVENT_NAMES):

canonical Pi extension event
sessionStart session_start
sessionEnd session_shutdown
preToolUse tool_call
postToolUse tool_result
preModelInvocation context
beforeSubmitPrompt input
stop agent_end
preCompact session_before_compact

Hook matchers are honored as regexes tested against event.toolName on the tool events, matching the OpenCode plugin semantics. Commands and matchers are embedded via JSON.stringify so arbitrary quoting/backslashes cannot break the generated code. The generated extension observes events only — command hooks run (via the platform shell through node:child_process) but never block or mutate Pi events. Import is unsupported (supportsImport: false), same as OpenCode/Kilo, since arbitrary extension code cannot be parsed back into the canonical schema.

Scope / conventions checklist

  • pi added to hooksProcessorToolTargetTuple and registered in hooks-processor.ts (project + global scope)
  • Unit tests including a smoke test that loads the generated module via tsx and asserts the registered subscriptions
  • Hooks e2e matrix extended (project, global, and orphan-deletion cases)
  • docs/reference/file-formats.md prose updated; supported-tools tables and .gitignore regenerated
  • Not adopted from the issue proposal: stdin event payload, timeout/exit-code semantics, and blocking — these have no precedent in the existing generated-plugin hooks (OpenCode/Kilo) and would expand canonical semantics; they can be layered on later if needed.

Test plan

  • pnpm cicheck (green)
  • npx vitest run --config vitest.e2e.config.ts src/e2e/e2e-hooks.spec.ts (66 tests green)
  • Manual CLI verification: rulesync generate with a pi-targeted rulesync.jsonc produces a loadable extension with correct mappings, matcher gating, and pi.hooks override merge

Closes #2319

🤖 Generated with Claude Code

cm-dyoshikawa and others added 2 commits July 19, 2026 20:14
Pi Coding Agent has no static hooks config; bridge canonical hooks by
generating a rulesync-owned TypeScript extension in Pi's extension
discovery paths (.pi/extensions/rulesync-hooks.ts project-scope,
~/.pi/agent/extensions/rulesync-hooks.ts global-scope), following the
OpenCode/Kilo generated-plugin precedent.

- map canonical events to Pi extension events (sessionStart ->
  session_start, sessionEnd -> session_shutdown, preToolUse ->
  tool_call, postToolUse -> tool_result, preModelInvocation -> context,
  beforeSubmitPrompt -> input, stop -> agent_end, preCompact ->
  session_before_compact)
- honor hook matchers as regexes tested against event.toolName on tool
  events; embed commands/matchers via JSON.stringify for safe codegen
- the generated extension observes events only (no block/mutate) and
  executes command hooks via the platform shell
- register pi in the hooks processor and target tuple, add unit tests
  (including loading the generated module via tsx and asserting the
  registered subscriptions), extend the hooks e2e matrix, and update
  docs/tables/gitignore

Closes #2319

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… stop mapping note

Applies review feedback: the repo coding guidelines require object
arguments for multi-parameter functions, and the CANONICAL_TO_PI_EVENT_NAMES
docstring now notes the agent_end vs agent_settled trade-off for the
canonical stop event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dyoshikawa
dyoshikawa merged commit ab77118 into main Jul 20, 2026
9 checks passed
@dyoshikawa
dyoshikawa deleted the resolve-issue-2319-pi-hooks branch July 20, 2026 04:06
@dyoshikawa dyoshikawa mentioned this pull request Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Pi Coding Agent hooks support via generated extension

2 participants