pigo runs tools on your machine (or in an optional Docker container). Treat project-local resources and credentials as the two trust boundaries.
| Location | What |
|---|---|
~/.pigo/agent/auth.json |
API keys and OAuth tokens (mode 0600) |
| Provider env vars | ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, … |
--api-key |
In-process only; not written to disk or copied into the environment |
| Session JSONL | Transcripts (mode 0600, directory 0700) |
models.json |
Optional plaintext apiKey (chmod 0600 when a key is present) |
Override the config root with PIGO_CODING_AGENT_DIR (or --config-dir).
See auth.md.
Print a stored secret only when you mean to: pigo auth print-api-key /
print-bearer-token. OAuth loopback binds 127.0.0.1 by default.
PIGO_OAUTH_CALLBACK_HOST is ignored unless it is a loopback address.
Local .pigo/ files, ancestor .agents/skills, and project sandbox.json
do not load until the project is trusted. User ~/.agents/skills always
loads.
Resolution order:
--approve/--no-approve(this process only)- No project-local resources → treated as trusted
- Saved decision in
~/.pigo/agent/trust.json(cwd or a parent) settings.defaultProjectTrust:ask(default),always, ornever
ask without a saved decision is untrusted. In the TUI use /trust, then
restart the session so project resources actually load. Print / JSON / RPC
modes never prompt; they stay untrusted until --approve or a stored
always.
Untrusted projects skip cwd/.pigo/settings.json, SYSTEM.md,
APPEND_SYSTEM.md, prompts, themes, skills, extensions, package trees under
.pigo/npm / .pigo/git, and cwd/.pigo/sandbox.json.
An extension is a subprocess, not an in-process plugin. The host talks
length-prefixed JSON over stdin/stdout. pigo does not load *.ts in-process.
Load paths (see extensions.md):
-e/--extension(local command,npm:<pkg>, orgit:<url>)~/.pigo/agent/extensions/- package manifests and
settings.extensions[]
--no-extensions skips discovery. Explicit -e still loads.
Project-local extension trees need trust, the same as other .pigo/
resources.
Extensions inherit a filtered environment: API keys, tokens, and
*_SESSION_FILE are stripped. Host methods model.getApiKey* /
model.getProviderAuth return an error instead of credentials. Use
model.stream / model.complete so the host attaches auth. exec still
runs as the current user — only load extensions you would run as a binary
on this machine.
Two optional layers; both off by default. --no-sandbox disables both.
OS sandbox (tools.md): Linux/darwin only. Wraps
host bash via sandbox.json (bwrap on Linux, seatbelt on Darwin).
Skipped when Docker isolation is on. Windows never wraps.
Docker (tools.md): opt-in
settings.container.image. pigo and auth.json stay on the host.
read / write / edit / bash / grep / find / ls and ! / !!
run in a session-long container. The container uses --network=none unless
container.network is true. API keys and OAuth tokens are never passed
into the container, even if named in container.env. Extension tools and
Windows powershell stay on the host. Missing Docker is an error, not a
fallback to the host.
pigo server Unix sockets are chmod 0600. /share redacts common secret
patterns before upload. Self-update verifies checksums.txt from the GitHub
release.