Proper UI

AI agents & the Proper UI Skill

One portable Skill for Claude Code, Codex, Cursor and Lovable, plus the two CLI commands that install it and let an agent inspect a project before it writes any UI code.

Proper UI ships one authored Skill (skills/properui/SKILL.md in the repo) that works across Claude Code, Codex, Cursor and Lovable. It encodes the same workflow every integration page already documents by hand: inspect the project, search the registry before writing markup, prefer a full-page example for a whole screen, keep semantic tokens and accessibility intact, verify before reporting done. Two CLI commands make that Skill installable and the project it targets inspectable.

properui agent init

Installs the Skill for one or more AI coding tools. Run it once per project, per tool:

npx @properui/cli@latest agent init --client claude
npx @properui/cli@latest agent init --client codex
npx @properui/cli@latest agent init --client cursor
npx @properui/cli@latest agent init --client lovable

Or install for everything at once; this is also the default when --client is omitted:

npx @properui/cli@latest agent init --client all

What each client gets

ClientFiles writtenNotes
Claude Code.claude/skills/properui/SKILL.md + a short pointer appended to CLAUDE.md (created if missing)Claude Code loads project skills from .claude/skills/ automatically: no further setup.
Codex.agents/skills/properui/SKILL.md + a rules block appended to AGENTS.md (created if missing)Codex discovers skills under .agents/skills/, and reads AGENTS.md for every session regardless.
Cursor.cursor/rules/properui.mdc (alwaysApply: true)Cursor's rules system only reads .mdc files with frontmatter from .cursor/rules (it does not read SKILL.md), so the same guidance is written as a Cursor rule instead.
LovableNothing written locallyLovable runs in the browser with no access to this checkout. agent init --client lovable prints the Skill's public GitHub URL and what to paste into Lovable's knowledge / custom instructions panel.

agent init also registers the MCP server where the client reads a project-level MCP config: .mcp.json for Claude Code and .cursor/mcp.json for Cursor. An existing file is merged (other servers are kept, and an existing properui entry is left alone unless you pass --overwrite). Codex keeps MCP servers in ~/.codex/config.toml, outside the project, so for Codex the TOML block is printed instead. Pass --no-mcp to skip all of this.

CLAUDE.md and AGENTS.md are never overwritten wholesale: the block agent init adds lives between a pair of HTML comment markers, so re-running the command updates that section in place and leaves the rest of the file untouched. Running agent init again after an update to the Skill is always safe.

Command options

OptionDescription
--client <name>claude, codex, cursor, lovable, or all (default).
--overwriteReplace the installed SKILL.md / rule file even if it already exists and differs: useful after editing the Skill upstream. Does not affect the CLAUDE.md/AGENTS.md marker block, which is always kept in sync.
--no-mcpSkip registering the MCP server (.mcp.json, .cursor/mcp.json, the printed Codex block).
-y, --yesAccept every default; never prompt.
--cwd <path>Run against a directory other than the current one.

properui info --json

Reports everything an agent needs before touching UI code: detected framework, platform (react or html), TypeScript, Tailwind version, package manager, the components.json aliases and theme CSS path (when the project has been through init), which registry entries are already installed, and the installed versions of @properui/ui and the properui CLI itself.

npx @properui/cli@latest info --json
{
    "framework": "next-app",
    "platform": "react",
    "typescript": true,
    "tailwindVersion": 4,
    "packageManager": "pnpm",
    "config": {
        "present": true,
        "aliases": { "components": "@/components", "utils": "@/utils", "ui": "@/components/base", "hooks": "@/hooks" },
        "theme": "src/styles/theme.css",
        "css": "src/app/globals.css",
        "registry": "https://properui.dev/r"
    },
    "packages": {
        "@properui/ui": { "installed": null, "declared": null },
        "@properui/cli": { "installed": "0.3.1", "declared": null }
    },
    "installed": [{ "name": "badges", "layer": "base", "type": "component" }]
}

installed is computed the same way properui diff finds local components: every non-example entry in the registry index is checked against the project's files, and anything present is reported. Without --json, the same data prints as a short human-readable report instead: useful for a quick check from your own terminal, not just from an agent.

Command options

OptionDescription
--jsonPrint machine-readable JSON instead of the formatted report.
--registry <source>Registry directory or base URL for this run (see docs/cli.md).
--cwd <path>Run against a directory other than the current one.

platform is the first thing to read. react means the TSX components; html (Vue, Nuxt, Angular, Svelte, SvelteKit, Astro, plain HTML) means add installs <name>-html snippets and the project should get @properui/elements tags or plain pui- markup, never TSX. installedHtml lists the html entries already installed. See Frameworks.

The Skill itself tells an agent to run this before deciding anything: whether to run init first, which alias to use in hand-written imports, and which components are already installed and shouldn't be re-added.

MCP server

@properui/mcp is a Model Context Protocol server that gives an assistant the registry and the CLI's add as tools, so it can search, read and install components without shelling out for every lookup. It is the CLI's own code (registry client, fuzzy search, add, info, check) bundled behind MCP, so a file it writes is exactly what properui add would have written. The Skill tells an agent to prefer these tools when they are connected, and to fall back to the CLI when they are not.

ToolSame asWhat it returns
list_componentslist --jsonRegistry entries (name, layer, type, title, description), filtered by layer and type
search_componentssearch <query>Fuzzy matches over names, titles, descriptions, example names and exported symbols
get_component/r/<name>.jsonEvery file with its source, npm and registry dependencies, usage guidance and the docs URL
get_component_docs/<route>.mdThe entry's docs page as markdown
add_componentadd <names...>Files written, the installed record in components.json, and the install command for npm deps
get_project_infoinfo --jsonThe same report as above
check_tokenscheck [dir]Raw palette classes, dark: variants and arbitrary colour values

The registry index is also a resource (properui://registry/index), and so is every entry (properui://registry/<name>).

Claude Code

claude mcp add properui -- npx -y @properui/mcp

Add --scope project to write it to the project's .mcp.json (which is what agent init --client claude does).

Cursor

.cursor/mcp.json in the project, or ~/.cursor/mcp.json for every project:

{
    "mcpServers": {
        "properui": {
            "command": "npx",
            "args": ["-y", "@properui/mcp"]
        }
    }
}

Codex

~/.codex/config.toml:

[mcp_servers.properui]
command = "npx"
args = ["-y", "@properui/mcp"]

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
    "mcpServers": {
        "properui": {
            "command": "npx",
            "args": ["-y", "@properui/mcp"]
        }
    }
}

VS Code

.vscode/mcp.json in the project (VS Code uses servers, not mcpServers):

{
    "servers": {
        "properui": {
            "type": "stdio",
            "command": "npx",
            "args": ["-y", "@properui/mcp"]
        }
    }
}

The server reads the same registry the CLI does: --registry <source> after the package name, then PROPERUI_REGISTRY, REGISTRY_URL, the registry field of the project's components.json, and finally https://properui.dev/r. A local directory works too, e.g. "args": ["-y", "@properui/mcp", "--registry", "./packages/registry/dist"]. Tools act on the directory the client starts the server in (the project root, for every client above); each project tool also takes an explicit cwd.

FAQs

Using Proper UI through the shadcn CLI and MCP

Proper UI also mirrors its registry in shadcn's own format, under the namespace @properui: https://properui.dev/r/shadcn/registry.json is the index, https://properui.dev/r/shadcn/<name>.json is one entry (packages/registry/src/shadcn.ts generates both from the native registry every pnpm registry:build). This is a second path to the same components, alongside the properui CLI and the Skill above — pick whichever your tool already speaks.

Point a project's own components.json at the namespace:

{
    "registries": {
        "@properui": "https://properui.dev/r/shadcn/{name}.json"
    }
}

and then install with shadcn's own CLI instead of ours:

npx shadcn@latest add @properui/buttons

This resolves registryDependencies and rewrites imports the same way properui add does, because both read the same underlying files — the shadcn build only changes the JSON shape, never the component source. Without a components.json yet, the same file installs standalone from its full URL: npx shadcn@latest add https://properui.dev/r/shadcn/buttons.json.

An agent connected to shadcn's own MCP server gets this for free, too: that server discovers items through whichever registries are listed in the project's components.json, so once @properui is added there, the same MCP tools that search and install any other shadcn registry also search and install Proper UI — no separate Proper UI MCP configuration needed for this path. See docs/ecosystem.md for how @properui gets (or already is) listed in shadcn's official registry directory, and for the equivalent submission steps for registry.directory, 21st.dev and the skills marketplaces.