agentsclimarketplace

Workbench builder

Skill theagenticguy/agentic-plugins/plugins/agentic-skills/skills/workbench-builder

Public Claude Code plugin marketplace — installable skills and agents for AI coding agents. Drop-in capabilities you add with one command.

Install
npx -y skills add theagenticguy/agentic-plugins --skill workbench-builder

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Builds disposable localhost workbenches — Flask + raw sqlite3 + htmx + Server-Sent Events apps — that give an agentic coding/eval/PR/data session a live UI with no build step, npm install, or deploy. The signature move is a two-way human↔agent loop over one SQLite file: the human acts in the browser (htmx POST → SQLite → fragment + SSE invalidation), the agent acts from the terminal (httpx → SQLite → SSE), both seeing the same state update live with no reload. Ships recipes for eval viewers, PR review rooms, document review / redline surfaces, trace replays, refactor cockpits, and more. Use when the user wants a quick local UI for a coding/eval/PR/data task, OR mentions localhost workbench, eval viewer, PR review room, review/redline a document, select text and leave comments, htmx+SSE app, live invalidation, two-way agent loop, or "build me a little UI for this." Do NOT use for production apps or React/Vue/Svelte SPAs (use frontend-design), or static one-shot data pages / HTML reports (use generative-ui).

SKILL.md

13.0 KB, as published. Nobody here has run it

Contents

FileWhen to load
references/orchestrator.mdRunning the pipeline — the five phases, the subagent prompt shape, check-in cadence, stuck detection
references/write-protocol.mdCanonical write-protocol block, copied verbatim into every phase worklog and subagent prompt
references/architecture.mdThe boring-on-purpose stack — SSE-as-invalidation, the fan-out, the two-way loop, threading, gotchas
references/cdn-deps.mdVerified CDN dependency catalog — SRI hashes, the uncompressed-bytes rule, package-name traps
references/rendering.mdThe markdown/mermaid/highlight/sanitize pipeline, progressive disclosure (chip → modal/sheet), charts
references/recipes.mdThe recipe catalog — one data model + layout per workbench type, with the unique value of each
templates/app.pyBackend scaffold — SQLite schema, db helpers, SSE fan-out + publish(), partial routes, loop endpoints
templates/index.htmlFrontend scaffold — CDN tags with verified SRI, design tokens, htmx-SSE wiring, render engine, overlays
templates/terminal-helper.pyPEP 723 httpx helper the terminal/agent runs to act on shared state and close the loop
templates/worklog-skeleton.mdPer-phase worklog with the write-protocol block embedded and a Status: IN PROGRESS line

Workbench builder

One skill, one pipeline. Takes a coding/eval/PR/data task → a running localhost workbench through five phases. The heart of the work is Phase 0: deciding what KIND of workbench this is and, more importantly, what the shared state / data model is. The data model is the design — everything downstream (partials, SSE targets, loop endpoints) falls out of it. The reference implementations are the eval viewer at ${CLAUDE_PLUGIN_ROOT}/skills/workbench-builder/workbench/, the PR review room at ${CLAUDE_PLUGIN_ROOT}/skills/workbench-builder/pr-workbench/, and the document-review / redline surface at ${CLAUDE_PLUGIN_ROOT}/skills/workbench-builder/doc-review/; the templates here are generalized from them.

Pipeline at a glance

flowchart LR
    A[Phase 0<br/>Route<br/>kind + data model] --> B[Phase 1<br/>Scaffold backend<br/>app.py]
    B --> C[Phase 2<br/>Build UI<br/>index.html + partials]
    C --> D[Phase 3<br/>Wire the loop<br/>terminal helpers]
    D --> E[Phase 4<br/>Verify<br/>headless browser]
    E --> |Console error / no live update| C
    E --> F[Run it<br/>uv run app.py]

Phase 0 is inline orchestrator work — name the workbench type and write the data model. Phases 1–3 each own one artifact and can run as a general-purpose Agent against references/orchestrator.md; for a single-surface workbench it is faster to run them inline in sequence. Phase 4 is non-negotiable and runs a real browser, because curl cannot see SRI mismatches, missing JS globals, or layout overflow. Full runbook with prompts, check-in cadence, and stuck detection lives in references/orchestrator.md.

What to build

The recipe is a different data model + layout over the same stack. Route on the verb the user reached for.

User signalRecipe / scope
"eval viewer" / "show me my judge runs" / "pass/fail board"Eval viewer — evals + runs + events; status pills, history chart
"PR review room" / "review these N PRs" / "which order do I merge"PR review room — prs + pr_files + concerns + requests; collisions → merge order
"review this doc" / "let me redline this" / "select text and comment"Document review / redline — annotations; char-perfect span anchoring, agent resolves
"trace replay" / "step through this agent run" / "what did the agent do"Agent trace replay — steps timeline + tool-call detail sheet
"refactor cockpit" / "track this big refactor" / "what's left to touch"Refactor cockpit — targets + edits + progress over modules
"data cleanup" / "let me triage these rows" / "fix these records"Data-cleanup surface — rows + decisions; keep/fix/drop per row
"prompt lab" / "skill lab" / "compare these prompt variants"Prompt/skill lab — variants + cases + scores
"decision board" / "ADRs" / "log our architecture choices"ADR board — decisions + options + status
"incident timeline" / "build the postmortem timeline"Incident timeline — events ordered, severity lanes
"migration planner" / "plan this migration in waves"Migration planner — items + waves + dependency edges
"build me a little UI for this <task>"Route to the closest recipe; if none fits, design a fresh data model

If you cannot name the shared state in one sentence, stop and frame it before scaffolding — see references/recipes.md. Run end-to-end with no approval gates when the ask is clear; the whole thing is disposable and bound to 127.0.0.1, so there is nothing to roll back. Use one AskUserQuestion only when the workbench type or the central data model is genuinely ambiguous.

Write-protocol discipline

Each phase writes its artifact to disk as it goes — one unit of thought → edit the file → next unit. Partial work on disk survives timeouts and context pressure; state held in working memory does not. The canonical block lives in references/write-protocol.md and is copied verbatim into every phase worklog (templates/worklog-skeleton.md) and every subagent prompt — one source of truth, no paraphrasing. The load-bearing artifacts are app.py, templates/index.html, the per-region partials under templates/partials/, and the terminal helper(s) under scripts/. Nothing else is.

The stack, and why it's boring on purpose

Flask + raw sqlite3 (no ORM) + Jinja partials, bound to 127.0.0.1, with app.run(host="127.0.0.1", port=..., debug=True, threaded=True). threaded=True keeps the long-lived SSE stream from blocking other requests; debug=True gives hot reload while you reshape the UI mid-session. "Boring" means no toolchain — no npm, no bundler, no build step, no deploy — not no capability. The capability comes from how the pieces compose:

  • SSE is an invalidation signal, not data transport. A state change emits a tiny NAMED event (event: <region>\ndata: stale). The browser opens ONE EventSource via the htmx SSE extension on <body> (hx-ext="sse" sse-connect="/events"); each live region carries hx-trigger="sse:<region>" + hx-get="/partials/<region>", so a named event re-fetches exactly that one server-rendered partial over a normal GET. A fan-out of subscriber queues backs publish(*targets). No payload, no client state model. (See workbench/app.py publish()//events and index.html.)
  • The two-way loop is what makes it a workbench, not a dashboard. Human acts in the browser; terminal/agent acts via httpx; both share one SQLite file. The human→agent channel — a requests table plus /claude/queue (pull) and /claude/respond (answer) — closes the loop so the human steers and the agent answers, both watching the same state live. (See pr-workbench/app.py and scripts/review_loop.py.)
  • Terminal helpers are PEP 723 inline-dep scripts (# /// scriptdependencies = ["httpx"]) run with uv run.

CDN libraries load with verified Subresource Integrity hashes. Hash the uncompressed bytes (curl -sL -H "Accept-Encoding: identity" … | openssl dgst -sha384 -binary | openssl base64 -A) because the browser hashes the decompressed file — see references/cdn-deps.md for the full catalog and the package-name traps (highlight.js browser build, non-min marked-highlight, d3-before-Plot).

When NOT to use this skill

  • A production app, an authenticated multi-user service, or a React/Vue/Svelte SPA. Use frontend-design. This skill ships a 127.0.0.1, no-auth, throwaway surface — it is the opposite of production.
  • A static, one-shot data page or a shareable HTML report with no live updates and no agent loop. Use generative-ui — a self-contained file is the right tool when nothing changes after render.
  • A read-only dashboard where nothing acts back. If there is no human↔agent loop, you do not need SSE or SQLite — a static page is simpler. A workbench earns its stack only when both sides act on shared state.
  • A persistent internal tool. If it needs auth, deploy, or a real DB, this is a prototype that has outgrown the skill — graduate it.

Anti-patterns

  • Reaching for React, npm, a bundler, or a build step. The entire value proposition is zero toolchain. The moment you npm install, you have left the skill. htmx + server-rendered partials cover the interactivity a workbench needs.
  • Shipping a read-only dashboard. A surface that only displays is not a workbench. Close the two-way loop — requests table + /claude/queue + /claude/respond — or you have built the wrong thing.
  • Pushing data over SSE. SSE carries event: <region>\ndata: stale, nothing more. The instant you serialize state into the event payload you have a second source of truth and a client-side state model to keep in sync. Keep events as pure invalidation; let the GET re-render the partial.
  • Trusting curl-only verification. curl cannot catch an SRI mismatch, a missing JS global (require is not defined), or a CSS grid overflow. Phase 4 drives a real headless browser (Chrome via Playwright, domcontentloaded — never networkidle, since the open SSE stream keeps the network forever active) and asserts a terminal-side POST updates an already-open browser via SSE with ZERO console errors.
  • Recomputing the verified SRI hashes casually. The catalog in references/cdn-deps.md was hashed over uncompressed bytes and confirmed in-browser. If you re-hash, you MUST use Accept-Encoding: identity, or the browser will block the script on an integrity mismatch. Do not paste a hash from a curl that let jsDelivr compress the response.
  • Forgetting threaded=True. A single-threaded Flask blocks every other request behind the long-lived SSE generator. The whole UI freezes. It is one keyword; do not drop it.
  • CSS grid overflow on wide artifacts. Grid items default to min-width:auto and refuse to shrink below their content, so wide tables and mermaid diagrams escape the panel. Add min-width:0 + overflow-wrap:anywhere on the column and the .md cell. (Pills are the exception — use white-space:nowrap in a scrollable container, not overflow-wrap, which stacks letters vertically.)
  • Re-rendering markdown only on first load. SSE-swapped fragments arrive after page load, so re-run the whole marked → highlight → mermaid → DOMPurify pipeline on htmx:afterSwap, and run mermaid.run({nodes}) only after the HTML lands and after sanitizing with {ADD_TAGS:['pre'], ADD_ATTR:['class']}. (See index.html htmx:afterSwap handler.)

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.