genjutsu

cast

The Illusionist. How the cast pipeline reads your stack, states an interaction thesis, implements motion in your own APIs, and audits the code against the thesis.

All documentation

cast gives an interface motion. It adapts to what is already there, which makes it the right entry point for anything short of a full visual rebuild: a hover state, a section, a scroll narrative, a whole page that feels inert.

With the Claude Code plugin it is /genjutsu:cast. After an npx install or on claude.ai, type /genjutsu or just ask; the router sends motion work here.

The pipeline

Seven stages. Two of them are gates where nothing proceeds without you.

1. Scan

Before asking you anything, it reads the project. On web that means package.json for the framework, the CSS layer, and any animation library. On Apple it means Package.swift or the Xcode project, distinguishing iOS from macOS by platform declaration or SDK root. On Android it means the Gradle files, including whether the Kotlin Multiplatform and Compose plugins are both present.

It also works out whether the context is mobile, desktop, or both, and notes whether the project mixes modern UI with legacy layouts (XIBs, storyboards, layout XML, setContentView).

The scan decides which modules load later. You do not get asked what stack you are on, because the answer is in the repository.

One check follows the scan, before anything is asked. When the request is a whole site or web app on a web stack (or no project yet), the session can spawn subagents, and the brief has real material, two audiences or languages, a first version meant for a client, or asks for the full treatment, cast proposes bunshin once, with its cost range and the two times it would ask you. It switches only on a yes, and never proposes it again in that session. With nobody there to answer, it names bunshin in one line and in the final report, and carries on.

2. Discover

It starts by saying what it thinks it is looking at, in one line: what the product is, who it is for, the direction it seems to be heading, and the stack. Then it waits for you to correct it before asking anything else. A wrong read caught here costs one sentence.

Discovery is skipped when your request is already specific. “Add a hover scale on this button” needs no interview.

It is used when the request is open-ended. “Make this page feel more alive” could go in a dozen directions, so it asks: mood, references, constraints, what is explicitly out of scope. One question at a time, because the second question depends on your answer to the first.

Vague answers get pushed on rather than silently interpreted. “Something modern” comes back as a question about what the motion is for: at the moment this moves, should someone feel that it is fast, that it is precise, that something was saved? The options come from the product’s own moments, never from another brand’s site, because naming one anchors the thesis on a famous default. If that stalls, the inverse question follows: what would feel wrong.

3. Scope

Scope Example Modules Variants
Light One isolated component: hover, toggle, dropdown 1 to 2 No
Medium A page or section: hero, gallery, navigation 2 to 3 2 to 3
Full An app, or a complete overhaul Full pipeline 2 to 3

The rule this table exists to enforce: a hover effect never justifies a scroll-driven animation pipeline.

4. Thesis, and this is a gate

One sentence, naming the feel and the technique. Three examples of the form:

This dropdown will use 150ms CSS micro-transitions with slide plus fade, for a snappy, modern feel.

This hero will combine scroll-triggered parallax with staggered text reveals, for cinematic impact.

This SwiftUI tab transition will use matchedGeometryEffect with a .smooth spring (response 0.5, damping 0.85), for a tactile, spatial feel.

It also has to pass a guessability test: a thesis that could have been written from the product category alone is the category’s default motion, not a decision, and it is rewritten from this product’s own moments.

Under the thesis sits one more line, Allowed patterns:, naming every deliberate device the design relies on that could pass for decoration or habit: mono labels, hairline rules, a looping animation, a live clock. It reads Allowed patterns: none when there are none. You see the list before you say yes, and the audit reads it: a tell counts as allowed only when this line names it.

Nothing is written until you validate it. If you reject it, it does not start over from zero; it asks what feels wrong and adjusts.

Before the first gate that shows you something, it asks once how you want to see it: a rendered page if the session can render one (on Claude, an artifact), otherwise a throwaway HTML file; a live preview route in your own project; or plain text in the conversation. The choice holds for the session. The preview carries what a sentence cannot, like the easing curve plotted with its exact value and an element actually performing the motion, and it is never ported into the real implementation. What each mode means on each host is further down.

The reason this gate exists is arithmetic. A wrong thesis caught here costs one sentence. Caught after implementation, it costs the implementation.

5. Load

Motion foundations always. Then the platform layer (mobile or desktop principles), the stack modules the scan identified, and the audit module when the scope is full. On a web stack at medium or full scope it also loads tells, right after the thesis is validated, so the defaults it lists are avoided while the code is written rather than found afterwards. See the module reference for what each one carries.

Modules load in separate shell calls, one per heavy module, so no single read is too long for the agent to see in full.

6. Implement

Light scope goes straight to code. Medium and full scope propose variants first, graded by how far they push:

Variant A (subtle) - the feel, and the technique, in one line. Variant B (balanced) - the feel, and the technique, in one line. Variant C (impressive) - the feel, and the technique, in one line.

You pick before anything is written. Whatever you pick, the validated thesis still governs; a variant is a way of expressing the thesis, not a way around it.

If the motion the thesis promised cannot be delivered in working order, cast ships the static version and says so. Half-broken motion is never the fallback.

7. Audit

Not optional, not skipped because the result looks good. The audit is split into what can be checked here, with evidence, and what has to be handed to you.

Checked here, with evidence. The first item is the thesis against the code: every promise the thesis made (durations, easing, springs, palette, type, layout family) is matched to the file:line that keeps it, or reported as missing. Then reduced-motion support, exit animations, no layout-property animation, visible focus, all five interactive states, tokens rather than magic numbers, computed contrast (4.5:1 for body text), and semantics. When tells was loaded, the tells audit runs too, and every finding is confronted with the thesis. It has one of three outcomes: the audit quotes the entry of the Allowed patterns: line that allows it; it is not this tell, when the detection contradicts the entry’s own marker (a loop that reports a real loading state, a blur that is a modal backdrop), with the file:line that proves it, and never on a matter of taste; or it is a problem. A problem on a line the run wrote is fixed before the report, and the check runs again, two passes at most; what still fails is reported with its file:line. A tell that was already in your project is listed for you and never changed by the audit.

Handed over, marked unverified. An agent cannot open a profiler or move a pointer, so frame timing, the four breakpoints (375, 768, 1024, 1440), Reduce Motion on a device, recomposition counts on Compose, and the Hitches instrument on SwiftUI come back as a block with the exact thing to run and the pass condition. They are never ticked on its word.

The report reads like “9 checked, 2 problems found, 8 handed over”, and it ends with two lines naming the modules that loaded and the ones that did not.

When nobody is there to answer

Some sessions run without a human, in a pipeline or an evaluation. cast then takes the preview mode it announced, takes the thesis it proposed and labels it as not validated, installs nothing, and marks the final report UNVALIDATED so no one mistakes it for an approved direction.

The preview, host by host

cast and paint ask the same question, once, before the first gate that shows you something: a rendered page, a live preview, or inline. The answer holds for the session. Later gates announce the mode in one line, and you switch by saying so (“show me that as text”, “put it on a page”). Whatever the mode, the preview is throwaway: it exists to be looked at, never to become the implementation.

A rendered page carries the easing curve plotted with its exact value, an element performing the motion with a replay button, the raw numbers and a reduced-motion toggle; for a design system, swatches with their contrast ratios, a real type specimen and the five states of every component. Inline is the sentence, which is still the right answer for a 150ms hover.

Host Rendered page Live preview Inline
claude.ai A native artifact A throwaway route in your project Text in the conversation
Cowork The host’s persistent artifact, which outlives the turn Usually unavailable: often no project checkout to write into The host’s inline widget
Claude Code The Artifact tool when the session has it, else as on any other host A throwaway route, or a @Preview / #Preview scratch file on Compose or SwiftUI Text in the conversation
Any other host Its HTML rendering tool if it has one, else a throwaway HTML file, opened in a browser the session can drive or handed over as a path A throwaway route Text in the conversation

An option that cannot work on the host is not offered, and one line says why. When nothing can render a page, the gate falls back to inline rather than failing.

The gate works out the host itself, before any module loads. Cowork is checked before Claude Code: both can have a ~/.claude folder, and only Cowork has the per-session skills mount, so the more specific signal wins.

bunshin never asks this question: its direction cards go on Impeccable’s decision page when it is installed, and on a rendered page, announced in one line, otherwise.

Writing a good request

The pipeline works better with a target than with an adjective.

  • Name the element. “The pricing cards” beats “the page”.
  • Name the feeling, not the technique. “Should feel physical, like they have weight” gives more to work with than “add a spring”.
  • Name what you do not want. Constraints sharpen a thesis faster than aspirations do.
  • Mention a reference if you have one. One URL can replace three questions.

When to use paint, or bunshin, instead

Reach for paint when there is no visual direction to adapt to, or when the existing one is what you want gone. cast improves what exists; paint decides what should exist. When what should exist is a whole site, first version, bunshin builds it with a team of subagents.