npx claudepluginhub patchorbit/domscribe --plugin domscribeThis skill is limited to using the following tools:
Domscribe bridges running UI and source code. It maps every rendered element to its exact source location and captures live runtime context (props, state, DOM). This works in two directions:
Verifies tests pass on completed feature branch, presents options to merge locally, create GitHub PR, keep as-is or discard; executes choice and cleans up worktree.
Guides root cause investigation for bugs, test failures, unexpected behavior, performance issues, and build failures before proposing fixes.
Writes implementation plans from specs for multi-step tasks, mapping files and breaking into TDD bite-sized steps before coding.
Share bugs, ideas, or general feedback.
Domscribe bridges running UI and source code. It maps every rendered element to its exact source location and captures live runtime context (props, state, DOM). This works in two directions:
If domscribe.status returns active: false, Domscribe is not yet configured in this workspace. The .domscribe/ directory is created automatically when the dev server starts with the Domscribe bundler plugin configured. Follow this procedure to set it up:
domscribe.status. If active: false, proceed. Note the cwd in the response.package.json (at cwd, or at the appRoot from domscribe.config.json if it exists) and match dependencies against the table below.pnpm add -D @domscribe/next).references/config-patterns.md for the exact import, transformation, and example for each framework..gitignore — if .domscribe is not already listed, append a # Domscribe artifacts comment and .domscribe entry.Check dependencies and devDependencies in package.json. Match top-down (first match wins):
| Dependency | Framework |
|---|---|
next | next |
nuxt | nuxt |
react + vite | react-vite |
react (no vite) | react-webpack |
vue + vite | vue-vite |
vue (no vite) | vue-webpack |
vite only | other-vite |
webpack only | other-webpack |
| Framework | Package | Config file |
|---|---|---|
| next | @domscribe/next | next.config.ts |
| nuxt | @domscribe/nuxt | nuxt.config.ts |
| react-vite | @domscribe/react | vite.config.ts |
| react-webpack | @domscribe/react | webpack.config.js |
| vue-vite | @domscribe/vue | vite.config.ts |
| vue-webpack | @domscribe/vue | webpack.config.js |
| other-vite | @domscribe/transform | vite.config.ts |
| other-webpack | @domscribe/transform | webpack.config.js |
| Lockfile | Package manager |
|---|---|
pnpm-lock.yaml | pnpm |
yarn.lock | yarn |
bun.lock / bun.lockb | bun |
| (none) | npm |
Install command pattern: <pm> add -D <package> (pnpm/yarn/bun) or npm install -D <package>.
If domscribe.config.json exists at the project root with an appRoot field, the frontend app lives in that subdirectory. Install packages and find the bundler config relative to appRoot.
If the project appears to be a monorepo (e.g., apps/, packages/ directories, workspace config in package.json) but no domscribe.config.json exists, ask the user which directory contains the frontend app. Then write domscribe.config.json at the project root:
{ "appRoot": "apps/web" }
The MCP server starts in dormant mode when no .domscribe/ directory exists. After the user starts their dev server, the bundler plugin creates .domscribe/ automatically. The MCP server will need to restart to detect the new workspace and transition to active mode with the full tool suite.
Why query runtime state? Source code alone doesn't tell you what props a component actually received, whether a conditional branch rendered, what CSS classes were applied, or what text the user sees. domscribe.query.bySource gives you the live truth from the browser.
When to query (these tasks benefit):
className, inline styles, and computed attributes so you can see what CSS is winning.rendered: false or shows the actual props/state that control the condition.componentProps with the actual values flowing through, revealing where the chain breaks.When NOT to query (save the round-trip):
Prerequisite: Runtime queries require the user's dev server to be running and the target component to be rendered in an open browser tab. Before calling domscribe.query.bySource, confirm with the user that they have the relevant page open. If you get browserConnected: false or runtime.rendered: false, ask the user to navigate to the page that renders the component and retry.
Workflow:
domscribe.query.bySource with the file path and line number. Inspect runtime.componentProps, runtime.componentState, and runtime.domSnapshot.domscribe.query.bySource again to verify your changes took effect in the live browser.| Command | Purpose |
|---|---|
process_next | Process next queued annotation |
check_status | System health and queue counts |
explore_component | List elements in a component |
find_annotations | Search annotation history |
Tool names below use their MCP registration names (e.g., domscribe.query.bySource). Your client may map these differently — use whatever tool name your environment exposes for the domscribe MCP server.
| Tool | Purpose |
|---|---|
domscribe.query.bySource | Get runtime context for a source location (file + line) |
domscribe.manifest.query | Find all manifest entries by file, component, or tag name |
domscribe.manifest.stats | Manifest coverage statistics (entry/file/component counts) |
| Tool | Purpose |
|---|---|
domscribe.resolve | Get source location for element ID |
domscribe.resolve.batch | Resolve multiple element IDs |
| Tool | Purpose |
|---|---|
domscribe.annotation.process | Claim next queued annotation (atomic) |
domscribe.annotation.respond | Store your implementation message |
domscribe.annotation.updateStatus | Mark as processed or failed |
domscribe.annotation.list | List annotations by status |
domscribe.annotation.get | Get full annotation details |
domscribe.annotation.search | Search by element, file, or text |
| Tool | Purpose |
|---|---|
domscribe.status | Relay health, manifest, queue counts |
domscribe.query.bySourceWhen you're working in a source file and want to understand what an element looks like at runtime, query by file path and line number:
Input:
file (required): Absolute file path as stored in the manifest. Use domscribe.manifest.query to discover exact paths.line (required): Line number (1-indexed).tolerance (optional): Match elements within N lines of the target (default: 0, exact match).column (optional): Narrow to a specific column (0-indexed).includeRuntime (optional): Skip the browser query if you only need manifest data (default: true).Output:
sourceLocation: Confirmed file, line range, tag name, component name.runtime: Live data from the browser (if connected) — componentProps, componentState, domSnapshot (tag, attributes, innerText).browserConnected: Whether a browser client is connected via WebSocket.Use domscribe.manifest.query first if you don't know the exact line — it returns all entries for a file, component, or tag, which you can then target with domscribe.query.bySource.
queued → processing → processed
↘ failed (with errorDetails)
any status → archived
errorDetails)Claim an annotation via domscribe.annotation.process
Understand the response:
userIntent: What the user wants (e.g., "Make this button red")sourceLocation.file: Source file pathsourceLocation.line: Line numbersourceLocation.componentName: React/Vue component nameelement.innerText: Visible text (verify correct element)runtimeContext.componentProps: Current prop valuesNavigate to sourceLocation.file:sourceLocation.line
Implement the change based on userIntent
Verify via domscribe.query.bySource — call with the same file and line to confirm your changes are reflected in the live browser (HMR will have updated the page)
Store your response via domscribe.annotation.respond with the annotation ID and a message describing what you did
Complete the annotation via domscribe.annotation.updateStatus with status processed (or failed with errorDetails)
| Situation | Action |
|---|---|
found: false | No match — queue empty or no manifest entry |
browserConnected: false | Runtime data unavailable; manifest data still returned |
| Source file missing | Mark failed with details |
| Ambiguous intent | Ask user for clarification before implementing |
| Partial success | Mark processed, note limitations in response |
| Cannot implement | Mark failed with errorDetails explaining why |
userIntent carefully — it's the user's actual wordsdomscribe.query.bySource to verify runtime state before and after changeselement.innerText to confirm you're changing the right elementruntimeContext to understand current component statedomscribe.annotation.responddomscribe.annotation.search to check for related prior work