{"_id":"@amabush/understudy","name":"@amabush/understudy","dist-tags":{"latest":"0.3.0"},"versions":{"0.3.0":{"name":"@amabush/understudy","version":"0.3.0","description":"An agent-agnostic skill (Claude Code + Codex): the bundled CLI measures a site's whole brand identity (color, typography, spacing, radii, motion) from the live page; the agent learns its feel on top, reconciled against the measurement.","keywords":["brand","design-tokens","design-system","color-extraction","typography","motion","animation","playwright"],"type":"module","license":"MIT","author":"Amir Abushanab (https://github.com/Amir-Abushanab)","repository":{"type":"git","url":"git+https://github.com/Amir-Abushanab/understudy.git"},"homepage":"https://github.com/Amir-Abushanab/understudy#readme","bugs":"https://github.com/Amir-Abushanab/understudy/issues","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"engines":{"node":">=22"},"bin":{"understudy":"dist/index.js"},"dependencies":{"playwright":"^1.49.0","yaml":"^2.6.0"},"devDependencies":{"@types/node":"^22.10.0","publint":"^0.3.23","tsx":"^4.23.1","typescript":"^5.7.0"},"scripts":{"dev":"tsx src/index.ts","capture":"tsx src/index.ts capture","sync-skill":"cp SKILL.md .agents/skills/understudy/SKILL.md && cp SKILL.md plugins/understudy/skills/understudy/SKILL.md","build":"pnpm run sync-skill && tsc","typecheck":"tsc --noEmit","test":"tsc && node --test \"dist/**/*.test.js\"","test:unit":"tsx --test src/analyze/*.test.ts src/emit/*.test.ts src/validate.test.ts src/capture/assemble.test.ts","validate":"node scripts/validate.mjs","verify-agents":"bash scripts/verify-agents.sh","stress":"node scripts/stress-capture.mjs","lint:plugins":"node scripts/validate-plugins.mjs","lint:package":"publint","lint":"pnpm run lint:plugins && pnpm run lint:package"},"_nodeVersion":"24.19.0","_id":"@amabush/understudy@0.3.0","dist":{"integrity":"sha512-vozcaUFEGXaafVKNcfrIYJNQQirtMw3Ncg98GRod0OZvFBQKFjbGAUUir0V/VF2i0LIAS2HkHzdEcNTPmdRSpA==","shasum":"2f2e3a738809711486b45cadd24a1f8a05931d3b","tarball":"https://registry.npmjs.org/@amabush/understudy/-/understudy-0.3.0.tgz","fileCount":124,"unpackedSize":761725,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCAqZDuWns4PFOfmiIVhmAwiYXOhy+/3HR0dqoBtVFt1AIhAPsPnsIYw7QIXfwQLYIFoKRCyFGU0gARfDzrTG5onX+D"}]},"_npmUser":{"name":"amabush","email":"amabush@outlook.com"},"directories":{},"maintainers":[{"name":"amabush","email":"amabush@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/understudy_0.3.0_1787590598588_0.531784714875172"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-24T16:56:37.763Z","0.3.0":"2026-08-24T16:56:38.758Z","modified":"2026-08-24T16:56:39.618Z"},"maintainers":[{"name":"amabush","email":"amabush@outlook.com"}],"description":"An agent-agnostic skill (Claude Code + Codex): the bundled CLI measures a site's whole brand identity (color, typography, spacing, radii, motion) from the live page; the agent learns its feel on top, reconciled against the measurement.","homepage":"https://github.com/Amir-Abushanab/understudy#readme","keywords":["brand","design-tokens","design-system","color-extraction","typography","motion","animation","playwright"],"repository":{"type":"git","url":"git+https://github.com/Amir-Abushanab/understudy.git"},"author":"Amir Abushanab (https://github.com/Amir-Abushanab)","bugs":"https://github.com/Amir-Abushanab/understudy/issues","license":"MIT","readme":"<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/Amir-Abushanab/understudy/master/docs/logo.svg\" width=\"440\" alt=\"understudy\">\n</p>\n\n<p align=\"center\">Measure a website's brand from the live page, then learn its feel.</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/Amir-Abushanab/understudy/actions/workflows/ci.yml\"><img src=\"https://github.com/Amir-Abushanab/understudy/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"></a>\n</p>\n\nPoint it at a URL. understudy opens the page in a real browser, reads the brand off what actually rendered, and writes out design tokens and an interactive report. Your coding agent adds the qualitative feel on top, cited and checked against the measurements.\n\n<p align=\"center\">\n  <a href=\"https://amir-abushanab.github.io/understudy/example-report.html\"><img src=\"https://raw.githubusercontent.com/Amir-Abushanab/understudy/master/docs/report.png\" width=\"820\" alt=\"An understudy brand report: OKLCH palette, light/dark switch, and a color-format switcher.\"></a>\n</p>\n<p align=\"center\"><a href=\"https://amir-abushanab.github.io/understudy/example-report.html\">Open a full report</a> (measured from github.com, with an authored feel and its sources)</p>\n\n## What you get\n\n- The palette (roles, light and dark), type families and scale, spacing, and radii, read from computed styles rather than guessed off a screenshot.\n- Motion, which most tools skip: durations, easings, springs, stagger, and scroll choreography, including the `requestAnimationFrame` animations (GSAP, Lenis, Framer Motion) that browser dev tools can't see.\n- Output as `design-model.yaml`, CSS variables, a Tailwind config, W3C DTCG tokens, or a standalone HTML report with an OKLCH palette, a hex/rgb/hsl switch, a light/dark toggle, playable easing curves, and click-to-copy.\n\n## Install\n\nNode 22+.\n\n```bash\ngit clone https://github.com/Amir-Abushanab/understudy && cd understudy\npnpm install && pnpm exec playwright install chromium\n```\n\nOr skip the clone and run the CLI from npm (first run needs Chromium: `pnpm dlx playwright install chromium`):\n\n```bash\npnpm dlx @amabush/understudy capture https://linear.app -o model.yaml\n```\n\n## Use it\n\n```bash\npnpm capture https://linear.app -o model.yaml                                    # tokens\npnpm capture https://linear.app --report report.html                             # + HTML report\npnpm capture https://linear.app --css t.css --tailwind t.config.js --dtcg t.json # + token formats\npnpm capture https://linear.app --rationale feel.json --report report.html       # + an authored feel\n```\n\nA slice of what a capture writes (stripe.com):\n\n```yaml\nprimary_mode: light\nconfidence: { brand: 0.9, motion: 0.71 }\ncolors:\n  light:                       # light and dark both appear when a site themes\n    background: \"#ffffff\"\n    text1: \"#061b31\"           # primary by contrast; text2 is the muted secondary\n    accent: \"#533afd\"\ntypography:\n  families: [ sohne-var, SourceCodePro ]\n  display: { family: sohne-var, size: 48px, weight: 300, line_height: 1.15 }\nspacing: [ 0, 8, 16, 24, 32, 48, 64 ]   # snapped to the detected base grid\nmotion:\n  primitives:\n    duration: { fast: 160, base: 240, slow: 420 }\n    easing: { standard: [0, 0, 0.58, 1] }   # declared, cross-verified\n  personality: { archetype: premium }\n```\n\nColors are hex when opaque, `rgba(...)` when translucent. `--motion-only` writes just the motion block. Validate any output with `node scripts/validate.mjs model.yaml`. The full contract lives in [`understudy-spec.md`](./understudy-spec.md).\n\n## From a coding agent\n\nunderstudy is one `SKILL.md` that every agent reads the same way:\n\n| Agent                | Invoke                                                          |\n| -------------------- | -------------------------------------------------------------- |\n| Claude Code          | `/understudy <url>`                                            |\n| Codex                | `$understudy <url>`, or install the bundled plugin             |\n| OpenCode / Kilo Code | auto-discovered; ask it to learn a URL's brand                 |\n| Goose                | `goose run --recipe recipes/understudy.yaml --params url=<url>` |\n\nInstall it as a plugin:\n\n```bash\n# Claude Code — via the amir-skills marketplace\n/plugin marketplace add Amir-Abushanab/skills\n/plugin install understudy@amir-skills\n\n# Codex\ncodex plugin marketplace add Amir-Abushanab/understudy\ncodex plugin add understudy@understudy\n\n# Any agent (Cursor, OpenCode, …) — via the skills CLI\nnpx skills add Amir-Abushanab/understudy\n```\n\nAdding this repo directly as a marketplace also works: `/plugin marketplace add Amir-Abushanab/understudy`, then `/plugin install understudy@understudy`. To hack on the skill locally, symlink the repo and it loads as a local skill:\n\n```bash\nln -s \"$PWD\" ~/.claude/skills/understudy\n```\n\nThe feel is where the agent does real homework. It reads widely: the brand's own design docs and engineering blog, designer talks, podcasts, and interviews, and independent teardowns of the design system. It cites what it used and reconciles any stated numbers against the measurement, so the feel is triangulated across sources rather than taken from one page.\n\nThe measuring is deterministic and costs no model tokens. That research is the only token-heavy step: roughly **100K–300K tokens** per site (`SKILL.md` has the breakdown). `pnpm verify-agents` checks the wiring for every agent at once.\n\n## Confidence\n\nEvery capture reports how sure it is. A low `confidence` means the measurement was genuinely shaky: thin sampling, a poor curve fit, or motion that never ran during the capture window. Trust the number instead of smoothing it over.\n\n## Name and license\n\nAn understudy learns a performance by watching, then plays the part as themselves. That's the idea here: it studies a page's timing, not its artifact, and only from URLs you supply. MIT.\n\nThanks to [Hue](https://github.com/dominikmartn/hue), whose schema this builds on.\n","readmeFilename":"","_rev":"1-fdeffdc0f8eff8fff29c1b1a3c0e8e0d"}