@@ -5,21 +5,148 @@ user-invocable: true
55allowed-tools : Bash
66---
77
8- Local-development variant of ` /askdiff ` . Starts the WS server ** and**
9- the browser UI's Vite dev server (with HMR). Vite is configured to
8+ Local-development variant of ` /askdiff ` . Starts the WS server ** and** the
9+ browser UI's Vite dev server (with HMR), and exercises the in-repo
10+ TypeScript instead of the published npm package. Vite is configured to
1011proxy ` /ws ` to the WS server, so the UI uses the same same-origin
1112` new WebSocket('ws://host/ws') ` URL in dev as in prod. The
1213` ASKDIFF_DEV_WS_TARGET ` env var tells Vite which port to forward to.
1314
14- Use this when editing ` packages/ui-browser ` and you want changes to
15- reload instantly instead of rebuilding the npm package.
15+ Use this when editing ` packages/server ` or ` packages/ui-browser ` and you
16+ want changes to reload instantly instead of rebuilding/republishing.
17+
18+ > ** Keep Step 1–3 in sync with ` .claude/skills/askdiff/SKILL.md ` .** The
19+ > diff-resolution flow (interpret → git → temp file → label) must behave
20+ > identically in both skills; only Step 4 (launch) differs. If you change
21+ > the table or the bash blocks below, change them in the user-facing
22+ > ` askdiff ` skill too.
23+
24+ ## Step 1 — figure out which diff the user wants
25+
26+ Look at the message that invoked this skill. Anything after ` /askdiff-dev `
27+ is the user's diff description (may be empty).
28+
29+ | User said | git command | Suggested label |
30+ | ---| ---| ---|
31+ | ` /askdiff-dev ` (no args) | working tree — see Step 2 | ` Working tree ` |
32+ | ` /askdiff-dev last commit ` | ` git diff HEAD~1 HEAD ` | ` HEAD~1..HEAD ` |
33+ | ` /askdiff-dev last 3 commits ` | ` git diff HEAD~3 HEAD ` | ` HEAD~3..HEAD ` |
34+ | ` /askdiff-dev the 5th latest commit ` | ` git diff HEAD~5 HEAD~4 ` | ` HEAD~5..HEAD~4 ` |
35+ | ` /askdiff-dev current branch against feature/test ` | ` git diff feature/test...HEAD ` (three-dot, PR semantics) | ` feature/test…HEAD ` |
36+ | ` /askdiff-dev main vs my branch ` | ` git diff main...HEAD ` | ` main…HEAD ` |
37+ | ` /askdiff-dev abc123 vs def456 ` | ` git diff abc123 def456 ` | ` abc123..def456 ` |
38+ | ` /askdiff-dev staged ` | ` git diff --cached ` | ` staged ` |
39+
40+ Defaults when the user is ambiguous:
41+ - "branch X against branch Y" / "X vs Y" between two named refs ⇒ three-dot
42+ (` git diff X...Y ` ) — matches how GitHub renders PRs.
43+ - Two arbitrary commits ⇒ two-dot (` git diff A B ` ).
44+ - "Nth latest commit" ⇒ that single commit's changes
45+ (` git diff HEAD~N HEAD~(N-1) ` ).
46+
47+ ### When the description is vague
48+
49+ If the description doesn't fit the table — e.g. "the commit where I added
50+ the favicon", "the last commit by my coworker David", "where we ripped out
51+ the old auth code", "the commit that broke CI last week" — pin down a
52+ single commit with the ladder below, then diff ` <sha>^..<sha> ` (same shape
53+ as the "Nth latest commit" pattern). Try in order until exactly one commit
54+ matches; if several match, pick the most recent and ** tell the user which
55+ one you chose** ; if none match, stop and ask — do not guess.
56+
57+ 1 . ** Author.** "by <name >", "<name >'s last", "by my coworker":
58+ ``` bash
59+ git log --author=< pattern> -i -1 --format=' %H %an %s'
60+ ```
61+
62+ 2 . ** Commit message.** "the migration commit", "where I bumped deps":
63+ ``` bash
64+ git log --grep=< keyword> -i -1 --format=' %H %s'
65+ ```
66+
67+ 3 . ** Diff content.** "where I added/removed/touched <thing >". ` -S ` matches
68+ when a string's count changed in any file; ` -G ` is a regex over the
69+ diff text:
70+ ``` bash
71+ git log -S" <distinctive-string>" -1 --format=' %H %s'
72+ git log -G" <regex>" -1 --format=' %H %s'
73+ ```
74+
75+ 4 . ** File history.** When you can identify the file but not the commit
76+ (e.g. "where the homepage was added" — search the working tree for a
77+ plausible path first, then ask git):
78+ ``` bash
79+ git ls-files | grep -i < hint> # find candidate path
80+ git log --follow -1 --format=' %H %s' -- < path> # most recent touch
81+ git log --follow --diff-filter=A -1 --format=' %H %s' -- < path> # commit that introduced it
82+ ```
83+
84+ Once a SHA is in hand, build the label as ` <short-sha>: <one-line gloss> `
85+ (e.g. ` d0b332b: add favicon ` ) and use ` git diff <sha>^ <sha> ` as the
86+ diff command. If the user's count and description disagree (e.g. "my 3rd
87+ previous commit, where I added a favicon" but the favicon is at HEAD~ 2),
88+ trust the description over the count and ** flag the off-by-one to the
89+ user** so they know what you picked.
90+
91+ ** Validate every ref first.** Run ` git rev-parse --verify <ref>^{commit} ` for
92+ each ref the user named directly. If any fails, stop and tell the user
93+ which ref didn't resolve — do not launch the server. (Refs returned by the
94+ search ladder are already validated by virtue of ` git log ` finding them.)
95+
96+ ## Step 2 — write the diff to a temp file
97+
98+ ``` bash
99+ diff_file=$( mktemp /tmp/askdiff-diff.XXXXXX)
100+ ```
101+
102+ (macOS ` mktemp ` only substitutes trailing X's, so the template can't have
103+ a ` .diff ` suffix. The server doesn't care about the extension.)
104+
105+ ** Working tree (no description).** Untracked files don't appear in
106+ ` git diff HEAD ` , so we union them in via ` --no-index ` :
107+
108+ ``` bash
109+ {
110+ git -C " $project_cwd " diff HEAD --no-color
111+ git -C " $project_cwd " ls-files --others --exclude-standard -z \
112+ | while IFS= read -r -d ' ' f; do
113+ git -C " $project_cwd " diff --no-index --no-color -- /dev/null " $f " || true
114+ done
115+ } > " $diff_file "
116+ ```
117+
118+ (In an empty repo with no HEAD, replace ` HEAD ` with the empty-tree SHA
119+ ` 4b825dc642cb6eb9a060e54bf8d69288fbee4904 ` .)
120+
121+ ** Description path.** Just run the resolved command:
16122
17- Run this as a single Bash command so discovered values survive into the
18- launch:
123+ ``` bash
124+ git -C " $project_cwd " diff < args> --no-color > " $diff_file "
125+ ```
126+
127+ For the description path, if the resulting file is empty, ** stop** — tell the
128+ user the requested diff is empty and don't launch. The working-tree path
129+ * can* legitimately be empty (clean tree); launch anyway and the UI will
130+ show "No changes."
131+
132+ ## Step 3 — pick a short label
133+
134+ Use the "Suggested label" column above. For the working-tree case, use
135+ ` Working tree ` . Keep it under ~ 40 chars. This becomes ` ASKDIFF_DIFF_LABEL ` .
136+
137+ ## Step 4 — launch (in-repo)
138+
139+ Run as a single Bash command so the discovered values survive into the
140+ launch. Substitute ` EXTRA_DIFF_FILE ` and ` EXTRA_DIFF_LABEL ` literally with
141+ the values from Step 2/3.
19142
20143```
21144set +e
22145
146+ # Filled in by Step 2/3.
147+ EXTRA_DIFF_FILE=""
148+ EXTRA_DIFF_LABEL=""
149+
23150# 1. Free port for the WS server (default 7837, bump until free).
24151port=7837
25152while lsof -iTCP:$port -sTCP:LISTEN -t >/dev/null 2>&1; do
@@ -36,8 +163,14 @@ if [ -f "$session_file" ]; then
36163 [ -n "$manifest_cwd" ] && project_cwd="$manifest_cwd"
37164fi
38165
39- # 3. Start the WS server.
40- cd "$project_cwd" && PORT=$port ASKDIFF_SESSION_ID="$session_id" ASKDIFF_PROJECT_CWD="$project_cwd" nohup pnpm --filter @askdiff/server exec tsx src/main.ts > /tmp/askdiff.log 2>&1 &
166+ # 3. Start the WS server (in-repo via tsx).
167+ cd "$project_cwd" \
168+ && PORT=$port \
169+ ASKDIFF_SESSION_ID="$session_id" \
170+ ASKDIFF_PROJECT_CWD="$project_cwd" \
171+ ASKDIFF_DIFF_FILE="$EXTRA_DIFF_FILE" \
172+ ASKDIFF_DIFF_LABEL="$EXTRA_DIFF_LABEL" \
173+ nohup pnpm --filter @askdiff/server exec tsx src/main.ts > /tmp/askdiff.log 2>&1 &
41174disown
42175sleep 1.5
43176head -5 /tmp/askdiff.log
@@ -81,6 +214,7 @@ echo "UI: $ui_url"
81214Then tell the user:
82215- the WS server port (visible in the ` listening on ws://... ` line)
83216- the resolved Claude session ID (from the ` claude session: ` line)
217+ - the diff label (always set)
84218- the WS log file: ` /tmp/askdiff.log `
85219- the Vite log file: ` /tmp/askdiff-ui.log `
86220- the UI URL (last echoed line) — already opened in their default browser
0 commit comments