English | 日本語
An open-source UI library designed for the LLM as its primary consumer. LLMを第一の消費者として設計する、オープンソースUIライブラリ。
Status: on npm — 12 components, CLI, and MCP server. See CHANGELOG for the current version. Docs: axiom-ui.joinclass.jp — live catalog with previews, generated from the components themselves.
# One-shot: copy a component into your repo
npx @joinclass/axiom-ui add button
# Or install once and reuse
npm install -D @joinclass/axiom-ui
npx axiom-ui listRequires Node.js 22+ and Tailwind CSS in the target project.
| Command | Effect |
|---|---|
axiom-ui list |
Print every component with its short intent. |
axiom-ui add <name> [--dir <path>] [--force] |
Copy <name>.tsx into your repo (defaults to ./src/components/). Refuses to overwrite without --force. |
axiom-ui mcp |
Start the MCP server on stdio (see below). |
The CLI copies files verbatim. What ships is what the LLM saw — no post-processing, no dependency injection. You own the code after add.
Point Claude Code, Cursor, or any MCP-capable agent at axiom-ui mcp and it gets two tools:
list_components— every component's name and intent.get_component— the full.tsxsource plus the structured manifest for one component.
Example Claude Code config (~/.claude/mcp.json or per-project .mcp.json):
{
"mcpServers": {
"axiom-ui": { "command": "npx", "args": ["-y", "@joinclass/axiom-ui", "mcp"] }
}
}The agent discovers components via the manifest, reads the source once, and generates correct usage in a single shot — no docs URL to paste.
get_component always returns the original source that shipped in the package version you installed. If you edit a component after running add, the MCP server won't reflect your local edits — it's a package-scope tool, not a workspace-scope one. This is intentional: the manifest describes what the library ships, not what you own.
Form primitives: button, input, textarea, checkbox, select, combobox
Layout / structure: dialog, tabs
Overlay / feedback: popover, menu, tooltip, toast
Run npx @joinclass/axiom-ui list for the intent of each.
For domains where a third-party library already dominates, use it — Axiom does not ship an inferior in-house version:
| Need | Use |
|---|---|
| Command palette (⌘K) | cmdk |
| Data table (sort, filter, virtualize) | TanStack Table |
| Advanced date picker | react-day-picker (native <input type="date"> for the simple case) |
| Forms & validation | React Hook Form + Zod |
| Charts | Recharts |
Toast queue / imperative toast() sugar |
Sonner |
Native HTML already covers the following, so Axiom doesn't ship them either: <details> (accordion), <progress>, <input type="range"> (slider), <input type="date"> (date input), <input type="file"> (file input), <input type="radio"> (radio group), <hr>, <aside>, <nav><ol> (breadcrumb), <table> (simple), <img> (avatar).
Every existing UI library is optimized for human DX. Axiom UI is optimized, from first principles, for generation, comprehension, and modification by LLMs. Humans are the secondary beneficiaries.
If shadcn/ui is accidentally AI-friendly, Axiom is AI-first by design.
Every design decision must pass one question:
"Does this decision raise or lower the probability that an LLM generates this component correctly in one shot?"
If it doesn't raise it, we don't build it.
Read the full Design Philosophy (Japanese).
The five-step algorithm — applied in order, irreversibly:
- Question every requirement. Every prop, component, and option must justify its existence.
- Delete. The best prop is no prop. One way to do each thing — variants are hallucination fuel. The best component is no component.
- Simplify. Polish only what survived deletion.
- Accelerate. Tokens and bytes per component are measured and gated in CI. Fat components don't merge.
- Automate — last. MCP server, CLI, doc generation come only after deletion and unification.
| Decision | Consequence |
|---|---|
| 1 component = 1 file | Implementation, types, docs, examples, and manifest co-located. Fits in a single context window — by constraint, not by luck. |
| Type as the contract | strict: true, discriminated unions, no any. Types are the primary documentation. |
| Copy & own | No npm runtime dependency. A CLI injects code into your repo. You own it; LLMs can freely modify it. No black boxes. |
| MCP-first distribution | An MCP server ships alongside the library, so agents (Claude Code, Cursor, …) fetch version-accurate specs without wasting tokens. |
| Machine-readable manifest | Each component carries { intent, props, states, a11y, examples } as structured data, so agents can select and render components — the foundation for generative UI — instead of being told about them. |
| Zero-config defaults | Works correctly with no props. Escape hatches exist but are never required. |
| Choice | Why |
|---|---|
| React only | Go narrow and deep. One abstraction layer deleted. |
| Tailwind CSS | Class strings are directly readable and generatable by LLMs. |
| TypeScript strict | Type = contract = primary documentation. |
| CLI injection + MCP server | Zero black-box dependencies. |
| Minimal runtime dependencies | Keeps the idiot index — actual cost over essential cost — low. |
These are v0 decisions, not philosophy. They can be replaced for better reasons — but never in the direction of more options.
- Infinite theme customization (one good default instead)
- Multi-framework support (in v0)
- Anything claiming to "cover every use case"
- A second API for the same purpose
- Config options for features nobody asked for
Measured, not felt:
- token/component — the average component fits in a single context window
- bundle/component — bytes per component are tracked and never regress
- one-shot generation rate — the primary KPI: how often an LLM generates correct code with zero fixes
- deletion ratio — lines deleted vs. lines added, recorded per release
Before requesting review, every PR must answer:
- Does this delete something? If not, why can't it?
- Does this introduce a second way to do something?
- Does the component still fit in a single context window?
- Can an LLM use this correctly by reading the types alone?
- Does this keep
token/componentandbundle/componentfrom regressing?
If you're stuck on any of these, it's not ready to merge.
The best part is no part. The best process is no process. — This library is an attempt to apply that to UI.