Skip to content

Run pi-warden's guards in Claude Code, Codex and OpenCode #127

Description

@DevMortimer

pi-warden runs inside Pi today. This issue tracks running its guards in Claude Code, Codex and OpenCode as well. Pi stays the main host and the product keeps its name.

Approach

  • A layer that does not depend on Pi. Most guards are already plain functions (evaluateRules, evaluateDone, evaluateStuck, evaluateAction, ...). Add a normalized event type (session start, prompt, after tool, end of turn), a decide(event) that calls the existing guards, and one small adapter per host that turns the host's hook payload into an event and the decision back into the host's output.
  • A CLI: pi-warden hook <agent> <event> (reads the hook payload on stdin, always exits 0, fails open), pi-warden init <agent> [--project], pi-warden uninstall <agent>.
  • State between hook processes: other hosts start a new process per event, and parallel tool calls run hooks at the same time. State lives under ~/.pi/agent/pi-warden/state/<agent>/<session>/, one file per record, created exclusively. No shared file is read and then rewritten.
  • One config and one key for every host: ~/.pi/agent/pi-warden/. Consent and key come from PI_WARDEN_ENABLED=1 and the backend key variable on hosts without Pi's UI.
  • A stable hook command: the command written into a host's settings never contains a version. Codex trusts hooks by their hash, so a changing command would switch the guards off after every upgrade.

What each host supports

Guard Claude Code Codex OpenCode
Rules full (PostToolUse) full (apply_patch needs a patch parser) full (tool.execute.after)
Done-check full (Stop with decision: block) full partial (no stop hook; session.idle plus a new prompt)
Code slop, security in written code full full full
Stuck, call waste full, state in files full, state in files full
Action holds partial (deny works; no retry after approval, no plan text) partial (ask is not supported, so confirm becomes deny) partial (block by throwing)
Context saver, output masking partial (replacement must match each tool's output shape) partial (all-or-nothing replacement) full
Runaway not possible (no stream hook that can abort) not possible partial
warden_* tools needs an MCP server needs an MCP server plugin tools

Suggested order

  1. CLI skeleton, state store, and the Claude Code adapter with the rules guard and the done-check.
  2. Codex adapter (payload mapping, apply_patch parser, a note on re-trusting hooks).
  3. OpenCode plugin (in-process, own deadlines, continuation on session.idle).
  4. Action guard on all three, after measuring how many requests it adds without Pi's sibling batching.

Risks

  • A hook that times out does not block the call. Every hook needs its own deadline well under the host's.
  • Pi's plan text and message dedupe have no equivalent on the other hosts, so intent checks will be weaker there.
  • OpenCode's turn continuation is not documented as a contract, and its experimental.* hooks may change.

References

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions