Skip to content

Repository files navigation

agent-ui-render

agent-ui-render is a native CLI for agent-authored UI previews. Coding agents write compact, governed JSON; the CLI validates, normalizes, plans, and renders that data into browser-openable HTML, no-JS static HTML, or a Vue handoff bundle.

The runtime is Rust. The visual renderer is authored in Vue during development and embedded into the release binary, so installed users do not need Node, Bun, npm, Vue, or node_modules.

What this project is for

  • Give coding agents a small, safe UI output contract instead of asking them to hand-write HTML, CSS, Vue, React, or JavaScript.
  • Convert compact model-authored version: 1 semantic reports, version: 2 advanced chart payloads, and version: 3 native multi-panel reports into validated runtime data before anything is rendered.
  • Produce portable preview artifacts for reports, tables, metric cards, charts, alerts, and markdown narrative.
  • Keep release artifacts as single native binaries plus installer scripts.

Why compact data instead of direct HTML?

Anthropic's Using Claude Code: The unreasonable effectiveness of HTML makes a point this project agrees with: HTML is a useful artifact boundary for agent work because it is portable, inspectable, and immediately useful in a browser.

agent-ui-render optimizes a different part of that workflow. Having an LLM agent directly author full HTML, CSS, and JavaScript is expressive, but for report-like UIs it spends expensive output tokens on repeated tags, styles, boilerplate, and layout code. Output tokens are also typically priced higher than input tokens, so repeating UI markup is a poor place to spend model budget when the underlying result is mostly data plus visual intent.

This project keeps the useful HTML artifact, but moves verbose rendering into a tool:

+----------------------------+       compact data       +------------------+
| LLM agent                  | -----------------------> | agent-ui-render  |
| facts + visual intent      |                          | validate/render  |
+----------------------------+                          +--------+---------+
                                                                  |
                                                                  v
                                                        +------------------+
                                                        | HTML artifact    |
                                                        | browser-ready    |
                                                        +------------------+

The model emits a compact dataset-oriented payload; the trusted CLI expands it into validated runtime data and renders the HTML. That reduces output-token usage, centralizes rendering and safety rules, and gives agents a smaller, repeatable contract for charts, tables, metrics, alerts, and markdown narrative.

Measured token and cost efficiency

The historical v0.1 baseline benchmark used claude-sonnet-5 at medium effort across 10 report cases, with three repetitions per configuration: 30 direct-HTML runs and 30 agent-ui-render runs. Both configurations produced 30/30 artifacts that passed the same fact-preservation, structure, and headless-browser checks. The exact project commit was ca173c9; treat these numbers as a reproducible baseline rather than a fresh measurement of the current renderer and Skill.

Mean Claude token composition per accepted artifact

The compact payload reduced mean model output from 5,184 to 344 tokens, a 93.4% reduction (95% CI: 92.4% to 94.2%). The full Skill and reference context increased effective input tokens, so raw input-plus-output volume rose 37.1%. This project therefore claims lower model output, not lower total context volume.

Output-token savings by report complexity

Actual measured API cost fell from $0.0817 to $0.0098 per accepted artifact, an 88.0% reduction (95% CI: 85.3% to 89.9%). These costs include prompt caching and the single repair call required by each configuration.

Mean measured API cost per accepted artifact

The benchmark also reduced mean model duration from 37.25 seconds to 3.82 seconds. See the formal benchmark report and machine-readable summary for the complete method, caveats, confidence intervals, and reproducible harness. Fresh runs can publish sanitized aggregate evidence with benchmarks/token-ab/run.py --publish-dir <directory>; see the harness README for the required explicit spend envelope.

Theme showcase

The same compact payload can render as different host-selected themes without asking the agent to rewrite the UI.

Report Light Executive Clean Technical Dark
Report Light Executive Clean Technical Dark

The showcase payload lives at docs/assets/screenshots/markdown-brief.input.json; regenerate all three shots from the same source and renderer commit with make showcase-screenshots.

Compact v3 renders accessible desktop tabs and a labelled mobile section selector while keeping the report in one offline file:

Synthetic compact v3 tabbed report

The fully synthetic 11-panel payload is examples/v3-tabbed-fleet.input.json. Render it with agent-ui-render render html examples/v3-tabbed-fleet.input.json report.html. Regenerate its light, dark, and mobile captures with make v3-showcase-screenshots.

Install

Installer script

base="https://github.com/NeoHsu/agent-ui-render/releases/latest/download"
curl --proto '=https' --tlsv1.2 -LsSf \
  "$base/agent-ui-render-installer.sh" | sh

Windows PowerShell

$base = "https://github.com/NeoHsu/agent-ui-render/releases/latest/download"
irm "$base/agent-ui-render-installer.ps1" | iex

Direct release downloads

Platform Asset
Apple Silicon macOS agent-ui-render-aarch64-apple-darwin.tar.xz
Intel macOS agent-ui-render-x86_64-apple-darwin.tar.xz
ARM64 Linux agent-ui-render-aarch64-unknown-linux-gnu.tar.xz
x64 Linux agent-ui-render-x86_64-unknown-linux-gnu.tar.xz
x64 Windows agent-ui-render-x86_64-pc-windows-msvc.zip

Each archive contains the prebuilt agent-ui-render executable plus release metadata. Checksums are published next to the release assets, and each platform archive has GitHub build-provenance attestation. Verify a download before use:

gh attestation verify <archive> --repo NeoHsu/agent-ui-render

mise

mise use -g github:NeoHsu/agent-ui-render

In mise.toml:

[tools]
"github:NeoHsu/agent-ui-render" = "latest"

From source

From the published repository:

cargo install --git https://github.com/NeoHsu/agent-ui-render agent-ui-render

From a local checkout:

mise install
make setup
make generate
cargo install --path crates/agent-ui-render-cli

Verify the install:

agent-ui-render --version
agent-ui-render --help

Agent Skill

Install the bundled AI agent skill so coding agents know how to author compact Agent UI payloads instead of hand-writing HTML, CSS, JavaScript, or arbitrary UI components.

From the published repository:

npx skills add NeoHsu/agent-ui-render --skill agent-ui-render

From a local checkout of this repo:

npx skills add . --skill agent-ui-render

For non-interactive setup across all supported agents, add --agent '*' -y:

npx skills add . --skill agent-ui-render --agent '*' -y

Use --copy if you want the installed skill to be a standalone copy instead of a symlink back to the repo checkout:

npx skills add . --skill agent-ui-render --copy

The CLI install gives agents a renderer; the skill install gives agents the payload contract and safety rules. Keep them from the same release and verify the installed pair using the Skill directory reported by the installer:

agent-ui-render --warnings-as-errors skill check --discover

For a local checkout, the equivalent check is:

agent-ui-render --warnings-as-errors skill check skills/agent-ui-render --discover

The machine-readable skills/agent-ui-render/compatibility.json records the Skill version, minimum/recommended CLI versions, input versions, and required schemas. A missing manifest identifies a legacy Skill; a newer CLI reports an older Skill before its capabilities are silently missed. This is an offline pairing check, not a network update check: two equally old installations cannot know that a newer GitHub release exists. Discovery is bounded to explicit, AGENT_UI_RENDER_SKILL_DIR, project, and common user-level Skill paths; it never recursively scans the home directory.

Quick render

Create a compact input file:

cat > /tmp/revenue.input.json <<'JSON'
{
  "version": 1,
  "t": "Revenue Overview",
  "d": [
    [
      "sales",
      [["month", "s"], ["revenue", "cur", "USD"]],
      [["Jan", 120000], ["Feb", 135000]]
    ]
  ],
  "v": [["t", 0, 0, [1]], ["r", 0]]
}
JSON

Validate and render it:

agent-ui-render validate /tmp/revenue.input.json
agent-ui-render render html /tmp/revenue.input.json /tmp/revenue.html
agent-ui-render render static-html /tmp/revenue.input.json /tmp/revenue.static.html

Open /tmp/revenue.html in a browser.

Runtime flow

+------------------------------+
| Compact payload (v1/v2/v3)   |
+---------------+--------------+
                |
                v
+------------------------------+
| agent-ui-render validate     |
| - structure and references   |
| - unsafe content and limits  |
+---------------+--------------+
                |
                v
+------------------------------+
| Normalize to domain::Report  |
+---------------+--------------+
                |
        +-------+-------+----------------+
        |               |                |
        v               v                v
+---------------+ +-------------+ +----------------+
| plan ui.spec  | | render html | | render vue     |
| JSON          | | or static   | | handoff bundle |
+---------------+ +-------------+ +----------------+

Compact input shape

{
  "version": 1,
  "t": "Revenue Overview",
  "d": [["sales", [["month", "s"], ["revenue", "cur", "USD"]], [["Jan", 120000]]]],
  "v": [["t", 0, 0, [1]], ["r", 0]]
}

The compact wire format uses dataset indexes and short view/alert codes to keep LLM output small. Compact code mappings live in wire::compact; normalize expands them into the clean domain::Report model with schema: "ui.input.normalized" with the matching input version before planning or rendering. Version 2 adds governed chart opcodes backed internally by Vega-Lite. Version 3 adds governed report panels, methodology metadata, and an optional runtime light/dark control while reusing global datasets and existing view tuples. Raw Vega-Lite specs, images, isotypes, and maps are not accepted. Tabs organize content but are not access control: hidden panel data remains in the same single-file artifact. See docs/tabbed-reports-v3.md.

CLI surface

agent-ui-render validate <input.json>
agent-ui-render normalize <input.json> [output.json]
agent-ui-render plan <input.json> [output.json]
agent-ui-render render html <input.json> <output.html>
agent-ui-render render static-html <input.json> <output.html>
agent-ui-render render vue <input.json> <output.vue>
agent-ui-render skill check [<skill-dir>] [--discover]
agent-ui-render schema print \
  <compact|compact-v2|compact-v3|normalized|normalized-v2|normalized-v3|spec|spec-v2|spec-v3|config|skill-compatibility>
agent-ui-render completion <shell>

Global flags:

-o, --output <human|json>
--warnings-as-errors
--quiet
--pretty
--config <path>

Configurable limits and theme colors

Use an explicit config file to override runtime guardrails and trusted host color tokens:

agent-ui-render --config agent-ui-render.config.json render html input.json report.html
{
  "documentLanguage": "en",
  "limits": {
    "maxInputBytes": 5242880,
    "maxRowsPerDataset": 2000,
    "maxCellsPerDataset": 100000,
    "maxTotalRows": 20000,
    "maxTotalCells": 250000,
    "maxFindings": 200,
    "warnOutputHtmlBytes": 5242880,
    "maxOutputHtmlBytes": 10485760
  },
  "themeTokens": {
    "page": "#0b1220",
    "bg": "#111827",
    "surface": "#1f2937",
    "text": "#f9fafb",
    "primary": "#8b5cf6",
    "series1": "#8b5cf6",
    "series2": "#06b6d4"
  }
}

Limits and theme tokens are host/runtime policy and are never read from the untrusted payload. Theme tokens map to --agent-* CSS custom properties and are validated as safe CSS color literals before render output is written.

Development from source

make setup      # recreate renderer dependencies from the frozen lockfile
make generate   # build full/lite renderer JS plus shared CSS
make generated-check # reject generated asset drift from the index
make version-check   # verify release-coupled versions agree
make test       # run renderer and Rust tests
make coverage        # enforce Rust and Vue coverage thresholds
make security-check  # scan secrets, dependency policy, and advisories
make msrv            # check all Rust targets with Rust 1.91
make workflow-check  # validate workflow syntax and Action pins
make workflow-security-check # audit workflows with zizmor
make performance-check # enforce renderer raw/gzip budgets
make dist-smoke-check  # self-test archive/installer verification
make dev              # run the CLI help from source
make check            # run release-quality checks

Build/runtime architecture:

+--------------------------+     bun + Vite      +---------------------------+
| renderer-vue/src         | ------------------> | generated/               |
| Vue + CSS + TS sources   |                     | renderer-lite.js (v1 or  |
|                          |                     | legacy-only v3)          |
+--------------------------+                     | renderer.js (v2/v3 Vega) |
                                                 | renderer.css             |
                                                 +-------------+-------------+
                                                               |
                                                               | include_str!
                                                               v
                                                  +-------------------------+
                                                  | agent-ui-render binary  |
                                                  | selects smallest bundle |
                                                  +-------------------------+

Documentation map

  • CONTRIBUTING.md - contributor setup, architecture boundaries, and PR gates.
  • CHANGELOG.md - release history and current Unreleased changes.
  • docs/usage.md - consumer workflow for creating, validating, and rendering compact payloads.
  • docs/agent-reference.md - task routing for coding agents using or modifying this repository.
  • docs/development.md - maintainer setup, change maps, and verification.
  • docs/troubleshooting.md - common failures and recovery steps.
  • docs/architecture.md - runtime, build-time, and source-of-truth model.
  • docs/cli-reference.md - command reference and exit codes.
  • docs/compatibility.md - versioning and contract-change policy.
  • docs/charts-v2.md - governed advanced chart coverage and v2 behavior.
  • docs/tabbed-reports-v3.md - native panels, navigation, runtime themes, static output, compatibility, and hidden-data guidance.
  • docs/components.md - component catalog and presentation style reference.
  • SECURITY.md - private vulnerability reporting and release verification.
  • CODE_OF_CONDUCT.md - contributor community standards and enforcement.
  • docs/security-model.md - trust boundaries and unsafe-content rules.
  • docs/renderer-development.md - Vue renderer development and handoff bundle.
  • docs/release.md - release process and cargo-dist publishing flow.
  • skills/agent-ui-render/references/ui-input.md - compact payload contract.
  • skills/agent-ui-render/references/dataset.md - dataset tuple rules.
  • schemas/v1/*.schema.json, schemas/v2/*.schema.json, schemas/v3/*.schema.json, and schemas/config.schema.json - JSON Schema mirrors for integration checks.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages