Use before implementing, scaffolding, prototyping, or adding a feature when the work should start with the smallest useful code path, avoid speculative archi...
--- name: demi description: Use before implementing, scaffolding, prototyping, or adding a feature when the work should start with the smallest useful code path, avoid speculative architecture, or prevent overbuilding before reduce would be needed. --- # demi A demi-glace starts concentrated. Nothing extra goes in just because the kitchen has it nearby. You do the same with code: build the smallest useful version that satisfies the ticket, fits the repo, and can be verified. Complexity has to earn its way into the pan. **Core principle:** start simple enough that [reduce](../reduce/SKILL.md) should not be needed immediately afterward. Small means understandable and verifiable, not cramped. The shortest version that hides intent is not demi; it is just dense. ## The demi ladder Before writing custom code, stop at the first rung that holds: 1. **Does this need to exist?** If the current behavior already satisfies the actual ask, skip the change and say why. 2. **Can the repo already do it?** Use existing commands, helpers, components, config, conventions, and tests before inventing new ones. 3. **Does the standard library cover it?** Prefer built-in language or framework features over custom code. 4. **Does the platform cover it?** Native browser, database, shell, operating system, framework, or deployment features beat owned code when they fit. 5. **Does an already-installed dependency cover it?** Use what is already in the project. Do not add a dependency for a few clear lines. 6. **Can one explicit local change do it?** One function, one component, one endpoint, one flag, one small data path. 7. **Only then:** write the minimum custom implementation that works and can be checked. The ladder is quick. Do not turn it into a research project. If two rungs work, take the higher one unless it is less correct on edge cases. ## The demi pass Run this before editing: 1. **Restate the actual ask.** One sentence. If the task is vague, choose the smallest useful interpretation that still satisfies it. 2. **Find the local pattern.** Read the nearest existing code, helpers, tests, and naming conventions. Prefer what the repo already uses. 3. **Climb the ladder.** Check existing behavior, repo primitives, standard library, platform, installed dependencies, and local one-change solutions before new infrastructure. 4. **Name the smallest useful slice.** Define the first complete behavior the user can actually run, click, test, or review. 5. **Cut speculative scope.** Remove features, settings, abstractions, options, data models, and UI states that are not required for that slice. 6. **Pick the boring implementation.** Use direct code, existing helpers, and local composition. New abstractions need evidence. 7. **Set a growth trigger.** Write down what future fact would justify expanding the design: a second consumer, a third repeated pattern, a measured performance limit, a public API boundary, or an explicit user requirement. 8. **Verify the slice.** Run the narrowest meaningful check through [check](../check/SKILL.md). If behavior is hard to pin down, use [taste](../taste/SKILL.md) for a focused test before expanding. ## Simplicity gates Before adding a new layer, answer these. If any answer is no, keep it local. - **Is this required by the current request?** - **Does the repo already have a pattern for this?** - **Is there a standard library, platform, or existing dependency path?** - **Will at least two real callers use this now?** Three is better for shared abstractions. - **Would a future maintainer understand this faster than the direct version?** - **Can I verify the behavior after this change?** ## What to build first Prefer these moves: - One vertical slice over a broad scaffold. - One explicit function over a generic utility. - Existing components, commands, config, and test harnesses over new infrastructure. - Clear local logic over premature indirection. - A small typed data shape over a general schema system. - A direct UI state path over a reusable state machine. - A narrow CLI flag over an interactive prompt or new config file. - A plain file or local module over a package, service, queue, plugin, or database. - A small runnable check over a full testing framework when the repo does not already have one. ## What to refuse early Do not build these unless the current task proves they are needed: - Framework swaps. - Plugin systems. - Generic registries. - New persistence layers. - Background workers. - Multi-provider abstractions. - Config formats for a single value. - Theme systems for one screen. - Large component libraries for one view. - Repository-wide rewrites. - Public API reshapes. - "Future-proof" abstractions without a future requirement. ## Not skimping `demi` is not permission to be careless. Never simplify away: - Trust-boundary validation. - Error handling that prevents data loss. - Security controls. - Accessibility basics. - Compatibility shims that protect real users. - Calibration or tuning points for real hardware or external systems. - Tests or checks for non-trivial branches, loops, parsers, money paths, auth paths, or security-sensitive logic. - Anything the user explicitly asked for after you challenged the scope once. A simple implementation without a check is not finished. Use the smallest meaningful check, not necessarily the biggest test harness. ## Shortcut notes If the small version has a known ceiling, name it in the plan or final report. Add an inline comment only when future maintainers would otherwise mistake the simplification for ignorance. Examples: - `Global lock is fine for single-user CLI; move to per-account locks if concurrent accounts matter.` - `Linear scan is fine below the current file sizes; index when measured input size makes it hot.` - `Native date input is enough here; custom picker only if design or browser support requirements change.` ## The one-screen plan For non-trivial work, write this before editing: ```markdown ## demi: <task> Actual ask: <one sentence> Smallest useful slice: <what will work when done> Highest rung that holds: existing behavior | repo primitive | stdlib | platform | installed dependency | local change | custom code Existing pattern to follow: <file/helper/test/component> Cut from scope: <what is intentionally not being built> Growth trigger: <what would justify expanding later> Verification: <command/check/user-visible proof> ``` Keep it short. This is a guardrail, not a design doc. ## Mode `demi` is apply-by-default. After the quick pass, implement the smallest slice unless the task is architectural, public-interface-heavy, security-sensitive, under-specified in a way that changes the outcome, or the user explicitly asks for options first. In those cases, report the demi plan and wait. For large work, combine with [recipe](../recipe/SKILL.md): use `demi` to keep each recipe task small, vertical, and verifiable. ## Boundaries - Use [mise](../mise/SKILL.md) when context is missing. - Use [recipe](../recipe/SKILL.md) when the work needs sequencing. - Use [taste](../taste/SKILL.md) when the slice needs tests before confidence. - Use [check](../check/SKILL.md) before claiming done. - Use [reduce](../reduce/SKILL.md) only after code exists and needs behavior-preserving cleanup. ## Common mistakes | Mistake | Reality | |---|---| | Building a full framework because the feature might grow | Growth is a trigger, not a prediction. Ship the slice. | | Adding config before there are real variants | One value can be code. Two may still be code. Three starts a conversation. | | Creating a generic utility from one use | That is not reuse, it is disguise. Keep it local. | | Scaffolding every future state | Build the path the user asked for and leave clean edges. | | Calling fewer files "less complex" | A thousand-line god file is not demi. Small means understandable, not cramped. | | Picking the shortest algorithm when it drops edge cases | Lazy means less owned code, not flimsier behavior. Correctness wins ties. | | Skipping local pattern discovery | Simple in isolation can be weird in the repo. Match the kitchen. | | Treating YAGNI as technical debt | YAGNI keeps quality high and scope small. Skimping leaves a mess for later. |
don't have the plugin yet? install it then click "run inline in claude" again.
restructured original guidance into implexa's six-component format (intent, inputs, procedure with 7 steps, decision points covering architectural and security cases, output contract specifying deliverables, outcome signal for verification), added external reference guidance for related skills, clarified demi-ladder as explicit procedure step, preserved all original author teaching without alteration, added shortcut notes section for ceiling documentation.
a demi-glace starts concentrated. nothing extra goes in just because the kitchen has it nearby. you do the same with code: build the smallest useful version that satisfies the ticket, fits the repo, and can be verified. complexity has to earn its way into the pan.
core principle: start simple enough that reduce should not be needed immediately afterward. small means understandable and verifiable, not cramped. the shortest version that hides intent is not demi; it is just dense.
use demi before implementing, scaffolding, prototyping, or adding a feature when the work should start with the smallest useful code path, avoid speculative architecture, or prevent overbuilding before reduction would be needed. demi is a discipline for climbing from existing behavior to custom code in seven explicit steps, then shipping the minimum that works. apply it by default unless the task is architectural, touches public interfaces, is security-sensitive, or under-specified in a way that changes the outcome.
write one sentence that captures what the ticket really needs. if the request is vague (add a feature, improve performance, refactor), pick the smallest useful interpretation that still satisfies it. if the statement feels too broad, narrow it. if it feels incomplete, use mise to fill gaps before proceeding.
output: one-sentence restatement, written down or stated aloud.
read the nearest existing code, helpers, tests, and naming conventions in the repo. do not start a research project; scan a few related files to see what the kitchen already does. if the repo has a similar feature or data shape, prefer the local pattern over what you know from other codebases.
output: identified pattern or helper (filename, function name, component name, or config convention).
check each rung in order. stop at the first one that holds and satisfies the ask:
do not turn the ladder into a research project. if two rungs work, take the higher one unless the lower rung is more correct on edge cases.
output: the rung you land on (name it explicitly) and why.
define the first complete behavior the user can run, click, test, or review. this is not a line of code; it is a whole feature end-to-end that satisfies the ask and nothing more. ignore options, variants, edge cases that are not in the current ticket, and future growth paths.
output: clear description of what will work when done (e.g., "fetch a single user by ID and return their name and email address").
remove features, settings, abstractions, options, data models, and UI states that are not required for that slice. ask:
if any answer is no, keep it local or do not build it.
output: list of what is intentionally not being built (and why).
use direct code, existing helpers, and local composition. new abstractions need evidence (a second consumer, a third repeated pattern, a measured performance limit, a public API boundary, or an explicit user requirement).
prefer these moves:
do not build these unless the current task proves they are needed:
output: implementation sketch or decision (e.g., "add one function to index.ts using the repo's existing request helper").
write down what future fact would justify expanding the design: a second consumer, a third repeated pattern, a measured performance limit, a public api boundary, or an explicit user requirement. do not design for growth; design for today.
run the narrowest meaningful check through check. if behavior is hard to pin down, use taste for a focused test before expanding.
output: growth trigger (written) and verification command or user-visible proof (passed).
if the task is vague or under-specified (and it changes the outcome): use mise to gather context first. do not proceed with demi until the actual ask is clear.
if the task is architectural, touches public interfaces, or is security-sensitive: report the demi plan (one-screen plan, below) and wait for explicit approval before implementing. do not assume you can narrow the scope alone.
if a rung higher than "custom code" holds (e.g., an existing feature already does it): skip the change and document why. this saves work and keeps the repo lean.
if the smallest useful slice is unclear or depends on user feedback: use taste to prototype a minimal version first, then build the real slice based on what users say.
if the work is multi-step and sequencing matters: use recipe to plan the sequence. use demi on each recipe task to keep individual steps small and verifiable.
if the implementation has known ceilings (e.g., single-user lock, linear scan below X files, native date input without custom picker): name the ceiling inline or in a shortcut note (below). document what fact would trigger a redesign.
if the code is complete but behavior is hard to verify: use check before claiming done. if a full test harness is not in place and is not being added, use taste for focused validation.
a demi pass produces one or more of these deliverables, depending on the task:
## demi: <task>
actual ask: <one sentence>
smallest useful slice: <what will work when done>
highest rung that holds: <existing behavior | repo primitive | stdlib | platform | installed dependency | local change | custom code>
existing pattern to follow: <file/helper/test/component or none>
cut from scope: <what is intentionally not being built>
growth trigger: <what would justify expanding later>
verification: <command/check/user-visible proof>
you know demi worked when:
if you find yourself designing a framework, debating abstractions, or adding options before two real use cases exist, you have missed demi. pause and reread step 5 and step 6.
for non-trivial work, write this before editing:
## demi: <task>
actual ask: <one sentence>
smallest useful slice: <what will work when done>
highest rung that holds: <existing behavior | repo primitive | stdlib | platform | installed dependency | local change | custom code>
existing pattern to follow: <file/helper/test/component>
cut from scope: <what is intentionally not being built>
growth trigger: <what would justify expanding later>
verification: <command/check/user-visible proof>
keep it short. this is a guardrail, not a design doc. once you land on a rung and name the slice, start coding.
demi is apply-by-default. after the quick pass (steps 1-4), implement the smallest slice unless the task is architectural, public-interface-heavy, security-sensitive, under-specified in a way that changes the outcome, or the user explicitly asks for options first. in those cases, report the demi plan and wait.
for large work, combine with recipe: use demi to keep each recipe task small, vertical, and verifiable.
demi is not permission to be careless. never simplify away:
a simple implementation without a check is not finished. use the smallest meaningful check, not necessarily the biggest test harness.
| mistake | reality |
|---|---|
| building a full framework because the feature might grow | growth is a trigger, not a prediction. ship the slice. |
| adding config before there are real variants | one value can be code. two may still be code. three starts a conversation. |
| creating a generic utility from one use | that is not reuse, it is disguise. keep it local. |
| scaffolding every future state | build the path the user asked for and leave clean edges. |
| calling fewer files "less complex" | a thousand-line god file is not demi. small means understandable, not cramped. |
| picking the shortest algorithm when it drops edge cases | lazy means less owned code, not flimsier behavior. correctness wins ties. |
| skipping local pattern discovery | simple in isolation can be weird in the repo. match the kitchen. |
| treating yagni as technical debt | yagni keeps quality high and scope small. skimping leaves a mess for later. |