@vieko/pi-redact
Keeps secrets out of pi session transcripts: stable placeholders in, real values back for local tools.
Package details
Install @vieko/pi-redact from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@vieko/pi-redact- Package
@vieko/pi-redact- Version
0.2.0- Published
- Nov 12, 2026
- Downloads
- 267/mo · 10/wk
- Author
- vieko
- License
- MIT
- Types
- extension
- Size
- 117.9 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./extensions/pi-redact.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-redact
A pi extension that keeps secrets out of session transcripts. A key that you paste, that a tool prints, or that sits in AGENTS.md becomes a stable placeholder such as [REDACTED-SECRET-5c1e9a7b]. The model works with the placeholder. When the model puts the placeholder in a local tool call, the extension puts the real value back first, so curl -H "Authorization: Bearer [REDACTED-SECRET-5c1e9a7b]" still authenticates.
A key that reaches the conversation stays there: pi sends it on every later turn, stores it in the session .jsonl, and replays it into forks, compaction and audits. The only fix is to keep it out.
Detection is vendored from ray-amjad/claude-code-mods (src/detect.ts, MIT): about 70 vendor key shapes, entropy tests, base64 that hides a key, passwords in URLs and CLI flags. See NOTICE for local changes.
Install
pi install npm:@vieko/pi-redact
Where it hooks in
| pi event | What it does |
|---|---|
input |
Swaps keys in your prompt. !cmd runs as typed. |
before_agent_start |
Swaps keys in context files (secrets only). |
tool_call |
Puts real values back for local tools: bash, powershell, write, edit, read, grep, find, ls. Nested codemode calls are covered, because they go through the same event. |
tool_result |
Swaps keys in content, structuredContent and details. A value handed to a call is hidden again wherever its output prints it. A scan failure withholds the result. |
message_end |
Backstop for user, custom and tool-result messages before they persist. |
context |
Last net, per request: !cmd output, idle custom messages, and history from sessions recorded before the extension. |
Placeholders stay placeholders in git commit/git tag and gh pr|issue|api|..., and in every tool that is not in the restore list (codemode itself, send_message, MCP tools, web tools).
Placeholders
A placeholder is an HMAC-SHA256 of the value. The key belongs to the session lineage (a fork or clone uses its root's key) and comes from a machine key in ~/.pi/agent/pi-redact.key, created with mode 0600 on first use. After /reload, a restart or a resume, the same value gets the same placeholder, so the history pi sends does not change and the prompt cache holds. Two unrelated sessions get different placeholders. The machine key never reaches the model, so a placeholder cannot be matched to a guessed value. If the key file cannot be read or written, placeholders fall back to random tags per process.
Tracking
Each value seen for the first time in a session is logged as a pi-redact custom entry. Its fields are source (channel), values (new distinct values), vendor (new values with a known vendor shape), and families (family name to count, summing to values). The entry holds counts only, never the value or a piece of it, and is not sent to the model. Families are uuid, prefixed-id, identifier, and high-entropy; vendor-shaped values use the detector's public prefix or pattern as their family.
Old sessions
scripts/scrub-sessions.ts rewrites vendor-shaped keys out of saved sessions and reports how many leaked, where, and when:
node scripts/scrub-sessions.ts --report leaks.json # dry run
node scripts/scrub-sessions.ts --write --report leaks.json # rewrite in place
It trusts only vendor shapes and private key blocks, because rewritten history cannot be restored. Each key becomes [REDACTED-SECRET-<sha256/8>], the same in every file. Signed fields are never touched, files open in a process or modified in the last 15 minutes are skipped, and rewritten files keep their mtime.
Commands
/redact shows the count and settings. /redact off and /redact on toggle it for the session.
Settings
Optional ~/.pi/agent/pi-redact.json, same keys as the upstream plugin:
{ "pii": false, "allow": "", "allowPrefixes": "", "restoreTools": "bash,write,edit,read,grep,find,ls", "notify": true }
allowPrefixes is added to the built-in public ids (dpl_, prj_, team_, wrun_, gen_01).
Limits
- The vault lives in memory. After
/reload, a restart or a resume, an old placeholder maps to its value again only when that value turns up again; until then it reaches tools as written. - Output of
!cmdis persisted by pi before any hook sees it. The model gets placeholders (thecontextnet), but the raw output stays in the session file. - Custom messages appended while pi is idle are persisted without
message_end; thecontextnet covers what the model sees. - Sessions recorded before you install it keep their raw values on disk until you run
scripts/scrub-sessions.ts.
Develop
Releases: see docs/releasing.md.
npm install
npm run check # tsc + extension tests + vendored detector tests
pi -ne -e ./extensions/pi-redact.ts