obsidian-plugin/skills/dev-tools/SKILL.md
Obsidian plugin/theme dev: DevTools, CDP, JS eval, console/error buffers, CSS/DOM inspection, mobile emulation, screenshots. Use when debugging the app.
npx skillsauth add laurigates/claude-plugins dev-toolsInstall 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.
| Use this skill when... | Use the alternative instead when... |
|---|---|
| Developing or debugging a community plugin / theme | Enabling or disabling plugins as a user — use plugins-themes |
| Running JavaScript against the live app API | Triggering an Obsidian command — use command-palette |
| Inspecting CSS or DOM in the running app | Switching themes or snippets in normal use — use plugins-themes |
| Capturing console errors during agent-run plugin tests | Reading note content — use vault-files |
These commands are for development and diagnostics. They expose the same surface as the in-app DevTools window plus a captured buffer of console output and JavaScript errors that survives between calls — the leverage point for agentic plugin testing.
dev:debug and dev:cdp: Chrome DevTools Protocol available
(Electron-based Obsidian — true on desktop)# Toggle the in-app DevTools panel
obsidian devtools
# Read state from the live app
obsidian eval code="app.vault.getFiles().length"
obsidian eval code="app.workspace.getActiveFile()?.path"
# Drive the app — anything you could type in the DevTools console
obsidian eval code="app.commands.executeCommandById('editor:toggle-bold')"
# Multi-statement: wrap in an IIFE
obsidian eval code="(()=>{const f=app.vault.getFiles();return f.filter(x=>x.extension==='md').length})()"
eval returns the expression's value (or last statement's value in an IIFE)
serialised to text. Use JSON.stringify(...) inside the expression for
structured output you can parse downstream.
The CLI maintains rolling buffers of console.* calls and JavaScript errors
from the running app — invaluable for agent-driven plugin testing where the
agent doesn't have the DevTools window open.
# Recent console messages (default limit 50)
obsidian dev:console
obsidian dev:console limit=200
obsidian dev:console level=error
obsidian dev:console level=warn
# Clear the console buffer (e.g. before a test run)
obsidian dev:console clear
# Captured JS errors
obsidian dev:errors
obsidian dev:errors clear
Typical agent loop:
obsidian dev:errors clear
obsidian dev:console clear
obsidian plugin:reload id=my-plugin
obsidian command id=my-plugin:run-test
obsidian dev:errors # any uncaught exceptions?
obsidian dev:console level=error
# All CSS rules matching a selector, with source location
obsidian dev:css selector=".workspace-leaf"
# Filter to one property
obsidian dev:css selector=".workspace-leaf" prop=background-color
Useful for tracking down which snippet or theme is winning a cascade.
# First match — full outerHTML
obsidian dev:dom selector=".nav-folder-title"
# Inner HTML only
obsidian dev:dom selector=".nav-folder-title" inner
# Just the text content
obsidian dev:dom selector=".nav-folder-title" text
# All matches (not just the first)
obsidian dev:dom selector=".nav-folder-title" all
# Element count
obsidian dev:dom selector=".nav-folder-title" total
# Read an attribute or computed CSS prop
obsidian dev:dom selector=".workspace-leaf.mod-active" attr=data-type
obsidian dev:dom selector=".workspace-leaf.mod-active" css=display
# Attach the CDP debugger
obsidian dev:debug on
obsidian dev:debug off
# Run an arbitrary CDP method
obsidian dev:cdp method=Page.captureScreenshot
obsidian dev:cdp method=Runtime.evaluate params='{"expression":"location.href"}'
CDP is the right tool when eval is too coarse — anything you'd reach for
in chrome://inspect.
# Capture the running window
obsidian dev:screenshot path=/tmp/state.png
# Toggle mobile emulation (responsive testing without leaving desktop)
obsidian dev:mobile on
obsidian dev:mobile off
obsidian dev:console clear
obsidian dev:errors clear
obsidian plugin:reload id=my-plugin
obsidian command id=my-plugin:run-tests
errors=$(obsidian dev:errors)
[ -z "$errors" ] && echo "PASS" || { echo "FAIL"; echo "$errors"; }
for theme in Default Minimal Things; do
obsidian theme:set name="$theme"
obsidian dev:screenshot path="/tmp/theme-$theme.png"
done
obsidian eval code="JSON.stringify({file: app.workspace.getActiveFile()?.path, view: app.workspace.activeLeaf?.view?.getViewType()})"
| Context | Command |
|---------|---------|
| Run JS, parseable output | obsidian eval code="JSON.stringify(...)" |
| Errors since last check | obsidian dev:errors |
| Reset error buffer | obsidian dev:errors clear |
| Console (errors only) | obsidian dev:console level=error |
| DOM element count | obsidian dev:dom selector=X total |
| Screenshot for diff | obsidian dev:screenshot path=/tmp/X.png |
| CSS source for property | obsidian dev:css selector=X prop=Y |
testing
Verify accumulated bug claims at upstream HEAD and dedup against trackers before filing issues. Use when filing upstream reports from backlogs, audit docs, or git-history findings.
documentation
Gate outward-bound text (upstream issues, docs, PR bodies) through isolated haiku fresh-reader critique before publishing. Use when an artifact must survive a reader with zero project context.
tools
Suggest improvements to SKILL.md content, descriptions, or tool config from eval results. Use when raising pass rates, fixing triggering, or iterating on a skill after evaluation.
tools
deadbranch CLI for stale-branch cleanup — dry-run preview, TUI or non-interactive delete, protects main/develop/WIP. Use when asked to clean up branches, prune branches, or remove stale branches.