masicn
v0.0.4
Published
CLI for masicn — copy-paste React Native UI components
Maintainers
Readme
masicn CLI
The
npx masicncommand — copy-paste React Native UI components into your project.
Built from scratch by Manish Kumar · Developed at skipp.co.in
masicn is a shadcn/ui-style component system for React Native. Run a command, get the source. You own it, you modify it, no lock-in.
Before You Begin
masicn works with React Native CLI projects only. Expo is not supported yet.
Requirements
| Requirement | Minimum | Notes |
|-------------|---------|-------|
| Node.js | 18 | Check: node --version |
| React Native | 0.73 | CLI project, not Expo |
| CocoaPods | any | macOS + iOS only |
| Xcode | any | macOS + iOS only |
Create a project first
npx @react-native-community/cli@latest init MyApp
cd MyAppThen run masicn inside it. The CLI reads package.json and react-native.config.js to detect a React Native project — running it outside one will warn or abort.
Installation
No global install needed:
npx masicn@latest <command>Or install globally to drop the npx:
npm install -g masicn
masicn <command>How It Works
npx masicn@latest init → copies the design system, patches babel/RN config, installs native deps, downloads fonts
npx masicn@latest add button → fetches Button.tsx from the registry, writes it to your projectComponents are plain .tsx files. They import from your local design system copy (src/masicn/) — not from any npm package. The CLI tracks what you've installed in masicn.json.
Machine-readable output (--json)
Every data-returning command accepts a global --json flag that switches stdout to a single, deterministic JSON line. No colors, no spinners, no prompts — only the JSON object. This is the stable API surface used by the mcp server and any scripting tool.
npx masicn@latest list --json
npx masicn@latest search button --json
npx masicn@latest info button --json
npx masicn@latest add button --dry-run --json
npx masicn@latest status --json
npx masicn@latest diff button --json
npx masicn@latest graph --json
npx masicn@latest usage --jsonEnvelope
Every response uses a consistent wrapper:
Success:
{
"success": true,
"data": { ... },
"meta": { "command": "list", "timestamp": 1714000000000 }
}Error:
{
"success": false,
"error": { "code": "COMPONENT_NOT_FOUND", "message": "..." }
}Error codes
| Code | When |
|------|------|
| CONFIG_NOT_FOUND | masicn.json is missing |
| REGISTRY_FETCH_FAILED | Network or HTTP error reaching the registry |
| COMPONENT_NOT_FOUND | Component name not in the registry index |
| NOT_INSTALLED | Component not recorded in masicn.json |
| INTERACTIVE_REQUIRED | add called with no component names and --json (interactive picker requires a TTY) |
| RESOLUTION_FAILED | Dependency resolver threw (circular deps, missing dep) |
| UNKNOWN | Unexpected error |
Per-command data shape
| Command | data fields |
|---------|---------------|
| list | { components: [{ name, category, latestVersion, installed, installedVersion }] } |
| search | { query, results: [{ name, displayName, score, category, description, tags, installed }] } |
| info | { name, displayName, description, category, version, masicnVersion, installed, installedVersion, props, subComponentProps, peerDependencies, registryDependencies, tags, hasTests, hasAccessibility } |
| add | { installed: string[], skipped: string[], errors: string[], dryRun: boolean } |
| status | { components: [{ name, currentVersion, latestVersion, hasUpdate, modified }], summary: { total, updatesAvailable, modified } } |
| diff | { component, installedVersion, latestVersion, files: [{ file, identical, changes: [{ type, lineNumber, content }] }] } |
| graph | { nodes: [{ name, category }], edges: [{ from, to }], cycles: string[][] } |
| usage | { scannedFiles, components: [{ name, version, usages, files }] } |
Note: Commands that are inherently interactive (
init,interactive,theme create) do not support--json. Themcpcommand uses its own JSON-RPC protocol and is unaffected.
Commands
Setup
init— first-time project setupdoctor— run 8 automated health checksupgrade— refresh design system + update all components in one step
Components
add— copy components into your projectupdate— pull newer versions of installed componentsremove— delete a component from your projectlist— browse all available componentsstatus— see installed versions and available updatesdiff— compare your local file to the registry versioninfo— full metadata for a component
Discovery
search— find components by name, tag, or descriptiongraph— visualise the dependency treeusage— scan which installed components are actually used
Tooling
migrate— apply breaking-change migrationstheme create— generate a custom colour palette
Advanced
mcp— start an MCP server for AI tool integrationinteractive— full TUI browser and installer
init
Set up masicn in your project. Run this once.
npx masicn@latest init
npx masicn@latest init --interactive
npx masicn@latest init --skip-installWhat it does, in order
- Re-init guard — warns if
masicn.jsonalready exists and confirms before proceeding. - Project detection — looks for
package.jsonwith React Native. Aborts if not found. @alias detection — checkstsconfig.json,tsconfig.base.json, andtsconfig.app.jsonfor an@/*path mapping. If found, import paths use@/…; otherwise relative./…paths are used.- Package manager detection — detects
npm,yarn,pnpm, orbunfrom lockfiles. - Palette selection — interactive list of 15 colour palettes.
- Install native dependencies — installs the following if not already in
package.json:react-native-reanimatedreact-native-workletsreact-native-gesture-handlerreact-native-safe-area-contextreact-native-svgreact-native-screens
- Copy design system — downloads ~91 files from GitHub into
src/masicn/(tokens, theme, primitives, hooks, animation, utils, system). Thetheme/palettes/directory is never copied; instead the selected palette is written as a single editabletheme/colors.ts, andtheme/light.ts/theme/dark.tsare generated locally to import from it. - Download fonts — fetches Inter, Poppins, and Outfit
.ttffiles intoassets/fonts/and runsnpx react-native-assetto link them. - Write
masicn.json— config file in your project root. - Create
react-native.config.js— if not present, adds font asset path config. - Patch
babel.config.js— appendsreact-native-reanimated/pluginas the last plugin. - Patch
App.tsx— wraps the root withGestureHandlerRootViewandMasicnProvider. Uninstalls@react-native/new-app-screenafterward. pod install— runs on macOS to link the native modules.
Flags
| Flag | Description |
|------|-------------|
| --interactive | Full wizard — lets you customise output dirs, design system path, and whether to auto-patch App.tsx. |
| --skip-install | Skip npm install and pod install. Useful for CI or when you want to install manually. |
Files written to your project
assets/
└── fonts/ ← Inter, Poppins, Outfit .ttf files
src/
├── masicn/ ← design system (~91 files)
│ ├── tokens/ ← spacing, radius, typography, motion, elevation, borders, sizes
│ ├── theme/
│ │ ├── colors.ts ← your selected palette (single file, edit freely)
│ │ ├── light.ts ← generated: exports lightTheme from colors.ts
│ │ ├── dark.ts ← generated: exports darkTheme from colors.ts
│ │ └── ... ← createTheme(), ThemeContext, ThemeProvider, theme.ts
│ ├── primitives/ ← Box, Stack, Row, Text, Pressable, Surface, Center, Spacer, …
│ ├── hooks/ ← useTheme(), useTokens(), useReducedMotion(), useResponsive(), …
│ ├── animation/ ← spring presets, motion easing
│ ├── utils/ ← rgba(), clamp(), color helpers
│ └── system/ ← MasicnProvider, Masicn, PortalHost
└── shared/
├── components/ ← components land here (empty until you run `add`)
└── blocks/ ← blocks land here
masicn.json
react-native.config.js ← created if absent
babel.config.js ← patched (reanimated plugin added last)
App.tsx ← patched (GestureHandlerRootView + MasicnProvider)Palette strategy: the
theme/palettes/directory is never copied to your project. Copying all 15 palettes would require a barrel re-export that breaks TypeScript when only one palette is present. Instead,initfetches only the palette you selected, writes it astheme/colors.ts, and generatestheme/light.ts+theme/dark.tsthat bothimport { <palette>Palette } from './colors'. You get one editable file — no dangling imports, no surprises.
doctor
Run 8 automated health checks against your project and print pass/fail for each.
npx masicn@latest doctorChecks
| # | Check | What it verifies |
|---|-------|-----------------|
| 1 | masicn.json | File exists and has all required fields |
| 2 | MasicnProvider in App | App.tsx / App.js contains MasicnProvider |
| 3 | Reanimated babel plugin | react-native-reanimated/plugin is present and last in plugins[] |
| 4 | GestureHandlerRootView in App | Root is wrapped with GestureHandlerRootView |
| 5 | gesture-handler import | react-native-gesture-handler is the first import in index.js |
| 6 | Peer deps in node_modules | reanimated, gesture-handler, safe-area-context, worklets are installed |
| 7 | Font assets | Inter, Poppins, and Outfit .ttf files exist in assets/fonts/ |
| 8 | Design system files | Core files (index.ts, tokens/spacing.ts, theme/theme.ts, primitives/Text.tsx) exist in your design system dir |
Each failed check prints a fix: hint. Exits with code 1 if any check fails.
upgrade
Re-fetch the design system from GitHub and update all installed components to their latest registry versions — in one step, non-interactively.
npx masicn@latest upgrade
npx masicn@latest upgrade --channel devWhat it does
- Step 1/2 — Re-downloads all design system files from GitHub (equivalent to
npx masicn@latest update --design-system --force). - Step 2/2 — Compares every installed component against the registry and updates any that are behind (equivalent to
npx masicn@latest update --force).
Flags
| Flag | Description |
|------|-------------|
| --channel <channel> | Git branch to fetch the design system from. master (default) or dev. |
add
Copy one or more components into your project.
npx masicn@latest add button # single component
npx masicn@latest add button card modal # multiple at once
npx masicn@latest add # interactive searchable picker
npx masicn@latest add --all # every component and block in the registry
npx masicn@latest add button --dry-run # preview without writingWhat it does
- Reads
masicn.jsonto load config and the registry URL. - Fetches the registry index.
- Resolves transitive
registryDependencies— ifavatar-groupdepends onavatar, both are installed. Already-installed dependencies are skipped unless--forceis used. - Downloads each component file, rewrites import paths to match your project layout, and writes the file to
outputDir(components) orblocksDir(blocks). - Updates
masicn.json → installedComponentswith the installed version.
Flags
| Flag | Description |
|------|-------------|
| -f, --force | Overwrite existing files without prompting. |
| -n, --dry-run | Preview what would be installed without writing any files. |
| --all | Install every component and block available in the registry. |
| --json | Emit { installed, skipped, errors, dryRun } as a JSON object. Requires explicit component names — the interactive picker is not supported in JSON mode (INTERACTIVE_REQUIRED error is returned instead). |
Import path rewriting
When a file is written to your project, all imports are automatically rewritten:
| Original (registry source) | Rewritten to |
|---|---|
| @masicn/ui | Your masicnAlias (e.g. @/masicn) |
| ../../../masicn | Your masicnAlias |
| ../../components | Your importAlias (e.g. @/shared/components) |
| ../avatar/Avatar | ./Avatar (same-dir sibling) |
update
Pull the latest registry version of installed components.
npx masicn@latest update button # one component
npx masicn@latest update # all installed components
npx masicn@latest update -d # refresh only the design system files
npx masicn@latest update -d -f # refresh design system, no confirmation promptFlags
| Flag | Description |
|------|-------------|
| -f, --force | Overwrite local changes without prompting. Without this, locally-edited files are skipped. |
| -d, --design-system | Re-fetch all design system files from GitHub instead of updating components. |
remove
Delete a component from your project.
npx masicn@latest remove button
npx masicn@latest remove button --yesWhat it does
- Verifies the component is listed in
masicn.json. - Fetches the component's registry metadata to find which files were written.
- Prompts for confirmation (unless
--yes). - Deletes each file from the output directory.
- Removes the entry from
masicn.json.
If the registry is unreachable, files on disk are left in place but the masicn.json entry is still removed.
Flags
| Flag | Description |
|------|-------------|
| -y, --yes | Skip the confirmation prompt. |
list
Browse all available components and blocks.
npx masicn@latest list
npx masicn@latest list --installed
npx masicn@latest list --category formOutput is grouped by category. Installed components are marked with a green checkmark and their installed version.
Flags
| Flag | Description |
|------|-------------|
| --category <category> | Filter by category: display · form · feedback · interactive · layout · navigation · overlay · blocks |
| --installed | Show only components currently recorded in masicn.json. |
| --json | Emit a single JSON object (see Machine-readable output). |
status
See all installed components, their versions, and whether updates are available.
npx masicn@latest status
npx masicn@latest status --check-modifiedOutput
button v0.0.1 ✔ up to date
card v0.0.1 ↑ v0.0.2 available
bottom-sheet v0.0.1 ✔ up to date (modified locally)Flags
| Flag | Description |
|------|-------------|
| --check-modified | Fetch each component's registry copy and compare to your local file. Flags components whose source has been edited. Makes one HTTP request per installed file — slightly slower. |
| --json | Emit a single JSON object. modified is null unless --check-modified is also passed. |
diff
Line-by-line diff between your local file and the current registry version.
npx masicn@latest diff button
npx masicn@latest diff button --json # structured diff, not raw textOutputs lines prefixed with - (your local copy) and + (registry version). Shows "no changes" when the files are identical. Useful before running update to see exactly what changed.
With --json the diff is returned as structured data — each changed line is an object { type: "added"|"removed", lineNumber, content } — instead of colored terminal output.
The component must be installed (
masicn.jsontracks it). Runmasicn addfirst if needed.
info
Full metadata for a single component.
npx masicn@latest info button
npx masicn@latest info bottom-sheet
npx masicn@latest info button --json # full metadata as a JSON objectOutput includes:
- Display name, version, category
- Description
- Install status — whether it's installed, at which version, and the file path on disk
- Peer npm dependencies (
peerDependenciesthe component requires) - Registry dependencies (other masicn components it needs)
- Tags and accessibility flag
- Full props table — name, TypeScript type, required flag, default value, description
- Sub-component props (for compound components like
Tabs.Tab,Accordion.Item) - JSDoc usage examples
search
Find components by name, tag, description, or AI usage pattern.
npx masicn@latest search button
npx masicn@latest search "swipe gesture"
npx masicn@latest search sheet --top 5Results are scored and ranked:
| Match field | Score | |-------------|-------| | Tag | +3 | | Name | +2 | | Display name | +2 | | Description | +1 | | AI prompt | +1 | | AI usage pattern | +1 |
Each result shows the name, version, category, description, tags, and a one-liner install hint.
Flags
| Flag | Description |
|------|-------------|
| --top <n> | Maximum number of results to show (default: 10). |
| --json | Emit a single JSON object including relevance scores. |
graph
Visualise the dependency tree for one or all components.
npx masicn@latest graph # full ecosystem overview (grouped by category)
npx masicn@latest graph button # tree for a single component
npx masicn@latest graph --cycles # only show components involved in circular dependenciesOutput (single component)
avatar-group
└─ avatar
└─ (no dependencies)Flags
| Flag | Description |
|------|-------------|
| [component] | Component name to inspect. Omit for the full ecosystem graph. |
| --cycles | Only print components involved in dependency cycles. Exits cleanly if none. |
| --json | Emit { nodes, edges, cycles } — a machine-readable adjacency list for the full ecosystem. Single-component and --cycles modes are merged into this unified output. |
usage
Scan your source files to see which installed components are actually imported.
npx masicn@latest usage
npx masicn@latest usage --unused
npx masicn@latest usage --src app/srcOutput
Component Version Usages
─────────────────────────── ────────── ──────
button 0.0.2 4
card 0.0.2 2
tooltip 0.0.2 0Zero usages are printed in red — potential dead code.
Flags
| Flag | Description |
|------|-------------|
| --unused | Only show components with zero import sites. |
| --src <dir> | Source directory to scan (default: src). |
| --json | Emit { scannedFiles, components } — each component entry includes the list of file paths that import it. |
migrate
Report and auto-apply breaking-change migrations when components have been updated with prop renames or variant changes.
npx masicn@latest migrate # report all installed components that need migration
npx masicn@latest migrate button # report one component
npx masicn@latest migrate --apply # auto-fix transforms across source files
npx masicn@latest migrate --apply --dry-run # preview transforms without writingWhat it does
- Reads the
migrationmetadata from each installed component's registry entry. - Reports breaking changes for every component that is behind its latest version.
- With
--apply, runs auto-fixable transforms (prop renames, variant renames) across your.ts/.tsxsource files. - Manual-only changes (removed props, structural changes) are listed but never auto-applied — the report tells you what to fix.
Flags
| Flag | Description |
|------|-------------|
| [component] | Limit migration check to a single component. |
| --apply | Apply auto-fixable transforms to source files. |
| --dry-run | Preview which files would be changed without writing (use with --apply). |
| --src <dir> | Source directory to search for usages (default: src). |
theme create
Generate a custom full-theme palette from two brand colours.
npx masicn@latest theme create brand
npx masicn@latest theme create brand --previewWhat it does
- Prompts for a primary brand colour (hex, e.g.
#3b82f6). - Prompts for a secondary accent colour (hex, e.g.
#f59e0b). - Derives all 53 semantic colour tokens (light + dark) using
chroma-js. - Writes
<designSystemDir>/theme/palettes/<name>.ts.
With --preview, prints a terminal colour swatch before writing and asks for confirmation.
Flags
| Flag | Description |
|------|-------------|
| --preview | Print a terminal colour swatch and confirm before writing the file. |
Using the generated palette
import { brandPalette } from '@/masicn/theme/palettes/brand';
<MasicnProvider palette={brandPalette}>
<App />
</MasicnProvider>interactive
Full terminal UI for browsing and installing components — alias i.
npx masicn@latest interactive
npx masicn@latest iFlow
- Fetches the full registry index.
- Presents a grouped multiselect list (components → blocks → flows → screens), with installed versions shown as hints.
- Resolves and displays the full dependency tree for your selection.
- Asks for confirmation, then installs.
Keyboard shortcuts
| Key | Action |
|-----|--------|
| ↑ / ↓ | Navigate |
| Space | Toggle selection |
| Enter | Confirm |
| Esc / Ctrl+C | Cancel |
mcp
Start a Model Context Protocol server on stdin/stdout so AI tools (Claude, Cursor, etc.) can browse and install components on your behalf.
npx masicn@latest mcpThe MCP server speaks JSON-RPC 2.0 over stdin/stdout. It implements the same four operations as the --json commands — list, search, get details, install — by calling the same underlying libraries (RegistryClient, resolveComponents, installComponents) directly. The registry index is lazy-fetched on first tool call and cached in memory for the lifetime of the process.
Wiring it up in Claude Desktop
Add to your Claude config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"masicn": {
"command": "npx",
"args": ["masicn@latest", "mcp"]
}
}
}Available MCP tools
| Tool | Description |
|------|-------------|
| list_components | List all registry components and blocks. Optional category filter. |
| get_component_details | Full metadata (props, deps, examples) for a named component. |
| search_components | Ranked search by name, tag, description, or AI usage pattern. |
| get_installed_status | All installed components with current + latest versions and update flags. Supports checkModified. |
| diff_component | Structured line diff (added/removed per line) between local and registry version. |
| get_dependency_graph | Full nodes + edges adjacency list with cycle detection. Optional single-component subtree. |
| get_component_usage | Import-site counts per component across your source files. |
| run_health_check | Run all 8 doctor checks — returns pass/fail per check with detail and fix hints. |
| install_component | Install a component (resolves deps automatically). Supports dryRun. |
| update_component | Update one or all components to latest registry versions. |
| remove_component | Delete a component's files and remove it from masicn.json. |
Using --json directly for scripting
If you're building a custom integration (not MCP), use --json directly — it's simpler and guaranteed stable:
# List and parse in one line
result=$(npx masicn@latest list --json)
echo $result | jq '.data.components[] | select(.installed)'
# Add from a script
npx masicn@latest add button card --json | jq .datamasicn.json
Created by init in your project root. Read by every command. Edit manually if needed.
{
"version": "1",
"registry": "https://raw.githubusercontent.com/masicn-ui/registry/master/registry.json",
"outputDir": "src/shared/components",
"importAlias": "@/shared/components",
"blocksDir": "src/shared/blocks",
"blocksAlias": "@/shared/blocks",
"designSystemDir": "src/masicn",
"masicnAlias": "@/masicn",
"palette": "nord",
"localDesignSystem": true,
"fontSetup": "masicn",
"installedComponents": {
"button": "0.0.2",
"card": "0.0.2"
}
}Field reference
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| version | string | "1" | Config schema version. Do not change. |
| registry | string | GitHub raw URL | Where the CLI fetches component metadata. Change master to dev for the dev channel. |
| outputDir | string | src/shared/components | Where component .tsx files are written. |
| importAlias | string | @/shared/components | Import alias used by generated files to reference other components. |
| blocksDir | string | src/shared/blocks | Where block .tsx files are written. |
| blocksAlias | string | @/shared/blocks | Import alias for blocks. |
| designSystemDir | string | src/masicn | Where the local design system copy lives. |
| masicnAlias | string | @/masicn | Import alias for design system imports in generated files. |
| palette | string | masi | Active colour palette name. |
| localDesignSystem | boolean | true | Always true — masicn copies the design system locally, not as an npm package. |
| fontSetup | string | masicn | Font strategy: masicn (Inter/Poppins/Outfit), system, or manual. |
| installedComponents | object | {} | Map of componentName → version. Managed automatically by add, update, and remove. |
Colour Palettes
| Palette | Vibe |
|---------|------|
| masi | Warm papaya + deep teal — the default |
| ocean | Deep blues + aqua |
| sunset | Warm oranges + purples |
| forest | Earthy greens + warm browns |
| mono | Monochrome slate |
| rose | Soft pinks + cranberry |
| midnight | Deep indigo + electric violet |
| amber | Golden honey + espresso |
| nord | Arctic blue-grays + frost |
| coffee | Espresso browns + caramel |
| candy | Hot pink + vivid sky blue |
| citrus | Lime green + golden yellow |
| grapeSoda | Violet-purple + acid lime |
| jade | Deep emerald + warm gold |
| neonTeal | Electric teal + vivid violet |
Links
- npm: npmjs.com/package/masicn
- Registry: github.com/masicn-ui/registry
- Design system (
@masicn/ui): github.com/masicn-ui/masicn - Developer: Manish Kumar — manishh.in · @lordofthemind
- Company: skipp.co.in
License
The CLI and all component source files it copies into your project are MIT licensed. You own the copied code completely — change it, ship it in a commercial product, no restrictions.
Made with care by Manish Kumar at skipp.co.in
