Decide whether to trust a project
See what triggers a project-trust decision, how a saved decision outranks the default, and why AGENTS.md is not a trigger.
Pi asks a project-trust question only when the working directory holds something
that would load, and the answer decides which protected resources load. The
order is command-line flag, then a project_trust extension, then a saved
decision, then defaultProjectTrust. Context files such as AGENTS.md are not a
trigger and load either way. This is a decision-table walkthrough of the
Chapter 8 tests.
What triggers a decision
| Present from the working directory | Decision required |
|---|---|
.pi/settings.json |
yes |
.pi/mcp.json |
yes |
.pi/extensions, .pi/skills, .pi/prompts, .pi/themes |
yes |
.pi/SYSTEM.md, .pi/APPEND_SYSTEM.md |
yes |
.agents/skills in this or an ancestor directory |
yes |
a bare .pi directory |
no |
AGENTS.md or CLAUDE.md |
no — a context file |
Trust is requested because something would load, not merely because .pi exists.
A context file carries instructions and arrives regardless of the answer, which is
why declining trust does not stop it.
Saved decisions
Decisions are stored by canonical directory path in <agent-dir>/trust.json. The
closest path applies, so a parent decision covers its children:
{
"<canonical-directory>": true,
"<canonical-directory>/subdir": false
}Persisting a decision is what /trust does. Setting a path to null clears it.
The decision order
| Order | Source | Notes |
|---|---|---|
| 1 | --approve / --no-approve |
outranks everything, including an extension |
| 2 | project_trust handler |
first handler returning a decision owns it |
| 3 | saved decision in trust.json |
closest ancestor path wins |
| 4 | defaultProjectTrust |
agent-directory setting, default "ask" |
Print, JSON and RPC modes cannot show the prompt, so with nothing above them
"always" loads protected resources while "ask" and "never" skip them. Use
--approve or --no-approve for an explicit one-time answer in a script.
Mechanism and limitations
Documented: the pinned security.md trigger list, the trust.json location,
and defaultProjectTrust. Observed: trust.test.ts checks each trigger,
including that context files ask nothing, and decision.test.ts runs the shipped
pi in print mode with a project extension that writes a flag file, pinning the
order above and that a saved decision beats the default.
The order is a loading gate, not a sandbox: once Pi runs, enabled tools use the
process’s operating-system permissions. One contract detail the shipped binary
showed: a project_trust handler returns an object,
{ trusted: "yes" | "no" | "undecided", remember?: boolean }, not a bare string;
a bare string is silently ignored. The fragments here are illustrative.
Understand this example
Copy this prompt into your AI tool. No code runs here.
Apply this example
Copy this prompt into your AI tool. No code runs here.