pi-rewind-hook 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,18 +4,30 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- ### Changed
8
- - Added `pi-package` keyword for npm discoverability (pi v0.50.0 package system)
9
-
10
- ## [1.7.1] - 2026-01-22
7
+ ## [1.8.0] - 2026-04-03
11
8
 
12
9
  ### Changed
13
- - Reordered restore menus to show non-file-restorative options first (most common action)
14
- - Branch menu: "Conversation only" now appears first
15
- - Tree navigation: "Keep current files" now appears first
10
+ - Replaced the old git-ref checkpoint ledger with session-native `rewind-turn` and `rewind-op` records
11
+ - Rewind points are now aligned to visible session nodes: the triggering user node and each assistant step captured at `turn_end`
12
+ - Snapshot commits are now kept reachable through a single `refs/pi-rewind/store` keepalive ref instead of one ref per checkpoint
13
+ - Removed the fixed 100-checkpoint per-session pruning model; exact mode now has no cap by default
14
+ - `/fork` and `/tree` now persist resulting exact file state through `rewind-op.current`, including keep-current-files flows
15
+ - Undo snapshots now persist with the resulting session state instead of depending on old before-restore refs
16
+
17
+ ### Added
18
+ - Lineage-aware exact snapshot lookup through `parentSession`
19
+ - Exact assistant-node rewind for v2 captures
20
+ - Compaction and branch-summary snapshot aliasing without creating fresh snapshots when files did not change
21
+ - Optional retention over unique snapshot commits via `rewind.retention.maxSnapshots`, `rewind.retention.maxAgeDays`, and `rewind.retention.pinLabeledEntries`
22
+ - Retention discovery mode setting via `rewind.retention.scanMode` (`ancestor-only` default, optional `repo-sessions`)
23
+ - Startup retention sweep budget setting via `rewind.retention.startupBudgetMs`
16
24
 
17
25
  ### Fixed
18
- - Resume checkpoint now session-scoped (`checkpoint-resume-{sessionId}-{timestamp}`) for consistency with other checkpoint types
26
+ - Restore now deletes files absent from the target snapshot before worktree-only restore, producing exact restore for tracked and untracked non-ignored files in the snapshot domain without staging the repo index
27
+ - Rewind bookkeeping for reconstruction, capture, migration, and retention no longer depends on UI availability
28
+ - `/tree` restore options now match actual exact rewind availability: user, assistant, compaction, and branch-summary nodes only
29
+ - Critical rewind handlers now fail closed with user-facing errors instead of bubbling git/storage exceptions through `/fork` and `/tree`
30
+ - Turn capture/finalization now warns and recovers when snapshot writes fail, avoiding stale collector state
19
31
 
20
32
  ## [1.7.0] - 2026-01-15
21
33
 
@@ -37,12 +49,12 @@ All notable changes to this project will be documented in this file.
37
49
  - Old-format checkpoints are not pruned (to avoid cross-session interference)
38
50
  - New checkpoints are created in the new session-scoped format
39
51
 
40
- ## [1.6.0] - 2025-01-13
52
+ ## [1.6.0] - 2026-01-13
41
53
 
42
54
  ### Added
43
55
  - `rewind.silentCheckpoints` setting to hide checkpoint status and notifications
44
56
 
45
- ## [1.5.0] - 2025-01-10
57
+ ## [1.5.0] - 2026-01-10
46
58
 
47
59
  ### Changed
48
60
  - Replaced noisy stderr logging with clean TUI output
@@ -88,7 +100,7 @@ All notable changes to this project will be documented in this file.
88
100
  - Install script now migrates old hooks config and cleans up old directory
89
101
  - Renamed "Hook" to "Extension" throughout codebase and docs
90
102
 
91
- ## [1.2.0] - 2025-01-03
103
+ ## [1.2.0] - 2026-01-03
92
104
 
93
105
  ### Added
94
106
  - Tree navigation support (`session_before_tree`) - restore files when navigating session tree
@@ -102,13 +114,13 @@ All notable changes to this project will be documented in this file.
102
114
  - Removed `agent_end` handler that was clearing checkpoints after each turn
103
115
  - "Undo last file rewind" now cancels branch instead of creating unwanted branch
104
116
 
105
- ## [1.1.1] - 2024-12-27
117
+ ## [1.1.1] - 2025-12-27
106
118
 
107
119
  ### Fixed
108
120
  - Use `before_branch` event instead of `branch` for proper hook timing (thanks @badlogic)
109
121
  - Cancel branch when user dismisses restore options menu
110
122
 
111
- ## [1.1.0] - 2024-12-27
123
+ ## [1.1.0] - 2025-12-27
112
124
 
113
125
  ### Added
114
126
  - "Undo last file rewind" option - restore files to state before last rewind
@@ -122,7 +134,7 @@ All notable changes to this project will be documented in this file.
122
134
  ### Fixed
123
135
  - Code-only restore options now properly skip conversation restore
124
136
 
125
- ## [1.0.0] - 2024-12-19
137
+ ## [1.0.0] - 2025-12-19
126
138
 
127
139
  ### Added
128
140
  - Initial release
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Rewind Extension
2
2
 
3
- A Pi agent extension that enables rewinding file changes during coding sessions. Creates automatic checkpoints using git refs, allowing you to restore files to previous states while optionally preserving conversation history.
3
+ A Pi agent extension that records exact file-state rewind points, allowing restoration of file states during `/tree` navigation and across resumed and forked sessions
4
+
5
+ Rewind metadata lives in the session itself as hidden entries, so rewind history survives across forks, resumes, tree navigation, and compaction. Snapshot commits are kept reachable through a single git ref rather than one ref per checkpoint, and rewind points can be resolved across session lineage via `parentSession` links. Retention is optional and configurable; without it, exact history is kept indefinitely.
4
6
 
5
7
  ## Screenshots
6
8
 
@@ -10,9 +12,9 @@ A Pi agent extension that enables rewinding file changes during coding sessions.
10
12
 
11
13
  ## Requirements
12
14
 
13
- - Pi agent v0.35.0+ (unified extensions system)
15
+ - Pi agent v0.35.0+
14
16
  - Node.js (for installation)
15
- - Git repository (checkpoints are stored as git refs)
17
+ - Git repository
16
18
 
17
19
  ## Installation
18
20
 
@@ -24,173 +26,191 @@ This will:
24
26
  1. Create `~/.pi/agent/extensions/rewind/`
25
27
  2. Download the extension files
26
28
  3. Add the extension to your `~/.pi/agent/settings.json`
27
- 4. Migrate any existing hooks config to extensions (if upgrading from v1.2.0)
29
+ 4. Migrate any existing hooks config to extensions (if upgrading from an older version)
28
30
  5. Clean up old `hooks/rewind` directory (if present)
29
31
 
30
- ### Alternative Installation
31
-
32
- Using curl:
33
-
34
- ```bash
35
- curl -fsSL https://raw.githubusercontent.com/nicobailon/pi-rewind-hook/main/install.js | node
36
- ```
37
-
38
- Or clone the repo and configure manually:
39
-
40
- ```bash
41
- git clone https://github.com/nicobailon/pi-rewind-hook ~/.pi/agent/extensions/rewind
42
- ```
43
-
44
- Then add to `~/.pi/agent/settings.json`:
45
-
46
- ```json
47
- {
48
- "extensions": ["~/.pi/agent/extensions/rewind/index.ts"]
49
- }
50
- ```
51
-
52
- ### Platform Notes
53
-
54
- **Windows:** The `npx` command works in PowerShell, Command Prompt, and WSL. If you prefer curl on Windows without WSL:
55
-
56
- ```powershell
57
- Invoke-WebRequest -Uri "https://raw.githubusercontent.com/nicobailon/pi-rewind-hook/main/install.js" -OutFile install.js; node install.js; Remove-Item install.js
58
- ```
59
-
60
- ### Upgrading from v1.2.0
61
-
62
- If you're upgrading from pi-rewind-hook v1.2.0 (which used the hooks system), simply run `npx pi-rewind-hook` again. The installer will:
63
- - Move the extension from `hooks/rewind` to `extensions/rewind`
64
- - Migrate your settings.json from `hooks` to `extensions`
65
- - Clean up the old hooks directory
66
-
67
- **Note:** v1.3.0+ requires pi v0.35.0 or later. If you're on an older version of pi, stay on pi-rewind-hook v1.2.0.
32
+ Or clone the repo into `~/.pi/agent/extensions/rewind/` — Pi discovers extensions in that directory automatically.
68
33
 
69
34
  ## Configuration
70
35
 
71
- You can configure the extension by adding settings to `~/.pi/agent/settings.json`:
36
+ Optionally add settings to `~/.pi/agent/settings.json`. For example:
72
37
 
73
38
  ```json
74
39
  {
75
- "extensions": ["~/.pi/agent/extensions/rewind/index.ts"],
76
40
  "rewind": {
77
- "silentCheckpoints": true
41
+ "silentCheckpoints": true,
42
+ "retention": {
43
+ "maxSnapshots": 2000,
44
+ "maxAgeDays": 30,
45
+ "pinLabeledEntries": true
46
+ }
78
47
  }
79
48
  }
80
49
  ```
81
50
 
82
51
  ### Settings
83
52
 
84
- - **`rewind.silentCheckpoints`** (boolean, default: `false`): When set to `true`, disables checkpoint status messages. The footer checkpoint count (`◆ X checkpoints`) and checkpoint saved notifications (`Checkpoint X saved`) will not be displayed.
53
+ - `rewind.silentCheckpoints` hides footer/status and checkpoint notifications
54
+ - `rewind.retention.maxSnapshots` — optional cap on unpinned unique snapshot commits kept reachable
55
+ - `rewind.retention.maxAgeDays` — optional age limit for unpinned snapshot commits
56
+ - `rewind.retention.pinLabeledEntries` — when true, snapshot commits bound to **labeled nodes** in the Pi session tree are exempt from `maxSnapshots` and `maxAgeDays` pruning (useful for bookmarking important rewind points you want to prevent getting garbage-collected)
57
+ - `rewind.retention.scanMode` — retention discovery mode: `ancestor-only` (default, follow current session lineage only) or `repo-sessions` (scan discovered session roots)
58
+ - `rewind.retention.startupBudgetMs` — optional startup time budget for retention sweeps; if exceeded, startup sweep is skipped and deferred
85
59
 
86
- ## How It Works
60
+ If `rewind.retention` is omitted, Rewind keeps exact history with no automatic expiration. This can grow git object storage without bound over time.
87
61
 
88
- ### Checkpoints
62
+ ## Usage
89
63
 
90
- The extension creates git refs at two points:
64
+ ### Rewinding via `/fork`
91
65
 
92
- 1. **Session start** - When pi starts, creates a "resume checkpoint" of the current file state
93
- 2. **Each turn** - Before the agent processes each message, creates a checkpoint
66
+ 1. Type `/fork` in Pi
67
+ 2. Select a message to branch from
68
+ 3. Choose a restore option
94
69
 
95
- Checkpoints are stored as git refs under `refs/pi-checkpoints/` and are scoped per-session (so multiple pi sessions in the same repo don't interfere with each other). Each session maintains its own 100-checkpoint limit.
70
+ **Options:**
96
71
 
97
- ### Rewinding
72
+ | Option | Files | Conversation |
73
+ |--------|-------|-------------|
74
+ | **Conversation only (keep current files)** | Unchanged | Reset to that point |
75
+ | **Restore all (files + conversation)** | Restored | Reset to that point |
76
+ | **Code only (restore files, keep conversation)** | Restored | Unchanged |
77
+ | **Undo last file rewind** | Restored to before last rewind | Unchanged |
98
78
 
99
- To rewind via `/branch`:
79
+ `Restore all`, `Code only`, and `Undo last file rewind` are only shown when an exact rewind point or undo snapshot is available for the selected message.
100
80
 
101
- 1. Type `/branch` in pi
102
- 2. Select a message to branch from
103
- 3. Choose a restore option
81
+ When you restore files during `/fork`, the undo snapshot is persisted in the **new child session**, because that is where you continue working.
104
82
 
105
- To rewind via tree navigation:
83
+ ### Rewinding via `/tree`
106
84
 
107
85
  1. Press `Tab` to open the session tree
108
86
  2. Navigate to a different node
109
87
  3. Choose a restore option
110
88
 
111
- **For messages from the current session:**
89
+ **Options:**
112
90
 
113
91
  | Option | Files | Conversation |
114
- |--------|-------|--------------|
115
- | **Restore all (files + conversation)** | Restored | Reset to that point |
116
- | **Conversation only (keep current files)** | Unchanged | Reset to that point |
117
- | **Code only (restore files, keep conversation)** | Restored | Unchanged |
118
- | **Undo last file rewind** | Restored to before last rewind | Unchanged |
92
+ |--------|-------|-------------|
93
+ | **Keep current files** | Unchanged | Navigated to that point |
94
+ | **Restore files to that point** | Restored | Navigated to that point |
95
+ | **Undo last file rewind** | Restored to before last rewind | Navigated to that point |
119
96
 
120
- **For messages from before the current session (uses resume checkpoint):**
97
+ If you navigate with `Keep current files`, Rewind still persists the resulting session position's exact current file baseline via `rewind-op.current`.
121
98
 
122
- | Option | Files | Conversation |
123
- |--------|-------|--------------|
124
- | **Restore to session start (files + conversation)** | Restored to session start | Reset to that point |
125
- | **Conversation only (keep current files)** | Unchanged | Reset to that point |
126
- | **Restore to session start (files only, keep conversation)** | Restored to session start | Unchanged |
127
- | **Undo last file rewind** | Restored to before last rewind | Unchanged |
128
-
129
- ### Resumed Sessions
130
-
131
- When you resume a session (`pi --resume`), the extension creates a resume checkpoint. If you branch to a message from before the current session, you can restore files to the state when you resumed (not per-message granularity, but a safety net).
99
+ ### Examples
132
100
 
133
- ## Examples
134
-
135
- ### Undo a bad refactor
101
+ **Undo a bad refactor:**
136
102
 
137
103
  ```
138
104
  You: refactor the auth module to use JWT
139
105
  Agent: [makes changes you don't like]
140
106
 
141
- You: /branch
107
+ You: /fork
142
108
  → Select "refactor the auth module to use JWT"
143
109
  → Select "Code only (restore files, keep conversation)"
144
110
 
145
111
  Result: Files restored, conversation intact. Try a different approach.
146
112
  ```
147
113
 
148
- ### Start fresh from a checkpoint
114
+ **Start fresh from an earlier point:**
149
115
 
150
116
  ```
151
- You: /branch
117
+ You: /fork
152
118
  → Select an earlier message
153
119
  → Select "Restore all (files + conversation)"
154
120
 
155
121
  Result: Both files and conversation reset to that point.
156
122
  ```
157
123
 
158
- ### Recover after resuming
124
+ ## How Rewind works
159
125
 
160
- ```bash
161
- pi --resume # resume old session
162
- ```
126
+ Rewind stores its ledger in hidden session `custom` entries:
163
127
 
164
- ```
165
- Agent: [immediately breaks something]
128
+ - `rewind-turn` — one per prompt, containing the triggering user-node snapshot plus any assistant-node snapshots produced during that prompt
129
+ - `rewind-op` sparse records for `/fork`, `/tree`, compaction aliases, summary aliases, and undo state
166
130
 
167
- You: /branch
168
- → Select any old message
169
- → Select "Restore to session start (files only, keep conversation)"
131
+ Snapshots are only considered at visible boundaries:
170
132
 
171
- Result: Files restored to state when you resumed.
172
- ```
133
+ - the user pre-prompt boundary
134
+ - each assistant `turn_end`
135
+ - selected stateful session operations
173
136
 
174
- ## Viewing Checkpoints
137
+ Rewind does not create per-tool snapshots.
175
138
 
176
- List all checkpoint refs:
139
+ ### Canonical exact rewind points
177
140
 
178
- ```bash
179
- git for-each-ref refs/pi-checkpoints/
141
+ Exact file restore is available for:
142
+
143
+ - user nodes
144
+ - assistant nodes
145
+ - compaction nodes aliased to the current exact state
146
+ - branch-summary nodes aliased during `/tree`
147
+
148
+ Exact file restore is not offered for toolResult nodes.
149
+
150
+ ### Git storage model
151
+
152
+ Snapshot commits are kept reachable through a single repo-local ref:
153
+
154
+ ```text
155
+ refs/pi-rewind/store
180
156
  ```
181
157
 
182
- Checkpoint ref format: `checkpoint-{sessionId}-{timestamp}-{entryId}`
158
+ That ref is only for git object reachability; the session ledger is authoritative.
159
+
160
+ ### Deduplication
161
+
162
+ Before creating a snapshot commit, Rewind captures the worktree tree SHA. If it matches the latest exact snapshot tree, Rewind reuses that existing snapshot commit instead of creating a new one.
163
+
164
+ ### Restore exactness and scope
165
+
166
+ Rewind restores the exact file state for the snapshot domain it owns:
167
+
168
+ - tracked files
169
+ - untracked, non-ignored files
170
+ - without staging the real git index during restore
171
+
172
+ Before restoring target contents, it deletes paths present in the current snapshot but absent from the target snapshot, then restores the target snapshot into the worktree only.
173
+
174
+ Out of scope:
175
+
176
+ - ignored files
177
+ - empty directories
178
+ - exact rewind points for `toolResult` nodes
179
+ - exact rewind points for `bashExecution` nodes
180
+
181
+ ## Lineage and resume behavior
182
+
183
+ Rewind resolves exact rewind points across session lineage by following `parentSession` links and reading rewind metadata from ancestor session files.
184
+
185
+ Rewind v2 uses only session-native `rewind-turn`/`rewind-op` metadata and does not read legacy checkpoint refs.
186
+
187
+ ## Retention
188
+
189
+ Retention only affects git reachability. Session JSONL metadata is append-only and is never compacted by Rewind.
190
+
191
+ When retention is enabled, Rewind keeps snapshot commits alive if they are referenced by:
192
+
193
+ - a `rewind-turn` or `rewind-op` binding in a discovered same-repo session
194
+ - the latest `rewind-op.current` for a discovered same-repo session
195
+ - the latest `rewind-op.undo` for a discovered same-repo session
196
+ - a labeled bound entry when `pinLabeledEntries` is enabled
197
+
198
+ If a snapshot commit has been pruned, Rewind validates commit existence before offering restore.
199
+
200
+ If retention discovery yields an empty live set, Rewind preserves the existing `refs/pi-rewind/store` ref rather than deleting it.
201
+
202
+ ## Viewing storage
183
203
 
184
- Manually restore to a checkpoint (copy ref name from list above):
204
+ Show the store ref head:
185
205
 
186
206
  ```bash
187
- git checkout refs/pi-checkpoints/checkpoint-abc12345-...-... -- .
207
+ git rev-parse refs/pi-rewind/store
188
208
  ```
189
209
 
190
- Delete all checkpoints:
210
+ Show the hidden rewind ledger in a session file:
191
211
 
192
212
  ```bash
193
- git for-each-ref --format='%(refname)' refs/pi-checkpoints/ | xargs -n1 git update-ref -d
213
+ grep '"customType":"rewind-' ~/.pi/agent/sessions/**/*.jsonl
194
214
  ```
195
215
 
196
216
  ## Uninstalling
@@ -199,19 +219,17 @@ git for-each-ref --format='%(refname)' refs/pi-checkpoints/ | xargs -n1 git upda
199
219
  ```bash
200
220
  rm -rf ~/.pi/agent/extensions/rewind
201
221
  ```
202
- On Windows (PowerShell): `Remove-Item -Recurse -Force ~/.pi/agent/extensions/rewind`
203
222
 
204
- 2. Remove the extension from `~/.pi/agent/settings.json` (delete the line with `rewind/index.ts` from the `extensions` array)
223
+ 2. Remove any `rewind` key from `~/.pi/agent/settings.json` if you added one
205
224
 
206
- 3. Optionally, clean up git refs in each repo where you used the extension:
225
+ 3. Optionally, clean up the git reachability ref in each repo where you used the extension:
207
226
  ```bash
208
- git for-each-ref --format='%(refname)' refs/pi-checkpoints/ | xargs -n1 git update-ref -d
227
+ git update-ref -d refs/pi-rewind/store
209
228
  ```
210
229
 
211
230
  ## Limitations
212
231
 
213
232
  - Only works in git repositories
214
- - Checkpoints are scoped per-session (multiple sessions in the same repo don't share checkpoints)
215
- - Resumed sessions only have a single resume checkpoint for pre-session messages
216
- - Tracks working directory changes only (not staged/committed changes)
217
- - Each session has its own 100-checkpoint limit (pruning doesn't affect other sessions)
233
+ - Session metadata grows append-only; retention only trims git reachability
234
+ - Discovery for retention is best-effort across discovered Pi session roots and explicit `parentSession` ancestors
235
+ - Ignored files and empty directories are outside the snapshot model
package/banner.png ADDED
Binary file