# pi-tree-undo

> 中文文档见 [README.zh_CN.md](./README.zh_CN.md)

A Pi extension for **file undo/redo driven by session tree navigation**. No slash commands needed — moving backward and forward in `/tree` automatically reverts or re-applies file changes.

```
  open /tree
      │
      ▼
  ├── earlier node ◀── select & Enter = undo (files restored to that state)
  │
  └── later node   ◀── select & Enter = redo (files restored to that state)
```

## Features

- **Navigation is undo/redo**: in `/tree`, moving backward undoes, moving forward redoes. Branch crossing is handled automatically (abandoned branch undone, target branch applied).
- **Multi-step rewind**: jump back several nodes at once — every file change from every traversed turn is undone.
- **Change widget**: after navigating, a widget above the editor shows what happened to each file, including added/removed line counts:

  ```
  1 file(s) changed
  Modified:
    /path/src/a.ts (+12 -3)          ← +added lines -removed lines
  Added:
    /path/new.ts
  Deleted:
    /path/old.ts
  ```

- **External-edit protection**: if a file was modified outside the extension, its current content is first backed up to `<path>.pi-undo-conflict-<timestamp>`, then overwritten with the target state. The backup path is flagged in the widget (warning color).
- **Per-session isolation**: each session keeps its own snapshot store.

## Installation

Requires [pi](https://pi.dev).

### Try it without installing

```bash
pi -e ./src/index.ts
```

### Install as a package (then just run `pi`)

```bash
pnpm install
pnpm build          # compile to dist/
pi install ./       # register with pi
```

Uninstall: `pi uninstall ./`

## Quick start

1. Start pi with the extension loaded and confirm the `File undo ready` notice.
2. Have the model edit files (via `write` / `edit`).
3. Type `/tree` to open the session tree, move with the arrow keys, press Enter:
   - pick an **earlier node** → undo that change
   - pick a **later node** → redo
4. The widget above the editor shows each file's change (what changed, how many lines added/removed).
5. Navigate to any node to inspect that state; navigate back downstream to return to the present.

## Typical use cases

**1. Revert a bad change**

The model modified the wrong thing. Open `/tree`, select the node before the change, press Enter — the file is restored. Select the later node again to redo; you can change your mind at any point.

**2. Find which turn introduced a problem**

After several turns something broke. Step backward one node at a time and watch the widget to identify the exact turn, then stop at the node just before it.

**3. Switch between branches**

Fork two approaches from a node and edit files differently on each branch. Use `/tree` to flip between branches — the extension undoes the current branch's changes and applies the target branch's, so the workspace follows.

**4. Rewind multiple turns at once**

When undoing several turns, the widget shows the **precise net change** from the current state to the target state (a line edited in multiple turns counts once), e.g. `(+5 -2)` means the file gained 5 lines and lost 2 overall.

## How it works (brief)

- Every completed turn records a **snapshot** for each file modified via `edit`/`write` (a unified diff; `before` stores the full old content).
- Snapshots live in `~/.pi/agent/sessions/<project>/<sessionId>.undo-snapshots.json` and follow the session.
- On navigation the extension finds the common ancestor of old and new nodes, undoes the abandoned segment, and applies the target segment.
- Before applying, the on-disk content is checked against the snapshot; mismatches are backed up then overwritten, so manual edits are never silently lost.

## Limitations

- **Only `edit` / `write` are tracked**: files changed via `bash` (e.g. `echo >> file`) are not recorded and cannot be undone.
- **Deletions are not directly reversible**: pi has no dedicated delete tool, so removals typically go through `bash rm` and are out of scope; a file previously created by `write` can be resurrected on redo because its creation snapshot still exists.
- Manually edited files are **backed up before overwrite** — check the backup file if you need the old content back.

## Development

```bash
pnpm dev          # load the extension in pi: pi -e ./src/index.ts
pnpm typecheck    # tsc --noEmit
pnpm test         # run tests
pnpm build        # compile to dist/
```

Detailed development notes live in `AGENTS.md`.
