Worktree diffs
Open a worktree to read its changes. Keep several open to compare them. These paths, commits and patches are illustrative snapshots.
Keep reply drafts keyed by thread 2 modified · 1 untracked (excluded)
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
c8ebd603a4646f4c771bc7076a2ba4830b2def29- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/drafts.js b/runtime/drafts.js
index 7e24c4f..6b21e75 100644
--- a/runtime/drafts.js
+++ b/runtime/drafts.js
@@ -5,7 +5,7 @@ export function saveDraft(thread, text) {
}
export function draft(thread) {
- return activeDraft;
+ return drafts.get(thread.id) ?? "";
}
export function clearDraft(thread) {
diff --git a/tests/drafts.test.js b/tests/drafts.test.js
index 003e396..8eb2121 100644
--- a/tests/drafts.test.js
+++ b/tests/drafts.test.js
@@ -3,3 +3,9 @@ import { openThread, typeReply } from "./helpers.js";
test("opens a composer", () => {
expect(openThread("a").draft).toBe("");
});
+
+test("keeps each thread draft", () => {
+ typeReply("a", "Keep this text");
+ openThread("b");
+ expect(openThread("a").draft).toBe("Keep this text");
+});
Preserve the selected file after filtering 1 staged · 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
e1550c3bc496aebce09c28eb0e14a45a8e9708ac- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/widgets/file-tree.js b/widgets/file-tree.js
index 1f64b19..b7ca4fe 100644
--- a/widgets/file-tree.js
+++ b/widgets/file-tree.js
@@ -1,3 +1,3 @@
function select(file) {
- activePath = file.path;
+ navigateToDatum(target, file.key);
}
diff --git a/widgets/diff.js b/widgets/diff.js
index 9db353a..e392d0b 100644
--- a/widgets/diff.js
+++ b/widgets/diff.js
@@ -1 +1,2 @@
-const selected = files[0];
+const selected = files.find(file => file.key === current)
+ ?? files[0];
Show added and removed line counts 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/worktrunk- Current commit
243bd04ef5473061535abd2391bf9a26c6c5f0fa- Comparison base
214d8e109fd9abcdac34c52735a359ed64b96c57- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/src/summary.rs b/src/summary.rs
index 0f0860f..9374881 100644
--- a/src/summary.rs
+++ b/src/summary.rs
@@ -1,3 +1,3 @@
fn summary(added: usize, removed: usize) -> String {
- format!("{} lines", added - removed)
+ format!("+{added} -{removed}")
}
Clarify page authoring examples Clean
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
fd2d11d6a89297dd9101a6dddf55977c8bdc33fd- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
No changes against this base.
Try other sets · one, two, eight, or empty
These examples use the same widget. The larger set includes a binary change, a long branch name, and an unavailable snapshot.
One worktree
Keep reply drafts keyed by thread 2 modified · 1 untracked (excluded)
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
c8ebd603a4646f4c771bc7076a2ba4830b2def29- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/drafts.js b/runtime/drafts.js
index 7e24c4f..6b21e75 100644
--- a/runtime/drafts.js
+++ b/runtime/drafts.js
@@ -5,7 +5,7 @@ export function saveDraft(thread, text) {
}
export function draft(thread) {
- return activeDraft;
+ return drafts.get(thread.id) ?? "";
}
export function clearDraft(thread) {
diff --git a/tests/drafts.test.js b/tests/drafts.test.js
index 003e396..8eb2121 100644
--- a/tests/drafts.test.js
+++ b/tests/drafts.test.js
@@ -3,3 +3,9 @@ import { openThread, typeReply } from "./helpers.js";
test("opens a composer", () => {
expect(openThread("a").draft).toBe("");
});
+
+test("keeps each thread draft", () => {
+ typeReply("a", "Keep this text");
+ openThread("b");
+ expect(openThread("a").draft).toBe("Keep this text");
+});
Two worktrees
Keep reply drafts keyed by thread 2 modified · 1 untracked (excluded)
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
c8ebd603a4646f4c771bc7076a2ba4830b2def29- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/drafts.js b/runtime/drafts.js
index 7e24c4f..6b21e75 100644
--- a/runtime/drafts.js
+++ b/runtime/drafts.js
@@ -5,7 +5,7 @@ export function saveDraft(thread, text) {
}
export function draft(thread) {
- return activeDraft;
+ return drafts.get(thread.id) ?? "";
}
export function clearDraft(thread) {
diff --git a/tests/drafts.test.js b/tests/drafts.test.js
index 003e396..8eb2121 100644
--- a/tests/drafts.test.js
+++ b/tests/drafts.test.js
@@ -3,3 +3,9 @@ import { openThread, typeReply } from "./helpers.js";
test("opens a composer", () => {
expect(openThread("a").draft).toBe("");
});
+
+test("keeps each thread draft", () => {
+ typeReply("a", "Keep this text");
+ openThread("b");
+ expect(openThread("a").draft).toBe("Keep this text");
+});
Preserve the selected file after filtering 1 staged · 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
e1550c3bc496aebce09c28eb0e14a45a8e9708ac- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/widgets/file-tree.js b/widgets/file-tree.js
index 1f64b19..b7ca4fe 100644
--- a/widgets/file-tree.js
+++ b/widgets/file-tree.js
@@ -1,3 +1,3 @@
function select(file) {
- activePath = file.path;
+ navigateToDatum(target, file.key);
}
diff --git a/widgets/diff.js b/widgets/diff.js
index 9db353a..e392d0b 100644
--- a/widgets/diff.js
+++ b/widgets/diff.js
@@ -1 +1,2 @@
-const selected = files[0];
+const selected = files.find(file => file.key === current)
+ ?? files[0];
Eight worktrees
Keep reply drafts keyed by thread 2 modified · 1 untracked (excluded)
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
c8ebd603a4646f4c771bc7076a2ba4830b2def29- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/drafts.js b/runtime/drafts.js
index 7e24c4f..6b21e75 100644
--- a/runtime/drafts.js
+++ b/runtime/drafts.js
@@ -5,7 +5,7 @@ export function saveDraft(thread, text) {
}
export function draft(thread) {
- return activeDraft;
+ return drafts.get(thread.id) ?? "";
}
export function clearDraft(thread) {
diff --git a/tests/drafts.test.js b/tests/drafts.test.js
index 003e396..8eb2121 100644
--- a/tests/drafts.test.js
+++ b/tests/drafts.test.js
@@ -3,3 +3,9 @@ import { openThread, typeReply } from "./helpers.js";
test("opens a composer", () => {
expect(openThread("a").draft).toBe("");
});
+
+test("keeps each thread draft", () => {
+ typeReply("a", "Keep this text");
+ openThread("b");
+ expect(openThread("a").draft).toBe("Keep this text");
+});
Preserve the selected file after filtering 1 staged · 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
e1550c3bc496aebce09c28eb0e14a45a8e9708ac- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/widgets/file-tree.js b/widgets/file-tree.js
index 1f64b19..b7ca4fe 100644
--- a/widgets/file-tree.js
+++ b/widgets/file-tree.js
@@ -1,3 +1,3 @@
function select(file) {
- activePath = file.path;
+ navigateToDatum(target, file.key);
}
diff --git a/widgets/diff.js b/widgets/diff.js
index 9db353a..e392d0b 100644
--- a/widgets/diff.js
+++ b/widgets/diff.js
@@ -1 +1,2 @@
-const selected = files[0];
+const selected = files.find(file => file.key === current)
+ ?? files[0];
Show added and removed line counts 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/worktrunk- Current commit
243bd04ef5473061535abd2391bf9a26c6c5f0fa- Comparison base
214d8e109fd9abcdac34c52735a359ed64b96c57- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/src/summary.rs b/src/summary.rs
index 0f0860f..9374881 100644
--- a/src/summary.rs
+++ b/src/summary.rs
@@ -1,3 +1,3 @@
fn summary(added: usize, removed: usize) -> String {
- format!("{} lines", added - removed)
+ format!("+{added} -{removed}")
}
Clarify page authoring examples Clean
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
fd2d11d6a89297dd9101a6dddf55977c8bdc33fd- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
No changes against this base.
Refresh the application mark 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
7239fe1a28d2d206f915c9875977a9be2b404014- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
assets/mark.png changed. Binary content has no line
count.
Back off repeated reconnect attempts 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
f5275181a57c3010e3773b646acd818513c21c36- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/reconnect.js b/runtime/reconnect.js index a939cf9..fcb8367 100644 --- a/runtime/reconnect.js +++ b/runtime/reconnect.js @@ -1 +1 @@ -const delay = 1000; +const delay = nextBackoff(attempt);
Preserve selection across document updates 1 modified
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
171dedea105282ad085989622bc0d35c88126de2- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
diff --git a/runtime/selection.js b/runtime/selection.js
index dd0ac91..2f292a3 100644
--- a/runtime/selection.js
+++ b/runtime/selection.js
@@ -1 +1 @@
-replace(document);
+reconcile(document, { preserveSelection: true });
Make every control reachable by keyboard Status unavailable
Snapshot details · main merge-base → working tree
- Repository
/Users/maximilian/workspace/leaf- Current commit
5bd75b8ace5ecbc5d96cd70a90a37411c9542117- Comparison base
6f6d349144225c431962eb2ddab1cf55a82b6707- Captured
- 22 Oct 2026, 10:00 PT · illustrative snapshot
- Scope
- Tracked changes from the merge-base, including staged and unstaged edits. Untracked files excluded.
The worktree is in the supplied set, but its diff was not captured. Its change size is unknown.