Skip to content

feat: pi as a fifth backend - #338

Merged
scgopi merged 9 commits into
mainfrom
feature/pi-backend
Sep 12, 2026
Merged

scgopi merged 9 commits into
mainfrom
feature/pi-backend

Conversation

@scgopi

@scgopi scgopi commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Closes #214

Adds pi as a fifth CLI backend alongside Claude Code, Copilot, Codex and OpenCode.

What changes

  • --backend pi creates loops that run pi in a zmx session, from both the daemon and the app terminal.
  • Presence: a graphcode-written extension (PiPresenceExtension, loaded with -e) reports busy / idle / needs-input, tool activity and token usage, and banks the session id for resume. Works on remote hosts too.
  • Resume: --session <id>.
  • Settings: new Pi picker — --approve (trust the project, default) or ask.
  • Goals are given as prose (pi has no /goal); time-based loops use graphcode's heartbeat.
  • Summary writer and title suggestions use pi -p --no-tools --no-session.
  • README and site list five backends.
  • pi loops have no summary rail, by decision.
  • Version bumped to 0.1.69-beta1 (build 270).

Not yet

  • Export/import of pi sessions (an imported pi loop starts fresh).

Verification

Check Result
graphcode scheme tests ✅ 1731 tests passed, exit 0
graphcode-cli / graphcoded builds ✅ exit 0
swiftlint errors / swift format ✅ 0 / exit 0
Built CLI vs throwaway daemon (incl. node create --backend pi) ✅ 7/7 ok
Extension against real pi 0.85.1 with a fake zmx ✅ idle → busy → idle, session id banked

🤖 Generated with Claude Code

https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh

scgopi and others added 3 commits September 12, 2026 15:47
`pi [prompt]` opens the TUI already running the prompt, which is graphcode's session
model. Presence, activity, usage and the resume id come from one extension loaded with
`-e <path>`, writing the same zmx labels Claude Code's hooks do, so the Claude readers
serve pi unchanged. It reports idle on `agent_settled` rather than `agent_end`, because
pi can retry or run a queued follow-up after a run ends. Resume is `--session <id>`,
which exits 1 when the conversation is gone, so the resume-dead fallback applies.

pi has no tool approvals; its one unattended stall is the project-trust prompt, settled
by `--approve` (new PiProjectTrust setting, default approve). It has no `/goal`, `/loop`,
MCP or sub-agents, so goals ride as prose and time loops use the daemon's cadence.

Spiked against pi 0.85.1: flags read off `pi --help`, events off a probe extension run
against the real binary with a fake zmx. Not yet: the summary rail and export/import.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
pi keeps one JSONL per session under ~/.pi/agent/sessions/<cwd slug>/,
named <timestamp>_<id>.jsonl, whose header line names the id and cwd.
Export carries that file (locally by the banked id, remotely through the
same tar-over-ssh fetch Claude uses); restore rewrites the header's id to
a fresh UUID and its cwd to the target, installs it under the target's
slug, and banks the fresh id so --session <id> resumes it. The slug must
be the target's own: pi only offers an interactive fork prompt for a
session it finds under another project.

The layout and file-plumbing helpers move to SessionTransplant+Layouts
so the enum body stays under swiftlint's type_body_length limit, which
the base branch already exceeded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBuQWNV3dpDAtb6SnGN15P
scgopi and others added 2 commits September 12, 2026 16:02
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
pi names a session at startup but writes its JSONL only with the first
assistant message, and `pi --session <id>` exits 1 ("No session found
matching") on an id with no file. Banking at session_start left a dead id
for any session quit before its first reply, or a /new a reboot interrupted.
Bank when the file exists, retrying at tool_call and agent_settled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDp19dXj5ZKDEAMt65uRES
scgopi and others added 4 commits September 12, 2026 16:19
feat: carry pi sessions through node export/import (reviewed by PiBackendReview: MERGE)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
fix: pi extension banks a session id only once its file exists (review finding)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
Review findings F2 and F3. pi parses a positional argument starting with `-` as an
option and one starting with `@` as a file, so such a goal never reached the agent; it
now gets a leading space, on both the daemon and the app launch. `--` could not rescue
`@` and would swallow the remote `-e` suffix. pi's project-trust prompt runs before
session_start and fires no ui_prompt event, so the extension now reports awaitingInput
from project_trust and leaves the decision to pi. Verified live against pi 0.85.1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMVJyUtec3hpH5hF44xAgh
@scgopi
scgopi merged commit 9376013 into main Sep 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for pi agent

1 participant