@kickythrust/pi-fnox
Pi extension that injects fnox vault secrets into process.env and bash, scrubs them from output.
Package details
Install @kickythrust/pi-fnox from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@kickythrust/pi-fnox- Package
@kickythrust/pi-fnox- Version
0.1.0- Published
- Jul 3, 2026
- Downloads
- 44/mo · 10/wk
- Author
- kicky007
- License
- MIT
- Types
- extension
- Size
- 12.4 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
pi-fnox
A pi extension for fnox — automatic secret injection and scrubbing for AI agents.
What it does
- Injects fnox vault secrets into
process.envat startup — so anything reading env vars in-process (runline pluginenv:fallbacks, custom scripts, etc.) finds them. This is the main reason this extension exists. - Injects the same secrets into bash subprocesses spawned by Pi's built-in tool and user
!commands. - Scrubs secret values from all tool output — bash, read, grep, everything the LLM sees — as a safety net.
- Tells the LLM which secrets are available via the system prompt (names only, never values).
You: "deploy using the stripe key"
Agent runs: env | grep STRIPE_SECRET_KEY
→ STRIPE_SECRET_KEY=sk_live_…
Agent sees: STRIPE_SECRET_KEY=[REDACTED:STRIPE_SECRET_KEY]
The agent orchestrates. fnox holds the secrets (age-encrypted at rest in ~/.config/fnox/config.toml). The values never touch the context window.
Install
# Requires fnox on PATH
# mise use -g fnox # OR: brew install fnox, scoop install fnox, etc.
# Install the extension
pi install npm:@kickythrust/pi-fnox
Restart Pi. You should see [pi-fnox] loaded N secrets from … in stderr.
Setup
# Initialize fnox and add secrets (fnox's age provider is what we expect)
fnox init
fnox set STRIPE_KEY
fnox set DATABASE_URL
# Start pi — secrets automatically injected into every bash + process.env
pi
To scope to a subset of secrets, filter by fnox profile (the extension honors FNOX_PROFILE).
Commands
| Command | Description |
|---|---|
/fnox-list |
Show loaded secret names (never values) |
/fnox-reload |
Re-read fnox from disk (use after fnox set / fnox remove) |
Config (env vars)
| Env var | Default | Effect |
|---|---|---|
FNOX_CONFIG |
~/.config/fnox/config.toml |
Path to the fnox.toml to load from |
FNOX_PROFILE |
unset | fnox profile name to select (e.g. prod, staging) |
Why this exists
Runline's plugin loader resolves connection config via applyEnvOverrides, which reads process.env at connection-resolution time. Plugins whose schema fields declare env: "FOO_TOKEN" (github, cloudflareAccess, supabase, bugsink, etc.) need the parent Pi process to have the env loaded before Runline.fromProject() runs. Without this extension, those secrets would only reach bash subprocesses, leaving runline's in-process sandbox unauthenticated.
This extension hydrates process.env at Pi startup so runline plugins (and any other in-process tool) see the same env that bash subprocesses do.
How it works
- On startup, the extension runs
fnox -c ~/.config/fnox/config.toml export -f jsonand decrypts the result with the local age key. - Secrets are merged into
process.env. - The same secrets are injected into every bash invocation via
spawnHook(built-in tool) anduser_bashexec (user!commands). - After any tool completes,
tool_resultscrubs any leaked secret value out of the returned text. before_agent_startadds the list of loaded secret names to the system prompt so the LLM knows to use$SECRET_NAMEin bash.
Why fnox
- No biometric prompt. fnox decrypts locally with age — sub-100ms, no UI prompts, no human in the loop.
- Committed to git. fnox.toml stores only age-encrypted blobs. Audit-friendly, review-friendly, reproducible.
- One tool. fnox is the secret bus.
License
MIT