Skip to content

feat(pi): add pi extension porting the Claude hooks to pi events - #122

Open
jbanety wants to merge 6 commits into
uditgoenka:masterfrom
jbanety:feat/pi-extension
Open

jbanety wants to merge 6 commits into
uditgoenka:masterfrom
jbanety:feat/pi-extension

Conversation

@jbanety

@jbanety jbanety commented Sep 9, 2026 •

Copy link
Copy Markdown

Hi 👋
This PR adds a pi (coding agent) extension that ports the Claude Code autoresearch plugin to pi's extension event system, alongside the existing Claude/OpenCode/Codex integrations.

Guardrails

All 9 Claude hooks ported to pi events. All fail-open, all gated by the same AR_DISABLE_* env flags:

Claude hook pi event port
PreToolUse (Bash) tool_call (bash) scout / privacy / dangerous-cmd
PreToolUse (R/W/E) tool_call (read/…) scout / privacy
UserPromptSubmit before_agent_start iteration-context, dev-rules
UserPromptSubmit input simplify-gate
SessionStart session_start session-init
SessionEnd session_shutdown stop-notify
SubagentStart before_agent_start (child) + pi.events (parent) subagent-context

subagent-context integrates with the widely-used pi-subagents extension: on the child side (PI_SUBAGENT_CHILD=1) it injects the project/branch/active-TSV/iteration block at before_agent_start; on the parent side it logs delegation launches via the prompt-template:subagent:request event. Both fail open if pi-subagents isn't installed.

Commands

The 14 autoresearch commands as pi prompt templates (/autoresearch, /autoresearch_debug, …) + the dispatcher as a pi skill (/skill:autoresearch), contributed via resources_discover.

Canonical-source model

The pi bundle is generated from .claude/ by transform.sh (new transform_pi() + --pi flag), same as the OpenCode/Codex ports, not hand-copied. Keeps the slash-command + ctx.ui conventions correct and prevents drift. Idempotent; covered by test-maintenance.sh.

Install

./scripts/install.sh --pi --globa # guided
pi install git:github.com/uditgoenka/autoresearch # pi package
pi -e ./pi-extension # try without installing

Tests

New tests/test-pi.sh (58 cases): guardrail logic for every ported hook, env-flag disables, subagent-context, and a tsc --strict type-check against pi-coding-agent types.
Wired into the release-readiness CI (installs pi, runs on all 3 OS) and the release gate.

All five suites green: test-pi 58, test-hooks 228, test-orchestrator 195, test-regression 65, test-maintenance 50.

Files

  • pi-extension/: the extension (src/ guardrails, skills/, prompts/)
  • scripts/install.sh: --pi mode
  • scripts/transform.sh: transform_pi() + --pi
  • tests/test-pi.sh: guardrail + type-check suite
  • .github/workflows/release-readiness.yml: pi test step
  • README.md, AGENTS.md, CONTRIBUTING.md: docs

Build a self-contained pi extension (pi-extension/) that ports the Claude
Code autoresearch plugin to pi's extension event system, keeping the same
spirit as the claude and opencode integrations.

Guardrails (hooks -> pi events), all fail-open:
  PreToolUse (Bash)        -> tool_call (bash)      scout/privacy/dangerous-cmd block
  PreToolUse (Read/Write)  -> tool_call (read/...)  scout/privacy block
  UserPromptSubmit        -> before_agent_start    iteration-context + dev-rules inject
  UserPromptSubmit        -> input                 simplify-gate (block/warn shipping verbs)
  SessionStart            -> session_start         session-init
  SessionEnd              -> session_shutdown      stop-notify

Commands (14) are exposed as pi prompt templates (/autoresearch,
/autoresearch_debug, ...) and the dispatcher as a pi skill
(/skill:autoresearch), contributed via resources_discover. The AR_DISABLE_*
per-hook env flags are preserved.

Verified end-to-end: tsc --strict passes (0 errors), 22/22 logic tests pass,
extension loads under pi's jiti loader, and session-init/iteration-context/
scout-block/dangerous-cmd-block/simplify-gate/stop-notify all fire correctly
(confirmed in ~/.pi/agent/hooks/.logs/).

AGENTS.md documents the pi install path, agent-specific notes, and repo layout.
Declaring skills and prompts in both the package.json `pi` manifest AND the
extension's `resources_discover` handler caused pi to register each resource
twice, emitting `collision` diagnostics for every prompt (each colliding with
itself) and the skill.

Drop `pi.skills`/`pi.prompts` from the manifest; keep only `pi.extensions` (the
entry point). The skill + 14 prompt templates are contributed solely via
resources_discover at runtime, which works for `pi install`, `pi -e ./pi-extension`
(dir), and `pi -e ./src/index.ts` (bare file). Verified /autoresearch_plan and
/skill:autoresearch still load correctly with no manifest declaration.

README documents the single-contribution mechanism and the skill-name dedup
behavior (extension copy wins; stale global/project copies can be removed).
The extension wrote its bounded runtime log to ~/.pi/agent/hooks/.logs/, which
created a legacy hooks/ directory and triggered pi's migration warning
("Global hooks/ directory found. Hooks have been renamed to extensions.").

Move the log to ~/.pi/agent/autoresearch/.logs/<projectHash>/hook-log.jsonl —
a namespaced dir that does not trip the hooks→extensions deprecation. Verified
the hooks/ directory is no longer created and guardrails still fire + log.
Wire the pi extension into the same distribution, test, and release surface
as Claude/OpenCode/Codex:

- scripts/install.sh: add `--pi` mode (global/local). Copies the pi-extension/
  bundle to <config>/extensions/autoresearch-pi so pi auto-discovers it.
  Honors PI_AGENT_DIR for the config dir; pi-aware overwrite confirmation.
- tests/test-pi.sh: 53 cases covering the ported guardrails (shell tokenizer,
  ignore matcher, dangerous-cmd-block, scout-block, privacy-block,
  simplify-gate, iteration-context, env-flag disables) + a tsc --strict
  type-check against pi-coding-agent types. Gracefully skips the type-check
  when pi types aren't installed. All 53 pass; cleans up its own artifacts.
- .github/workflows/release-readiness.yml: install pi-coding-agent and run
  tests/test-pi.sh on every OS in the conformance matrix.
- scripts/release.sh + scripts/release.md: add test-pi.sh to the release gate.
- README.md: pi badge, intro, hook-parity note, and a pi Quick Start section
  (guided install / pi install / try-without-installing).

All five test suites green: test-pi 53, test-hooks 228, test-orchestrator 195,
test-regression 65, test-maintenance 50.
Bring the pi extension fully into the canonical-source model documented in
CONTRIBUTING.md: .claude/ is the source of truth, transform.sh regenerates
every platform port. Previously the pi-extension skill + prompts were
hand-copied from the Codex .agents/ bundle, which used $autoresearch syntax
and request_user_input — wrong conventions for pi (pi uses /autoresearch slash
commands and ctx.ui).

- scripts/transform.sh: add transform_pi() + --pi flag. Regenerates
  pi-extension/skills/autoresearch/ (SKILL.md + references) and
  pi-extension/prompts/ (14 flat underscore templates) from .claude/ with
  pi adaptations (colon→underscore, /autoresearch:X→/autoresearch_X,
  AskUserQuestion→ctx.ui). Adds the pi skills dir to sync_runtime_helpers
  so orchestrator/regression scripts stay in sync. Idempotent.
- pi-extension/: regenerated bundle now uses /autoresearch slash commands
  and ctx.ui (no more $autoresearch drift from Codex).
- CONTRIBUTING.md: document pi in the repo structure, file table, quick
  start, multi-platform sync, testing checks, and add a "pi Hook
  Development" section mirroring the Claude hook guide.

All five suites green (591 tests). transform.sh idempotent. /autoresearch_fix
prompt loads and expands correctly with the regenerated bundle.
The subagent-context hook was the one Claude hook not yet ported. pi has no
native subagent-spawn event in the extension API, but the widely-used
pi-subagents extension provides two clean connection points:

- Child side: pi subagents are full pi sessions that load this same extension
  and fire before_agent_start. When PI_SUBAGENT_CHILD=1, the hook injects the
  project/branch/active-TSV/iteration block — the direct port of Claude's
  SubagentStart injection. iteration-context already flows into children
  via the same handler; subagent-context adds the structured header.
- Parent side: listen for pi-subagents' `prompt-template:subagent:request`
  event on the shared pi.events bus to log delegation launches (bounded
  metadata only). Notification only — the request isn't mutated.

Both paths fail open if pi-subagents isn't installed (event never fires / env
not set). AR_DISABLE_SUBAGENT_CONTEXT gates both.

- pi-extension/src/hooks/subagent-context.ts: buildSubagentContext + isSubagentChild
- pi-extension/src/guardrails.ts: wire child-side injection at before_agent_start
  + parent-side pi.events listener
- tests/test-pi.sh: 5 new cases (58 total, all green)
- README/index.ts: document the pi-subagents integration

All five suites green (596 tests). transform.sh idempotent.
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.

1 participant