agentleFS
agegragegr/pi-web/AGENTS.md

pi-web

AGENTS.md8k starsChanged 3 days agoMITView on GitHub

Typecheck: node_modules/.bin/tsc --noEmit · Lint: npm run lint Never run next build during dev: it pollutes .next/ and breaks npm run dev. pi's packages up to 1.2.0 depend on each other with ^ ranges (1.3.0 pins them exactly), and the published pi-web's dependencies resolve afresh on install (no lockfile ships). Install every @earendil-works/* package the tree holds, the SDK's own dependencies included (pi-codemode, pi-mcp, pi-telemetry, …), with npm install --save-exact, so npm reuses those exact versions for the SDK's ranges.…

  • Installs packages

We split this AGENTS.md into the rules it gives an agent

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never fall back to next dev --webpack: the dev graph can fail on undici imports such as node:console.

    line 18

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Pi Web - Development Notes

Quick Start

npm run dev   # port 30141

Typecheck: node_modules/.bin/tsc --noEmit · Lint: npm run lint

Never run next build during dev: it pollutes .next/ and breaks npm run dev.

Dev server troubleshooting

  • First run lsof -nP -iTCP:30141 -sTCP:LISTEN and reuse a healthy Pi Web process. A second next dev on another port is no workaround: both contend for .next/dev/lock.
  • A browser-only Module ... factory is not available overlay usually means that tab has a stale Turbopack/HMR graph, not a broken server or source. Use the browser's explicit reload, then compare the server log and a direct HTTP/API request.
  • Restart only when the failure reproduces from a fresh page and the server-side checks fail too: stop that exact dev process gracefully, move .next into a mktemp -d backup, restart with npm run dev.
  • Never fall back to next dev --webpack: the dev graph can fail on undici imports such as node:console. Development uses Turbopack.
  • next dev may append a generated BEGIN:nextjs-agent-rules block to AGENTS.md. It is tooling output: check git status and keep it out of unrelated commits.

Upgrading pi

pi's packages up to 1.2.0 depend on each other with ^ ranges (1.3.0 pins them exactly), and the published pi-web's dependencies resolve afresh on install (no lockfile ships). Install every @earendil-works/* package the tree holds, the SDK's own dependencies included (pi-codemode, pi-mcp, pi-telemetry, …), with npm install --save-exact, so npm reuses those exact versions for the SDK's ranges. lib/pi-packages.test.mjs fails on any pi package that is not pinned that way; pi-web 0.12.0 pinned four, and installs after pi 1.2.0 paired pi-coding-agent 1.1.0 with pi-codemode 1.2.0.


Architecture

  • Browsing (read-only, no AgentSession): GET /api/sessions lists ~/.pi/agent/sessions/; GET /api/sessions/[id] reads the .jsonl through SDK SessionManager helpers and lib/session-reader.ts, or an open wrapper's in-memory SessionManager. GET /api/agent/running snapshots the running ids.
  • Sending: POST /api/agent/[id] → startRpcSession() (lib/rpc-manager.ts) creates the AgentSession in-process (createAgentSessionFromServices()); session.send(cmd) → session.prompt().
  • Events: GET /api/agent/[id]/events streams SSE data: {...} from session.onEvent(), fed by session.subscribe().
  • Product scope: a light web wrapper around pi, not an IDE or a platform of its own. Before adding a feature, check the out-of-scope list in CONTRIBUTING.md.
  • Extension compatibility (principle): extensions written for the pi CLI must behave the same here. Fix display problems in the web client; never add pi-web-only options or fields to the extension API (ctx.ui.* options, extension_ui_request). pi's TUI (node_modules/@earendil-works/pi-tui) is the reference for what an extension asking for something means.

File Map

app/api/
  sessions/route.ts                GET list all sessions
  sessions/[id]/route.ts           GET/PATCH/DELETE a session
  sessions/[id]/context/route.ts   GET ?leafId=&tail=&before= a page of a leaf's context (tail defaults to 50; before pages upward)
  sessions/[id]/export/route.ts    GET exported HTML
  sessions/[id]/fork/route.ts      POST copy the session's current branch into a new session (never starts an AgentSession)
  sessions/delete/route.ts         POST { ids } delete sessions and their subagents (a project's Delete all sessions); running ones kept
  sessions/stats/route.ts          POST { ids } each session's tokens, cost, tool calls, active time (the agent switcher's rows)
  sessions/[id]/state/route.ts     GET live wrapper state while running
  sessions/ui-state/route.ts       GET/POST sidebar pins, archive, project order and names (set, restore, pin-project, add-projects, move-project, rename-project)
  sessions/[id]/auto-name/route.ts POST generate a session title
  sessions/search/route.ts         GET session search
  agent/new/route.ts               POST { cwd, type: prompt|ensure_session (start only), message?, toolNames?, provider?, modelId?, thinkingLevel? }
  agent/[id]/route.ts              GET state (?systemPrompt=0: without the prompt) | POST any command
  agent/[id]/events/route.ts       GET SSE stream
  agent/[id]/lease/route.ts        POST reset the selected session's idle timer (with or without its stream; never starts one); reply: running, awaitingInput, subagentsActive
  agent/running/route.ts           GET running + awaiting-input session ids, sidebar pins/archive revision
  agent/debug/route.ts             GET ?session= the Debug panel's read-only snapshot: wrappers, streams, subagents, MCP, terminals, file watches
  auth/api-key/[provider]/route.ts POST/DELETE stored provider API key
  auth/login/[provider]/route.ts   GET OAuth/device-code SSE | POST manual code
  auth/logout/[provider]/route.ts  POST OAuth logout
  auth/providers/route.ts          GET OAuth and API-key provider lists
  cwd/validate/route.ts            POST validate/select a cwd
  cwd/browse/route.ts              GET browse any readable directory for the cwd picker | POST create child directory
  default-cwd/route.ts             POST create ~/pi-cwd/YYYYMMDD (local date)
  home/route.ts                    GET user home directory
  open-in-explorer/route.ts        GET availability | POST open a cwd in the OS file manager (loopback only)
  files/[...path]/route.ts         GET ?type=list|read|download|meta|preview|watch | POST ?type=upload|upload-check|allow-link
  file-index/route.ts              GET file list for @-mentions
  git/status/route.ts              GET changed files for a cwd
  git/diff/route.ts                GET diff of one changed file
  worktrees/route.ts               GET/POST/DELETE git worktrees
  terminal/route.ts                POST create a terminal session
  terminal/[id]/route.ts           GET { id, cwd } (404 once closed; stream at [id]/events) | POST input/resize | DELETE kill
  mcp/route.ts                     GET [?cwd=] Settings › MCP overview, files only | POST add/enable/disable/remove/undo/set-enabled/set-exposure/set-in-project/sign-out
  mcp/test/route.ts                POST { scope, name, cwd? } test one server once (entry read from its file)
  mcp/sign-in/route.ts             POST { scope, name, cwd? } start or join an OAuth sign-in
  mcp/sign-in/[flowId]/route.ts    GET flow state (polled) | POST { redirectUrl } | DELETE cancel
  project-trust/route.ts           GET trust status + project .pi/mcp.json servers (files only) | POST trust, rebuild the cwd's wrappers
  tools/settings/route.ts          GET/PUT defaultTools switches: PowerShell (Windows), Code mode automatic/always; codemode.mode, codemode.inlineBudget
  cache-miss-notices/route.ts      GET/PUT pi's global showCacheMissNotices (Settings › General)
  models/route.ts                  GET ?cwd= { models, modelList, defaultModel, … }
  models/enabled/route.ts          GET/PUT enabledModels switches
  models/default/route.ts          PUT default model / reasoning level for new sessions
  models/refresh/route.ts          POST fetch provider catalogs from pi.dev on demand
  models-config/route.ts           GET/PUT ~/.pi/agent/models.json
  models-config/catalog/route.ts   GET models.dev pricing presets
  models-config/discover/route.ts  POST fetch a configured provider's upstream model list
  models-config/test/route.ts      POST test a configured model/provider
  plugins/route.ts                 GET/POST package plugin management
  plugins/check/route.ts           POST check plugin package updates
  skills/route.ts                  GET/PATCH loaded skills, disable-model-invocation
  skills/content/route.ts          GET one loaded skill's bounded Markdown source, or ?document= a Markdown file in its folder
  skills/install/route.ts          POST install skills via npx skills add
  skills/search/route.ts           POST skills.sh search
  subagents/settings/route.ts      GET/PUT built-in subagent switch and maxConcurrent
  web-auth/route.ts                GET status | POST login | DELETE logout (browser password)
  provider-usage/query/route.ts    POST provider usage quotas
  push/config/route.ts             GET VAPID public key
  push/subscribe/route.ts          POST register a push subscription
  app-update/route.ts              GET current vs latest published pi-web version

lib/
  agent-client.ts           typed fetch helper for /api/agent commands
  missing-cwd.ts            client-safe `reason: "cwd-missing"` refusal of a folder that no longer exists: error class, body fields, parsing
  debug-types.ts            client-safe shapes of the Debug panel: GET /api/agent/debug and the page's own snapshot
  debug-snapshot.ts         buildDebugSnapshot(): the debug route's synchronous field reads, each source guarded
  stream-client.ts          an event stream's reported address and "Chrome · macOS" label, for the Debug panel's connected pages and SSE titles only
  page-stream-registry.ts   open terminal and file-watch streams with their page (`?holder=`) and client, for the Debug panel's connected pages
  page-debug.ts             client: the page's id (`?holder=` of its streams), EventSources, visibility history, protocol and running-poll record (Debug panel)
  file-watch-registry.ts    open ?type=watch streams, counted on globalThis for the Debug panel
  rpc-manager.ts            AgentSessionWrapper, registry, startRpcSession
  session-reader.ts         SessionManager wrappers, path cache, buildSessionContext adapter
  session-fork.ts           forkSessionBranch(): the sidebar's Fork, a leaf-branch copy on a fresh SessionManager named after its source, typed refusals
  session-fork-name.ts      client-safe Fork naming: source title + " · " + 4 hex; splitting the suffix off for the row and toast
  session-delete.ts         deleteSessions(): session files with their subagents, re-parenting what stays, wrapper shutdown, pins/archive cleanup
  session-tree.ts           sidebar row model: pinned section, project groups and their order, archived predicate, virtual rows, drop targets
  session-ui-state.ts       pi-web-session-state.json (pins, archive, project order and names): lock, atomic write, revision, corrupt backup
  session-ui-state-shared.ts client-safe types and rules of that state: request parsing, apply, undo snapshot
  sidebar-prefs.ts          per-browser sidebar tab, group expand choices, archive folds, pinned-section collapse, files-section fold, folders found outside git
  sidebar-actions.ts        session row menu entries, a project group's name entries and rename request, fork refusal messages, delete-all requests
  session-links.ts          same-instance links: a session's (?session=<id>), a fresh composer's (?cwd=<dir>); the plain-click rule the sidebar keeps in the page
  new-session-context.ts    client-safe: what the project/worktree pickers show (project, worktrees, project list), lag-safe contextForCwd, the directory a group's + and Open in new tab use
  normalize.ts              normalizeToolCalls(): file-format vs our toolCall field names
  message-keys.ts           client-safe React keys of chat messages: a run's messages keep theirs when the file is read again
  types.ts                  shared TypeScript types
  pi-types.ts               local structural types for pi SDK objects
  pi-sdk-internals.ts       loader for SDK modules the package does not export (MCP connection, config, OAuth)
  tool-presets.ts           PRESET_NONE/READ_ONLY/DEFAULT/FULL + getPresetFromTools()
  tool-preset-preference.ts browser-persisted default preset for fresh sessions
  tool-fields.ts            a tool call's arguments as flat rows: all of them or no table
  builtin-extensions.ts     codemode / tool-search / mcp built-ins, sandbox self-test, -builtin: switches
  codemode-settings.ts      Code mode automatic/always (+codemode in global defaultTools), codemode.mode and inlineBudget; project overrides
  codemode-view.ts          display helpers for codemode cards
  global-settings-file.ts   locked read-modify-write of global settings.json (SettingsManager's lock)
  regular-file.ts           readRegularFileText(): non-blocking read of a regular file only, optional size cap
  default-preferences.ts    write defaultModel/defaultThinkingLevel; detect project shadowing
  deferred-provider-models.ts models of providers an extension registers only at session_start, re-added to listings
  enabled-models.ts         pure minimal-edit engine for the enabledModels pattern list
  enabled-models-runtime.ts SDK adapter for enabledModels: pattern resolution, provider kinds, settings IO
  model-context.ts          client-safe: managed models' contextWindow overrides in the models.json draft, the Save check
  model-image-limits.ts     client-safe: a custom model's inputLimits.images.resize.maxBytes in the draft, the Save check
  model-provider-check.ts   client-safe: Save refuses a models.json provider entry pi rejects on its own (Add provider's empty stub, oauth without a Base URL)
  subagent-settings.ts      read/write ~/.pi/agent/agents/settings.json
  file-access.ts            allowed file roots for /api/files and worktrees
  file-upload-client.ts     browser upload to /api/files ?type=upload, shared by the explorer and chat drops
  linked-directory.ts       directory links leading outside the allowed roots + the allow-link check
  file-paths.ts             client/server path encoding helpers
  file-version.ts           a watched file's size+mtime version: viewers skip reloading an unchanged file on reconnect
  delimited-table.ts        client-safe CSV/TSV parsing (RFC 4180, delimiter detection, file line per record) and table layout
  file-tree-visibility.ts   which entries the file tree lists (git check-ignore, name-list fallback)
  file-tree-expansion.ts    the file tree's open directories per cwd: page-memory LRU of 20 folders
  display-path.ts           display-only ~ / ./ path shortening for settings panels
  default-cwd.ts            dated ~/pi-cwd/YYYYMMDD path for "Use default directory"
  worktree.ts               project/worktree resolution and git worktree operations
  draft-store.ts            local draft persistence
  extension-ui-queue.ts     FIFO queues for extension dialogs and custom panels, by request id; isBlockingExtensionUiRequest() (which method a run waits on)
  session-stats-format.ts   client-safe compact counts, costs and active durations of the stats toolbar and agent switcher
  turn-duration.ts          getTurnDurationMs() / formatTurnDuration(): a finished turn's length from its anchor to its last response's end, on pi's timestamps
  transcript-notices.ts     client-safe: showCacheMissNotices notices on chat messages, TUI number formats, a fold's cache-miss sum
  transcript-notices-server.ts the notices derived from session entries (cache-stats port), live ones for message_end, the setting
  markdown.ts               shared markdown helpers
  markdown-blocks.ts        splitMarkdownBlocks(): where a streaming reply may be cut into blocks parsed apart
  highlight-queue.ts        code fences past a task's highlight budget get their colors in idle slices
  prism-languages.ts        loadPrismLanguages(): every Prism language in a chunk of its own, loaded when a highlighter first needs it
  gfm-autolink-email-loader.cjs  bundler loader: remark-gfm's email regex without a lookbehind literal
  node-cli.ts               locate bundled npm-cli.js / npx-cli.js to spawn npm/npx without a shell (Windows)
  npx.ts                    npx runner for skill install
  plugin-updates.ts         npm view update checks for /api/plugins/check
  jsonc.ts                  JSON with comments and trailing commas (models.json is read through it)
  shell-words.ts            split a pasted command line into words without a shell; refuses | && ; redirects $(…)
  key-serializer.ts         serializeByKey(): one globalThis promise chain per key
  stacked-dialog.ts         Escape and focus handling for Settings and dialogs stacked above it
  project-trust.ts          project trust status and decisions; fresh-folder trust-and-write
  mcp-host.ts               per-session MCP host: registers mcp.json servers before prompts, reports status
  mcp-transport.ts          MCP transport factory; stdio gets a sanitized env, never PI_WEB_PASSWORD
  mcp-command.ts            client-safe: who owns /mcp (built-in or another extension)
  mcp-read-only-policy.ts   read-only sessions block MCP tools without readOnlyHint (nested calls too)
  mcp-config-key.ts         canonicalJson() and mcpConfigKey(), the per-process HMAC statuses are keyed by
  mcp-config-values.ts      client-safe: the values pi resolves and the PI_WEB_PASSWORD rule
  mcp-config-read.ts        Settings › MCP reads of both mcp.json files; nothing resolved or run
  mcp-config-file.ts        the mcp.json writer: SDK editor's bytes, lock, atomic write, typed refusals
  mcp-override.ts           project overrides of global servers: the SDK's isOverride() and loader refusals
  mcp-json-error.ts         JSON.parse error messages that never quote the source
  mcp-undo.ts               removed mcp.json entries kept 60 s for undo; only a token reaches the browser
  mcp-status.ts             last known connection state per mcp.json entry (tests and sessions)
  mcp-test.ts               Settings › MCP Test: one bounded, masked SDK connection (sign-in reuses its steps)
  mcp-entry-request.ts      route checks before connecting one mcp.json entry (Test, sign-in); guards /api/mcp and /api/project-trust share
  mcp-sign-in.ts            Settings › MCP OAuth sign-in flows (as pi mcp login), polled by id
  mcp-sign-out.ts           OAuth store keys (name + URL); guard barring token writes by runs started before a sign-out
  mcp-secrets.ts            pure secret classification and masking for MCP config values
  mcp-add.ts                POST /api/mcp add's checks before it writes
  mcp-import.ts             pure paste importer (+ mcp-import-core/json/cli/links.ts)
  mcp-server-display.ts     client-safe display helpers for McpServerInfo (hidden-character escapes, labels)
  mcp-tool-display.ts       server/tool label of an mcp__ call from its result details, never the name

components/
  AppShell.tsx             layout, URL state, tab management
  SessionSidebar.tsx       toolbar row (Sessions | Files tabs, or the Pi Web brand with the files below them; new, search): tree, archive, menus, toast; files section (resizable, foldable; one header row with the file keys and changed-files count, the picker's row) or tab (picker boxes + file buttons), FileExplorer
  PiWebTitle.tsx           the sidebar's "Pi Web" brand (files below the sessions only): a click scrambles it into the versions
  SessionTree.tsx          virtualized rows of the session tree and the archive view
  SidebarMenu.tsx          sidebar popup menu (bottom sheet on phones), portaled to body: filter field, item secondary actions, the files tab's classic look
  ProjectWorktreePicker.tsx project and worktree boxes + menus: the files' (one row below the sessions, stacked in the tab) and the new-session bar's
  NewSessionContextBar.tsx the picker in its own row under the brand, right above the empty new-session composer; moves go through the sidebar
  WorktreeCreateForm.tsx   "New worktree…" form, a SidebarMenu body
  SidebarToast.tsx         sidebar one-line toast: archive Undo/View, failed saves
  SidebarIcons.tsx         sidebar stroke icons
  ChatWindow.tsx           chat composition + completion sound
  ChatInput.tsx            input bar + model/thinking/tools/compact controls
  MessageView.tsx          one message (user/assistant/toolCall/toolResult)
  CodemodeToolView.tsx     codemode card: the tool calls its script made
  BranchNavigator.tsx      in-session branch switcher
  ChatMinimap.tsx          scroll minimap beside the message list
  MarkdownBody.tsx         markdown renderer
  SvgBlock.tsx             a ```svg fence: preview only as an <img> data URL, source toggle, zoom, download (MermaidBlock's pieces)
  ModelsConfig.tsx         Settings › Models: models.json editor
  EnabledModelsSection.tsx model switches inside ModelsConfig (enabledModels)
  ModelContextWindow.tsx   a managed model row's context-window field (blank: no override)
  OAuthPastePanel.tsx      paste box for a sign-in's redirected address or code (Models, MCP)
  ProjectTrustDialog.tsx   trust confirmation listing the project's MCP servers
  AgentsConfig.tsx         built-in subagent toggle + agent profile editor
  SubagentViewer.tsx       read-only right-panel tab of a subagent's transcript (polls the context route)
  DebugPanel.tsx           Debug top panel (toolbar, left of the stats): page and server state, its own tick and poll, error boundary
  debug-panel-state.ts     pure helpers of DebugPanel: formatting, server clock, poller, issues, session grouping, poll samples
  PluginsConfig.tsx        Settings › Plugins: installed package plugins
  SkillsConfig.tsx         Settings › Skills: loaded, search, install
  McpConfig.tsx            Settings › MCP: servers, switches, exposure, remove/undo, Test, sign-in, Code mode, trust
  mcp-config-helpers.ts    pure helpers and requests for McpConfig
  McpSignIn.tsx            a server's Sign-in row in Settings › MCP
  mcp-sign-in-helpers.ts   pure helpers and requests for McpSignIn
  McpAddServer.tsx         Settings › MCP add pane: paste, preview, values, name, scope
  mcp-add-helpers.ts       pure helpers and the add request for McpAddServer
  FileExplorer.tsx         file tree in the sidebar
  FileIcons.tsx            file icon helpers
  FileViewer.tsx           file content in a tab
  DelimitedTable.tsx       a CSV/TSV file's Preview: virtualized table, gutter of file lines
  TabBar.tsx               file panel tab bar (file, terminal and subagent tabs)
  TranscriptNotices.tsx    a message's cache and cost notice lines, the fold header's cache-miss text

hooks/
  useAgentSession.ts       messages, streaming, SSE, fork/navigate, reconciliation; built-in slash commands (/session, bare /mcp)
  useStreamingSelector.ts  one value of the streaming store (lib/streaming-message.ts): a chunk re-renders only its subscribers
  useAudio.ts              completion sound + AudioContext unlock
  useDragDrop.ts           chat drop zone: dropped files, folders marked
  useFilesPlacement.ts     per-browser choice: the desktop sidebar's file browser below the sessions or in its own tab
  useGroupDrag.ts          dragging a sidebar project group: mouse threshold, touch/pen long-press, auto-scroll, drop
  useIsMobile.ts           responsive breakpoint
  usePageHidden.ts         HIDDEN_PAGE_GRACE_MS; true once the page has been hidden that long (file watches pause)
  useSessionUiState.ts     sidebar pins, archive, project order: optimistic writes in order, refetch on revision change
  useSidebarMotion.ts      the sidebar's fold and archive-view motion: phase, end fallback, reduced motion, what shows meanwhile
  useKeyboardShortcuts.ts  Esc stops the running agent unless a field or nearer handler took it; Ctrl+Alt+N
  useResizablePanel.ts     drag/keyboard panel size kept per key; persistClamp: false never saves a short window's clamp
  usePrismLanguages.ts     true once the Prism languages are loaded; starts the load for a highlighter
  useTheme.ts              theme state
  useTerminalTheme.ts      the terminal's own dark/light choice (localStorage), apart from the app theme

Topic Notes

Design decisions and traps live in docs/agents/, one note per area. Read every note whose files a change touches before making it. Add new notes to the area's file, not here.

  • sessions.md: AgentSession lifecycle and shutdown, fork vs in-session branching, the sidebar's on-disk Fork, session file rewrites, toolCall normalization, a run's message keys across the file read, SSE reconnect and tool events, a tool card's flat arguments as rows, transcript system / usage / context-edit entries, running-state polling, custom-message collapsing, streamed chunks re-rendering only the reply, streaming markdown block by block, hand-written anchors in rendered Markdown landing after the sanitizer's id prefix, Windows drive-letter Markdown links becoming file:/// before sanitizing, user messages' raw HTML shown as text, ```svg fences previewed only as an <img>, display math's Copy button, long thinking rendered in pieces, a finished turn's duration, history caches (tool-result images, subagent runs, session views) and deferred code highlighting with Prism languages loaded on demand, a patch shown in one column or two, the session sidebar (toolbar row and its brand, project groups, their order and display names, pins, archive, new-session project adoption, the files below the sessions or in a tab), the project/worktree bar above a fresh composer (the header: brand, then the bar) and what it carries across the remount, exported HTML, the extension status bar and its command: buttons, cache and cost notices (showCacheMissNotices), the read-only Debug panel (connections, server state, sessions the server holds). Files: lib/rpc-manager.ts, lib/session-reader.ts, lib/session-fork*.ts, lib/session-delete.ts, lib/normalize.ts, lib/message-keys.ts, lib/session-tree.ts, lib/session-ui-state*.ts, lib/sidebar-prefs.ts, lib/sidebar-actions.ts, lib/session-links.ts, lib/new-session-context.ts, hooks/useAgentSession.ts, hooks/useSessionUiState.ts, hooks/useSidebarMotion.ts, hooks/useGroupDrag.ts, hooks/useFilesPlacement.ts, hooks/useResizablePanel.ts, app/api/agent/**, app/api/sessions/**, components/SessionSidebar.tsx, components/PiWebTitle.tsx, components/SessionTree.tsx, components/SidebarMenu.tsx, components/SidebarToast.tsx, components/SidebarIcons.tsx, components/ProjectWorktreePicker.tsx, components/NewSessionContextBar.tsx, components/WorktreeCreateForm.tsx, handleNewSession, handleSelectSession and the bar's handlers in components/AppShell.tsx, components/BranchNavigator.tsx, components/MessageView.tsx, lib/message-display.ts, lib/patch.ts, components/FileViewer.tsx, components/MarkdownBody.tsx, lib/markdown.ts, lib/markdown-blocks.ts, lib/streaming-message.ts, hooks/useStreamingSelector.ts, lib/turn-duration.ts, components/MermaidBlock.tsx, components/SvgBlock.tsx, lib/highlight-queue.ts, lib/prism-languages.ts, hooks/usePrismLanguages.ts, lib/session-view-cache.ts, components/CodemodeToolView.tsx, components/ExtensionStatusBar.tsx, components/ExtensionWidgets.tsx, lib/transcript-notices*.ts, components/TranscriptNotices.tsx, app/api/cache-miss-notices/**, lib/tool-fields.ts, lib/debug-*.ts, lib/stream-client.ts, lib/page-stream-registry.ts, lib/page-debug.ts, lib/file-watch-registry.ts, components/DebugPanel.tsx, components/debug-panel-state.ts.
  • tools.md: tool presets and Chat only, exact system prompts, tool exposure, the codemode / tool-search / mcp built-ins, the read-only MCP policy, the Code mode and PowerShell defaultTools switches. Files: lib/tool-presets.ts, lib/tool-preset-preference.ts, lib/chat-only.ts, lib/exact-system-prompt.ts, lib/builtin-extensions.ts, lib/mcp-read-only-policy.ts, lib/codemode-settings.ts, lib/powershell-settings.ts, lib/global-settings-file.ts, app/api/agent/new/route.ts, app/api/tools/settings/route.ts, tool selection in lib/rpc-manager.ts.
  • mcp-runtime.md: the per-session MCP host (when servers register and connect, reported states, trust read on every sync, idle release); /mcp in the composer. Files: lib/mcp-host.ts, lib/mcp-transport.ts, lib/mcp-status.ts, lib/mcp-command.ts, lib/mcp-config-key.ts, MCP wiring in lib/rpc-manager.ts and lib/builtin-extensions.ts, /mcp handling in hooks/useAgentSession.ts.
  • mcp-settings.md: Settings › MCP reads without running anything, masking, the trust dialog's server list, row states, notices, Code mode choice, trust from Settings, Escape stacking, every mcp.json write and undo. Files: app/api/mcp/route.ts, app/api/project-trust/route.ts, lib/mcp-config-read.ts, lib/mcp-config-file.ts, lib/mcp-override.ts, lib/mcp-undo.ts, lib/mcp-secrets.ts, lib/mcp-server-display.ts, lib/mcp-json-error.ts, lib/project-trust.ts, lib/regular-file.ts, lib/stacked-dialog.ts, lib/settings-navigation.ts, components/McpConfig.tsx, components/mcp-config-helpers.ts, components/ProjectTrustDialog.tsx, components/SettingsPanel.tsx.
  • mcp-test-sign-in.md: Settings › MCP Test (route checks, bounded connection, !command queue, redaction, status store) and OAuth sign-in / sign-out. Files: app/api/mcp/test/**, app/api/mcp/sign-in/**, lib/mcp-test.ts, lib/mcp-entry-request.ts, lib/mcp-status.ts, lib/mcp-sign-in.ts, lib/mcp-sign-out.ts, components/McpSignIn.tsx, components/mcp-sign-in-helpers.ts, components/OAuthPastePanel.tsx.
  • mcp-add.md: Settings › MCP add (paste re-parsed on the server, host-variable confirmation, literal secrets kept global, fresh-folder trust, the add pane) and the paste importer's escaping and grammars. Files: lib/mcp-add.ts, lib/mcp-import*.ts, lib/shell-words.ts, fresh-folder trust in lib/project-trust.ts, components/McpAddServer.tsx, components/mcp-add-helpers.ts, the add action of app/api/mcp/route.ts.
  • models.md: default model and reasoning level, providers registered at session_start, mid-run reasoning changes, remote provider catalogs, enabledModels scoping and minimal edits, managed models' context-window overrides, provider auth listing and credentials, the extension-loaded runtime those routes share. Files: app/api/models/**, app/api/models-config/**, app/api/auth/**, lib/model-runtime.ts, lib/default-preferences.ts, lib/model-scope.ts, lib/enabled-models*.ts, lib/model-context.ts, lib/model-image-limits.ts, lib/model-provider-check.ts, lib/model-catalog-refresh.ts, lib/deferred-provider-models.ts, lib/provider-listing*.ts, components/ModelsConfig.tsx, components/EnabledModelsSection.tsx, components/ModelContextWindow.tsx, components/ModelSelector.tsx, components/SelectorRow.tsx.
  • files-and-access.md: worktrees and project grouping, the file access allow-list (the /api/files security boundary), file tree visibility and its open directories per folder, uploads and chat file drops, the source view's languages by extension, the CSV/TSV table view, web password throttling. Files: app/api/files/**, app/api/cwd/**, app/api/worktrees/**, app/api/file-index/**, app/api/web-auth/**, proxy.ts, lib/path-security.ts, lib/file-access.ts, lib/linked-directory.ts, lib/session-file-references*.ts, lib/file-tree-visibility.ts, lib/file-tree-expansion.ts, lib/file-upload-client.ts, lib/file-version.ts, lib/worktree.ts, lib/paths.ts, lib/auth-throttle.ts, components/ProjectWorktreePicker.tsx, components/NewSessionContextBar.tsx, components/FileExplorer.tsx, lib/delimited-table.ts, components/DelimitedTable.tsx, the table branch of components/FileViewer.tsx, hooks/useDragDrop.ts.
  • settings-ui.md: General's sidebar file-browser choice, Plugins and Skills routes, sidebar group switches, the shared SettingsUi blocks every settings panel and add pane uses. Files: app/api/plugins/**, app/api/skills/**, lib/skills-service.ts, components/SettingsUi.tsx, components/settings-ui-helpers.ts, components/SkillsConfig.tsx, components/PluginsConfig.tsx, hooks/useFilesPlacement.ts; also before adding a settings section or add pane.
  • subagents.md: the built-in subagent setting, profiles and their files, run status, completion notifications, the subagent viewer tab. Files: lib/subagent*.ts, app/api/subagents/**, components/AgentsConfig.tsx, components/SubagentViewer.tsx, components/subagent-viewer-state.ts.
  • client-platform.md: the global shortcuts (Ctrl+Alt+N on macOS's dead-key Option+N and Windows AltGr, Esc stacking), mobile software keyboard and viewport height, the terminal's extra keys, its own dark/light theme and its font size following the chat's, completion sound, the launcher opening the browser only after the first page is served. Files: hooks/useKeyboardShortcuts.ts, hooks/useViewportHeight.ts, hooks/useAudio.ts, components/TerminalExtraKeys.tsx, lib/terminal-extra-keys.ts, lib/terminal-theme.ts, hooks/useTerminalTheme.ts, terminalFontSize() in hooks/useChatAppearance.ts, the keyboard-open CSS, bin/browser-opener.js, the browser opening in bin/pi-web.js.

Old Safari (iOS 16.2)

  • / renders entirely on the client, so one script chunk the browser cannot parse is a blank page. Next 16 targets Safari 16.4+; the browserslist in package.json lowers Safari and iOS to 16.2 so SWC turns class static {} blocks into private static fields. That covers Next's client runtime; other node_modules keep their syntax unless listed in transpilePackages (mermaid and @mermaid-js/parser are, for their lazy diagram chunks). Keep the other browserslist entries at Next's defaults.
  • Never write a RegExp lookbehind ((?<=, (?<!) in client code: SWC cannot downlevel it and Safari parses it only from 16.4. lib/markdown.ts emulates its leading lookbehinds with replaceNotPrecededBy(). A lookbehind built at runtime (new RegExp("(?<=…)") in try) fails only when run; that is how lib/gfm-autolink-email-loader.cjs fixes mdast-util-gfm-autolink-literal's email regex. The loader is registered for webpack and Turbopack in next.config.ts and fails the build if that regex changes upstream.

Pi Session File Format

Location: ~/.pi/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl

{"type":"session","version":3,"id":"<uuid>","timestamp":"...","cwd":"/path","parentSession":"/abs/path/to/parent.jsonl"}
{"type":"model_change","id":"<8hex>","parentId":null,"provider":"zenmux","modelId":"claude-sonnet-4-6","timestamp":"..."}
{"type":"message","id":"<8hex>","parentId":"<8hex>","message":{"role":"user","content":"..."}}
{"type":"message","id":"<8hex>","parentId":"<8hex>","message":{"role":"assistant","content":[...],...}}
{"type":"message","id":"<8hex>","parentId":"<8hex>","message":{"role":"toolResult","toolCallId":"...","content":[...]}}
{"type":"compaction","id":"<8hex>","parentId":"<8hex>","summary":"...","firstKeptEntryId":"<8hex>","tokensBefore":N}
{"type":"session_info","id":"...","parentId":"...","name":"user-defined name"}

SessionContext.entryIds[] parallels messages[]: each displayed message's .jsonl entry id, used for fork and navigate_tree.

CSS Variables (app/globals.css)

--bg --bg-panel --bg-hover --bg-selected --border
--text --text-muted --text-dim
--accent --user-bg --tool-bg
--font-mono

Download now (ZIP)

Trending

More talk lately.about the whole repository

Dec 2025: 0 mentionsJan 2026: 0 mentionsFeb 2026: 0 mentionsMar 2026: 0 mentionsApr 2026: 0 mentionsMay 2026: 0 mentionsJun 2026: 1 mentionJul 2026: 4 mentionsAug 2026: 3 mentionsSep 2026: 6 mentionsOct 2026: 7 mentionsNov 2026: 0 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the agegr/pi-web repository that our weekly crawl found. There is no adoption data for this file yet.

Who's talking about agegr/pi-web

The biggest 5 of 21 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 21

Talked about on GitHub and Bluesky (21 times).

On GitHub · 17

12 more on GitHub

On Bluesky · 4

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.