skills/locate-ui-from-code/SKILL.md
Code to screen capture
npx skillsauth add laststance/skills locate-ui-from-codeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When running this skill in Codex, translate Claude Code-only primitives before acting: AskUserQuestion -> chat/request_user_input, TodoWrite -> update_plan, Task/TaskCreate/TeamCreate/SendMessage -> spawn_agent/send_input/wait_agent when available and allowed, and EnterPlanMode/ExitPlanMode -> a concise chat plan plus explicit approval.
Resolve Read/Write/Edit/Bash/WebSearch/WebFetch to Codex file/shell/web tools, and map ~/.claude/... paths to ~/.agents/... or ~/.codex/... unless the task explicitly targets Claude Code.
When running this skill in Cursor Agent, translate Claude Code-only primitives before acting: AskUserQuestion -> AskQuestion; TodoWrite -> Cursor TodoWrite or an equivalent checklist; Task/TaskCreate/TeamCreate/SendMessage/multi-agent flows -> Cursor Task (subagents), parallel Tasks, or run_in_background when allowed (TeamCreate/SendMessage may have no exact match); EnterPlanMode/ExitPlanMode -> Plan mode (SwitchMode / CreatePlan) plus explicit user approval.
Resolve Read/Write/Edit/StrReplace/Bash/web/search/MCP via Cursor Composer or Agent equivalents. MCP names written as mcp__server__tool typically map to call_mcp_tool with configured server identifiers. Map ~/.claude/... to ~/.cursor/skills/, .cursor/skills/, and .cursor/rules/ unless the task explicitly targets Claude Code.
Resolve the question: "this component / selector / class — where does it actually render in the running app?" by capturing a screenshot of just that element plus the DOM information that DevTools' Elements panel would show.
<ComponentName> って画面上のどれ?" / "Where does <X> render?"FolderHeader)[data-testid="folder-header"])フォルダ1)role=button name="Submit")data-* source-attribution attribute if your codebase has one (e.g. data-insp-path, data-component-line)Plus: a way to get the app into the right state (URL + login + any expansion / tab activation needed).
grep the codebase for the component / token to find both the definition and the render sites.aria-label / aria-roledescriptiondata-testid / data-cygrep -rn "FolderHeader" --include="*.tsx" -l
# definition + usages -> trace to the page route
If the project ships an inspector attribute like data-insp-path="<file>:<line>:<col>:<Component>", prefer it: [data-insp-path*="FolderHeader"] is a one-shot locator that survives className changes.
Pick the tool for the current environment:
| Environment | Primary | Fallback | |---|---|---| | Claude Code (chrome-devtools MCP installed) | chrome-devtools MCP | playwright-cli | | Cursor | playwright-cli | — | | Codex CLI | playwright-cli | — | | Any shell | playwright-cli | — |
Install playwright-cli if missing:
npx --no-install playwright-cli --version || npm install -g @playwright/cli@latest
Open + login + persist auth (one-time):
playwright-cli open http://localhost:8080/
# fill login form, click submit (use snapshot refs)
playwright-cli state-save .auth.json
Subsequent runs:
playwright-cli state-load .auth.json
playwright-cli goto http://localhost:8080/<page>
Respect project rules. If the repo's CLAUDE.md / AGENTS.md / README forbids URL direct navigation (e.g. "正規動線のみ"), navigate by clicking nav / links instead of goto.
playwright-cli snapshot
# Read the a11y tree, note the ref of your target (e.g. e15)
When multiple candidates exist (lists, tables, repeated patterns), narrow down with eval:
playwright-cli --raw eval "() => Array.from(
document.querySelectorAll('[data-insp-path*=\"FolderHeader\"]')
).map((el, i) => ({ i, text: el.textContent.slice(0, 40), rect: el.getBoundingClientRect().toJSON() }))"
Pick the index you want, then re-snapshot or use a more specific text-based locator.
Element-only screenshot:
playwright-cli screenshot e15 --filename=<save-path>/<name>_visual.png
DevTools Elements-panel-equivalent dump (outerHTML / rect / computed styles / a11y / 1-level children):
playwright-cli eval "(el) => ({
outerHtmlPreview: el.outerHTML.slice(0, 600),
rect: el.getBoundingClientRect().toJSON(),
computed: Object.fromEntries(['display','height','padding','gap','cursor','transform','transition']
.map(p => [p, getComputedStyle(el)[p]])),
ariaAttrs: Object.fromEntries(['role','aria-roledescription','aria-label','aria-disabled','tabindex']
.map(p => [p, el.getAttribute(p)])),
children: Array.from(el.children).map(c => ({
tag: c.tagName.toLowerCase(),
classes: (c.className?.toString() || '').slice(0, 50),
text: (c.textContent ?? '').slice(0, 30)
}))
})" e15
Save path priority (pick the first that applies):
.claude/tasks/assets/<task>/spec_reference/ → use itdocs/screenshots/ or docs/images/ → use it<repo-root>/screenshots/<name>_visual.png (gitignore as needed)Naming: <component-or-purpose>_visual.png — never screenshot.png / image1.png / 1.png.
Present with these sections (skip any that don't apply):
outerHTML truncated to ~600 chars in a fenced blockdata-insp-path / similar is present, decode to file:line:componentstate-save, reload with state-load.snapshot.outerHTML.slice(0, 600) in responses; for full dumps write to a file via --filename.getBoundingClientRect() is in CSS px; multiply by devicePixelRatio only when comparing against raw screenshot pixels.e15, uid=2_19) are valid only for the snapshot they came from. Re-snapshot after navigation / DOM change.references/tool-equivalents.md — Claude Code MCP / playwright-cli command translation tablereferences/example-walkthrough.md — End-to-end example: locate FolderHeader in a Next.js + Chakra + dnd-kit apptesting
Cited research briefs
development
Daily coding habit prompts JP
development
React core deep-dive JP
data-ai
Copy last agent reply