Skip to content

trotsky1997/pi-hookify

Repository files navigation

pi-hookify

Hookify V2 for Pi.

This package turns Pi extension hooks into declarative YAML rules stored under .pi/. Rule files are parsed from YAML and validated with Zod, so invalid on / when / do / respond structures fail fast with clear parse errors. Development is Bun-first (bun test, bun run smoke, bun run check), while the shipped runtime stays Node-compatible for Pi portability. Instead of the old event + action + message model, Hookify V2 uses a Pi-native rule DSL built around:

  • on - which Pi hook to subscribe to
  • when - predicates over normalized event fields
  • do - side effects such as notify, ask, approval, shell execution, and custom messages
  • respond - event-specific return data used to transform or intercept the hook

Rule files

Store rules in:

  • .pi/hookify.<name>.local.yaml

Example:

name: quick-rewrite
enabled: true
priority: 100
on:
  event: input
when:
  field: input.text
  op: starts_with
  value: "?quick "
do:
  - kind: notify
    level: info
    text: Rewriting quick prompt
respond:
  action: transform
  textTemplate: "Respond briefly: {{input.text}}"

Supported events in the first V2 wave

  • input
  • tool_call
  • tool_result
  • before_agent_start
  • context
  • user_bash

Hookify also accepts observe-only Pi lifecycle hooks for side-effect rules, including:

  • session_start
  • session_shutdown
  • agent_start
  • agent_end
  • turn_start
  • turn_end
  • message_start
  • message_update
  • message_end
  • tool_execution_start
  • tool_execution_update
  • tool_execution_end
  • model_select
  • before_provider_request
  • resources_discover
  • session_compact
  • session_tree
  • session_before_switch
  • session_before_fork
  • session_before_compact
  • session_before_tree

Some of these currently support side effects only. Event-specific respond handling is implemented first for the main transformation and interception hooks.

Predicates

A rule can use a single leaf predicate:

when:
  field: tool.input.path
  op: contains
  value: package.json

Or nested groups:

when:
  all:
    - field: tool.name
      op: eq
      value: read
    - any:
        - field: tool.input.path
          op: contains
          value: package.json
        - field: tool.input.path
          op: contains
          value: tsconfig.json

Supported operators:

  • eq
  • neq
  • contains
  • not_contains
  • starts_with
  • ends_with
  • regex
  • exists
  • in
  • gt
  • gte
  • lt
  • lte

Effects

Current do effect kinds:

  • notify
  • send_message
  • send_user_message
  • run_shell
  • ask
  • request_approval

notify

do:
  - kind: notify
    level: warning
    text: Dangerous command detected

send_message

do:
  - kind: send_message
    customType: hookify-audit
    template: "Read triggered for {{tool.input.path}}"
    deliverAs: steer

run_shell

do:
  - kind: run_shell
    command: npm run lint -- --fix
    blockOnFailure: true

ask

do:
  - kind: ask
    questions:
      - question: Which release type is this?
        header: Release
        options:
          - label: Patch
            description: Bug fixes only
          - label: Minor
            description: Backward-compatible features
    messageOnAnswer: Thanks, I captured the release details.

request_approval

do:
  - kind: request_approval
    title: Approve dangerous action?
    message: Dangerous command detected.
    remember: true

Respond examples

input

respond:
  action: handled

Or:

respond:
  action: transform
  textTemplate: "Respond briefly: {{input.text}}"

tool_call

respond:
  patchInput:
    - path: command
      template: "source ~/.profile\n{{tool.input.command}}"
  block: false

Or:

respond:
  block: true
  reason: Dangerous command

tool_result

Structured content blocks are supported, not just text shorthands:

respond:
  replaceContent:
    - type: text
      text: reviewed output
  appendContent:
    - type: image
      data: aGVsbG8=
      mimeType: image/png

before_agent_start

respond:
  appendSystemPrompt: "
Be extra careful about release safety."
  injectMessage:
    customType: hookify-release-guard
    content: Release-related request detected.
    display: true

context

You can still filter messages, or replace them completely with typed message specs:

respond:
  replaceMessages:
    - role: user
      contentText: Fresh user context
    - role: custom
      customType: hookify-context
      contentText: Fresh custom context
      display: true
    - role: toolResult
      toolCallId: call-1
      toolName: read
      isError: false
      contentBlocks:
        - type: text
          text: tool output

user_bash

Return a full result:

respond:
  result:
    output: BLOCKED
    exitCode: 1
    cancelled: false
    truncated: false

Or declaratively wrap Pi's local shell backend with rewritten commands:

respond:
  operations:
    kind: local_shell
    prependCommand: source ~/.profile

session_before_compact

respond:
  compaction:
    summary: compacted summary
    firstKeptEntryIdTemplate: "{{meta.preparation.firstKeptEntryId}}"
    tokensBeforePath: meta.preparation.tokensBefore

session_before_tree

respond:
  summary:
    summary: branch summary
  customInstructions: Focus on the recent refactor
  replaceInstructions: true
  label: reviewed

Commands

  • /hookify <description> - create a starter YAML rule in .pi/
  • /hookify:list - list parsed Hookify V2 rules
  • /hookify:configure - enable or disable a rule

Install

pi install git:github.com/trotsky1997/pi-hookify

Testing

Run the Bun test suite:

bun test

Run watch mode, coverage, or the Bun smoke/check workflows:

bun run test:watch
bun run test:coverage
bun run smoke
bun run check

Notes

  • Hookify V2 is a clean-slate redesign. Old markdown/frontmatter rule files are not part of the new format.
  • Templated strings use {{path.to.field}} with normalized event fields such as input.text, tool.name, tool.input.path, result.content, and agent.prompt.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors