shtml — The .shtml File Format
.shtml is the file format for SLICC's interactive UI panels (sprinkles) and inline chat cards. Sprinkles are HTML fragments or full documents rendered inside sandboxed iframes, with a bridge API for communicating with the agent.
Rendering Modes
-
Fragment mode (default)
Plain HTML without
<!DOCTYPE html>,<html>, or<body>tags. Use the built-in.sprinkle-*CSS classes — do not write custom CSS. In CLI mode, fragments are injected directly into the DOM. In extension mode, fragments route throughsprinkle-sandbox.html(a CSP-exempt manifest sandbox page). -
Full-document mode
Complete HTML documents starting with
<!DOCTYPE html>or<html>. Rendered inside ansrcdociframe. Use this for complex layouts, custom CSS, canvas/SVG, or split-pane UIs. The bridge script and S2 theme tokens are auto-injected into the document head.
Rendering by Runtime
-
CLI mode
Fragments: injected into the page DOM directly (no iframe).
Full documents: rendered viasrcdociframe with injected bridge script. -
Extension mode
ALL content (fragments and full documents) routes through
sprinkle-sandbox.html, a CSP-exempt manifest sandbox. Full documents render in a nestedsrcdociframe inside the sandbox. This bypasses Chrome extension Content Security Policy restrictions.
Bridge API (Panel Sprinkles)
Panel sprinkles (sidebar .shtml files) get the full slicc bridge object, available as window.slicc in scripts and as slicc in onclick attributes.
-
slicc.lick(event)Send a lick event to the agent. Accepts a string (
slicc.lick('refresh')) or an object (slicc.lick({action: 'save', data: {id: 1}})). The cone routes the event to the scoop that owns the sprinkle. -
slicc.on('update', callback)Listen for data pushed from the agent via
sprinkle send <name> '<json>'. Useslicc.off('update', callback)to remove a listener. -
slicc.readFile(path)Read a file from the VFS. Returns a
Promise<string>. -
slicc.setState(data)/slicc.getState()Persist and retrieve sprinkle state. Survives side panel close/reopen. Stored in
localStoragekeyed by sprinkle name. -
slicc.open(path)Open a VFS file in a browser tab via the preview service worker.
-
slicc.close()Close the sprinkle panel.
-
slicc.nameRead-only string — the sprinkle's name.
Inline Sprinkles
Agent ```shtml fenced code blocks in chat messages are hydrated into sandboxed iframes after streaming completes. Inline sprinkles have a minimal bridge: only slicc.lick() is available. There is no readFile, no setState/getState, no on('update'). Inline cards are ephemeral.
Auto-height is handled via ResizeObserver — the iframe resizes to fit its content automatically.
CSS Component Library
Use the built-in .sprinkle-* classes. Do not write custom CSS in fragment mode.
.sprinkle-action-card— compact card for inline interactions. Children:__header,__body,__actions(all optional)..sprinkle-btn— pill-rounded button. Variants:--primary(accent CTA),--secondary(outline),--negative(destructive red)..sprinkle-badge— solid-fill badge. Variants:--notice,--success,--positive,--negative,--informative. Styles:--subtle,--outline..sprinkle-card— card with shadow..sprinkle-stat-cardfor stats..sprinkle-table— table with bold headers and row hover..sprinkle-grid,.sprinkle-stack,.sprinkle-row— layout utilities..sprinkle-text-field— styled text input..sprinkle-progress-bar,.sprinkle-meter— progress indicators.
Run read_file /workspace/skills/sprinkles/style-guide.md for the full component reference.
When to Use What
-
Panel sprinkle (
.shtmlfile)Persistent sidebar UI — dashboards, editors, forms. Full bridge API. Lives in
/shared/sprinkles/<name>/<name>.shtml. Managed with thesprinkleshell command. -
Inline card (
```shtmlcode block)Ephemeral in-chat card — confirmations, choices, status updates. Lick-only bridge. Appears inline in the conversation.
-
Sprinkle chat (
sprinkle chat)Show inline HTML in chat during a tool call. Buttons with
data-action="name"return an action result to the calling tool. Used for quick interactive prompts during agent execution.
Example: Action Card with Buttons
<div class="sprinkle-action-card">
<div class="sprinkle-action-card__header">
Deploy to production
<span class="sprinkle-badge sprinkle-badge--notice">pending</span>
</div>
<div class="sprinkle-action-card__body">3 files changed, all tests passing.</div>
<div class="sprinkle-action-card__actions">
<button class="sprinkle-btn sprinkle-btn--secondary"
onclick="slicc.lick('cancel')">Cancel</button>
<button class="sprinkle-btn sprinkle-btn--primary"
onclick="slicc.lick({action:'deploy',data:{env:'prod'}})">Deploy</button>
</div>
</div>
See Also
man sprinkle— the sprinkle shell commandread_file /workspace/skills/sprinkles/style-guide.md— full CSS component referenceread_file /workspace/skills/sprinkles/SKILL.md— sprinkle creation skill guide