Skip to content
  • Introduction
    nativecn is shadcn for Expo apps: Components you copy into your app and own, built so AI agents can build and verify whole mobile apps.
  • Installation
    Create a new Expo app with nativecn, or add nativecn to an existing one.
  • components.json
    The project file that records your Preset, Structure, aliases and agents.
  • CLI
    Every nativecn-cli command and flag: init, create, add, agents and mcp.
  • Changelog
    What changed in each nativecn release.
  • Theming
    Tokens, Colour Roles, Scale, Scheme, createStyles and fonts.
  • Presets & Styles
    Style, Base Colour, Accent Colour, Radius and fonts: chosen once, baked into your code.
  • Folder structure
    Flat and feature Structures, Destinations and the placement rule.
  • AI agents
    Rules, Skills, the nativecn MCP server, the Plugin and the Visual QA Loop.
  • Alert
    Alert, AlertTitle and AlertDescription: an inline message with Variants (default, destructive, success, warning, info), each with a default icon.
  • Avatar
    Round user image (expo-image) with fallback initials, in sizes sm, md and lg.
  • Badge
    Small status label with Variants default, secondary, outline, destructive, success and warning.
  • Button
    Button with Variants (primary, secondary, outline, ghost, destructive, link), Sizes, an icon slot, loading and status; icon-only requires aria-label.
  • Card
    Card surface with CardHeader, CardTitle, CardDescription, CardContent and CardFooter; onPress makes the whole card pressable.
  • Checkbox
    Checkbox with an optional label, controlled or uncontrolled, an indeterminate (mixed) state and a haptic tick.
  • Chip
    Chip (plain, toggle or removable, with an optional icon) and ChipGroup (single or multiple choice on the SelectionGroup Primitive), with a haptic tick.
  • Container
    Wraps a Screen: safe-area edges, scrolling, keyboard avoidance, Token padding and a max content width.
  • Drawer
    Drawer panel content for Expo Router's drawer (expo-router/drawer): DrawerContent, DrawerHeader, DrawerSection, DrawerItem (label, icon, href, badge; active from the current route) and DrawerFooter.
  • Empty State
    What a Screen or list shows when there is nothing to show yet: an icon, a title, a description and an action.
  • FormField
    Lays out a control with its Label, description and error, and links them for screen readers ("Email, text field, Enter a valid email").
  • Icon
    Every glyph: a Lucide icon at a Token size in a Colour Role, decorative unless labelled.
  • Input
    Single-line text field with Sizes, a leading icon, error/success status, a focus ring and an automatic Show/Hide password toggle.
  • InputOTP
    One-time code field: one hidden input drives N cells; numeric keyboard, SMS/Keychain autofill, paste, onComplete, error/success status and secure.
  • Label
    A field's visible label in the label type Variant, with a required marker read as "required".
  • List
    Settings-style rows: ListSection, ListSectionHeader, ListSectionFooter and ListItem (title, description, icon, trailing, chevron, destructive, onPress); FlashList-safe.
  • Progress
    A horizontal progress bar: a value 0–100 that animates, or indeterminate; role progressbar with its value.
  • RadioGroup
    RadioGroup and RadioGroupItem: a single choice from a list on the SelectionGroup Primitive, vertical or horizontal, with a haptic tick.
  • SchemeSwitcher
    Theme switcher / dark mode toggle: System, Light and Dark as SegmentedTabs, or one icon button cycling through them. Calls setScheme, which persists the choice.
  • SearchField
    Search box with a search icon, an automatic clear (×) button, a loading spinner and onSubmit from the keyboard's Search key.
  • SegmentedTabs
    In-screen tabs (not navigation): segmented or underline Variants, an animated indicator, and only the selected tab's content rendered.
  • Separator
    A hairline divider, horizontal or vertical, decorative by default.
  • Skeleton
    A placeholder shape shown while content loads; pulses unless Reduce Motion is on, hidden from screen readers.
  • Slider
    Pick a number in a range by dragging or tapping (Gesture Handler + Reanimated), snapped to steps with a haptic tick; adjustable for screen readers.
  • Spinner
    An indeterminate loading indicator in a Colour Role, announced as busy; still under Reduce Motion.
  • Switch
    A themed on/off Switch, identical on iOS and Android, with an optional label, a thumb that slides (instant under Reduce Motion) and a haptic tick.
  • TabNavigation
    The bottom tab bar: the custom tabBar of an Expo Router JS Tabs Layout, with classic and floating Variants, per-tab icons and badges from Tabs.Screen options.
  • Text
    All text: the type ramp as Variants, text Colour Roles, alignment and the font-scaling switch.
  • Textarea
    Multi-line text field that grows from minRows to maxRows, with a character counter when maxLength is set.
  • Toast
    Sonner-style Toasts: a <Toaster /> in the root Layout and toast(), toast.success/error/info/warning/dismiss. At most 3 stacked, 4s auto-dismiss, swipe away, announced, above native modals.
  • Profile header + grouped sections
    Drawer panel with a profile header (avatar, name, email, plan Badge), labelled sections (Main, Workspace, Support) and Log out pinned in the footer.
  • SaaS workspace
    Drawer panel for a SaaS workspace: logo and name with a close button, an Accent Colour onboarding item with a 5 Steps Badge, main items, a bottom group (Notifications with a count, Settings, Docs, Help) and a footer with a team switcher and the user's avatar.
  • Cover header
    Drawer panel with a dark cover (large avatar, name, View profile, a bell with a count, an overflow button and a round + action), icon items active in Accent Colour text, a divider and text-only secondary items.
  • Classic centred
    A centred sign-in Screen: logo, email and password, Forgot password, an "or" divider, then Apple and Google, and a Sign up link.
  • Social-first hero
    A social-first sign-in Screen: a dark brand hero (logo, headline, subtitle, centred) above a panel where Apple and Google lead and "Continue with email" reveals the email form.
  • Email-first, two steps
    An email-first sign-in Screen in two steps: the email, then the password, with "Email me a code instead" switching to a 6-digit code (InputOTP). Lucide chevron-left Back buttons.
  • Classic single form
    A classic sign-up Screen on one scroll: Apple and Google on top, "or", then name, email and password, a terms Checkbox with Terms and Privacy Policy links, Create account, and a Sign in link.
  • Step-by-step wizard
    A sign-up wizard, one question per step under a Progress bar: email, name, password, then a 6-digit code (InputOTP). Lucide chevron-left Back buttons; the Continue button rides above the keyboard.
  • Social-first + verify
    A brand-led, passwordless sign-up Screen: the logo and headline centred above Apple and Google; "Sign up with email" reveals the email field, and Send code moves on to a 6-digit code (InputOTP).
  • announce
    Reliable screen-reader announcements on iOS and Android (Button and Input status, Toast, error, success and warning Alerts).
  • FocusChain
    Automatic Next/Done between fields in on-screen order; Done submits the form.
  • FormField context
    Links a field to its label, description and error for screen readers; passes status, disabled and required down.
  • Keyboard
    KeyboardProvider setup, a scroll view that keeps the focused field above the keyboard, and a footer that keeps a form's main button above it.
  • Portal
    Renders content above every Screen (above native modals on iOS), layered and safe-area aware.
  • Pressable
    Pressed look from a Style Slot, tap area extended to 48, no handlers while disabled or loading, optional haptics, role and aria-* states.
  • SelectionGroup
    Single or multiple choice within a group, with radio, tab or checkbox roles and selected states.
  • useControllableState
    One implementation of controlled and uncontrolled values for form controls.
  • useMotion
    Enter/exit animations and timing/spring configs from the motion Tokens; instant when Reduce Motion is on.
  • Theme
    Tokens, Scale, Colour Roles, ThemeProvider, createStyles and the navigation theme.

AI agents

Rules, Skills, the nativecn MCP server, the Plugin and the Visual QA Loop.

View as Markdown

nativecn is built so that AI agents can build whole mobile apps with it and check the result on a real device. Every project gets the Agent Kit: the Rules, Skills and nativecn MCP server, with a Plugin for agent hosts.

create and init write the Agent Kit for the agents you choose with --agents. Supported agents are Claude Code (claude), Codex (codex), Cursor (cursor) and Antigravity (antigravity). To add agents or refresh the kit later, run:

npx nativecn-cli@latest agents --agents claude,cursor --update

If fetching the Skills fails (for example, offline), create and init still finish and print how to retry.

Rules

A Rule is a project-level instruction file that constrains how an agent writes code in your app. nativecn writes its Rules into AGENTS.md (or appends a nativecn section to yours) and adds @AGENTS.md to CLAUDE.md for Claude Code. AGENTS.md stays under 24 KB.

  1. Styling: Tokens only, via createStyles. No hard-coded colours or sizes; t.scaleValue(n) for genuine one-offs. No Tailwind, NativeWind or className.
  2. Building blocks: all text uses Text, all glyphs use Icon, and Screens are wrapped in Container.
  3. Feedback: never Alert.alert or any platform alert. Use nativecn's own toast() and Alert Components.
  4. Navigation: the drawer comes only from expo-router/drawer; never install @react-navigation/* or the npm package expo-drawer. SegmentedTabs is for tabs inside a Screen and TabNavigation for the bottom bar; neither is Expo Router's Tabs.
  5. Dependencies: npx expo install for Expo SDK packages. Anything else: ask the user first.
  6. Storage: AsyncStorage holds only non-sensitive preferences. Tokens, credentials and personal data go in expo-secure-store.
  7. Placement: follow structure and the placement rule.
  8. The Preset is fixed. Never change preset in components.json or try to switch Style.
  9. Adding items: use the MCP tool get_add_command or nativecn-cli add. Always pass --route for Screen Blocks, and --feature too in feature mode. Run --diff before updating, and use -o only when the user asks for their edits to be replaced.
  10. Forms: react-hook-form and zod, wired through FormField, with fields inside FocusChain.
  11. Accessibility: meet the accessibility checklist. Never remove role or aria-* props.
  12. After changes: run get_audit_checklist and fix anything it flags.

AGENTS.md also lists the Skills, the MCP tools and the key commands.

Skills

A Skill is a packaged set of instructions that teaches an agent one mobile task with nativecn. nativecn ships five. The CLI writes one copy of each to .agents/skills/<name>/ (read by Codex, Cursor and Antigravity) and links .claude/skills/<name> to it for Claude Code (a copy on Windows).

SkillUse it forWhat it teaches
nativecn-setup"start a new app", "add nativecn"create/init flags, custom Presets, applying the Init Layout snippet, choosing agents. Carries the Rules for Plugin-only users.
nativecn-build-screen"build a login screen", "add a settings screen"Picking a Block with list_block_variants, adding it with --route/--feature, composing Components, wiring routes and Layouts.
nativecn-theme"change colours", "dark mode", "different font"Editing Tokens in the Theme, Scheme switching, migrating Expo's default theme files.
nativecn-component-authoring"new component", "add a variant"The Component contract, the accessibility checklist, Primitives, createStyles and the placement rule.
nativecn-visual-qa"match the design", "screenshot and fix"The Visual QA Loop.

The nativecn MCP server

The nativecn MCP server tells an agent which Components, Blocks, Block Variants and Themes exist and what they contain, like shadcn's MCP. It is read-only: it never writes files or runs the CLI.

ToolReturns
list_itemsevery Component, Primitive and Block, by type and category
search_itemsitems matching a query (for example, "dark mode toggle" finds SchemeSwitcher)
view_itemsfiles, props, Variants and docs, rendered in the project's Style
get_item_examplesready-to-copy usage examples
get_add_commandthe exact nativecn-cli add command, with the right --route and --feature for this project
get_project_configthe project's components.json
get_audit_checklista post-change checklist from the Rules: Tokens only, no Alert.alert, the placement rule, accessibility
list_block_variantsthe Block Variants for a purpose, with what makes each one different
list_preset_options + build_preset_codeevery Style, colour, radius and font, and the short code for a custom Preset

Local and remote

  • Local (npx -y nativecn-cli@latest mcp, over stdio) reads your components.json, so its answers fit your Style, Structure and routes. This is what create, init and agents configure.
  • Remote (https://nativecn.dev/mcp) is for browsing without a project. It has the same tools except get_project_config, and answers with the default settings.

Both fetch live data from the nativecn.dev Registry, cache it for a few minutes, and return a clear error rather than a guess when the Registry is unreachable.

MCP config files

The CLI writes one config file per chosen agent:

AgentFile
Claude Code.mcp.json
Cursor.cursor/mcp.json
Codex.codex/config.toml
Antigravity.agents/mcp_config.json (uses serverUrl for the remote server)

For example, .mcp.json:

{
  "mcpServers": {
    "nativecn-cli": {
      "command": "npx",
      "args": ["-y", "nativecn-cli@latest", "mcp"]
    }
  }
}

Codex loads .codex/config.toml only in a trusted project.

To browse without a project, point an agent at the remote server instead. In Claude Code:

claude mcp add --transport http nativecn https://nativecn.dev/mcp

AI-friendly docs

Everything on nativecn.dev is also available as plain text for agents, generated from the same sources as the pages:

  • Copy for AI, at the top of every docs page, copies the page as clean markdown.
  • .md twins: append .md to any docs URL, e.g. /docs/installation.md.
  • /llms.txt indexes every page and Registry item; /llms-full.txt has every page in one file.
  • Copy to LLM, on every Component and Block page, copies one item's description, add command, props, usage examples and source as a single prompt-ready block. For example, the Pressable Primitive:

Plugin

A Plugin is an agent-host package that bundles the Agent Kit for one-step installation. The nativecn Plugin contains the five Skills and the local MCP server, packaged as a Claude-format marketplace (for Claude Code and Codex) plus Cursor and Antigravity manifests.

Plugins install per user, not per project, so create and init print the install command for each chosen agent rather than running it. A Plugin can't write AGENTS.md, so the nativecn-setup Skill carries the Rules and tells the agent to run init (or agents) the first time it is used in a project.

Visual QA Loop

The Visual QA Loop is an agent-driven design and UX review of your running app, run by the nativecn-visual-qa Skill. The agent navigates Screens and User Flows on a device, captures screenshots, judges them against the Reference Design, traces each problem to its root in the code, fixes small and safe problems, and reports the rest.

It is not pixel comparison and not a test runner, and there is no nativecn-cli qa command. nativecn provides only the Skill and Rules; the agent drives devices with the platform's own tools: adb for Android and xcrun simctl for the iOS Simulator.

The design folder

All optional, at the root of your app:

design/screens/<screen>.png        Reference Design images, such as Figma exports (+ <screen>.dark.png)
design/flows.md                    confirmed User Flows
design/expectations.md             your description of Screens that have no image
  • A Reference Design is what a Screen is meant to look like: an image in design/screens/ when there is one, otherwise your description in design/expectations.md.
  • A User Flow is a confirmed sequence of Screens and actions, such as sign up → verify code → home. The agent derives flows from your code and docs, asks you to confirm or correct them, and saves them in design/flows.md.
  • For a Screen with no image, the agent asks what it should look like or do and records your answer.
  • If a Figma MCP server is connected, the agent also reads the design's real values from it.

How the agent judges

At the design-system level, never pixel by pixel:

  • spacing on the Token scale;
  • typography: the right Text Variant for each role, and a clear hierarchy;
  • layout: alignment, safe areas, clipping and overlap;
  • Components: the right Component and Variant, with all states present;
  • Colour Roles in light and dark;
  • misalignment and broken Components;
  • non-functional actions: every action does something and leads where the User Flow says.

Every confirmed User Flow is checked end to end against the Screens and the code.

Fix or report

The rule: the agent fixes a problem itself only if the fix is visual-only, stays inside one Screen, uses what already exists (Tokens, Components, Variants) and is easy to undo. Otherwise it reports the problem and waits for you.

Auto-fixedReported for you to decide
A hard-coded colour → the matching Colour RoleNavigation and flow: where actions lead, routes, missing Screens
Spacing or size off the scale → the nearest Token, or t.scaleValue(n)Non-functional actions (the intended behaviour can't be guessed)
The wrong Text Variant for its roleLogic: data, API, state, validation rules, form behaviour
Misalignment: alignment, a missing gap, uneven paddingAuth, storage, permissions and security
Safe-area and keyboard problems → wrap the Screen in ContainerTheme or Preset changes in src/theme/, which affect the whole app
Clipping or overflow: numberOfLines, shrink or wrapEdits to shared Components in src/components/, which affect every Screen
Broken Component usage: a misspelled prop, a wrong Variant, a missing required propPackages, app.json and config
Missing visual states when the data already exists (such as loading)Copy and content, images and assets
Inconsistent icon sizes or coloursLayout redesigns: moving sections, changing hierarchy, swapping Components
Tap targets under 48 → hitSlopDeleting code or features
Accessibility gaps: a missing role or labelA design that conflicts with the Rules, or an unclear design

Limits on auto-fixes:

  • Each stays within one Screen file and its private parts.
  • A fix needing more than about 30 changed lines becomes a report.
  • After fixing, the agent captures the Screen again to confirm. A fix that doesn't hold after three attempts is reverted and reported.
  • The agent never commits. Auto-fixes stay uncommitted for you to review.

The report

Shown in chat and saved as report.md in the run's temp folder. Each finding gives where (the Screen and file:line), what's wrong, the root cause in the code, options with trade-offs (one recommended), the severity (broken, wrong or polish) and the status (auto-fixed or awaiting you).

Allowed device commands

The agent opens, navigates and screenshots only the app under development (its scheme, package and bundle id from app.json, or Expo Go's exp:// URL), using only these commands. Nothing else on the device unless you ask.

PurposeAndroid (adb)iOS Simulator (xcrun simctl)
list devicesadb devices -lxcrun simctl list devices booted -j
open a Screenadb shell am start -a android.intent.action.VIEW -d <scheme>://<route> -p <package>xcrun simctl launch booted <bundleId>, xcrun simctl openurl booted <scheme>://<route>
navigateadb shell input tap, swipe, text, keyevent BACK; adb exec-out uiautomator dump /dev/ttydeep links only
screenshotsave, pull, delete (below)xcrun simctl io booted screenshot <tmp>/…
light and darkadb shell cmd uimode night yes / noxcrun simctl ui booted appearance dark / light
status bardemo mode, via adb shell settings and am broadcastxcrun simctl status_bar booted override --time 9:41 --batteryLevel 100

Android screenshots are saved, pulled to your computer, then deleted from the phone, every time:

adb shell screencap -p /sdcard/nativecn-qa.png
adb pull /sdcard/nativecn-qa.png <tmp>/nativecn-qa/<device>/<timestamp>-<screen>.png
adb shell rm /sdcard/nativecn-qa.png
  • With exactly one Android device attached, commands leave out -s. With several, the agent adds -s <serial> and you are asked to approve.
  • iOS commands use booted instead of a Simulator id. iOS flows use deep links plus reading the code, since there is no tap tool.
  • Screenshots go to <OS temp>/nativecn-qa/<device>/, and only the last 20 per device are kept. Nothing is left on the phone.
  • Installing apps, clearing data, adb push, other adb shell commands, and automation tools such as Maestro are out of scope.

--qa-permissions

By default your agent asks before each device command. To skip those prompts, opt in when you run init or agents:

npx nativecn-cli@latest agents --qa-permissions

It writes auto-approve rules for exactly the commands above:

AgentWhere
Claude Code.claude/settings.json
Codex.codex/rules/*.rules (loaded only in trusted projects)
Cursor.cursor/permissions.json and .cursor/cli.json
Antigravitya snippet is printed for your settings; it has no project-level rules
  • Allow rules only. The rules only skip the confirmation prompt for matching commands. Every other command still asks, and nothing is blocked. The Rules and the Skill remain the real guard.
  • No deny rules, because they would give false assurance: extra commands can be smuggled through adb shell.
  • Cursor: the project files replace your own IDE terminal allowlist in this project, which is why the flag is opt-in.