Skip to content

undeemed/ocd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ocd

validate Claude Code plugin License: MIT

A Claude Code plugin that does a zero-tolerance audit-and-fix pass over your project: visual polish first, code quality second.

Born from a real session of building a terminal UI, where "close enough" kept not being close enough: the % label that resizes its whole column when it ticks from 9% to 13%, the glyph that can never truly center over an even-width bar, the controls that drift one cell the moment a progress bar appears. This plugin hunts exactly that class of bug, and fixes it instead of listing it.

The hard rule behind all of it: measurements, not impressions. Render it, count the cells, fix the root cause, re-measure.

How a pass works

  1. Inventory every screen and state the UI can render
  2. Render and measure - browser screenshot, char-frame dump, test render; never judge alignment from source
  3. Simulate the states - empty vs full, 0% vs 100%, shortest vs longest string; layout bugs live in the transitions
  4. Fix the root cause - one guard in the shared function, not a patch at the call site
  5. Re-measure - a fix is not done until rendered again
  6. Report - terse table, no essays

What it checks

Visual invariants (measured against rendered output, never eyeballed from source):

  • Alignment to computed anchor columns, not hardcoded offsets
  • Layout shift across every dynamic state (empty vs full, 0% vs 100%, first vs last selection)
  • Centering parity: odd-over-odd, manual padding, no trust in flexbox rounding
  • Spacing hierarchy vs dead space
  • One separator glyph, one prefix style, stable color roles
  • Animations that use their full range, with floor-and-ceiling normalization for live data

Code invariants:

  • Root cause over symptom: trace the callers, fix the shared function
  • Reuse before writing, smallest correct diff
  • Tests and typecheck green, one runnable check for new logic
  • No dead code, stale comments, or debug residue

Does it actually help? (measured)

Fair skepticism: a strong model already fixes plenty of UI bugs on its own. So the skill was A/B tested - the same audit run with it and without it, scored by a script that renders the output and measures pixels, not by opinion.

The headline result is on the exact bug class this plugin exists for: a layout shift that only appears in a state the default view never shows. An agent is handed a toolbar and told only "audit this" - the bug is never named - across 8 trials per condition:

ocd vs baseline on a hidden-state layout shift

  • Without the skill: 0/8 found it. Every run fixed a different, visible issue (the buttons' font) and never simulated the changing count, so the shift sailed through.
  • With the skill: 8/8 found it. Its "simulate every state" rule renders the count at 3 and at 9999, sees the buttons drift, and reserves the width.

That is the skill doing the one thing a fast read cannot: catching the bug you only see when you render a state that isn't on screen.

Honest scope, because the same study measured it: when a bug is named, visible on sight, or readable in the source - even buried in a real, heavy landing page - a strong base model already fixes it, and the skill adds no correctness there while costing 2-3x more tokens. Its edge is specifically the source-invisible, state-dependent bug. Full write-up, all five rounds, both render-and-measure scorers, and every number including the ties: eval/ablation.

Install

As a plugin (recommended, gets updates):

/plugin marketplace add undeemed/ocd
/plugin install ocd@ocd

Or as a standalone skill:

git clone --depth 1 https://github.com/undeemed/ocd /tmp/ocd && cp -r /tmp/ocd/skills/ocd ~/.claude/skills/ocd

Use

/ocd

Or just complain naturally: "this is triggering my OCD", "the arrows aren't aligned", "something shifted". The description is written to trigger on those.

It ends every run with a terse report:

FIXED
src/ui/progress.tsx:41 - label resizes column at 100% - padded to fixed 4-char width
src/ui/panel.tsx:12 - header centers against variable content - centered in fixed box
CLEAN
empty/full lists, 0%/100%, first/last selection, separators, color roles

wideshot: screenshot the scene, not the subject

The companion skill for visual verification. The natural move after changing a button is to screenshot the button - a frame in which nothing can be verified, because alignment and spacing are relations to siblings and the crop deleted the siblings. /wideshot computes the meaningful container (control pane, toolbar, table, modal) with a landmark-walking heuristic and screenshots that instead:

  • changed a control button -> shoots the whole control pane
  • changed a table cell -> the table
  • changed a nav link -> the nav bar

It uses whatever browser tooling the session already has, or falls back to a bundled ~50-line puppeteer-core script that reuses your installed Chrome (no browser download, <2s per shot). The heuristic handles shadow DOM, inner scroll containers, display:contents, and position:fixed, and returns why it picked the frame.

Verified, not asserted

Those handling claims are backed by an eval + bench, not just prose - fittingly, given the skill's own "measurements, not impressions" rule. The suite lives in skills/wideshot/scripts/test (12 correctness cases in real headless Chrome, plus a perf bench): npm test, npm run bench.

The heuristic is a container-selection step that runs before a screenshot, so the fair comparison is against the framing other tools give you. Measured on one engine (puppeteer-core + Chrome), same page and target, so the only variable is what gets framed (Apple M5, arm64 - ratios matter, not absolute ms):

framing strategy time (median) output note
element-only (Playwright / shot-scraper / capture-website --element) 25.1 ms 40 x 30 px no siblings -> alignment/shift unverifiable
wideshot 24.5 ms 920 x 50 px frames the pane, same speed as element-only
full-page 41.9 ms 1280 x 4400 px captures everything, 1.7x slower, unfocused

The heuristic itself adds < 0.1 ms (p95), below the performance.now() floor. So wideshot costs the same as a plain element shot but returns a frame you can actually verify in - where element-only deleted the siblings and full-page buried the change. Every other tool screenshots exactly the selector you hand it or the whole page; only wideshot walks to the meaningful container. Full matrix and how-to in the eval README.

Structure

.claude-plugin/
  plugin.json                plugin manifest
  marketplace.json           lets `/plugin marketplace add undeemed/ocd` work
skills/
  ocd/SKILL.md               the audit-and-fix pass
  wideshot/SKILL.md          context-framed screenshots for visual verification
  wideshot/scripts/          container heuristic + fallback capture tool
  wideshot/scripts/test/     eval (12 cases) + perf bench for the heuristic

Skills under skills/ are auto-discovered by the plugin. To add one, create skills/<name>/SKILL.md with name and description frontmatter - nothing to register. Agents (agents/*.md), commands (commands/*.md), and hooks (declared in plugin.json) slot in the same way when needed.

Contributing

New invariants and verification tricks welcome - see CONTRIBUTING.md. Scope stays narrow on purpose: audit-and-fix passes only.

Star history

Star History Chart

License

MIT

About

Claude Code plugin: zero-tolerance audit-and-fix pass for visual polish and code quality. Measures rendered output, fixes every violation, reports tersely.

Topics

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors