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
| 1 | import type { Args, On } from 'claude-code' |
| 2 | import { mock } from 'claude-code/testing' |
| 3 | |
| 4 | import { gitIn } from './git-in.js' |
| 5 | import { HINT_DRAWN } from './hint-drawn.js' |
| 6 | import { keeping } from './keeping.js' |
| 7 | import { REPOSITORY } from './repository.js' |
| 8 | import { startsSession } from './starts-session.js' |
| 9 | |
| 10 | /** |
| 11 | * A session in a repository git answers for from a script (REPOSITORY, in |
| 12 | * /work, when none is given), keeping what the plugin does there. |
| 13 | * |
| 14 | * Kept: each git run, ring move, pane opened or closed, status line. The clock |
| 15 | * starts at 0 and the engine draws the hint. A test that rewrites the |
| 16 | * script between calls changes what git answers next. |
| 17 | * |
| 18 | * @param on the test's `on` |
| 19 | * @param script git's output for each invocation whose line holds the key |
| 20 | * @param stored what the plugin's store holds at the start |
| 21 | * @returns the runs, the ring's moves, the panes opened and closed, the |
| 22 | * statuses, the clock |
| 23 | */ |
| 24 | export function inRepository( |
| 25 | on: On, |
| 26 | script: Readonly<Record<string, string>> = REPOSITORY, |
| 27 | stored: Readonly<Record<string, unknown>> = {}, |
| 28 | ) { |
| 29 | const runs: Args<'process.run'>[] = [] |
| 30 | const focused: Args<'ui.focus'>[] = [] |
| 31 | const statuses: (string | undefined)[] = [] |
| 32 | const opened = keeping<Args<'ui.open'>>() |
| 33 | const closed = keeping<Args<'ui.close'>>() |
| 34 | const clock = startsSession(on) |
| 35 | |
| 36 | on('process.run', ($, e) => { |
| 37 | runs.push(e) |
| 38 | |
| 39 | return { value: gitIn(e.argv, script) } |
| 40 | }) |
| 41 | |
| 42 | on('ui.focus', (_engine, e) => { |
| 43 | focused.push(e) |
| 44 | |
| 45 | return {} |
| 46 | }) |
| 47 | |
| 48 | on('ui.status', ($, e) => { |
| 49 | statuses.push(e.text) |
| 50 | |
| 51 | return { value: undefined } |
| 52 | }) |
| 53 | |
| 54 | on('ui.open', opened.hook) |
| 55 | on('ui.close', closed.hook) |
| 56 | on('ui.invalidate', () => ({ value: undefined })) |
| 57 | on('ui.render', { component: 'PromptHint' }, () => HINT_DRAWN) |
| 58 | on('session.messages', () => ({ value: [] })) |
| 59 | mock.store(on, stored) |
| 60 | |
| 61 | return { |
| 62 | runs, |
| 63 | focused, |
| 64 | opened: opened.kept, |
| 65 | closed: closed.kept, |
| 66 | statuses, |
| 67 | clock, |
| 68 | } |
| 69 | } |