From 13a2ec65819d2ce3e3871bf25375cc42ead5e2e8 Mon Sep 17 00:00:00 2001 From: David Kong Date: Fri, 24 Jul 2026 12:36:57 +1000 Subject: [PATCH] initial commit --- AGENTS.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ DESIGN.md | 61 +++++++++++++++++++++++++++++++++++++++++ README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 AGENTS.md create mode 100644 DESIGN.md create mode 100644 README.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7cc49a4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,71 @@ +# AGENTS.md — pi-worktree Extension + +## Project Structure + +``` +.pi/extensions/pi-worktree.ts # Single-file extension (all tool + command logic) +README.md # User-facing documentation +DESIGN.md # Architecture and design decisions +DOMAIN.md # Domain concepts and terminology +``` + +## Tech Stack + +- **Language**: TypeScript +- **Schema**: TypeBox (`@sinclair/typebox`) for tool parameter schemas +- **Runtime**: pi coding agent extension API (`ExtensionAPI`, `ExtensionContext`) +- **Git**: native via `pi.exec("git", [...])` — no external git packages +- **No npm dependencies** in v1 beyond what pi provides + +## Extension Entry Point + +The extension is a single default-exported function: + +```typescript +import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import { Type } from "typebox"; + +export default function (pi: ExtensionAPI) { + // register tools and commands here +} +``` + +## Tool Conventions + +- Each tool is a `Type.Object` schema + async execute function. +- Execute signature: `(toolCallId, params, signal, onUpdate, ctx)` +- Always check `result.exitCode !== 0` for git failures — surface the message with suggested fixes. +- **Fail fast**: refuse dangerous operations (existing paths, current branch, uncommitted changes) with clear messages and suggestions. No silent auto-correction. + +## Command Conventions + +- Register via `pi.registerCommand("name", { description, handler })`. +- Use `ctx.ui.select()` for interactive pickers. +- Parse structured data from tool results (not raw text). + +## State Management + +- Tools are **stateless** — each call works independently based on current git state. +- Session memory is ephemeral (per pi process lifetime) for back-switching behavior only. + +## Error Handling Pattern + +```typescript +if (result.exitCode !== 0) { + return { + content: [{ type: "text", text: `Error: ${result.stderr}. Suggestion: ` }], + isError: true + }; +} +``` + +Always include a suggested fix in error messages. + +## Validation Checklist + +- [ ] Extension loads without errors when pi starts +- [ ] All four tools registered with correct signatures +- [ ] Error paths return `isError: true` with helpful messages +- [ ] `/worktree` command shows interactive picker +- [ ] Branch display updates after switching worktrees +- [ ] No external dependencies beyond TypeBox + pi SDK diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..0d8c2f9 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,61 @@ +# DESIGN.md — Architecture & Design Decisions + +## Overview + +A pi extension that manages git worktrees through tool commands and an interactive `/worktree` command, with tight session integration. + +## v1 Scope + +- Four tools: `git_worktree_create`, `git_worktree_list`, `git_worktree_switch`, `git_worktree_remove` +- One command: `/worktree` (interactive picker) +- Session hooks: branch display update + offer new session after switch +- **Out of scope**: auto-worktree creation, smart defaults, persistent state + +## Architecture + +``` +pi-worktree.ts +├── Tools +│ ├── git_worktree_create(path, branch?, create_branch?) +│ ├── git_worktree_list() +│ ├── git_worktree_switch(target) +│ └── git_worktree_remove(path) +├── Command: /worktree (interactive picker) +└── Session hooks + ├── Update pi's git branch display on switch + └── Offer new session creation after switch +``` + +## Key Design Decisions + +### Stateless Tools, Ephemeral Memory +Tools are stateless; only in-memory mapping of worktree→session during a process lifetime for back-switching. Lost on restart. + +### Fail Fast, No Auto-Correction +Refuse dangerous operations (existing path, current branch, uncommitted changes) with clear messages and suggested fixes. Never silently auto-correct. + +### Session Integration Depth (v1) +Update branch display + offer new session creation. No automatic worktree creation per branch — keeps complexity down and avoids assumptions about workflow. + +## Tool Behaviors + +| Tool | Key Behavior | Fail Conditions | +|------|-------------|-----------------| +| `create` | `git worktree add [branch]`, `-b` for new branches | Path exists, branch is current | +| `list` | Parses `git worktree list` output into structured data | No git repo present | +| `switch` | Changes cwd to target worktree path | Already there, uncommitted changes in source | +| `remove` | `git worktree remove ` | Target is main repo, uncommitted changes | + +## Edge Cases + +1. **Nested worktrees**: Not supported by git — surface native error +2. **Detached HEAD**: Use path for identification instead of branch name +3. **Untracked files on removal**: Suggest removing/moving them first +4. **Same-branch worktrees**: Let git handle it, surface the error + +## Rollout Phases + +1. Core tools (create, list, switch, remove) with error handling +2. `/worktree` interactive command with picker + back-switching +3. Session integration hooks (branch display, new session offer) +4. Polish: edge cases, README, user testing diff --git a/README.md b/README.md new file mode 100644 index 0000000..9503861 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# pi-worktree + +A pi extension for managing git worktrees through intuitive tool commands and an interactive picker. + +## Tools + +### `git_worktree_create` + +Create a linked worktree for a branch in the current repo. + +```typescript +{ + path: string, // Path for the new worktree + branch?: string, // Branch name (new or existing). Defaults to 'main'. + create_branch?: boolean // Create a new branch? Defaults to true if branch doesn't exist. +} +``` + +**Example**: `git_worktree_create({ path: "./feature-x", branch: "feature-x" })` + +### `git_worktree_list` + +List all linked worktrees in the current repo. + +```typescript +// No parameters required +``` + +Returns structured data with `branch`, `path`, and `isCurrent` for each worktree. + +**Example output**: +``` +main — /home/user/repo (current) +feature-x — /home/user/repo/feature-x +``` + +### `git_worktree_switch` + +Switch pi's working directory to a linked worktree. + +```typescript +{ + target: string // Path or branch name of the target worktree +} +``` + +**Example**: `git_worktree_switch({ target: "./feature-x" })` + +After switching, you'll be offered the option to create a new session for that worktree context. + +### `git_worktree_remove` + +Remove a linked worktree. + +```typescript +{ + path: string // Path of the worktree to remove +} +``` + +**Example**: `git_worktree_remove({ path: "./feature-x" })` + +## Command + +### `/worktree` + +Interactive picker to switch between linked worktrees. + +Lists all worktrees with a branch-first display and lets you select one to switch to. Automatically updates pi's branch display after switching. + +## Behavior + +- **Fail fast**: Refuses dangerous operations (existing paths, current branch, uncommitted changes) with clear messages and suggested fixes. +- **Stateless tools**: Each call works independently based on current git state. +- **Session integration**: Branch display updates automatically; you're offered a new session after switching worktrees. +- **Back-switching**: When returning to the main repo, pi restores the previous session. + +## Requirements + +- Git 2.x with worktree support (all modern versions) +- No external npm dependencies — uses only pi's extension API and TypeBox schemas.