phi

pulseaiclubMIT活跃维护

用 Go 写的终端编码 Agent,支持 RPC 插件、子 Agent 和 MCP 协议,能在命令行里快速完成代码修改与任务编排。

A fast coding agent, rpc plugin, sub-agents, sloppy edits, and mcp

v0.29.8发布于 2026-11-09 06:15 UTC1,002star +69 / 7 天42fork同步于 2026-11-10 23:52 UTC

怎么上手

由 README 提炼,执行前请确认
curl -fsSL https://raw.githubusercontent.com/pulseaiclub/phi/main/scripts/install.sh | bash
phi config
phi
硬件要求按 README 说明

README 未说明显存或 GPU 要求;发布二进制约 15 MB,仅链接系统库,不依赖 Node/Electron/Python,macOS arm64 有实测数据。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

轻量快速的终端编码 agent,自带子代理、diff 审阅和 MCP 扩展

用 Go 写的终端编码 Agent,支持 RPC 插件、子 Agent 和 MCP 协议,能在命令行里快速完成代码修改与任务编排。

核心能力

  • 用子代理拆分 explore/review/worker 角色并行干活
  • 锚定式 sloppy edits 让模型改代码更省 token
  • 内置全屏 git diff 审阅,可留行内批注交回 agent
  • 渐进式 MCP 加载,按需接入外部工具
  • 权限门控支持 interactive/readonly/autopilot 等模式

容易踩的坑

首次启动必须先在 ~/.phi/config.yaml 配好模型和 api_key,否则无法使用;搜索工具 fd、rg 缺失时会在后台下载到 ~/.phi/bin;从源码构建需要 Go 1.26.3+。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.29.8
  1. v0.29.8最新正式版2026-11-09 · 2026-11-09 06:15 UTC

    Removed

    • Tool-round budgets: the loop no longer caps tool rounds. Removed max_rounds from config.yaml, the --max-rounds flag and exit code 2 from phi run, the "max rounds" palette entry, the config-UI field, and ErrMaxRounds itself. Headless runs now exit 1 on any loop error.
    • Extensions: removed the turn_stopping hook and the InterceptResp.Continue wire field (PXB tag 12) across the Go host and the Go / Rust / TS SDKs (OnTurnStopping / on_turn_stopping / onTurnStopping). Wire event code 14 is retired; a tool_result handler returning Stop remains the way to end the loop early.

    Changed

    • /new now lists before /sessions in the slash command menu, so the frequent "fresh session" action comes first.
    • Skills picker moved from the Ctrl+K command palette to a /skill slash command. Typing /skill opens a filterable list overlay (same picker as /sessions and /branch); accepting a row attaches the skill to the next turn. The skill no longer appears in the palette root, the list drops the blank leading column, and long descriptions elide with … instead of a hard cut.

    Added

    • TUI: /fork copies the current session's branch into a new session (new id, source recorded as parent) with the same compaction context and switches to it; the source file is never touched and stays in /sessions. Forking is refused while a reply or command is running, and extra arguments report usage. Session listings show the fork's source as ↳ <id>. phi sessions fork <id> does the same headlessly and prints the new id.

    Fixed

    • Resuming a session sends session_shutdown to the outgoing extensions before replacing their processes, instead of notifying the newly loaded instances.
    • Sessions with image or tool entries larger than 8 MiB can be forked, resumed, and listed without hitting a per-line read limit. Failed fork reloads remove the unused copy and report cleanup errors.
    • Child agents no longer overwrite shared extension host session metadata or the parent engine's built-in tool list.
    • Extension confirmation dialogs restore the prior activity, so idle slash commands remain idle after confirmation and expired cancellation statuses do not reappear.

    Security

  2. v0.29.72026-11-05 · 2026-11-05 09:07 UTC
    查看更新说明

    Removed

    Changed

    • Splash sphere gradient now follows the active theme (brand identity color), so a theme switch repaints the hero. The Dark theme keeps its curated teal.
    • Dark theme: composer and panel borders brightened (ANSI 244 → 250) so the box edge reads solid instead of a faint hairline on dark backgrounds.
    • Agent/model loop errors now open a modal error dialog (Retry / Copy to Clipboard / Dismiss) instead of appending a red "Error:" block to the transcript. Retry resumes the failed turn without duplicating the user message; Esc dismisses. Manual cancellation does not open an error dialog, and interrupted streams release the composer. Error actions stay visible when long messages must be clipped to fit the terminal.

    Added

    • phi config: model entries now expose max_tokens, including preset defaults and editable overrides.

    Fixed

    • Cancelling an agent response with Esc after partial thinking or text no longer panics when the provider reports an error during cancellation. Cleanup events from compaction and tool batches also stop reaching an exited consumer.

    Security

  3. v0.29.62026-11-04 · 2026-11-04 02:56 UTC
    查看更新说明

    Removed

    • TUI: removed the live sub-agent job count from the bottom footer.
    • CLI: dropped phi tui (pure alias of phi), the PHI_OFFLINE env var (self-documented duplicate of PHI_SKIP_VERSION_CHECK), and the duplicate phi sessions list binding (phi sessions already lists).

    Changed

    • Permissions: permissions.mode: allow-all replaces the boolean dangerously_allow_all; the old key still loads as allow-all and is dropped on the next save. phi run --yolo maps to the same mode. The TUI approval dialog's "Allow All for Every Session" now writes permissions.mode instead of hand-editing one YAML line.

    Added

    • TUI: The model picker shows Ctrl+S once in the bottom border. Press it, then Y/Enter to apply the highlighted model and save it as the global default; N/Esc cancels in place, like the sessions picker's delete confirmation. Enter outside confirmation switches only the current session.

    Fixed

    • TUI: A finished model-list fetch stays pending until the config editor applies it, so pressing f again reports "already fetching models…" instead of starting a second request that overwrites the first result.
    • MCP: read mcp://<server>/tools/<tool> now includes enum values in the compact parameter summary (env:s{dev|prod}), so the model sees the valid choices instead of guessing a value the server rejects. Long enums cap at 8 values with a +N tail.
    • TUI: Persist the selected model with each session. Resuming restores that session's model, while new sessions inherit the most recently selected one. Model changes are append-only records; forks inherit the model on their selected branch without rewriting existing conversation logs. Startup uses the configured default without scanning past sessions.
  4. v0.29.52026-11-02 · 2026-11-02 01:52 UTC
    查看更新说明

    Added

    • Shell: !!cmd runs the command locally like !cmd but also adds its output to the model context for the next turn. The transcript row is marked · ctx; a resumed session keeps the row instead of replaying it as a user message.
    • TUI: /branch <name> <base> creates and switches to a new branch off <base> (local or remote-tracking; a short base name resolves to origin/<base> when only the remote side has it). An unknown base refuses instead of silently branching off HEAD.

    Fixed

    • MCP: Keep full tool descriptions when inspecting tools.

    Security

    • Archive extraction: phi plugin install / update, self-update, and tool downloads unpack release archives with in-process Go readers that validate every entry path before writing. Parent-directory elements (../, ..\), absolute paths, and paths escaping the extract directory are rejected (Zip Slip, CWE-22), and zip symlink entries are refused. Extraction no longer shells out to tar / PowerShell Expand-Archive, which trusted archive paths as-is.
  5. v0.29.42026-10-30 · 2026-10-30 08:58 UTC
    查看更新说明

    Added

    Fixed

    • TUI: long bash commands now wrap in full, with continuation lines aligned to the command. Wrapping follows the available width only, so command chains are no longer split after &&, || and pipes — that broke arguments mid-token and misread quoted or substituted shell constructs. Sub-agent commands keep their tree guide and use readable foreground text.
    • Sub-agent tool guidance now recommends waiting with only job_id, which waits until completion and returns as soon as the result is ready, to avoid repeated short waits caused by guessing task durations.
    • Terminal: upgrade xui to v0.1.9 to correctly detect synchronized output, preventing input cursor flicker during animated redraws on supported terminals.
    • Models: IDs that pin a build with a four-digit suffix, such as deepseek-v4.1-flash-1017, now match their preset instead of falling back to generic defaults (no thinking, no context window, the default output limit).

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译
    • 15 MB · ~31 ms · sub-agents · anchored sloppy edits · permission gate · progressive MCP · PXB extensions · native diff review & code selection · OpenAI / Anthropic / Gemini

    phi welcome

    phi TUI

    phi diff review

    Sponsors

    Quick start

    Install the latest release (macOS / Linux):

    curl -fsSL https://raw.githubusercontent.com/pulseaiclub/phi/main/scripts/install.sh | bash
    

    Windows (PowerShell 5.1+):

    irm https://raw.githubusercontent.com/pulseaiclub/phi/main/scripts/install.ps1 | iex
    

    First launch needs a model. Open the config editor (creates ~/.phi layout and writes ~/.phi/config.yaml):

    phi config
    

    Or set env vars for a one-off run:

    export PHI_MODEL=gpt-4o
    export PHI_API_KEY=sk-...
    

    Then start the TUI:

    phi
    

    Or build from source (Go 1.26.3+, see go.mod):

    make build          # produces ./phi
    make install        # build and install into $GOBIN
    

    On first start, phi automatically creates ~/.phi/{bin,skills,hooks,session}. Search tools (fd, rg) download into ~/.phi/bin in the background when missing.

    The TUI gives the model four core tools — read, write, edit, and bash — plus grep, find, and ls. The model uses these to fulfill your requests. External HTTP fetch is available via MCP when configured.

    Footprint

    Lean is not enough — phi is built to feel instant and stay cheap under load. phi numbers are a stripped release build (CGO_ENABLED=0, -ldflags="-s -w") on macOS arm64. Other harnesses use published Linux PSS / interactive PTY figures.

    Time to first frame

    Idle RAM · 1 session

    Idle RAM · 10 sessions

    Metricphi
    Release binary~15 MB
    Idle RSS (1 session)~21 MB
    10 idle sessions (total RSS)~221 MB
    Time to first frame~31 ms (26–49 ms)
    Cold go build (empty GOCACHE)~5.5 s
    Warm rebuild~0.7 s
    Go source (excl. tests)~22k LOC / 107 files
    Go packages32
    Direct module deps6 (15 modules total)
    Linked runtimessystem libs only (no Node / Electron / Python)

    Configuration

    phi reads ~/.phi/config.yaml (standard YAML). Environment variables override it for one-off runs. phi config opens a full-screen terminal editor for the same file — nothing is written until you save, and the previous file is kept as config.yaml.bak.

    phi config keys
      ↑↓ ←→      move / cycle a value        a   add a model
      ⏎          edit or open a picker       d   delete the focused row
      esc        close, or quit              f   fetch model ids from the provider
      ^s         save                        s   save        q  quit
    

    An empty field means "not set", i.e. the value the loader would fill in; the placeholder shows that value.

    # ~/.phi/config.yaml
    models:
      - name: gpt-4o
        api: OpenAI             # OpenAI | OpenAIResponses | Anthropic | Gemini (empty → OpenAI-compatible)
        api_key: sk-...         # or set PHI_API_KEY
        base_url: https://api.openai.com/v1   # default; PHI_BASE_URL overrides
        context_window: 128000  # optional
        default: true           # the model used at startup; first entry wins if absent
      - name: claude-sonnet-4-20250514
        api: Anthropic          # required — no name/URL guessing
        api_key: sk-ant-...
        base_url: https://api.anthropic.com
        context_window: 200000
      - name: deepseek-flash    # built-in preset: base_url / context / thinking filled in
        api_key: sk-...
      - name: gemini-2.5-flash  # built-in preset (api: Gemini)
        api_key: ...
        think_level: high       # optional: off | minimal | low | medium | high | …
    
    skill_path: ~/.phi/skills # where SKILL.md files are loaded from; "~/…" is expanded
    max_rounds: 64            # tool round budget; 0 → engine default (64)
    
    agents:
      enabled: true           # default; set false to disable agent_* sub-agent tools
      models:                 # optional per-role defaults; omit → inherit parent model
        explore: cheap-model
        review: strong-model
        worker: coding-model
    
    permissions:
      mode: interactive       # interactive | readonly | autopilot | headless-strict | allow-all
      bash:
        default: ask          # ask | allow | deny
        allow:
          - "go test ./..."
        deny:
          - "rm -rf *"
      rules:                  # extra rules; deny > ask > allow, always
        - kind: read
          resource: url
          decision: ask
          reason: external lookup needs approval
    

    Built-in presets and thinking wire formats: doc/models.md.

    Environment overrides:

    VariableOverrides
    PHI_API_KEYmodels[].api_key (default model)
    PHI_MODELmodels[].name (default model)
    PHI_BASE_URLmodels[].base_url (default model)
    PHI_SKILL_PATHskill_path
    PHI_THINK_LEVELmodels[].think_level (default model; off disables)
    PHI_PROMPT_HISTORYComposer prompt recall (on enables; off by default, writes prompts.json in the project's session directory)

    Provider routing uses the explicit api field (OpenAI / Anthropic / Gemini). See Supported models.

    Workspace layout

    ~/.phi/
    ├── config.yaml   # global configuration
    ├── bin/          # downloaded search tools (fd, ripgrep)
    ├── skills/       # SKILL.md skill directories
    ├── extensions/   # PXB binaries + phi.yaml
    ├── jobs/         # sub-agent job artifacts (meta, logs, result.md)
    └── session/      # persisted sessions, one dir per working directory
        └── <encoded-cwd>/
    

    Interactive mode

    phi starts the TUI: a chat transcript on top, an editor at the bottom, and a footer with the current activity. When a newer release is available, the footer shows a hint like 0.2.0 available · phi update.

    Assistant output is rendered as Markdown (CommonMark/GFM): headings, emphasis, strikethrough, links, blockquotes, lists, task checkboxes, and tables are styled with the active theme; fenced code blocks get a muted language caption and per-language syntax highlighting. Structural markers (#, `, *) are stripped.

    The editor supports:

    • @ — fuzzy file mention picker (type @ and start typing a path)
    • / — slash command picker (/sessions, /branch, /skill, /new, /diff, /code)
    • ? — shortcut help picker (lists /, !, @, and key bindings; Esc closes)
    • !command — run a shell command locally and stream its output into the transcript (see Commands)
    • Ctrl+K — command palette: settings → model / theme / permissions / agents (incl. per-role models), hooks

    Keyboard shortcuts

    KeyAction
    Ctrl+CQuit phi
    EscCancel the running agent / close pickers
    Ctrl+KToggle the command palette
    Ctrl+AJump to the start of the line
    Ctrl+EJump to the end of the line
    Ctrl+UClear the composer input, images, and skills
    Ctrl+Shift+CCopy the selected transcript text

    Themes: Dark (default), Darcula, Pink, and Terminal, switchable from the palette under settings → theme.

    Diff review

    /diff is a full-screen git review inside the TUI — read the change, leave line notes, then hand them to the agent without leaving the terminal.

    CommandWhat opens
    /diffWorking tree (git diff)
    /diff stagedStaged changes
    /diff HEADLast commit (git show)
    /diff @pathOnly that file — @ comes from file completion, the -- separator is added for you
    /diff staged @a.go @b.goStaged changes in two files
    /diff HEAD @pathThat file against HEAD
    /diff main..feat @pathThat file across a range

    /diff -- <argv> runs the given git command instead of a diff — /diff -- git show HEAD~1 for one.

    Slash-picker Enter inserts /diff plus a trailing space into the composer; submit to open. Inside the overlay: s side-by-side, i add/edit a note, x delete, a send notes to the agent, ? help, q / Esc close. Notes live in the overlay's memory only — switching diffs drops them and nothing is written to disk.

    Code viewer

    /code <path>[:line] opens a full-screen source viewer: syntax highlighting, a CJK-aware caret (j/k, h/l, gg/G), in-file search (/, then n/N), :line to jump to a line, and v for lines or p for the paragraph under the caret, then a to hand the selection to the chat input as a path:12-18 reference the model reads. The pane reads files itself and answers to the same deny list as the tool gate, so sensitive paths (~/.ssh, .env, …), binaries and files over 8 MiB are refused with a toast.

    Esc closes, or cancels a search back to where / was pressed. The status row shows the path, caret and line count while reading, the selection size while v is active, and the match counter (2/5) while a search is live.

    Branch switching

    /branch opens the branch picker for the working directory. Two columns: the branch name, and its most recent commit. A ● marks the branch HEAD is on. Rows are ordered where you are, where you came from (git reflog), the other local branches, then remote-tracking branches.

    Enter runs git switch on the selected row — off the UI goroutine, so a slow checkout does not freeze the composer. Picking a remote row checks out the local branch that tracks it, the same thing git switch feat does for origin/feat.

    /branch <name> skips the picker: it switches to that branch, or creates it from HEAD when no branch carries the name yet. Naming is the whole "new branch" flow — three characters typed beat a form.

    Uncommitted work is never touched: git refuses rather than lose it, and its reason is toasted verbatim. Switching is blocked while a reply or command is running, and while a merge, rebase, cherry-pick, revert, or bisect is unfinished.

    Commands

    CommandDescription
    phiStart the interactive TUI
    phi run -p "…"Run one agent loop headlessly (see below)
    phi updateDownload and install the latest GitHub release
    phi update --checkQuery the latest release without installing
    phi sessionsList persisted sessions for this directory
    /sessionsList sessions for this directory (TUI)
    /branchSwitch the working branch — see Branch switching
    /newStart a fresh empty session (TUI)
    /diffFull-screen git review — see Diff review
    /codeFull-screen source viewer — see Code viewer
    !commandRun a shell command locally, stream output into the transcript; Esc cancels it

    In the TUI, !command runs locally via bash -c — outside the agent loop. It doesn't count toward agent busy state, and the running command can be cancelled with Esc without touching an in-flight agent turn.

    Sessions

    Sessions persist automatically per working directory under ~/.phi/session/<encoded-cwd>/ as JSONL trajectories.

    • phi sessions — list session id, mtime, and preview for the current directory
    • /sessions in the TUI — same, in-app
    • /new — start a fresh session (new id, empty transcript)
    • phi run --session <id> / phi run --continue-last — resume headlessly

    Headless mode

    phi run -p "fix the failing test in internal/tools"
    

    Runs one agent loop without a TUI. Human logs go to stderr; with --jsonl, machine-readable events go to stdout, one JSON object per line.

    Flags:

    FlagDescription
    -p, --prompt STRINGPrompt to run (required)
    --jsonlEmit JSONL events to stdout
    --yoloSkip all permission checks for this run (benchmarks / CI only)
    --max-rounds NCap tool rounds (default 64)
    --timeout DURATIONLimit the agent run wall-clock time (e.g. 10m; disabled by default)
    --session IDResume a persisted session by id or unique prefix
    --continue-lastResume the newest persisted session for this directory
    --session-dir DIROverride the session storage directory
    --tools LISTEnable only these comma-separated built-in tools

    --tools accepts built-in names such as read,ls,grep. MCP and agent tools still append when configured; the flag only scopes the built-in toolset.

    Exit codes: 0 success · 1 runtime/LLM error · 2 max rounds reached · 3 config/usage error.

    Exhausting the tool-round budget stops the run with exit code 2, both in the interactive TUI and in headless phi run.

    In headless mode, permission ask decisions are denied (there is no approval UI), so readonly-style safety applies without extra flags. For benchmarks that need arbitrary shell (pytest, npm test, …), pass --yolo to skip the permission gate for that run only.

    Skills

    Skills are directories containing a SKILL.md file with YAML frontmatter and a Markdown body. They are loaded from ~/.phi/skills/ (or skill_path / PHI_SKILL_PATH) and injected into the agent's context, letting you give the model reusable procedures:

    The Agent Skills locations ~/.agents/skills/ and .agents/skills/ are read too, so a skill pack installed for another agent works here without configuration. Project .agents/skills/ directories are discovered from the working directory upward, stopping at the repository root when there is one. Roots are searched in order — skill_path first, then ~/.agents/skills, then the project directories — and the first root wins when two of them define the same skill name. A leading ~ in skill_path or PHI_SKILL_PATH expands to your home directory.

    Security: skill files are workspace content, not trusted input — a project .agents/skills/ is picked up without confirmation. Review skills the way you review AGENTS.md before trusting a checkout.

    ---
    name: My Skill
     description: What this skill does
    license: MIT
    compatibility: claude, openai
    disable-model-invocation: false
    ---
    Instructions the agent should follow when this skill is relevant.
    

    disable-model-invocation: true keeps a skill out of the system prompt catalog — good for the ones you only want on explicit request. It stays in the /skill list and is still applied when you pick it there. Only a case-insensitive true counts; any other value means false. This is a catalog filter, not access control: the model can still find the file with ls / find.

    In the TUI, type /skill and pick a row from the list, then submit the message with the selected skills applied.

    Permissions

    Tool execution is gated by a permission policy, so the agent can run read-only by default and ask before anything destructive. Configure it under permissions: in ~/.phi/config.yaml.

    Modes:

    ModeBehavior
    interactiveDefault. ask decisions prompt in the TUI.
    readonlyDeny writes / bash; read tools still work.
    autopilotFold ask → allow, run unattended.
    headless-strictFold ask → deny (used by phi run).
    allow-allSkip every permission check.

    Per-tool rules: bash.default / bash.allow / bash.deny (regexes against the command). permissions.rules adds your own rules by tool, kind, command, path, or workspace scope; they are evaluated strictest-first (deny > ask > allow), so a rule can tighten a policy but never loosen one. Global keys: workspace_only_writes (default true) and ask_timeout_sec. The deprecated dangerously_allow_all: true still loads as mode: allow-all. Full semantics and examples: doc/permissions.md.

    In the TUI, an approval dialog replaces the editor with options to approve, deny with feedback, or allow all for the session / for every session. The palette's settings → permissions entry toggles session-wide bypass.

    Extensions

    Extensions are native binaries speaking the PXB binary protocol over stdin/stdout (author SDKs: Go github.com/pulseaiclub/phi/ext/go/phi, Rust ext/rust (phi-ext), and TypeScript ext/ts (@pulseaiclub/phi-ext)). They subscribe to tool/session events, register LLM tools, and add slash commands.

    go get github.com/pulseaiclub/phi/ext/[email protected]
    
    package main
    
    import (
    	"github.com/pulseaiclub/phi/ext/go"
    	"github.com/pulseaiclub/phi/ext/go/phi"
    )
    
    func main() {
    	m := phi.New("hello", "0.1.0")
    	m.OnToolCall(func(ev ext.ToolCallEvent) *ext.ToolCallResult {
    		// return &ext.ToolCallResult{Block: true, Reason: "..."}
    		return nil
    	})
    	_ = m.Run()
    }
    

    Install under ~/.phi/extensions/<name>/ with a phi.yaml pointing at the binary. In the TUI: Ctrl+K → extensions. Disable with PHI_EXTENSIONS=off. Full guide: doc/extensions.md.

    Codec throughput on Apple Silicon (release, single-threaded):

    ImplementationHello encode+decodeFrame write+read (in-memory)Allocs
    Rust PXB (phi-ext)~0.12 µs~0.06 µs—
    Go PXB (ext/go/pxb)~0.11 µs~0.05 µs3 / op
    Go JSON lines~1.2 µs—15 / op

    The ~10× gap over JSON lines is the protocol (fixed header + tagged fields), not the language — Rust and Go are within noise on the same codec work. Real extension latency is dominated by process spawn and pipe RTT anyway. Re-probe: cargo run --release --example bench in ext/rust.

    MCP

    Configure 100 MCP servers. Pay ~0 schema tokens until you call one.

    Most MCP hosts dump every tools/list schema into the model context before you ask a question — browser stacks alone can burn 50k+ tokens. phi does not.

    Instead MCP is a URL namespace on the regular tools, and the system prompt lists configured server names (no schemas):

    ActionCall
    List tools on a serverls mcp://<server>/tools/
    Fetch a slim parameter summaryread mcp://<server>/tools/<tool>
    Invokewrite mcp://<server>/tools/<tool> with content = JSON args

    Flow: pick a server from the prompt → ls → read → write. Subprocesses start lazily on first use. Browsing is read-tier; invokes still go through PreHooks → write Gate / Ask → Run → PostHooks.

    phi mcp add browsermcp -- npx @browsermcp/mcp@latest
    phi mcp doctor
    # In the TUI, the model can use configured servers without guessing MCP exists
    

    Config: ~/.phi/mcp.json (project <cwd>/.phi/mcp.json overrides by name). Disable with PHI_MCP=off. Stdio and HTTP in v1.

    Full guide: doc/mcp.md.

    Sub-agents

    Sub-agent tools (agent_spawn, agent_wait, …) are on by default. To keep a session lean, disable them in ~/.phi/config.yaml:

    agents:
      enabled: false
    

    Or toggle for the current session via the palette: settings → agents. When disabled, those tools are not registered and the model cannot spawn jobs.

    Per-role model defaults (optional) under agents.models pick which configured model name each role uses when spawned. Omitted roles inherit the parent session model. Switch for the current session only via settings → agents → models → explore|review|worker (same session-only semantics as Enter in settings → model; does not write config.yaml). In the model picker, Ctrl+S then Y/Enter also saves the highlighted model as the global default.

    Sub-agents themselves use a role (explore default | review | worker):

    RoleToolsUse for
    exploreno write/edit; bash except hard deniesMulti-hop recon / map structure
    reviewsame as exploreDiffs / checks; report only
    workerfull tools except nesting; bash except hard deniesScoped, self-contained edits

    Default stays explore (no edits). Prefer worker when the task is to implement a scoped change in an isolated context.

    Tools

    Built-in tools the model can call (see internal/tools/):

    ToolPurpose
    bashRun a shell command in the working directory
    readRead a file
    writeWrite a file (gated by permissions)
    editTargeted edit of a file
    grepRegex search across files
    findFile patterns (fd)
    lsDirectory listing
    agent_spawnStart an isolated sub-agent job (async)
    agent_waitWait for a job; returns short summary only
    agent_cancelCancel a running job

    Sub-agent transcripts live under ~/.phi/jobs/<id>/ and are not injected into the parent context — only the wait/task summary is.

    Fast search tools (fd, ripgrep) are downloaded on first startup into ~/.phi/bin when missing.

    See Project layout for the source tree map.

    See CONTRIBUTING.md for development setup, code style, and commit conventions.