Static check
Scans your views and flags unknown controllers and misused target / value / action. It exits non-zero on errors, so you can wire it into CI.
Inspector
Scans your views and flags unknown controllers and misused target / value / action. It exits non-zero on errors, so you can wire it into CI.
Lists every available controller with its target / value / action / event — the public API, generated from the implementation.
--json emits a machine-readable check report or the raw manifest — for editors, pre-commit hooks, and MCP tools.
The catalog is generated from the implementation, never hand-written, so the docs never drift from what ships.
Stimeo UI ships a small command-line tool, stimeo-ui, in the npm package. It checks whether your markup uses stimeo--* correctly, prints the catalog of available controllers, and also runs as an MCP server that supplies the same information to AI coding agents.
The CLI is a Node tool, so the Ruby gem does not bundle it — but installing via the gem + importmap doesn't lock you out. npx stimeo-ui fetches and runs it on demand without adding npm to your app; the only requirement is a Node runtime, which GitHub-hosted Actions runners already include.
Still early. For now it ships a focused feature set — checking, catalog output, an MCP server, and a VS Code extension — as an early preview. More is on the way.
npx stimeo-ui check app/views
It recursively scans .html, .htm, and .html.erb files for unknown controllers and misused target / value / action. It also checks the accessibility contract — ARIA a component needs but that isn't written (say, a dialog's role / aria-modal / name), operation points keyboard users cannot reach (div-based slider thumbs that need tabindex, etc.), and ARIA id references that don't resolve within the same file (an aria-labelledby pointing nowhere — a warning, since references may legitimately cross partials). When it finds an error, the command exits with a non-zero status code (warnings alone keep it at 0), so wiring it into CI stops the build whenever something is wrong.
npx stimeo-ui catalog
Lists every available controller with its target / value / action / event. The list is generated from the implementation, so it is never hand-maintained and always matches the code. The output looks like this:
Stimeo UI catalog — 111 controller(s)
stimeo--dialog
targets: trigger, dialog
actions: close, closeOnBackdrop, open
stimeo--tabs
targets: tab, panel, list
actions: onKeydown, select
…
Add --json and either command returns machine-readable JSON:
npx stimeo-ui check --json app/views
npx stimeo-ui catalog --json
check --json: a check report — per-file diagnostics plus a summary.catalog --json: the controller list as-is (the raw manifest).The exit code is 1 when an error is found, so editors, pre-commit hooks, and MCP tools can read the JSON while CI relies on the exit code.
The same engine also runs as a Model Context Protocol (MCP) server. Register it once, and AI coding agents (Claude Code, Cursor, …) can look up which components exist, pull each one's exact usage contract and verified example markup straight from the official data, and check the markup they generated — before presenting it to you. It is the official supply line that cuts down plausible-but-wrong AI output.
claude mcp add stimeo -- npx -y stimeo-ui mcp
Or in a project's .mcp.json (Claude Code) / .cursor/mcp.json (Cursor):
{
"mcpServers": {
"stimeo": {
"command": "npx",
"args": ["-y", "stimeo-ui", "mcp"]
}
}
}
The server exposes four read-only tools:
| Tool | What the agent gets |
|---|---|
stimeo_check |
The same check as stimeo-ui check, run on a markup string the agent just generated |
stimeo_catalog |
Every controller with its target / value / action / event |
stimeo_controller |
One controller's full contract, including its accessibility requirements |
stimeo_example |
Verified example markup for one controller — the demo from this catalog, guaranteed to pass the checker |
The manifest and every example are also published as MCP resources (stimeo://manifest, stimeo://examples/<id>), so they can be attached to a conversation as up-front context without a tool round-trip. Two prompts — stimeo_build_ui ("build this UI") and stimeo_fix_markup ("check and fix this markup") — bake the whole workflow into templates; clients that support prompts surface them as slash commands.
Everything runs locally over stdio: the server reads only the data bundled inside the package, never touches your filesystem beyond that, and has no write-capable tools. While it is running, it sends nothing over the network — the only network access in the snippets above is npx downloading the package itself on first use.
The same checks also run live in your editor. Install Stimeo UI Inspector from the VS Code Marketplace (or search "Stimeo UI Inspector" in the Extensions view). Using a VS Code-based editor such as Cursor, VSCodium, or Windsurf? It is also published on Open VSX. No setup is needed: the checker is bundled into the extension and works as soon as you open an HTML/ERB file.
npx stimeo-ui check, shown inline while you edit, with "Did you mean …?" hints for misspelled names.stimeo--* name to see its usage contract: targets, values, actions, and the accessibility requirements the checker looks for.The extension picks the right catalog (manifest) for each file in three steps: an explicitly configured path wins (the stimeo.manifestPath setting), then the stimeo-ui package installed nearest to the file (in a monorepo, each app is checked against its own installed version), and finally a snapshot bundled with the extension — so it works even in projects that don't install the npm package.
Add --github and the check results come out as GitHub Actions workflow commands (::error / ::warning). Run it as-is in an Actions job and the findings appear inline on the pull-request diff — no extra action or upload step required:
npx stimeo-ui check --github app/views
Where you deliberately write something the static check cannot see (an id reference resolved in another partial, for example), add data-stimeo-ignore to that element to suppress findings for it and its subtree. List diagnostic codes (whitespace-separated) in the value to suppress only those codes — recommended; an empty value suppresses everything, so use it sparingly:
<div data-stimeo-ignore="unresolved-idref">
<%# aria-labelledby resolves to a heading in the layout %>
…
</div>
A mistyped code is itself reported as a warning (and cannot be suppressed).
The catalog the command prints and the API contract tables on each component page are built from the same source (dist/inspector/manifest.json). That source is generated from the implementation, so the docs never drift from what ships. See each component's API contract in the catalog for details.