# How Pi Web Uses Project Trust to Determine Allowed Operations

> Discover how Pi Web uses project trust to determine allowed operations, gating code execution before loading untrusted project-local resources.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: how-to-guide
- Published: 2026-08-15

---

**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`](https://github.com/agegr/pi-web/blob/main/.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`](https://github.com/agegr/pi-web/blob/main/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`](https://github.com/agegr/pi-web/blob/main/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:

```typescript
{
  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`](https://github.com/agegr/pi-web/blob/main/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.

```typescript
// 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`](https://github.com/agegr/pi-web/blob/main/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.

```typescript
// 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`](https://github.com/agegr/pi-web/blob/main/lib/file-access.ts) |
| **Executing `.pi/extensions`** | `requiresTrust === false` OR `trusted === true` | [`lib/project-trust.ts`](https://github.com/agegr/pi-web/blob/main/lib/project-trust.ts) |
| **Loading [`.pi/settings.json`](https://github.com/agegr/pi-web/blob/main/.pi/settings.json)** | Same gating as extensions | [`lib/project-trust.ts`](https://github.com/agegr/pi-web/blob/main/lib/project-trust.ts) |
| **Running `.agents/skills`** | Same gating as extensions | [`lib/project-trust.ts`](https://github.com/agegr/pi-web/blob/main/lib/project-trust.ts) |
| **SDK-evaluated session code** | Gated by `resolveProjectTrust` callback | [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/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`](https://github.com/agegr/pi-web/blob/main/lib/project-trust.ts) | Core API: `getProjectTrustStatus()`, `trustProject()`, `projectTrustReloadOptions()` |
| [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) | Creates `AgentSession` and passes trust-gate options to SDK |
| [`lib/request-security.ts`](https://github.com/agegr/pi-web/blob/main/lib/request-security.ts) | Request-level checks consulting trust status for extension/skill loading |
| [`lib/file-access.ts`](https://github.com/agegr/pi-web/blob/main/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`](https://github.com/agegr/pi-web/blob/main/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.