A shared intake engine you install once and reuse across every Claude skill you build. Skills hand off questions. The widget renders them. Neither side touches the other's logic.
The conventional approach puts intake logic inside each skill. Five skills means writing intake five times, debugging it five times, and keeping it consistent across five files. When something about how questions are asked needs to change, every skill needs a touch.
Elicitation Widget moves that logic out of individual skills and into a single shared engine. A skill has two responsibilities: declare a QUESTIONS array and invoke the widget at Step 0. The engine handles everything else — rendering, batching, payload assembly, and error reporting — without the skill knowing anything about how it works.
The engine never changes. Only the questions do. Improving the engine upgrades every skill that uses it. Adding questions to a skill never touches the engine. The two sides are fully independent.
SKILL.md is both the configuration and the executable. Installing the file installs the interface contract and the implementation in one document. No registry. No config file. No setup script. The file is the system.
The only shared surface between a calling skill and the widget is the format of the QUESTIONS array. The skill writes it. The widget reads it.
QUESTIONS = [
{
key: "Goal",
question: "What...",
type: "single_select",
options: [...]
}
]
[Elicitation complete]
Goal: Option B |
Audience: Internal |
Format: Full
Adding or removing questions never requires touching the engine. Improving the engine never requires touching any skill. The contract is stable.
Author-time. The calling skill defines its QUESTIONS array inline in its own SKILL.md. Static configuration, not runtime logic.
Runtime. Claude reads the calling skill's Step 0 instruction and loads the widget. This is the handoff point. From here the widget is in control.
The widget calls ask_user_input_v0 exactly once with the full QUESTIONS array. All questions appear together in a single native UI interaction. One call. One submission.
The user taps answers across all choice cards and submits once. No back-and-forth. No sequential questioning.
The widget collects answers, assembles a key-value payload, and hands control back to the calling skill immediately. No pause. No confirmation requested.
[Elicitation complete] Project type: Web application | Build stage: In active development | Ownership: Personal
Every entry in the QUESTIONS array must follow this structure exactly. The widget reads each field by name. Field names are not flexible.
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | Yes | Short label. Becomes the field name in the returned payload. Must be unique within the array. |
| question | string | Yes | The full sentence the user reads. Must be self-contained with no assumed context. |
| type | string | Yes | Always "single_select". No other values are supported in v4. |
| options | string[] | Yes | Between 2 and 4 short labels. Keep each label under 5 words. |
-- annotated example QUESTIONS = [ { key: "Project type", -- becomes payload key question: "What kind of project are you building?", type: "single_select", -- always this value options: ["Mobile app", "Web application", "CLI tool", "Game"] }, { key: "Ownership", question: "Who owns this project?", type: "single_select", options: ["Personal", "Company", "Client project", "Open source"] } ]
Download SKILL.md from this repository. In Claude Desktop, open Customize and add the file. That is the only file required. No dependencies. No configuration.
In your skill's SKILL.md, define a QUESTIONS array inline. This is the only thing unique to your skill. The widget reads it at runtime.
Before your first real step, add a Step 0 that loads the widget and passes your QUESTIONS array to it. That is the complete integration instruction.
After Step 0 completes, the widget hands back a key-value map. Reference values by key anywhere in your skill's subsequent steps. Never ask the user again for information already in the payload.
The widget includes a verification mode that proves ask_user_input_v0 is available and rendering correctly. Run it after installing or when moving to a new environment.
The self-test runs a live 5-question intake using a sample inventory built into the file. It bypasses Part A entirely and runs its own dedicated flow. A PASSED result confirms the engine is ready for production use.
If the tool fails to render, the engine stops and reports a FAILED message with instructions. No silent failures.
The widget's job is to call this tool. If your skill also calls it, you have two intake systems running in parallel. Remove all direct calls from your skill.
All questions go in one QUESTIONS array, presented in one interaction. The widget has no limit on array length. Do not add a second Step 0.
Keep the QUESTIONS array inline in your skill's SKILL.md. External references break portability and can fail at runtime.
The widget is shared infrastructure. Skill-specific questions belong in the skill, not the engine. Modifying the widget propagates changes to every skill that uses it.
After Step A3, control returns to the calling skill immediately. Any pause breaks the flow contract. Trust the user's selections.
Works in any environment that renders ask_user_input_v0 as a native UI interaction: Claude Desktop (chat), Claude.ai, Cowork, and Claude Code in the desktop interface are all confirmed. CLI terminal support is a future release.