About create-interface-skill
create-interface-skill guides creation of HumanSignal labeling interfaces as JSX modules for Label Studio. It is for interface authors and emphasizes schemas, domain-specific reference modules, and compatibility with the labeling shell.
Key features
- 01Create a single-file JSX interface module
- 02Define input and output schemas
- 03Use domain-specific interface references
- 04Follow theme and accessibility requirements
- 05Sync interfaces through label-studio-sdk
Use cases
- 01Build a text classification interface
- 02Create named-entity or spatial annotation screens
- 03Implement audio or video timeline labeling
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ humansignal/ create-interface-skill --skill create-interface-skillAfter installing, type/create-interface-skillin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
README.mdagents/openai.yamlreferences/example-audio.mdexamples.mdexample-classification.mdexample-spatial.mdexample-ner.mdcore-contract.mdschemas-spatial.mdreference.mdschemas.mdvideo-timeline.mdtext-spans.mdstyling-a11y.mdvideo-frames.mdspatial-bounding.mdDetails
From the project READMECreate Labeling Interface
Create a HumanSignal Interface: one JSX source file (Screen.jsx) whose final
expression is a parenthesized object literal with a default React component
and optional exports such as getResults, parseResults, paramsSchema,
outputSchema, and hotkeys.
This is the JSX-based Interfaces runtime. Do not use the older <ReactCode>
XML tag format unless the user explicitly asks for ReactCode.
Source of truth
The files under references/ are rendered from the same modules the
in-app "Create with Agent" assistant sends to its model. They are authoritative.
Follow their module contract, schema rules, pre-submit checklist, region
contract, and styling/accessibility requirements exactly.
Mandatory read order
- Read
references/core-contract.mdend-to-end. It is the base contract for every interface, including the pre-submit checklist. - Read
references/schemas.mdandreferences/styling-a11y.md. Every interface needs schemas and must support light and dark mode through design-system tokens. - Read the domain module(s) matching the request, and the matching complete example to adapt:
| Reference | Covers |
|---|---|
references/core-contract.md | Response/output format, defensive coding, pre-submit checklist, edit tools, dynamic screen module, params, accessibility basics, and task-data access. |
references/text-spans.md | Absolute-offset text highlighting, NER/entity spans, and selection-offset helpers. |
references/spatial-bounding.md | Spatial region persistence, ShellRegion shape, visibility/lock state, AnnotationResult shape, image navigation & selection tools (select, pan, zoom, fit / 100%), and ranking/ordering (legacy DIY only when Interface Components are off). |
references/video-frames.md | Seek-safe HTML5 video FPS probing and stable frame counters for timeline navigation (FIT-2803). |
references/schemas.md | inputSchema, outputSchema syntax, required output fields, dependsOn, and parseResults. |
references/schemas-spatial.md | Multi-select image URLs, spatial keypoint schemas, and PDF OCR / bounding box schemas. |
references/example-classification.md | A full Sentiment Analysis / Text Classification screen module example. |
references/example-ner.md | A full Named Entity Recognition (NER) screen module example. |
references/example-audio.md | Audio/waveform time-span regions with shell relation anchors and correct serialization (FIT-2247). |
references/example-spatial.md | A full Image Bounding Box / Spatial screen module example. |
references/video-timeline.md | Probe real fps on load via EditorDeps.video, keep frame counts monotonic, and never clip annotation frames to a 24fps fallback (FIT-2804). |
references/styling-a11y.md | Theme-aware tokens, typography, spacing, components, layout, and interaction/accessibility rules. |
- Read only the
references/reference.mdsections you need (start with Schemas & sample data whenever the UI readstask.data). Openreferences/examples.mdonly when reference.md sends you there.
Runtime notes for local authoring
- Injected globals. Beyond the
React/ hooks /getFieldglobals listed incore-contract, the sandbox injectsEditorUI(the@humansignal/uinamespace) andEditorDeps(e.g.EditorDeps.audioDecoder.WasmStreamingDecoder,EditorDeps.video.probeFrameRate). - Do not reference
window.InterfaceComponents(AudioCanvas,useComponentHotkeys) — they are gated behindfflag_interfaces_components, which is off. Build audio interfaces withEditorDeps.audioDecoder.WasmStreamingDecoderas shown incore-contractandexample-audio, and ignore anyInterfaceComponentsrecipes inreference.md. EditorUItwo-path trap.EditorUIis injected only inside the runtime iframe, not in the admin-time eval that extractsparamsSchema. A top-levelEditorUIreference throwsEditorUI is not definedand silently breaksparamsSchemain Labeling Settings. Reference it inside render only, or omit it and use inline styles with design tokens.- Shell-owned behavior. The labeling shell owns Submit/Update, undo/redo/reset, the Regions/Info/Relations
panels, region visibility, and comments. Drive them through the props and callbacks in
core-contractandspatial-bounding(addRegion,updateRegion,deleteRegion,selectRegion,selectedRegionIds, hidden/locked state). Do not re-implement them in the screen: a custom Delete button, local-only region state, or ignoring hidden state breaks the shell's panels and history. - Compiler extraction. The compiler turns the last parenthesized object literal into the module export. If the
file does not end with a bare
({ default: ... }), the editor rejects it with "Module missing 'default' function export." - No persistent storage.
localStorage/sessionStorageare in-memory shims that reset on every iframe remount; persist only through the mutation callbacks and annotation results. - Sample data. Keep
task.jsoncompact and use the exactdefaulttask-data paths from everydataFieldinparamsSchema/inputSchema. - Saving to Label Studio. Create or update the interface only with
label-studio-sdk interface sync <dir> --title "<Title>" --publish(new interface; add--workspace <id>when needed) orlabel-studio-sdk interface sync <dir> --message "<change>"(existing one, tracked by the sidecar file; that creates an unpublished draft, so add--publishwhen new projects should use it).syncextractsinputSchema/outputSchema/paramsSchemafrom the module and stores them with the code. NeverPOST/PATCH/api/interfaces/yourself: the server cannot read the schemas from the code, so a hand-built request saves an emptyoutput_schema/input_schemawithout any error, and projects created from the interface lose their Data Manager annotation filters. After syncing, confirmGET /api/interfaces/<id>/returns a non-emptyoutput_schema.