Extracting a style
Draft a style from stills, clips, live web pages, front-end code, or Figma with rapid style extract, then finish it with the extractor agent.
rapid style extract measures stills and clips, reads live pages and front-end code, and writes a draft style; the rapid-extractor agent finishes it. Values read from a source (tokens, type, faces, easing) win over values measured from pixels, so give it the page or the repository when there is one.
Extraction takes the feel of a look, never its identity: no logos, no marks, no faces you aren't licensed to use.
Run it
rapid style extract refs/*.jpg refs/clip.mp4 --name warm-field --out ~/styles/warm-field
<sources...>: any mix of stills and clips to measure,https://pages to read, and folders of front-end code. A folder that holds only stills and clips is taken as references.--name <name>: the draft's name (lowercase,a-z,0-9,-).--out <dir>: an empty or new folder for the draft. A folder that already holds files is refused.--frames <n>: frames sampled from each clip, 1 to 120 (default 12).--timeout <seconds>: how long to wait for each web page at each width (default 30).--assets <dir>: keep what a web page shows, in a new or empty folder; see keeping a page's assets.
rapid style extract https://example.test/ ./checkouts/site refs/clip.mp4 --name warm-field --out ~/styles/warm-field
It needs ffmpeg and ffprobe on your PATH. Run on a two-scene render and one still, it prints:
drafted /Users/you/styles/warm-field
palette
field #14171a 50.4%
ink #fefefe 4.2%
paper #f0ede4 45.4%
shots median 3.1s over 2 (even, steady)
tempo 200.3 BPM (confidence 0.389)
margins top 26.8% right 22.0% bottom 43.8% left 6.3%
motion 0.204/s (moderate)
formats reel, square
Few references give rough numbers, as the low tempo confidence says. Give it several clips and stills of the look.
What it measures
| What | How |
|---|---|
| palette | weighted k-means in OKLab over every sampled pixel, each frame weighing the same, then named as tokens |
| pacing | ffmpeg's scene-cut detection on clips: shot lengths, their median and mean, rhythm, and trend |
| music | tempo from the onset envelope of a clip's audio, with a confidence, and loudness per second |
| layout | where content stands apart from each frame's background colour, as insets from the edges |
| motion | how much the picture changes per second: a calm-to-kinetic number |
| formats | the built-in format nearest each reference's aspect ratio: reel, square, or wide |
From a live page
An https:// address opens in the headless Chrome rapid renders with, in its own browser context, closed after, with a time limit. The page's own scripts run; this is extraction, not rendering, so the render page's "nothing outside the page" rule does not apply. It loads the page at a phone width (390 px) and a desktop width (1440 px) and reads, from the page's computed styles:
| What | How |
|---|---|
| tokens | every custom property on :root, with its colour as hex where it is one |
| type | headings h1–h3, the body text (the style most text is set in), buttons, links, and small text: font-family stack, weight, style, size, line height, letter spacing, case, colour, and background |
| faces | the faces the page loaded (document.fonts): family, weight, style, and their url() and local() sources. Only names and addresses are recorded; no font file is downloaded or copied |
| colours | box backgrounds by the share of the screen they cover, and text colours by how much text is set in them |
| shapes | the commonest button and card: corner radius, border, and shadow |
| motion | computed transitions and animations (durations and timing functions), and @keyframes from the page's own stylesheets |
| margins | where the text starts in the first screen at each width: the container's real padding |
Before it reads, rapid waits out the page's loader and intro animations, then scrolls it a screen at a time so lazy pictures load and scroll-triggered sections play, and shoots every screen. Each stop waits briefly for the network and for motion to settle, so a long page takes a while.
Screenshots at both widths join the references, so the pixel analysis and the extractor agent see them; they land in refs/. A page that answers with an error, shows a sign-in form, or does not finish loading is reported plainly, and rapid continues with whatever did load.
Keeping a page's assets
With --assets <dir>, rapid also keeps what the page showed, for a video about the site. The files are the site's own: use them only for a video about that site.
rapid style extract https://example.test/ --name site --out ~/styles/site --assets ~/rapid/site-video/assets
| Kept | Notes |
|---|---|
| pictures | at the largest size their srcset offers |
| video clips and posters | the clip files and their poster pictures |
| backgrounds | CSS background images |
| inline vectors | saved with their drawn size and inherited colour, so each stands alone |
| icons and the share image | the page's icons and its og:image |
Each file is named for its alt text, else for the heading of its section, else for its address. The folder holds:
assets.json every kept file: what it is, where it came from, and its section
screens/ every screen of the scrolled page
contact.png every kept picture, clip frame, and vector in one labelled grid
contact.png shows the set at a glance, which is how a storyboarder chooses. Pointing --assets at a project's assets/ folder puts the files where scenes reach them.
From front-end code
A folder that is not a folder of stills is read as code, statically. Nothing in it runs. rapid skips dependencies and build output and reads:
| Format | What it reads |
|---|---|
| CSS, SCSS, Less | custom properties (--name: value, var() resolved within the folder) and @font-face families with their sources |
Tailwind config (tailwind.config.{js,ts,cjs,mjs}) | theme and theme.extend: colors, fontFamily, fontSize, borderRadius, transitionTimingFunction, transitionDuration; values the config computes in code are skipped |
| design tokens JSON | W3C design tokens ($value, $type, aliases such as {color.white}), and Style Dictionary value trees in files named for tokens or a theme |
| Swift | Color(red:green:blue:), Color(hex:), UIColor(red:…), and Font.custom / UIFont(name:) faces with their sizes |
Every value in analysis.json keeps the file it came from.
From Figma
rapid holds no Figma keys. When Figma's MCP server is connected in your Claude Code, ask the extractor agent to read a file or a frame: it uses that server's tools for the variables (colours, type, radii) and screenshots of the frames, saves the screenshots into the draft's refs/, and fills the same fields a page or a repository does, noting the source in taste.md. Run rapid style extract on the screenshots (or on the matching page or repository) first, so the draft has its measurements.
How exact values are used
The draft takes exact values over pixel guesses wherever a source gives one:
- palette:
fieldis the background covering the most screen,inkthe colour most text is set in,accentthe buttons' background (else the links' colour),paperthe cards' ground; a theme's colours are matched to those roles by their names (background,text,primary,card). Other token colours follow under their own names, then pixel colours none of them has. - type scale:
hero,title,body, andsmallfrom the real sizes ofh1,h2, the body text, and the small text, at the width nearest the format, scaled so the page's width fills the frame (390 CSS pixels to a reel's 1080). A theme's sizes are read as a phone's. - leading: from the headings' and the body's line heights.
- faces: each role (
displayfromh1,voicefrom the body text,uifrom buttons) names the source's face inanalysis.json; the draft uses it when it is installed here, else the first installed family of its stack, else a generic family. - margins: from the container's padding, as a share of the frame.
- easing: the commonest timing functions, as
motion.easing.inandout. - components: the card's and the button's radius, border, and shadow.
taste.md gets an Exact section that says where each of these came from.
What it writes
warm-field/
manifest.json kind style, version 0.1.0, tagged "draft", its file list filled in
style.json the measured palette, margins per format, shot length, and tempo
style.css the kit styled from the tokens alone, to make the style's own
taste.md the measurements as facts, with Motion, Type, and Composition left to write
analysis.json everything measured, by reference, and everything read from pages and code, by source
refs/ stills taken at the references' largest scene changes, and page screenshots
What code can't measure stays a placeholder: with no page or theme to read, every type role's face is sans-serif; and taste.md has no rules yet. The draft has no proof, and its style.css is the default kit sheet, which looks the same in every draft.
Finish it with the extractor agent
A video in the look finishes it itself: start it with rapid video <project> --look <draft> (or new_video with look), and the job runs the extractor, holds the draft to rapid style check, and pins it in the project's rapid.lock before the storyboard. To finish a draft on its own, the plugin's rapid-extractor agent does it. In Claude Code, ask for it:
Use the rapid-extractor agent to finish the draft style in ~/styles/warm-field.
It reads analysis.json and the refs, keeps every exact value over its own impression and notes where each came from, names the class of each type role, picks the closest installed face that is licensed for rendered videos, writes taste.md's rules (checkable ones with numbers from the analysis, and judgment ones in plain words), tunes style.json, and runs rapid style check --write until it passes. It keeps measured values unless the refs plainly contradict them, and records its reasoning in analysis.json.
Proving the draft against its references (rendering a sample in the new style beside them and tuning it until a judge says it reads right) is planned, not built. rapid style proof proves a style against itself, once you have written its sample.
Then
Review the faces and rules yourself, make style.css the style's own, render a scene in the style, and follow making a style from step 8 to prove it and pack it.