spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

diff: the session's start asks nothing of the repository; /diff or the first edit pins it when it comesBrowse files
poteat authored on Sep 15, 2026 parent f96c3b4 · commit 733a0dec8fa8
3 changed files+67 -17compared with f96c3b4
Mmods/diff/README.md
Mmods/diff/hooks/register.ts
Mmods/diff/tests/register.test.ts
@@ -47,7 +47,7 @@
4747
4848 | event | what the hook does |
4949 | --- | --- |
50-| `session.start` | Binds the engine once, registers `/diff` (a session where another `/diff` is listed leaves the plugin idle), and pins the repository. |
50+| `session.start` | Binds the engine once and registers `/diff` (a session where another `/diff` is listed leaves the plugin idle); asks nothing of the repository, which `/diff` or the first edit pins when it comes. |
5151 | `ui.render` of `PromptHint` | Reads the terminal's width, which decides whether the first edit opens the pane. |
5252 | `ui.render` of `Pane` | Draws the pane: docked, the header, base line, source picker, file list and toggles over the window of hunks; inline, the dialog. |
5353 | `command.run` of `diff` | Opens or closes the pane (focused and closing on Escape without the fullscreen layout), says which, and remembers the choice. |
@@ -29,9 +29,9 @@
2929 * Registers the diff pane: `/diff` once the built-in stands down, the
3030 * pane's drawing and refresh, its opening on Claude's first edit, the ask.
3131 *
32- * `session.start` registers `/diff`, binds the host every pinned backend
33- * reads through (currentOf: the latest start's, the engine only before
34- * bind()), and pins the backend (backendOf), asked again on `/diff`.
32+ * `session.start` registers `/diff` and binds the host (currentOf: the
33+ * latest start's) and asks nothing of the repository; `/diff` or the
34+ * first edit pins the backend (backendOf) when it first needs it.
3535 *
3636 * @param on the engine's registrar
3737 */
@@ -563,11 +563,7 @@
563563 if (!Names.BUILTIN_HOLDS_PATTERN.test(reason)) {
564564 engine.uiLog(Names.registerFailedTextOf(Views.sanitizeName(reason)))
565565 }
566-
567- return
568566 }
569-
570- await pinBackend(engine)
571567 }
572568
573569 on('session.start', async ($, e, next) => {
@@ -8,7 +8,19 @@
88 tier('builtin')
99
1010 describe('register', () => {
11- test('/diff at boot joins the boot probe, then asks again', async ($, on) => {
11+ test('the start asks nothing of git and registers /diff', async ($, on) => {
12+ const world = Fixtures.inRepository(on)
13+
14+ await $.session.start(Fixtures.SESSION)
15+
16+ expect(world.runs, "no git, as the built-in's start runs none").toEqual([])
17+
18+ expect(await $.command.run(Fixtures.DIFF), '/diff was registered').toEqual({
19+ text: 'Diff panel shown',
20+ })
21+ })
22+
23+ test('/diff whose probe never answers probes once more', async ($, on) => {
1224 const probes: (readonly string[])[] = []
1325 const clock = Fixtures.startsSession(on)
1426
@@ -24,26 +36,42 @@
2436 return { value: Fixtures.NOT_A_REPOSITORY }
2537 })
2638
27- const booting = $.session.start(Fixtures.SESSION)
39+ await $.session.start(Fixtures.SESSION)
2840
29- await clock.settle()
30-
3141 const ran = $.command.run(Fixtures.DIFF)
3242
3343 await clock.settle()
3444
35- expect(probes, 'the boot probe, which /diff joined').toHaveLength(1)
45+ expect(probes, "this /diff's probe, unanswered yet").toHaveLength(1)
3646
3747 await clock.advance(Limits.GIT_TIMEOUT_MS)
38- await booting
3948
4049 expect(await ran).toEqual({
4150 text: expect.stringContaining("isn't in a git repository"),
4251 })
4352
44- expect(probes, 'then one more of its own').toHaveLength(2)
53+ expect(probes, 'then one more, which answered').toHaveLength(2)
4554 })
4655
56+ test('two /diff typed together probe the repository once', async ($, on) => {
57+ const world = Fixtures.inRepository(on)
58+
59+ await $.session.start(Fixtures.SESSION)
60+
61+ const [first, second] = await Promise.all([
62+ $.command.run(Fixtures.DIFF),
63+ $.command.run(Fixtures.DIFF),
64+ ])
65+
66+ const probes = world.runs.filter(run =>
67+ run.argv.includes('--show-toplevel'),
68+ )
69+
70+ expect(first.text).toMatch(/^Diff panel (shown|hidden)$/)
71+ expect(second.text).toMatch(/^Diff panel (shown|hidden)$/)
72+ expect(probes, 'the second joined the probe in flight').toHaveLength(1)
73+ })
74+
4775 test('outside a repository /diff says so, opens nothing', async ($, on) => {
4876 const opened: string[] = []
4977
@@ -77,12 +105,20 @@
77105
78106 test('when the built-in holds /diff, the mod stands down', async ($, on) => {
79107 const logged: string[] = []
108+ const runs: Args<'process.run'>[] = []
80109
81110 mock.clock(on)
82111 on('session.start', ($, e) => ({ cwd: e.cwd }))
83112 on('command.register', () => ({ deny: Fixtures.BUILTIN_HOLDS }))
84113 on('command.run', () => ({ text: 'the built-in /diff ran' }))
114+ on('tool.call', () => ({ result: 'edited' }))
85115
116+ on('process.run', ($, e) => {
117+ runs.push(e)
118+
119+ return { value: Fixtures.gitIn(e.argv) }
120+ })
121+
86122 on('ui.log', ($, e) => {
87123 logged.push(e.text)
88124
@@ -95,7 +131,15 @@
95131 text: 'the built-in /diff ran',
96132 })
97133
134+ await $.tool.call({
135+ tool: 'Edit',
136+ file_path: '/work/app.ts',
137+ old_string: '1',
138+ new_string: '2',
139+ })
140+
98141 expect(logged).toEqual([])
142+ expect(runs, 'idle: no git for /diff or the edit').toEqual([])
99143 })
100144
101145 test('a refusal the built-in did not cause is said aloud', async ($, on) => {
@@ -127,10 +171,16 @@
127171
128172 await $.session.start(Fixtures.SESSION)
129173
174+ expect(world.runs, 'the start ran nothing').toEqual([])
175+
130176 expect(await $.command.run(Fixtures.DIFF)).toEqual({
131177 text: 'Diff panel shown',
132178 })
133179
180+ expect(world.runs[0]?.argv, '/diff found the repository first').toContain(
181+ '--show-toplevel',
182+ )
183+
134184 expect(world.opened).toEqual([
135185 { id: 'diff', title: 'Diff', holdToasts: true },
136186 ])
@@ -322,9 +372,13 @@
322372 expect(before.text).toContain("isn't in a git repository")
323373 expect(after.text).toBe('Diff panel shown')
324374 expect(world.opened[0]?.id).toBe('diff')
325- expect(probes).toHaveLength(3)
326375
327376 expect(
377+ probes,
378+ 'the first two /diff probed; the third was pinned',
379+ ).toHaveLength(2)
380+
381+ expect(
328382 world.runs.some(run => run.argv.includes('--git-dir=/else/.git')),
329383 ).toBe(false)
330384
@@ -380,7 +434,7 @@
380434 const probes = runs.filter(run => run.argv.includes('--show-toplevel'))
381435
382436 expect(text).toContain("isn't in a git repository")
383- expect(probes, "the boot's, then this /diff's; no retry").toHaveLength(2)
437+ expect(probes, "this /diff's alone; no retry").toHaveLength(1)
384438 })
385439
386440 test('/diff on a narrow terminal: the resize line', async ($, on) => {