Feedbacks — Unified Skill
This skill handles everything: first-time setup, launching the capture app, watching live captures, and analyzing sessions.
It works from any project directory.
FEEDBACKS_HOME: Read ~/.claude/settings.json and extract the path from mcpServers.feedbacks.args (the arg containing mcp_server.py), then take its parent directory.
Cache the result for the session. If not found, tell the user to install: git clone https://github.com/ytubecoder/feedbacks && cd feedbacks && claude mcp add feedbacks -- python3 $(pwd)/mcp_server.py
Determine what to do
Check $ARGUMENTS.command:
- If
setup → go to Setup
- If
start → go to Start
- If
watch → go to Watch (Live MCP Bridge)
- If
analyze or a file/directory path → go to Analyze
- If omitted → Auto-detect:
Auto-detect logic
- Resolve FEEDBACKS_HOME (see above). Check it exists:
ls $FEEDBACKS_HOME/start.sh
- If not → tell the user the feedbacks project isn't installed and provide clone instructions
- Check if
whisper.cpp/build/bin/whisper-server exists in FEEDBACKS_HOME
- If not → tell the user: "First time? Running setup." → go to Setup
- Check if whisper-server is already running:
curl -sf http://localhost:8081/health
- If not running → go to Start
- If running → check for active live capture via
feedbacks_status() MCP tool
- If active capture → go to Watch (Live MCP Bridge)
- If no active capture → go to Analyze (app is already up, user probably has a session to review)
Setup
Install whisper.cpp and download a model. Run these commands:
cd $FEEDBACKS_HOME
# Clone and build whisper.cpp
git clone https://github.com/ggerganov/whisper.cpp
cd whisper.cpp
cmake -B build
cmake --build build -j --config Release
cd ..
# Download the base English model
sh whisper.cpp/models/download-ggml-model.sh base.en
Run each step, check for errors between steps. If cmake or build tools are missing, install them:
sudo apt update && sudo apt install -y build-essential cmake
After setup completes, tell the user:
Setup complete! Run /feedbacks again to start the capture app.
Start
Launch the capture app and whisper server.
- First, check if ports 8080/8081 are already in use:
curl -sf http://localhost:8081/health && echo "Whisper already running" || echo "Whisper not running"
curl -sf http://localhost:8080/ && echo "App already running" || echo "App not running"
- Determine output directory based on context:
- If
FEEDBACKS_OUTPUT_DIR is already set in the environment, use it
- If launched from a project with a ticket/feature context (e.g., ticket takeaway), set it to:
{project_root}/.feedbacks/{ticket-id}/ (e.g., ~/projects/myapp/.feedbacks/FEAT-42/)
- If launched from a project without ticket context, set it to:
{project_root}/.feedbacks/
- If launched standalone (from feedbacks project itself), default to:
./sessions/ (the feedbacks project default)
- If not running, start them:
FEEDBACKS_OUTPUT_DIR=/path/to/output cd $FEEDBACKS_HOME && ./start.sh whisper.cpp/models/ggml-base.en.bin
Run this in the background so the user can continue using Claude Code.
- Tell the user:
Feedbacks is running at http://localhost:8080
Sessions will auto-save to: {output_dir}
Open it in Chrome, capture your session, then run /feedbacks to analyze it.
With ticket context:
If invoked as /feedbacks start {ticket-ID}:
- Include
?ticket={ticket-ID} in the URL: http://localhost:8080/?ticket={ticket-ID}
- The ticket ID will be pre-filled in the capture UI and embedded in the session output
- After recording, the ZIP filename will include the ticket ID:
feedbacks-{ticket-ID}-{timestamp}.zip
- Tell the user:
Feedbacks is running at http://localhost:8080/?ticket={ticket-ID}
Open it in Chrome, capture your session, then run /feedbacks to analyze it.
Saving session for /review integration:
After downloading the ZIP, if a ticket ID was set, suggest the unpack command:
unzip ~/Downloads/feedbacks-{ticket-ID}-*.zip -d docs/features/{ticket-ID}/feedbacks/$(date +%Y%m%d-%H%M%S)/
Then note: "Next time you run /review {ticket-ID}, it will automatically detect and use this session."
Watch (Live MCP Bridge)
Stream live capture data into the current Claude Code session via MCP tools.
This enables real-time awareness of what the user is seeing and saying during a capture.
Prerequisites
- Feedbacks server must be running (
python3 server.py in FEEDBACKS_HOME)
- The
feedbacks MCP server must be registered in ~/.claude/settings.json
- A capture must be active in the browser (user clicked "New Capture" at http://localhost:8080)
How to watch
- Call
feedbacks_status() MCP tool to check for an active capture
- If no active capture, tell the user to start one in the browser
- Call
feedbacks_poll(since=0) to get all events so far
- Review the transcript text inline. For screenshots, read key ones with the Read tool (they are PNG files on disk at the paths returned by the poll)
- Note the
latestSeqNum from the response
- Continue your current task (e.g., /review, coding, etc.)
- Periodically call
feedbacks_poll(since=<lastSeqNum>) to get new events
- A good cadence: poll after each substantive response, or when the user says "check capture"
- When the poll returns
active: false, the capture has ended — summarize what you observed
Integration with other tasks
The watch mode is designed to augment other workflows:
- During /review: The user narrates what they're reviewing while you see screenshots + transcript
- During debugging: The user shows you the bug visually while describing it
- During design feedback: The user walks through a UI while commenting on issues
You don't need to analyze every screenshot — focus on transcripts for context, and only read screenshots when the user says something like "look at this", "see here", or references something visual.
Example flow
User: /feedbacks watch
Claude: [calls feedbacks_status()] Active capture found: feedbacks-2026-04-03-...
Claude: [calls feedbacks_poll(since=0)] Got 5 events - 2 transcripts, 3 screenshots
Claude: "I can see your capture. You've mentioned the login form has a layout issue. Let me read that screenshot..."
Claude: [reads screenshot file] "I can see the form fields are overlapping on mobile width..."
... user continues talking ...
Claude: [calls feedbacks_poll(since=5)] 3 new events
Analyze
Ingest and analyze a captured feedback session.
Finding the session
If a path was provided in $ARGUMENTS.command, use it directly. Otherwise:
Check server output directory first — query the running server for its config:
curl -sf http://localhost:8080/config
If it returns an outputDir, use Glob to find the latest feedbacks-*/session.md in that directory.
Sessions are saved as extracted directories (not ZIPs) with this structure:
{outputDir}/feedbacks-{timestamp}/
session.md
player.html
images/001.png, 002.png, ...
Check project-specific .feedbacks/ directory — if running from a project context:
ls -dt {project_root}/.feedbacks/*/session.md 2>/dev/null | head -1
Fallback to Downloads — check the user's download directory for ZIP files:
Processing the session
Ticket-aware analysis:
When reading session.md, check for a Ticket: {ID} line after the header. If present:
- Note the ticket ID in the analysis output: "This session is linked to ticket {ID}"
- If
docs/features/{ID}/ exists in the current project, suggest archiving: "Consider saving this session to docs/features/{ID}/feedbacks/ for /review integration"
- If the session is already in
docs/features/{ID}/feedbacks/, note: "Session already archived for /review"
Read session.md from the session directory
Parse each section — they follow this pattern:
## TIMESTAMP

**[Marker N — user clicked at (x, y)]**
> Transcript text...
Coherence pass: The transcript was progressively transcribed in ~10s chunks. Quickly scan it for:
- Obvious chunk-boundary artifacts (cut-off sentences between sections)
- Repeated words at boundaries
- If you spot issues, silently smooth them in your interpretation — don't flag minor STT artifacts to the user
For each section, read the referenced screenshot image using the Read tool (it supports images)
Correlate markers with speech: When the transcript says "this", "here", "that area" etc., map those deictic references to the numbered markers visible in the screenshot. The marker number tells you exactly what the user was pointing at.
Describe each screenshot using this structured format. Extract as much context as possible from the image itself — the user's voice only tells half the story.
For each screenshot, produce:
### Screenshot N · {timestamp}
**Screen:** {what app/page is shown — e.g., "YouTube video player", "Settings > Billing page", "VS Code editor with server.py open"}
**URL:** {visible URL from browser address bar, or "not visible" if browser chrome is offscreen}
**Page title:** {tab title or page heading if readable}
**Cursor:** {where the cursor is — e.g., "hovering over the Subscribe button", "in the search input field", "not visible"}
**Marker {N}:** {what the marker is pointing at — e.g., "the 'Save' button in the toolbar", "the third pricing card", "a validation error message below the email field"}
**Interaction:** {what the user did — click, drag-select, hover. Derive from marker type: red circle = click, red rectangle = drag selection}
**Visible state:** {anything notable about the current UI state — e.g., "modal is open", "dropdown is expanded", "form has validation errors", "loading spinner visible", "dark mode active"}
**User said:** "{transcript text}"
**Interpretation:** {one sentence combining what the user pointed at with what they said — e.g., "User clicked the Save button and noted it doesn't provide visual feedback on success"}
Field rules:
- Screen: Identify the app from visual cues (favicon, logo, URL, layout). Be specific: "Stripe Dashboard > Customers list" not just "a dashboard".
- URL: Read it literally from the address bar. Include query params if visible. Write "not visible" if the address bar is cropped or offscreen — don't guess.
- Cursor: Describe position relative to UI elements, not pixel coordinates. "On the dropdown arrow next to the user avatar" is useful. "(450, 320)" is not.
- Marker: Describe what the marker is on top of, not the marker itself. "The red 'Delete' button" not "a red circle".
- Visible state: Only note what's relevant. A normal page load needs no comment. An error toast, a half-loaded spinner, a disabled button — those matter.
- Interpretation: This is the key output. Fuse the visual evidence (marker position, UI state) with the verbal evidence (transcript). One clear sentence.
If a screenshot has no marker and no transcript (auto-captured context frame), describe it briefly:
### Screenshot N · {timestamp}
**Screen:** {app/page}
**Context frame** — no user interaction. {Brief note of what's visible, e.g., "Page fully loaded, no errors."}
After presenting all sections, provide a summary analysis:
- Feedback points: Each issue the user raised, with screenshot number, marker, and one-line description
- Navigation path: The sequence of screens/pages the user visited (reconstructed from URLs and page titles across screenshots)
- UI/UX issues: Problems visible in the screenshots that the user may or may not have mentioned
- Suggested action items: Concrete fixes or investigations, each linked to a specific screenshot
Important
- Read images with their full path:
<session-dir>/images/NNN.png
- The transcript comes from Whisper (local or cloud) and may have minor errors — interpret charitably
- Screenshots contain numbered red circle markers or red selection boxes — these show exactly where the user clicked/selected
- Focus on understanding the user's intent by combining the visual markers with the spoken context
1---2name: feedbacks-23description: All-in-one skill — setup whisper.cpp, launch the capture app, analyze a session, or watch a live capture via MCP. Works from any project.4---56# Feedbacks — Unified Skill78This skill handles everything: first-time setup, launching the capture app, watching live captures, and analyzing sessions.9It works from **any project directory**.1011**FEEDBACKS_HOME:** Read `~/.claude/settings.json` and extract the path from `mcpServers.feedbacks.args` (the arg containing `mcp_server.py`), then take its parent directory.12Cache the result for the session. If not found, tell the user to install: `git clone https://github.com/ytubecoder/feedbacks && cd feedbacks && claude mcp add feedbacks -- python3 $(pwd)/mcp_server.py`1314## Determine what to do1516Check `$ARGUMENTS.command`:1718- If `setup` → go to **Setup**19- If `start` → go to **Start**20- If `watch` → go to **Watch (Live MCP Bridge)**21- If `analyze` or a file/directory path → go to **Analyze**22- If omitted → **Auto-detect**:2324### Auto-detect logic25261. Resolve FEEDBACKS_HOME (see above). Check it exists: `ls $FEEDBACKS_HOME/start.sh`27 - If not → tell the user the feedbacks project isn't installed and provide clone instructions282. Check if `whisper.cpp/build/bin/whisper-server` exists in FEEDBACKS_HOME29 - If not → tell the user: "First time? Running setup." → go to **Setup**303. Check if whisper-server is already running: `curl -sf http://localhost:8081/health`31 - If not running → go to **Start**32 - If running → check for active live capture via `feedbacks_status()` MCP tool33 - If active capture → go to **Watch (Live MCP Bridge)**34 - If no active capture → go to **Analyze** (app is already up, user probably has a session to review)3536---3738## Setup3940Install whisper.cpp and download a model. Run these commands:4142```bash43cd $FEEDBACKS_HOME4445# Clone and build whisper.cpp46git clone https://github.com/ggerganov/whisper.cpp47cd whisper.cpp48cmake -B build49cmake --build build -j --config Release50cd ..5152# Download the base English model53sh whisper.cpp/models/download-ggml-model.sh base.en54```5556Run each step, check for errors between steps. If `cmake` or build tools are missing, install them:57```bash58sudo apt update && sudo apt install -y build-essential cmake59```6061After setup completes, tell the user:62> Setup complete! Run `/feedbacks` again to start the capture app.6364---6566## Start6768Launch the capture app and whisper server.69701. First, check if ports 8080/8081 are already in use:71 ```bash72 curl -sf http://localhost:8081/health && echo "Whisper already running" || echo "Whisper not running"73 curl -sf http://localhost:8080/ && echo "App already running" || echo "App not running"74 ```752. **Determine output directory** based on context:76 - If `FEEDBACKS_OUTPUT_DIR` is already set in the environment, use it77 - If launched from a project with a ticket/feature context (e.g., ticket takeaway), set it to:78 `{project_root}/.feedbacks/{ticket-id}/` (e.g., `~/projects/myapp/.feedbacks/FEAT-42/`)79 - If launched from a project without ticket context, set it to:80 `{project_root}/.feedbacks/`81 - If launched standalone (from feedbacks project itself), default to:82 `./sessions/` (the feedbacks project default)833. If not running, start them:84 ```bash85 FEEDBACKS_OUTPUT_DIR=/path/to/output cd $FEEDBACKS_HOME && ./start.sh whisper.cpp/models/ggml-base.en.bin86 ```87 Run this in the background so the user can continue using Claude Code.884. Tell the user:89 > Feedbacks is running at **http://localhost:8080**90 > Sessions will auto-save to: `{output_dir}`91 > Open it in Chrome, capture your session, then run `/feedbacks` to analyze it.9293**With ticket context:**94If invoked as `/feedbacks start {ticket-ID}`:95- Include `?ticket={ticket-ID}` in the URL: `http://localhost:8080/?ticket={ticket-ID}`96- The ticket ID will be pre-filled in the capture UI and embedded in the session output97- After recording, the ZIP filename will include the ticket ID: `feedbacks-{ticket-ID}-{timestamp}.zip`98- Tell the user:99 > Feedbacks is running at **http://localhost:8080/?ticket={ticket-ID}**100 > Open it in Chrome, capture your session, then run `/feedbacks` to analyze it.101102**Saving session for /review integration:**103After downloading the ZIP, if a ticket ID was set, suggest the unpack command:104```bash105unzip ~/Downloads/feedbacks-{ticket-ID}-*.zip -d docs/features/{ticket-ID}/feedbacks/$(date +%Y%m%d-%H%M%S)/106```107Then note: "Next time you run `/review {ticket-ID}`, it will automatically detect and use this session."108109---110111## Watch (Live MCP Bridge)112113Stream live capture data into the current Claude Code session via MCP tools.114This enables real-time awareness of what the user is seeing and saying during a capture.115116### Prerequisites117- Feedbacks server must be running (`python3 server.py` in FEEDBACKS_HOME)118- The `feedbacks` MCP server must be registered in `~/.claude/settings.json`119- A capture must be active in the browser (user clicked "New Capture" at http://localhost:8080)120121### How to watch1221231. Call `feedbacks_status()` MCP tool to check for an active capture124 - If no active capture, tell the user to start one in the browser1252. Call `feedbacks_poll(since=0)` to get all events so far1263. Review the transcript text inline. For screenshots, read key ones with the Read tool (they are PNG files on disk at the paths returned by the poll)1274. Note the `latestSeqNum` from the response1285. Continue your current task (e.g., /review, coding, etc.)1296. Periodically call `feedbacks_poll(since=<lastSeqNum>)` to get new events130 - A good cadence: poll after each substantive response, or when the user says "check capture"1317. When the poll returns `active: false`, the capture has ended — summarize what you observed132133### Integration with other tasks134135The watch mode is designed to augment other workflows:136- **During /review**: The user narrates what they're reviewing while you see screenshots + transcript137- **During debugging**: The user shows you the bug visually while describing it138- **During design feedback**: The user walks through a UI while commenting on issues139140You don't need to analyze every screenshot — focus on transcripts for context, and only read screenshots when the user says something like "look at this", "see here", or references something visual.141142### Example flow143144```145User: /feedbacks watch146Claude: [calls feedbacks_status()] Active capture found: feedbacks-2026-04-03-...147Claude: [calls feedbacks_poll(since=0)] Got 5 events - 2 transcripts, 3 screenshots148Claude: "I can see your capture. You've mentioned the login form has a layout issue. Let me read that screenshot..."149Claude: [reads screenshot file] "I can see the form fields are overlapping on mobile width..."150... user continues talking ...151Claude: [calls feedbacks_poll(since=5)] 3 new events152```153154---155156## Analyze157158Ingest and analyze a captured feedback session.159160### Finding the session161162If a path was provided in `$ARGUMENTS.command`, use it directly. Otherwise:1631641. **Check server output directory first** — query the running server for its config:165 ```bash166 curl -sf http://localhost:8080/config167 ```168 If it returns an `outputDir`, use Glob to find the latest `feedbacks-*/session.md` in that directory.169 Sessions are saved as extracted directories (not ZIPs) with this structure:170 ```171 {outputDir}/feedbacks-{timestamp}/172 session.md173 player.html174 images/001.png, 002.png, ...175 ```1761772. **Check project-specific `.feedbacks/` directory** — if running from a project context:178 ```bash179 ls -dt {project_root}/.feedbacks/*/session.md 2>/dev/null | head -1180 ```1811823. **Fallback to Downloads** — check the user's download directory for ZIP files:183 - Check `~/.claude/memory/feedbacks_download_dir.md` for saved download path184 - Use Glob to find the latest `feedbacks-*.zip`185 - If no memory exists, ask the user for their download directory and save it to memory186 - If the path points to a `.zip` file, extract it:187 ```bash188 unzip -o <path-to-zip> -d /tmp/feedbacks-session189 ```190 Then use the extracted directory.191192### Processing the session193194**Ticket-aware analysis:**195When reading `session.md`, check for a `Ticket: {ID}` line after the header. If present:196- Note the ticket ID in the analysis output: "This session is linked to ticket {ID}"197- If `docs/features/{ID}/` exists in the current project, suggest archiving: "Consider saving this session to `docs/features/{ID}/feedbacks/` for /review integration"198- If the session is already in `docs/features/{ID}/feedbacks/`, note: "Session already archived for /review"1992001. Read `session.md` from the session directory2012. Parse each section — they follow this pattern:202 ```203 ## TIMESTAMP204 205 **[Marker N — user clicked at (x, y)]**206 > Transcript text...207 ```2083. **Coherence pass**: The transcript was progressively transcribed in ~10s chunks. Quickly scan it for:209 - Obvious chunk-boundary artifacts (cut-off sentences between sections)210 - Repeated words at boundaries211 - If you spot issues, silently smooth them in your interpretation — don't flag minor STT artifacts to the user2124. For each section, read the referenced screenshot image using the Read tool (it supports images)2135. **Correlate markers with speech**: When the transcript says "this", "here", "that area" etc., map those deictic references to the numbered markers visible in the screenshot. The marker number tells you exactly what the user was pointing at.2146. **Describe each screenshot** using this structured format. Extract as much context as possible from the image itself — the user's voice only tells half the story.215216 For each screenshot, produce:217218 ```219 ### Screenshot N · {timestamp}220221 **Screen:** {what app/page is shown — e.g., "YouTube video player", "Settings > Billing page", "VS Code editor with server.py open"}222 **URL:** {visible URL from browser address bar, or "not visible" if browser chrome is offscreen}223 **Page title:** {tab title or page heading if readable}224 **Cursor:** {where the cursor is — e.g., "hovering over the Subscribe button", "in the search input field", "not visible"}225 **Marker {N}:** {what the marker is pointing at — e.g., "the 'Save' button in the toolbar", "the third pricing card", "a validation error message below the email field"}226 **Interaction:** {what the user did — click, drag-select, hover. Derive from marker type: red circle = click, red rectangle = drag selection}227 **Visible state:** {anything notable about the current UI state — e.g., "modal is open", "dropdown is expanded", "form has validation errors", "loading spinner visible", "dark mode active"}228229 **User said:** "{transcript text}"230231 **Interpretation:** {one sentence combining what the user pointed at with what they said — e.g., "User clicked the Save button and noted it doesn't provide visual feedback on success"}232 ```233234 **Field rules:**235 - **Screen**: Identify the app from visual cues (favicon, logo, URL, layout). Be specific: "Stripe Dashboard > Customers list" not just "a dashboard".236 - **URL**: Read it literally from the address bar. Include query params if visible. Write "not visible" if the address bar is cropped or offscreen — don't guess.237 - **Cursor**: Describe position relative to UI elements, not pixel coordinates. "On the dropdown arrow next to the user avatar" is useful. "(450, 320)" is not.238 - **Marker**: Describe what the marker is *on top of*, not the marker itself. "The red 'Delete' button" not "a red circle".239 - **Visible state**: Only note what's relevant. A normal page load needs no comment. An error toast, a half-loaded spinner, a disabled button — those matter.240 - **Interpretation**: This is the key output. Fuse the visual evidence (marker position, UI state) with the verbal evidence (transcript). One clear sentence.241242 If a screenshot has no marker and no transcript (auto-captured context frame), describe it briefly:243 ```244 ### Screenshot N · {timestamp}245 **Screen:** {app/page}246 **Context frame** — no user interaction. {Brief note of what's visible, e.g., "Page fully loaded, no errors."}247 ```2482497. After presenting all sections, provide a **summary analysis**:250 - **Feedback points**: Each issue the user raised, with screenshot number, marker, and one-line description251 - **Navigation path**: The sequence of screens/pages the user visited (reconstructed from URLs and page titles across screenshots)252 - **UI/UX issues**: Problems visible in the screenshots that the user may or may not have mentioned253 - **Suggested action items**: Concrete fixes or investigations, each linked to a specific screenshot254255### Important256257- Read images with their full path: `<session-dir>/images/NNN.png`258- The transcript comes from Whisper (local or cloud) and may have minor errors — interpret charitably259- Screenshots contain numbered red circle markers or red selection boxes — these show exactly where the user clicked/selected260- Focus on understanding the user's intent by combining the visual markers with the spoken context