How Pi Web Uses Project Trust to Determine Allowed Operations

Pi Web gates code execution by checking project-trust status before loading any project-local resources that could run untrusted code.

Pi Web, an open-source agentic coding interface developed by agegr, implements a project-trust mechanism to isolate untrusted repositories. This security layer evaluates whether a directory contains executable resources and whether the user has explicitly granted trust before allowing those resources to load. Understanding how project trust determines allowed operations is essential for developers extending Pi Web or managing secure multi-repository workflows.

What Triggers a Trust Requirement

Pi Web scans the current working directory (cwd) to detect resources that could execute code. The hasTrustRequiringProjectResources() function from the @earendil-works/pi-coding-agent SDK identifies three indicator patterns:

  • .pi/extensions — custom extensions that run in the agent session
  • Project-level .pi/settings.json entries — configuration that may invoke executable logic
  • .agents/skills — custom skills implemented as code

If any of these exist, the project requires trust before Pi Web will load them. This detection happens in lib/project-trust.ts at lines 5-6, where the getProjectTrustStatus() function combines this check with stored user decisions.

How Trust Status Is Evaluated

The trust evaluation follows a two-part lookup stored in lib/project-trust.ts:

  1. Detect trust-requiring resources — hasTrustRequiringProjectResources(cwd) returns boolean
  2. Read stored trust decision — ProjectTrustStore(agentDir).get(cwd) checks ~/.pi/agent/trust.json

The getProjectTrustStatus() function returns an object with two properties:

{
  requiresTrust: boolean,  // true if cwd contains trust-requiring resources
  trusted: boolean         // true if user has granted trust for this cwd
}

Key behavior: if requiresTrust is false, the repository is automatically trusted—no user interaction needed. Only directories containing executable resources enter the trust-gating flow.

Gating Resource Loading with projectTrustReloadOptions

When Pi Web starts an agent session, it passes trust-gating parameters through projectTrustReloadOptions() in lib/project-trust.ts (lines 40-48). This function returns a reloadOptions object containing resolveProjectTrust—a callback the SDK invokes before importing any extension, skill, or project-level setting.

If requiresTrust is true and trusted is false, resolveProjectTrust returns false and all gated resources remain dormant. The session starts, but without executing any project-local code.

// lib/project-trust.ts — creating reload options for session creation
import { projectTrustReloadOptions } from '@/lib/project-trust';
import { startRpcSession } from '@/lib/rpc-manager';

const reloadOpts = projectTrustReloadOptions(process.cwd(), '/home/user/.pi/agent');
// reloadOpts.resolveProjectTrust() — called internally by SDK before loading extensions

await startRpcSession({
  cwd: process.cwd(),
  reloadOptions: reloadOpts,
});

Granting Trust: The trustProject Flow

Users grant trust through trustProject(cwd, agentDir), implemented in lib/project-trust.ts at lines 15-21. This function:

  1. Writes true for the cwd into ProjectTrustStore
  2. Persists to ~/.pi/agent/trust.json
  3. Returns updated status where trusted: true

Subsequent sessions immediately load gated resources without prompting.

// Trusting a project programmatically (e.g., from UI confirmation)
import { trustProject } from '@/lib/project-trust';

const status = trustProject(process.cwd(), '/home/user/.pi/agent');
// status: { requiresTrust: true, trusted: true }

Operations Allowed by Trust Level

Operation Trust Requirement Source File
Reading files via /api/files None—always allowed lib/file-access.ts
Executing .pi/extensions requiresTrust === false OR trusted === true lib/project-trust.ts
Loading .pi/settings.json Same gating as extensions lib/project-trust.ts
Running .agents/skills Same gating as extensions lib/project-trust.ts
SDK-evaluated session code Gated by resolveProjectTrust callback lib/rpc-manager.ts

Critical distinction: file access is not trust-gated. The security boundary applies strictly to code execution, not data reading. This design allows users to inspect repository contents safely before deciding to trust.

Key Implementation Files

File Role
lib/project-trust.ts Core API: getProjectTrustStatus(), trustProject(), projectTrustReloadOptions()
lib/rpc-manager.ts Creates AgentSession and passes trust-gate options to SDK
lib/request-security.ts Request-level checks consulting trust status for extension/skill loading
lib/file-access.ts Filesystem access rules—operates independently of trust layer

Summary

  • Project trust is Pi Web's single control point for code execution security
  • Automatic trust applies to directories without .pi/extensions, .agents/skills, or executable settings
  • projectTrustReloadOptions() supplies the resolveProjectTrust callback that gates SDK resource loading
  • trustProject() persists user decisions to ~/.pi/agent/trust.json
  • File reading remains unrestricted—trust governs execution, not inspection

Frequently Asked Questions

How does Pi Web decide a project needs trust?

Pi Web calls hasTrustRequiringProjectResources(cwd) from the SDK to scan for .pi/extensions folders, .agents/skills directories, or project-level settings entries that could execute code. If any exist, requiresTrust becomes true and the trust-gating flow activates.

Where is trust status stored between sessions?

Trust decisions persist in ~/.pi/agent/trust.json, managed by ProjectTrustStore in lib/project-trust.ts. This JSON store maps absolute directory paths to boolean trust values, surviving application restarts.

Can I use Pi Web with an untrusted repository?

Yes—file reading works immediately. However, any code execution through extensions, skills, or project settings remains disabled until you invoke trustProject() or use the UI to grant trust. The session loads, but gated resources stay inert.

What happens if I revoke trust for a previously trusted project?

The current implementation in pi-web does not expose a revokeTrust() API. To remove trust, you must manually edit ~/.pi/agent/trust.json and delete the entry for that directory path. Future sessions will then re-prompt for trust confirmation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →