@lystran/pi-serena-hooks
Run Serena lifecycle hooks from Pi coding agent
Package details
Install @lystran/pi-serena-hooks from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@lystran/pi-serena-hooks- Package
@lystran/pi-serena-hooks- Version
0.2.1- Published
- Sep 24, 2026
- Downloads
- 1,038/mo · 79/wk
- Author
- lystran
- License
- MIT
- Types
- extension
- Size
- 20.8 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@lystran/pi-serena-hooks
Connects Serena lifecycle commands to a Pi coding agent. The plugin injects JSON stdin into Serena hooks and uses Serena's claude-code hook format to match Pi's native tool events.
Prerequisites
- Pi coding agent
>=0.84.2 - Node.js
>=20 - The Serena CLI is installed on the system
- Both
serenaandserena-hooksare available onPATH - An MCP extension is installed and configured with the Serena MCP server
Verify the CLI installation before starting Pi:
serena --version
serena-hooks --help
Install Serena using the method documented by the Serena project: https://oraios.github.io/serena/
This plugin does not provide the Serena MCP server or install the Serena CLI. Configure Serena's MCP server through an MCP extension such as pi-mcp-adapter:
{
"mcpServers": {
"serena": {
"command": "serena",
"args": [
"start-mcp-server",
"--context=ide",
"--project-from-cwd"
]
}
}
}
The MCP extension and this hooks plugin have separate responsibilities: the MCP extension exposes Serena's symbolic tools to Pi, while this plugin runs Serena's lifecycle and remind hooks.
Installation
pi install npm:@lystran/pi-serena-hooks
For local development:
cd plugins/serena-hooks
pi install -l .
Integrated Plugins
@ff-labs/pi-fff
The plugin supports all three FFF operating modes:
| FFF mode | Search tools handled by Serena |
|---|---|
tools-and-ui |
ffgrep, optional fff-multi-grep |
tools-only |
ffgrep, optional fff-multi-grep |
override |
grep, optional multi_grep |
FFF path-search tools, fffind and overridden find, are intentionally not sent to remind.
pi-mcp-adapter
This is the recommended MCP companion plugin for exposing Serena's symbolic tools to Pi. It is not intercepted by remind; configure the Serena MCP server and its direct tools through pi-mcp-adapter separately.
Serena Hook Format
The plugin is compatible with the JSON hook protocol exposed by Serena's --client claude-code option. It sends session_id, tool_name, and tool_input through stdin, then handles Serena's hookSpecificOutput response:
additionalContextis forwarded to the Pi agent, after correcting Serena's stale session-start instruction to callactivate_project(see Session-start Activation Instruction)permissionDecision: "deny"blocks the current matching tool call, and itspermissionDecisionReasontogether withadditionalContextbecomes the blocked tool result the model reads- command failures, timeouts, and malformed output do not block Pi
Using the claude-code format does not require Claude Code and does not launch Claude Code. It only selects Serena's compatible hook input and output schema for this Pi adapter.
Session-start Activation Instruction
Serena's serena-hooks activate emits a session-start reminder that instructs the agent to call Serena's activate_project tool. That instruction is stale for the configuration this plugin documents.
Serena removes activate_project from its tool list when the MCP server is started with a context that uses single-project mode and a project is supplied at startup — for example --context=ide --project-from-cwd, the configuration shown above. In that case the project is already active and project switching is not allowed, so the tool does not exist at all. An agent that follows the reminder calls a non-existent tool, and may then spend turns searching for it instead of doing the task.
The plugin therefore rewrites only that clause into a conditional form:
- if Serena's
activate_projecttool is available, activate it unless already done.
Everything else in the reminder is forwarded byte for byte. This keeps the reminder correct under both configurations: with auto-activation the clause is skipped, and without it the agent is still told to activate the project. If a future Serena release fixes the upstream wording, the pattern no longer matches and the text passes through unchanged.
Lifecycle Mapping
| Pi event | Command |
|---|---|
Any session_start |
serena-hooks activate --client claude-code |
A session_tree navigation that rewinds the branch to before the first user message |
serena-hooks activate --client claude-code again |
| Before a model code-search call | serena-hooks remind --client claude-code |
session_shutdown with reason quit, new, resume, or fork |
serena-hooks cleanup --client claude-code |
activate context is queued with deliverAs: "nextTurn", so it is injected into the same turn as the next user message rather than one turn later. Rewinding is detected by inspecting the branch after navigation: navigating to a user message moves the leaf to that message's parent, so a branch without any user message means the branch now starts before the first user message. A navigation that leaves the leaf unchanged, and any further navigation before the next user message, does not re-inject the context. session_shutdown with reason reload keeps the same session and therefore skips cleanup.
remind watches model-initiated grep, ffgrep, multi_grep, and fff-multi-grep tools, plus Bash calls whose command starts with grep, rg, fgrep, egrep, ag, or ack. These calls are normalized to Serena's grep semantics, supporting Pi's native search tools and FFF's tools-and-ui, tools-only, and override modes. Ordinary Bash, skill reads, source reads, and documentation reads do not trigger the reminder. find and fffind search paths and do not trigger remind. Each command waits for at most 10 seconds. Missing commands, timeouts, and non-zero exits do not block Pi; each action produces at most one warning per session, while later events continue to attempt the command.
Shell commands executed directly by the user with ! or !! do not trigger remind.