From work-tree
Open an interactive diff review in the user's browser via `wd -c`, stream each comment back as the user writes it, and react to it (make the change, answer the question, or reply via the comment API). Use when the user says "review my changes", "open a wd review", "let me review with wd", "review with wd", or similar.
How this skill is triggered — by the user, by Claude, or both
Slash command
/work-tree:wd-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The `wd` CLI on this machine (a global npm bin) ships an interactive review mode. `wd -c` opens a side-by-side diff in the user's browser, lets them click any line number to leave an inline comment, and **streams each comment to stdout as it is saved**. You start the session, react to each comment as it arrives, and the session stays alive until the user clicks "End review" (or the process is k...
The wd CLI on this machine (a global npm bin) ships an interactive review mode. wd -c opens a side-by-side diff in the user's browser, lets them click any line number to leave an inline comment, and streams each comment to stdout as it is saved. You start the session, react to each comment as it arrives, and the session stays alive until the user clicks "End review" (or the process is killed).
Each line on wd -c stdout is one of these self-describing chunks:
--- review started ---
repos: <repo names>
files: <total file count>
url: http://127.0.0.1:<port>/
--- comment ---
**<repo>/<path>** : line <N> (<left|right>)
id: <hex> [· author: claude] [· reply-to: <hex>]
> <body line 1>
> <body line 2>
--- comment ---
**General review comment**
id: <hex>
> ...
--- comment deleted ---
id: <hex>
--- review submitted ---
count: <N>
[summary-id: <hex>]
(followed by `--- comment ---` chunks for each newly-published draft, in order, then:)
--- review batch end ---
--- review done ---
total: <N>
--- review aborted (signal) ---
The user can either post comments one-at-a-time ("Add single comment" — streams immediately) or batch them via "Start review" (drafts stay invisible until they click Submit, then everything arrives between --- review submitted --- and --- review batch end --- markers, optionally preceded by a general summary comment).
Anything on stderr is just status logging — ignore it.
Start wd -c in the background using Bash with run_in_background: true. The command blocks until the user clicks "End review", so it must not be foreground.
Before starting, walk any background tasks from earlier in this session that match wd -c or the marker-tailing Monitor (anything you yourself started for a prior review) and TaskStop them. Leaving stale wd -c shells around creates confusion: they hold ports, their monitors fire spurious events, and the user has to find them in Task Manager.
The URL for this session is announced on the FIRST --- review started --- marker (the url: line); read it from the Bash tool's output file the moment Monitor fires that marker, and keep it in conversation context. There's no on-disk URL file to cat — capturing it from the stream is the only way to learn it, which means you can never accidentally post to a review in a different worktree or a stale daemon.
Tail the output with Monitor, filtering only for marker lines. The exact output file path is reported by the Bash tool when you start the job (Output is being written to: <path>). Use a filter like:
tail -F -n +1 "<output-file>" 2>&1 \
| grep -E --line-buffered "^--- (comment|comment deleted|review started|review done|review aborted)"
Set persistent: true and timeout_ms: 3600000. Reviews can take a while.
On --- review started ---: confirm the session is live to the user, then sit and wait. Do not act until comments arrive.
On each --- comment --- event: read the last ~30 lines of the output file to get the body of the freshly-arrived comment (the Monitor only signals which marker fired, it does not deliver the body). Look at the most recent --- comment --- block.
author: claude, ignore — that's a defensive fallback.)id: value — you need it to post replies.On --- comment deleted ---: the user removed a comment they no longer cared about. Don't undo any work that's already shipped, just acknowledge.
On --- review done ---: the user closed the session. Summarise what you did in the chat (which comments triggered code changes, which got reply-only). Stop the Monitor with TaskStop.
On --- review aborted (signal) ---: same as done — wrap up and stop monitoring.
Pick the reply endpoint from the shape of the url: line you captured at the --- review started --- marker. wd -c runs in one of two modes and they post to different routes:
url: shape | Mode | Reply endpoint |
|---|---|---|
http://host:port/review/<hash> | work web scope (the normal case — wd -c registered a review scope on the singleton work web) | http://host:port/api/scopes/<hash>/comments |
http://host:port/ (no /review/ segment) | standalone server (fallback when work-web autostart failed) | http://host:port/api/comments |
Do NOT just append api/comments to the url: value — in scope mode that yields …/review/<hash>api/comments, which 404s. Parse the URL: if the path is /review/<hash>, the base is everything before /review/, and <hash> is that last segment.
Write the JSON body to a temp file and post via --data-binary "@file" — inline -d '...' will explode the moment your reply contains an apostrophe or a quote:
# Derive BASE + ENDPOINT from the captured url: line.
URL="<the url: value from the --- review started --- marker>"
if [[ "$URL" == */review/* ]]; then
BASE="${URL%/review/*}"
HASH="${URL##*/review/}"; HASH="${HASH%%/*}"
ENDPOINT="$BASE/api/scopes/$HASH/comments" # work web scope mode
else
ENDPOINT="${URL%/}/api/comments" # standalone server mode
fi
# Use mktemp, NOT $CLAUDE_JOB_DIR — that var isn't reliably set, and an empty
# value resolves to /reply.json → "Permission denied".
REPLY_JSON="$(mktemp)"
cat > "$REPLY_JSON" <<'EOF'
{"parentId":"<comment-id>","author":"claude","body":"<your reply, can contain ' and \" freely>"}
EOF
curl -s -X POST -H "Content-Type: application/json" \
--data-binary "@$REPLY_JSON" "$ENDPOINT"
rm -f "$REPLY_JSON"
If you forget the URL mid-conversation, re-scan the Bash output file from the wd -c background task — the url: line is at the top, in the first --- review started --- block.
The reply renders threaded under the original comment in the user's browser. Set author: "claude" so the UI distinguishes it visually.
side: left = old/deleted line, side: right = new/added line. Same convention as GitHub.side: general = a top-level review note, no anchor.lineContent is implied by the body.wd -c registers a distinct scope <hash> on the one shared work web server, so its URL is …/review/<hash> — the hash is what's unique per worktree, not a per-review port. Two wd -c instances in different worktrees coexist as two scopes on the same server. The URL/hash flows only through the stream you spawned, so post replies to the <hash> from your --- review started --- marker and you can't hit someone else's review. (In the standalone-server fallback each wd -c binds its own port instead.)wd -c on file edits. The watcher inside the running session reloads the browser automatically when you edit files.wd -c opens it. You only start the process.You stop monitoring when --- review done --- (or aborted) fires, and you have:
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub moberghr/cli-work-tree-manager --plugin work-tree