agent-ui
Fifteen React components for chat and agent UIs. Each one installs with a Cursor rule: when to use it, when not to, and which props matter. Colors come only from theme tokens, so the agent has nothing to hardcode.
Why build components myself
There are plenty of libraries: shadcn, Magic UI, Aceternity. They are made for a person who looks at a demo and copies the code. More and more, the one installing a component is an agent, and that is where the problems my other tools catch begin. ds-lint finds hardcoded colors in copied code. ds-coverage finds local copies next to the system. ds-eval shows an agent drawing its own button more often than taking the existing one.
You can fix that afterwards, the way ui-repair does. It is cheaper to ship components that need no fixing. That takes three things a regular library does not have:
- a description of when to use it and when not to, in the words of the task rather than a props list;
- theme tokens only: no hex, no
bg-zinc-900, so there is nothing wrong to copy; - a place where the agent finds all of this before installing anything.
The second reason is AI interfaces themselves. A tool call, a permission request, model reasoning, the context window: general kits do not have these primitives, and every product draws them again. I build them once, the way I want them in my own interfaces.
What's inside
The components page opens with a live interactive scene: an agent fixes hardcoded colors and pauses to ask permission for a command. You can approve, deny, or stop it directly in the browser and switch the theme accent token.
- Prompt InputAuto-growing prompt box: Enter sends, Send turns into Stop while the reply streams. Attachments and a model picker slot.
- MessageA user or assistant turn with a streaming caret and hover actions.
- ThinkingA shimmering "Thinking" that collapses into "Thought for 4s" with the reasoning text.
- Tool CallOne tool call: status, arguments, output, error.
- ApprovalThe agent asks to run one concrete command. After the decision the card collapses into a one-line record.
- Context MeterA context-window ring with a warning threshold.
- SuggestionsStarter prompts and follow-up questions.
- Agent DockA floating status bar for a background agent that opens into its step list on hover.
- PlanThe steps the assistant proposes before or during a task.
- ChoiceA question with two to five mutually exclusive options.
- Data TableA comparison or tool result inside an answer.
- Answer ChartOne bar or line series, up to eight points, in the primary token.
- Code BlockCode or a diff in an answer, with a filename and copy.
- SourcesCitations under an answer: title, address, short excerpt.
- ArtifactA file card in the thread. Its contents open in a side panel.
A rule next to the code
Every install writes two files: the component and a .mdc rule. The rule's description names the task, not the component ("an agent asks permission before a risky action"), so Cursor loads it only when it is relevant.
Every rule has a "do not use for" section that names the project primitive to use instead. That is where agents usually go wrong: an Approval in place of a confirm dialog, or Thinking in place of a loading skeleton.
components/agent-ui/approval.tsx
.cursor/rules/agent-ui-approval.mdc
> Ask before the agent deletes the build folder
agent loads agent-ui-approval.mdc
<Approval title="Run a shell command"
command="rm -rf ./build"
onApprove={...} onDeny={...} />
How different agents read the library rules:
| Environment / agent | Rule source | How it connects |
|---|---|---|
| Cursor | .cursor/rules/agent-ui-*.mdc | Installed automatically with the component via shadcn add and loaded by task description |
| Claude Code / Codex / other agents | llms.txt and llms-full.txt | Component index or all 15 rules in a single file to pass into context or link from CLAUDE.md / AGENTS.md |
Installation
The registry is shadcn-compatible. It needs Tailwind v4 and the shadcn theme as CSS variables.
npx shadcn@latest add https://antoshkin.tech/agent-ui/r/approval.json
npx shadcn@latest add https://antoshkin.tech/agent-ui/r/all.json
The registry build fails if a component gets a hex value, a palette class like text-neutral-500, or an arbitrary value like text-[14px]. Change the theme tokens and every component follows; the accent switch on the components page shows it.
Limitations
I have not measured with ds-eval how much the rules raise correct usage. For now it is a hypothesis; the next step is running a task suite with and without the rules.
The rules use Cursor's format. Other agents get the same text through llms-full.txt but do not load it automatically. Components read var(--muted-foreground) directly, so the older shadcn theme with HSL channels will not work.