Feedback that comes back as a prompt. A Claude Code skill that turns findings, plans, or backlog triages into a single-file interactive HTML review page — the reviewer clicks per-item decision chips, types notes in place, and copies everything back out as one structured prompt. No backend: it opens from file:// or any static host, works offline, and survives reload via localStorage.
Formerly interactive-feedback-report — old GitHub links redirect here.
Demo page with synthetic data (live HTML). Decision items come first, each with its actual options ("Ship variant B" / "Extend the test") rather than a generic approve — so the copied prompt carries real decisions.
You: I triaged our 70 open issues — here's the report. Turn it into an HTML
I can give feedback on, especially the ones that need my decision.
Claude: [invokes promptback]
→ builds review.html: decision items first (custom option chips),
then ratifiable close-candidates, then the build queues
→ verifies chips/persistence/copy in a real browser
→ opens it for you
You: [click through, add notes, hit "Copy decisions as prompt", paste back]
Claude: [applies every decision — no retyping, no lost context]
The copied prompt looks like:
Feedback on the Q3 storefront backlog triage. Apply these decisions:
- [KEEP-FIX] #18 — Legacy checkout: delete or keep?
- [SHIP] #42 — Checkout A/B test: ship variant B?
- [note] #57 — Search vendor renewal — Get one more quote first, decide by Friday.
Read docs/backlog-triage.md for full context before acting.
Claude Code:
# Plugin install (recommended)
/plugin marketplace add wan-huiyan/promptback
/plugin install promptback@wan-huiyan-promptback
# Git clone — copy the skill directory itself, not the repo root
git clone https://github.com/wan-huiyan/promptback.git /tmp/promptback
cp -R /tmp/promptback/plugins/promptback/skills/promptback ~/.claude/skills/promptback(Cloning the repo straight into ~/.claude/skills/promptback does not work — SKILL.md
lives at plugins/promptback/skills/promptback/, and a second copy at the repo root is
exactly the duplicate that goes stale, so the test suite forbids one. This README said
otherwise until v2.1.0.)
Cursor (2.4+):
npx skills add wan-huiyan/promptback --global
# or clone into ~/.cursor/skills/- One self-contained
.html— inline CSS/JS, no build step, no server, no dependencies. - Per-item widgets with single-select chips + a free-text note; answered items glow so progress is visible.
- Question-specific options where a real decision is needed (
data-optsper item), generic approve/revise/hold/drop elsewhere. - localStorage persistence — the reviewer can close the tab mid-review and resume later.
- A copy-as-prompt dock — one click collects every marked item into a structured, cold-startable prompt (with clipboard-API and
execCommandfallbacks). - A browser-based verification recipe — chip persistence across reload, deselect behavior, prompt construction, overflow geometry — so the page ships tested, not hoped-for.
| Flat report + chat feedback | promptback | |
|---|---|---|
| Reviewer effort | Re-type each decision into chat, from memory | Click a chip, optionally add a note |
| Decision fidelity | "Approve the third one… no, the other third one" | Stable item ids; options are the item's real choices |
| Interruptions | Feedback lost if the chat/tab resets | Picks persist in localStorage |
| Handback | Free-text the agent must re-parse | One structured prompt, cold-startable |
| Infrastructure | — | None (single file, file://-safe) |
| Step | What happens |
|---|---|
| 1 | Items are rendered as .fb widgets: stable data-id, human data-q title, optional data-opts decision chips |
| 2 | One JS injector builds every chip row (consistency; adding an option is a one-line change) |
| 3 | Selections/notes save to a versioned localStorage key; empty records are pruned; reload restores |
| 4 | The fixed dock's buildPrompt() emits - [DECISION] title — note lines plus a cold-start instruction line |
| 5 | Copy uses clipboard.writeText(t).then(ok, fallback) — the fallback chain matters (see Design Decisions) |
| 6 | The page is verified in a real browser via DOM evaluation before it ships |
writeText(t).then(ok, fallback), nevertry/catch— a blocked clipboard (iframe withoutallow="clipboard-write", headless) returns a rejected Promise, not a sync throw. Thetry/catchversion shows "Copied ✓" while copying nothing, and it only breaks in the embedded context, so local testing passes.- Decision items get their real options. A generic "approve" chip on "delete or keep the legacy page?" loses the answer.
data-optsper item keeps the copied prompt decision-bearing ([KEEP-FIX],[SHIP]). - Every widget attribute is escaped, and verified by reading it back out.
data-optsis single-quoted, so an apostrophe in a label (Haven't run it) closes it early and the widget loop throws — measured on the demo page, 4 of 7 widgets survive if it hits the fifth and 0 of 7 if it hits the first, killing the copy button either way.data-qis double-quoted and fails more quietly: a raw"truncates the title with no error at all. A page-level HTML checker passes both, because it validates structure and never parses an attribute value. So the check reads the attributes, not the page. - The copied prompt must cold-start the recipient. For your own next agent session, append "read
<paths>for context". For a client recipient, drop internal paths and say "paste this into your reply" — decide the audience before writing the copy string. - Versioned, low-entropy storage keys (
myreport_feedback_v1) — versioning prevents schema collisions with old saved input; low entropy avoids tripping CI secret scanners (gitleaks' generic-api-key rule flags high-entropy strings). - Addendum mode for live pages — if the reviewer may already be ticking a shipped page, only ever add widgets with new ids; never rename existing
data-id/data-q(ids key the store, titles feed the prompt).
- No aggregation across reviewers — localStorage is per browser profile. Two reviewers means two copied prompts to merge (or graduate to a backend endpoint; the skill notes the upgrade path).
- Not a form service — no validation, no auth, no server-side record. The durable artifact is the copied prompt, not the page state.
- localStorage is origin-scoped — moving the file to a different host/origin orphans earlier picks (they're not lost, just not visible from the new origin).
- Clipboard inside iframes needs the parent's cooperation (
allow="clipboard-write"); the fallback keeps the feature working but with an extra prompt dialog in the worst case.
None at runtime — vanilla HTML/CSS/JS in one file. For the verification step, any browser-automation MCP (e.g. Playwright) plus python3 -m http.server; without them, verify manually in a browser.
Quality checklist — what a page built with this skill guarantees
- Every
data-opts,data-qanddata-idreads back out of the HTML intact — option lists parse to non-empty[value, label]pairs, titles are not truncated - Chips + notes persist across reload (versioned localStorage key)
- Clicking the active chip deselects; empty records are pruned from the store
-
#fbCountreflects the store; answered widgets are visually marked -
buildPrompt()emits every marked item as- [DECISION] title — note - Copy works via clipboard API and falls back to
execCommand/prompt() - No horizontal overflow; dock pinned to the viewport bottom
- Test entries removed from localStorage before handoff (reviewer starts blank)
- All demo/example data is synthetic
- skill-anonymizer — the client-data audit used before publishing this skill
- data-provenance-verifier — provenance checks for skills that ship datasets
- 2.1.0 (2026-08-07) — Escape every widget attribute, and verify by reading them back out. An apostrophe in a
data-optslabel closes that single-quoted attribute early and the widget loop throws: measured on the demo page, 4 of 7 widgets survive if it hits the fifth, 0 of 7 if it hits the first, and the copy button dies either way. A raw"indata-qis quieter — the title truncates with no error, and a decision comes back attached to half a question. New: the escape rule for both, a verification step that parses the attributes and checks their shape, a fourth page piece that warns the reviewer on screen when a widget rendered no chips, and the reusable lesson that a page-level checker returns CLEAN on a page whose every widget is dead. Also fixed: a Node test harness's fake clipboard is silently discarded on Node 22+, and the README's git-clone install named a path with noSKILL.mdin it. - 2.0.0 (2026-07-17) — Renamed from
interactive-feedback-reporttopromptback. Identifier rename only, no functional change; major bump because the install string changed to/plugin install promptback@wan-huiyan-promptback. Old GitHub URLs redirect. - 1.1.0 (2026-07-17) — First full owner round-trip confirmed in production; new guidance: define tick SEMANTICS ("Meaning of ticks" legend in
buildPrompt()+ a.meaningline on the widget) whenever a chip means "adopt the recommendation" — a bare [APPROVE] on a recommendation-shaped question is ambiguous to the receiving session. - 1.0.0 (2026-07-16) — Initial public release: widget/state/dock pattern, question-specific decision chips, clipboard fallback chain, addendum mode, browser verification recipe, synthetic demo page + screenshots.
MIT — see LICENSE. All examples and screenshots use synthetic data.

