Context Files and Project Instructions
Which files on disk become instructions the model receives on every request, which tier wins, and why context files load even when you decline project trust.
Compaction summarized away the schema you explained. The model asks you to restate it. You will not restate it.
The fix is not a better prompt. It is a file. Chapter 23’s last paragraph pointed at this: durable facts belong on disk, where they are read fresh on every request instead of travelling through a history that gets compressed.
This chapter is about that mechanism — which files, in which order, and under what conditions.
Two systems, not one
Pi has two separate ways to deliver instructions, and confusing them is the root of most surprises.
how-pi-works.md fixes the order: “Pi resolves project trust before loading project settings and resources. After the trust decision and project-resource loading, Pi loads context files.”
So the sequence at startup is: trust decision, then project resources (settings, extensions, skills, SYSTEM.md), then context files. Context files come last, and they are not part of the trust gate.
Wrong: “Declining project trust stops the folder’s AGENTS.md from reaching the model.”
Correct: security.md is unambiguous — “Context files such as AGENTS.override.md, AGENTS.md, and CLAUDE.md load regardless of project trust unless you disable context loading. Treat instructions in a folder as untrusted input even when you decline project trust.”
Context files
From configuration.md: “Context files are separate from project .pi configuration. Pi loads them from the agent directory, the working directory, and its parent directories. A context file applies whenever Pi runs in its directory or anywhere below it.”
Three properties:
- Directories, not one file. Agent directory, working directory, and every parent of it.
- Inherited downward. A file applies “in its directory or anywhere below it.”
- Independent of trust. “Context-file discovery does not require project trust.”
The names, from the agent-directory table: AGENTS.override.md, AGENTS.md, AGENTS.MD, CLAUDE.md, or CLAUDE.MD — “User instructions applied across working directories.” So Pi reads a conventional set of names so that a repository already written for another tool works unchanged.
The override rule has a narrow scope that is easy to over-apply: “An AGENTS.override.md replaces AGENTS.md or CLAUDE.md only in the same directory. It does not suppress context files from the agent directory or other directories.”
flowchart TD
R["repo AGENTS.md"] -->|inherited below| M
S["repo/src AGENTS.md"] -->|inherited below| M
O["repo/src/billing AGENTS.override.md"] -->|replaces the repo file here only| M
A["agent dir AGENTS.md"] -->|applies to every working directory| M
M["instructions rebuilt on every request"]
Override is a sibling replacement, not a global kill switch.
Turn discovery off entirely for one invocation:
pi --no-context-files
Also -nc. cli.md describes it as “Disables AGENTS.md and CLAUDE.md discovery.” That is the switch security.md refers to when it says “unless you disable context loading.”
The system-prompt files
Different mechanism, different trust gate, different precedence.
| File | Effect |
|---|---|
<agent-dir>/SYSTEM.md |
Replaces Pi’s default system prompt |
<agent-dir>/APPEND_SYSTEM.md |
Adds instructions to Pi’s system prompt |
.pi/SYSTEM.md |
Replaces the system prompt for the project |
.pi/APPEND_SYSTEM.md |
Adds project-specific instructions |
The precedence rule is short and absolute: “For SYSTEM.md and APPEND_SYSTEM.md, the trusted project file takes precedence over the corresponding agent-directory file. Files with the same name are not combined.”
Not combined. A project APPEND_SYSTEM.md does not add to your personal one — it replaces it. If you want both, you have to say so in one file.
And these are trust-gated. .pi/SYSTEM.md and .pi/APPEND_SYSTEM.md are two of the resources that make Pi ask about project trust in the first place.
What triggers the trust question
security.md lists exactly what makes Pi ask:
.pi/settings.json.pi/mcp.json.pi/extensions,.pi/skills,.pi/prompts, or.pi/themes.pi/SYSTEM.mdor.pi/APPEND_SYSTEM.md- project
.agents/skillsin the current directory or an ancestor directory
“A bare .pi directory does not require project trust.” An empty .pi/ is not a request.
How the decision is reached, in order: “A command-line --approve or --no-approve override applies first.” Then “User-level and command-line extensions can handle the project_trust event. The first extension that returns yes or no owns the decision.” Then “Pi looks for a saved decision for the current directory or one of its parents. The closest decision applies.” Then “Pi follows the global defaultProjectTrust setting, whose default is "ask".”
Saved decisions live in ~/.pi/agent/trust.json, keyed by canonical directory path. /trust writes one.
There is a documented leak in this, and you should know about it rather than be surprised by it. “Pi reads the project sessionDir setting while selecting or creating a session, before it resolves project trust. Declining trust prevents the remaining project settings and protected resources from loading, but it cannot undo that initial session-directory lookup.” configuration.md says the same thing from the other side: “The only exception is sessionDir, which Pi reads before resolving trust so it can locate sessions.”
In non-interactive modes the prompt cannot be shown. “Print, JSON, and RPC modes cannot show the built-in trust prompt.” Then: defaultProjectTrust: "always" loads protected project resources; "ask" or "never" skip them. Note the default is the safe side — a CI run in an untrusted directory does not load that directory’s extensions.
defaultProjectTrust has one extra restriction from settings.md: “Can only be set in agent-directory settings.” Same for httpProxy. Those two cannot be set by a project, because a project must not be able to decide how it is trusted.
Putting it together
A repository that works well has one of each thing and a clear owner for each:
api-service/
├── AGENTS.md # project conventions, applies in every subdirectory
├── .pi/
│ ├── APPEND_SYSTEM.md # this project's addition to the prompt (needs trust)
│ └── settings.json # project defaults (needs trust)
├── src/
│ └── billing/
│ └── AGENTS.override.md # replaces ../AGENTS.md for billing work only
In a session started in src/billing/, the model receives api-service/src/billing/AGENTS.override.md instead of api-service/AGENTS.md, and your agent-directory file still with them. Add the project’s .pi/APPEND_SYSTEM.md to that set only if you trusted the project.
To check what actually loaded, read the startup header: usage.md says “The startup header lists the instructions and resources Pi loaded.”
And after editing any of it — settings, keybindings, instructions, resources — “Run /reload after manually changing settings, keybindings, instructions, or resources.” /reload is what turns a file edit into a live change.
Choosing where a fact belongs
Four destinations, and they are not interchangeable.
Context file when the fact is true of the code. “This service uses integer cents, never floats.” It survives compaction, it loads every session, it diffs in review.
Skill when the fact applies only in certain situations. ch13 and ch11 covered this: a skill’s description is in every request, its body loads on demand.
Extension context hook when the fact must be computed. Chapter 18’s context event transforms the assembled context, which is how an extension injects something that is not on disk at all.
Prompt template when it is something you say once, on request.
The mistake to avoid is putting a project-wide invariant into the first user message of a session. It works until the first compaction, and then it is gone — and the reader has no way to know why the model stopped following it.
What context files are not
A security boundary. security.md is blunt: “Files, comments, instructions, command output, and model responses can steer the model through prompt injection. Project trust controls which project resources load at startup, but it does not make that content or the resulting actions safe.”
“Safety comes from limiting the files, credentials, processes, and network services Pi can access and affect if a generated action is wrong or hostile. Watching the transcript, using project trust, and reviewing changes do not create a security boundary.”
And since context files load without trust, cloning an untrusted repository and running pi in it means its AGENTS.md reaches the model before you have approved anything. Treat instructions in a folder as untrusted input — which is exactly what the documentation says to do.
That is the layer that persists. Everything from chapter 23 to chapter 27 lives in the session and dies with it. This layer is rebuilt from disk on every request, which is why a fact that must never be lost belongs here.
That durability is also why the failure modes matter. Chapter 23 compacted away something you had told the model once; chapter 27 showed you an entry that is in the file and absent from the request. The next chapter covers the third way a session loses an instruction — not by forgetting, but by failing.