@sidshaytay/pi-secret-safe
Pi extension that keeps secrets out of model context, provider requests, tool output, and session history.
Package details
Install @sidshaytay/pi-secret-safe from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@sidshaytay/pi-secret-safe- Package
@sidshaytay/pi-secret-safe- Version
0.2.2- Published
- Oct 27, 2026
- Downloads
- 245/mo · 46/wk
- Author
- sidshaytay
- License
- MIT
- Types
- extension
- Size
- 80.1 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@sidshaytay/pi-secret-safe
Keep discovered secret values out of pi model requests, tool output, and session history while letting the agent use them through shell variables.
Quick start
Requires pi 0.85.1 or later (the declared minimum); this repository tests against pi 1.2.0. Current pi requires Node.js 22.19 or later.
Install the extension:
pi install npm:@sidshaytay/pi-secret-safePut your credentials in a project dotenv file such as
.env, or export them in your shell before starting pi. Use variable names such asOPENAI_API_KEYorDATABASE_URLso discovery can recognize them.Start pi, or run
/reloadin an existing session, then check:/secret-safe statusYou should see the current mode, protected-secret count, and redaction counters. Run
/secret-safe rescanafter changing dotenv values.Ask the agent to use the variable by name, for example: “Use
$OPENAI_API_KEYin the authorization header without printing its value.”
To try the extension from this repository's root for one invocation:
pi -e ./packages/pi-secret-safe/extensions/index.ts
Use a protected value
The model sees a placeholder instead of a discovered value:
«Redacted — read as environment variable $NAME via script»
NAME is the original variable name, such as OPENAI_API_KEY, or a generated SECRET_* name for a pattern match. With exportToShell enabled (the default), the extension exports the value so bash can expand $NAME at runtime.
The placeholder avoids quotes, backslashes, colons, and equals signs so it can appear inside JSON, YAML, or TOML string values. Short URL credentials are hidden in URLs without replacing unrelated words containing the same letters.
Choose a mode
/secret-safe strict
| Mode | Behavior |
|---|---|
redact (default) |
Redact discovered secrets without blocking operations. |
strict |
Also block sensitive file operations, secret-dumping commands, and commands or write/edit content containing secret literals. With a UI and promptOnBlock, ask whether to allow once or deny. |
off |
Disable protection for the session. |
Use /secret-safe redact or /secret-safe off to switch again. These changes last for the session; set mode in a config file for a persistent default.
| Command | Result |
|---|---|
/secret-safe or /secret-safe status |
Show mode, protected-secret and placeholder counts, counters, loaded config files, and config errors. |
/secret-safe rescan |
Re-read dotenv files and environment values. |
Configure protection
The extension reads these JSON files in order:
~/.pi/agent/secret-safe.json<project>/.pi/secret-safe.json
PI_CODING_AGENT_DIR changes the personal agent directory. Project settings override personal settings, except that patterns, allowPaths, blockPaths, and extraBlockCommands accumulate. dotenvFiles replaces the earlier list. Reload after editing configuration.
For example, put this in your project's .pi/secret-safe.json:
{
"mode": "strict",
"dotenvFiles": [".env", ".env.local"],
"allowPaths": ["docs/fixtures/**"],
"extraBlockCommands": ["vault\\s+read"]
}
| Setting | Default | Purpose |
|---|---|---|
mode |
"redact" |
"redact", "strict", or "off". |
dotenvFiles |
[".env", ".env.local", ".env.development", ".env.development.local"] |
Files to scan relative to the session directory. |
patterns |
[] |
Extra regular-expression rules for secret formats. |
allowPaths |
[] |
Strict-mode path exceptions overriding built-in rules. |
blockPaths |
[] |
Additional strict-mode blocked paths. |
extraBlockCommands |
[] |
Additional command regex sources for strict mode. |
scanEnv |
true |
Discover secrets in the process environment. |
exportToShell |
true |
Export discovered values so bash can use their variable names. When false, redaction continues but discovered values are not exported. |
minValueLength |
8 |
Minimum length for values discovered through environment/dotenv name matching. |
promptOnBlock |
true |
Ask before denying a blocked operation when a UI is available. |
Each custom pattern has name, regex, and optional flags:
{
"patterns": [
{ "name": "INTERNAL_TOKEN", "regex": "tok_[a-z0-9]{24}" }
]
}
Invalid config values fall back to defaults and appear in /secret-safe status.
Update or remove
Run pi update --extensions to update unpinned installations, then /reload. To stop loading this extension:
pi remove npm:@sidshaytay/pi-secret-safe
Run /reload afterward. Configuration and existing logs remain on disk. New requests and tool output will no longer receive this extension's protection.
Troubleshooting
The agent cannot use a secret in bash. Check exportToShell, run /secret-safe rescan, and have the agent reference $NAME instead of inserting the value into its command. Strict mode blocks recognized secret literals.
Strict mode blocks a legitimate operation. Allow the individual operation when prompted, or add a known-safe path to allowPaths and reload. /secret-safe redact keeps redaction while disabling blocking.
Configuration is missing or invalid. Check the paths and errors printed by /secret-safe status. Confirm the file contains valid JSON and the value types match the table.
Understand protection limits
- Detection uses known values and format patterns. Unrecognized secrets can pass through. Images are never redacted.
- Files on disk stay unchanged. The extension does not manage pi debug logs, terminal scrollback, or shell history. Rotate a credential if it has leaked.
- A user-run
!or!!command is stored as typed, even though its output is redacted. Do not type literal secrets into those commands. - User-command output is line-buffered. Multiline secrets that are not recognized private-key blocks may partially survive in session files.
- Messages injected by another extension through
sendMessagereach the session file before this extension can inspect them. - If a redaction hook throws, pi logs the error and can continue with the original unredacted content.
- Generic assignment rules stop at
#,,,;,}, and]. A secret not already discovered from the environment or dotenv may retain text after those characters.
Extension integration reference
| Hook | Purpose |
|---|---|
session_start |
Load config, discover values, and export them for shell use. |
before_agent_start |
Explain placeholders and $VAR usage to the model. |
input |
Redact incoming user text. |
context |
Redact conversation messages before model requests. |
before_provider_request |
Redact the final provider payload. |
tool_result |
Redact tool output, including SSH metadata and chunked private keys. |
message_end |
Redact finalized messages for session history. |
tool_call |
Apply strict-mode path, command, and secret-literal checks. |
user_bash |
Apply strict-mode checks and redact streamed user-command output. |
Links
Credits and adapted code · Development and tests · MIT license