pulseaiclub/phi

phi

a coding Agent, npc plugin, sub-agents, hashline edits, and mcp

待分类aiai-agentclaude
  • 15 MB · ~31 ms · sub-agents · anchored sloppy edits · permission gate · progressive MCP · PXB extensions · native diff review & code selection · OpenAI / Anthropic / Gemini
  • Sponsors
  • Docs
  • Quick start
  • Footprint
  • Configuration
  • Interactive mode
  • Diff review
  • Code viewer
  • Commands
  • Sessions
  • Headless mode
  • Skills
  • Permissions
  • Extensions
  • MCP
  • Tools
  • Project layout

Sponsors

phi is sponsored by Infistar.cc — one API key for every major model, priced for people who run agents all day.⚙️ Plug and play: set the base URL, API key, and model name, then call it directly.🧩 One key, every model: switch between Claude, GPT, Gemini, DeepSeek, and other leading models without editing config again.💰 Cheap and simple: some models cost as little as 1% of official rates, with RMB billing and invoices.🎁 phi perk: register through our link and get $5 in trial credits 👉 Free ~/.phi/config.yaml — phi ships the whole model block; paste it, swap in your key, start. models:

  • name: claude-opus-5-5

api_key: "" base_url: https://infistar.cc api: Anthropic

  • name: gpt-6-astra

api_key: "" base_url: https://infistar.cc/v1 api: OpenAIResponses

  • name: gemini-3-pro

api_key: "" base_url: https://infistar.cc api: Gemini

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

Metric · phi 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 packages · 32 Direct module deps · 6 (15 modules total) Linked runtimes · system 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
  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:

Variable · Overrides PHI_API_KEY · models[].api_key (default model) PHI_MODEL · models[].name (default model) PHI_BASE_URL · models[].base_url (default model) PHI_SKILL_PATH · skill_path PHI_THINK_LEVEL · models[].think_level (default model; off disables) PHI_PROMPT_HISTORY · Composer 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 (or phi tui) 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, /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), skills, hooks

Keyboard shortcuts

Key · Action Ctrl+C · Quit phi Esc · Cancel the running agent / close pickers Ctrl+K · Toggle the command palette Ctrl+A · Jump to the start of the line Ctrl+E · Jump to the end of the line Ctrl+U · Clear the composer input, images, and skills Ctrl+Shift+C · Copy 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.

Command · What opens /diff · Working tree (git diff) /diff staged · Staged changes /diff HEAD · Last commit (git show) /diff @path · Only that file — @ comes from file completion, the -- separator is added for you /diff staged @a.go @b.go · Staged changes in two files /diff HEAD @path · That file against HEAD /diff main..feat @path · That file across a range

/diff -- 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 [: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 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

Command · Description phi / phi tui · Start the interactive TUI phi run -p "…" · Run one agent loop headlessly (see below) phi update · Download and install the latest GitHub release phi update --check · Query the latest release without installing phi sessions list · List persisted sessions for this directory /sessions · List sessions for this directory (TUI) /branch · Switch the working branch — see Branch switching /new · Start a fresh empty session (TUI) /diff · Full-screen git review — see Diff review /code · Full-screen source viewer — see Code viewer !command · Run 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// as JSONL trajectories.

  • phi sessions list — 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 / 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:

Flag · Description -p, --prompt STRING · Prompt to run (required) --jsonl · Emit JSONL events to stdout --yolo · Skip all permission checks for this run (benchmarks / CI only) --max-rounds N · Cap tool rounds (default 64) --timeout DURATION · Limit the agent run wall-clock time (e.g. 10m; disabled by default) --session ID · Resume a persisted session by id or unique prefix --continue-last · Resume the newest persisted session for this directory --session-dir DIR · Override the session storage directory --tools LIST · Enable 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.

In the interactive TUI, exhausting the tool-round budget prompts Continue / Stop. Headless phi run has no confirmation UI, so it exits with code 2.