A standalone, harness-agnostic PHI/PII pre-outbound hook for coding agents. It runs before a prompt is sent to an LLM API or any outbound call, and blocks or redacts text that carries personal/health information — so a cloud-backed coding session can't exfiltrate PHI.
It is independent of any host platform: pip install phi-hook, verify and wire it with the
phi-hook CLI, and your agent invokes phi-hook-run on every outbound turn.
- Regex floor (always on, offline). A deterministic Korean-medical PHI pass (주민등록번호, 환자명, 등록번호, phone, email, dates, long IDs …). No model, no network — works air-gapped, and is the guarantee.
- Served model (optional, adds recall).
openai/privacy-filter— a 1.5B-param bidirectional token-classifier (Apache-2.0) detecting 8 PII categories. Runs on-box; the hook never returns text less redacted than the floor, and inremotemode fails closed if the model is required but unreachable.
local/* sessions are exempt (the model stays inside the boundary), matching the host
platform's privacy invariant.
pip install phi-hook # core: regex floor + hook + CLI (tiny, httpx-only)
pip install "phi-hook[model]" # + the openai/privacy-filter runtime (torch/transformers/opf)phi-hook doctor # regex floor + transformers/torch + weights + served-filter checks
phi-hook doctor --run # also run a real model forward pass on a probe string
phi-hook download # fetch weights to ~/.opf/privacy_filter (or set OPF_CHECKPOINT)Air-gapped sites: stage the weights into ~/.opf/privacy_filter (or OPF_CHECKPOINT) and
vendor the [model] wheels; phi-hook doctor validates the staged setup with no network.
phi-hook serve --host 127.0.0.1 --port 8088 # loads the model once, serves POST /redact
export PHI_HOOK_FILTER_URL=http://127.0.0.1:8088
export PHI_HOOK_FILTER_MODE=hybrid # best-effort; regex floor still guards if downWithout a server, set PHI_HOOK_FILTER_MODE=local (regex floor only) — or the hook can fall
back to the opf subprocess (slower; reloads the model per call).
phi-hook install --harness claude --scope project # .claude/settings.json
phi-hook install --harness codex --scope user # ~/.codex/hooks.json
phi-hook install --harness pi --scope project # .pi/extensions/phi-hook.mjs (shim)
phi-hook install --harness generic --scope project # .phi-hook/phi-hook-wrapper.sh + contract
phi-hook install --harness claude --dry-run # preview the config, write nothing- Claude Code & Codex share the same hook schema (
UserPromptSubmit+PreToolUseonBash|WebFetch); installs are idempotent and preserve existing hooks. - Pi uses JS/TS extensions, so a small shim bridges to
phi-hook-run(best-effort — Pi's API evolves; usegenericif it doesn't load). - Generic / any other harness: the contract is stdin → exit 2 blocks / redacted stdout.
| stdin | behavior | exit |
|---|---|---|
JSON hook payload ({hook_event_name, prompt, tool_input, model}) with PHI |
{"decision":"block"} (or --warn notice) |
2 (block) / 0 (warn) |
| JSON payload, clean | silent allow | 0 |
| plain text | redacted text on stdout | 0 |
model is local/* (payload or PHI_HOOK_MODEL/SUBAL_AGENT_MODEL/ANTHROPIC_MODEL) |
no-op | 0 |
| Variable | Default | Meaning |
|---|---|---|
PHI_HOOK_ACTION |
block |
block or warn |
PHI_HOOK_MODEL |
— | session model; local/* ⇒ hook is a no-op |
PHI_HOOK_FILTER_MODE |
local |
local (regex only), hybrid, remote |
PHI_HOOK_FILTER_URL |
— | served openai/privacy-filter endpoint |
OPF_CHECKPOINT |
~/.opf/privacy_filter |
model weights location |
SUBAL_* / PRIVACY_FILTER_URL / ANTHROPIC_MODEL are accepted as aliases for
drop-in compatibility with existing deployments.
Drop a module in phi_hook/harness/ that builds an Adapter and calls register(...).
JSON-hook harnesses can reuse phi_hook.harness._jsonhooks.