@sidshaytay/pi-secret-safe

Pi extension that keeps secrets out of model context, provider requests, tool output, and session history.

Packages

Package details

extension

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.

  1. Install the extension:

    pi install npm:@sidshaytay/pi-secret-safe
  2. Put your credentials in a project dotenv file such as .env, or export them in your shell before starting pi. Use variable names such as OPENAI_API_KEY or DATABASE_URL so discovery can recognize them.

  3. Start pi, or run /reload in an existing session, then check:

    /secret-safe status

    You should see the current mode, protected-secret count, and redaction counters. Run /secret-safe rescan after changing dotenv values.

  4. Ask the agent to use the variable by name, for example: “Use $OPENAI_API_KEY in 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:

  1. ~/.pi/agent/secret-safe.json
  2. <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 sendMessage reach 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