Skip to main content

CLI Tools

rn-iconify includes command-line tools for analyzing icon usage and generating offline bundles.

Available Commandsโ€‹

npx rn-iconify <command> [options]
CommandDescription
bundleGenerate offline icon bundle
analyzeAnalyze icon usage in your project
doctorReport icons that would be fetched at runtime
helpShow help message
versionShow version

Bundle Commandโ€‹

Generate bundled icon files for offline use:

npx rn-iconify bundle --auto --output ./assets/icons.bundle.json

Optionsโ€‹

OptionDescriptionDefault
--src <path>Source directory to analyze./src
--output <path>Output file path./assets/icons.bundle.json
--autoAuto-detect icons from source codetrue
--icons <list>Comma-separated list of icons to include-
--exclude <list>Comma-separated patterns to exclude-
--verboseShow detailed outputfalse
--prettyPretty-print JSON outputfalse

Examplesโ€‹

# Auto-detect and bundle icons from source
npx rn-iconify bundle --auto

# Bundle specific icons
npx rn-iconify bundle --icons "mdi:home,mdi:cog,heroicons:user"

# Custom output path
npx rn-iconify bundle --output ./src/generated/icons.bundle.json

# Verbose output
npx rn-iconify bundle --auto --verbose --pretty

Generated Bundleโ€‹

The bundle command creates a JSON file with icon data:

{
"version": "2.0.0",
"generatedAt": "2025-12-03T10:30:00Z",
"icons": {
"mdi:home": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z\"/></svg>",
"width": 24,
"height": 24
}
},
"count": 47
}

Analyze Commandโ€‹

Analyze icon usage across your project:

npx rn-iconify analyze

Outputโ€‹

๐Ÿ“Š Icon Usage Analysis

Found 47 unique icons across 23 files

By Icon Set:
mdi: 28 icons
heroicons: 12 icons
lucide: 7 icons

Most Used Icons:
1. mdi:home (12 usages)
2. mdi:arrow-left (8 usages)
3. heroicons:user (6 usages)

Recommendation:
npx rn-iconify bundle --icons "mdi:home,mdi:arrow-left,heroicons:user"

Optionsโ€‹

OptionDescriptionDefault
--src <path>Source directory to analyze./src
--format <type>Output format: table, json, markdowntable
--detailedShow file locations for each iconfalse
--verboseShow detailed outputfalse

Examplesโ€‹

# Analyze specific directory
npx rn-iconify analyze --src ./app

# JSON output for CI integration
npx rn-iconify analyze --format json > icon-usage.json

# Detailed view with file locations
npx rn-iconify analyze --detailed

# Markdown output for documentation
npx rn-iconify analyze --format markdown > ICONS.md

Doctor Commandโ€‹

Report what your build ships and what it will ask the network for:

npx rn-iconify doctor
๐Ÿฉบ rn-iconify doctor

Resolved from source : 105
Fetched at runtime : 71
Coverage : 60%

An icon the build cannot see is not a broken icon. IconRenderer fetches it from the Iconify API instead, in release builds as much as in development โ€” a request on every install, a placeholder until it lands, and nothing at all on a device with no connection. None of that is visible from inside the app, which is what this command is for.

Optionsโ€‹

OptionDescriptionDefault
--src <path>Project root to inspectcwd
--strictExit non-zero if any icon is fetched at runtimefalse
--pruneDrop names not rendered lately from usage.jsonfalse
--stale-days <n>How long a name may go unrendered before --prune drops it30
--format <type>text or jsontext
--verboseShow detailed outputfalse

Not strict by default: a project part-way through fixing this should be able to see the number without being blocked by it.

Clearing out names that are goneโ€‹

usage.json is written by the development server as your app renders icons the build could not find, and it is why those icons still ship. That also means nothing in it can be checked against your source โ€” it is exactly the set of names your source does not mention.

npx rn-iconify doctor --prune

It clears two things.

Names the build now finds on its own. This file carries what the scan cannot prove, so a name it can prove is carried for no reason โ€” and after the scan learns a new shape, that is usually most of the file. Removing one cannot change what ships, so nothing is weighed and nothing is waited for.

Names nobody has rendered lately. The only evidence a name is gone is that it has not been rendered since the screen was deleted, which is why each one carries the time it was last seen.

[rn-iconify] Removed 149 name(s) the build now finds in your source.
Nothing changes: they were already being bundled from the code itself.

[rn-iconify] Removed 3 name(s) not rendered in 30 day(s):
ยท ion:airplane-outline โ€” last seen 2026-05-02T09:14:22.101Z
ยท ion:cafe-outline โ€” last seen 2026-05-02T09:14:31.660Z
ยท ion:trail-sign-outline โ€” last seen 2026-04-28T17:02:08.934Z

Nothing is removed without being named, and nothing is lost by being wrong: if one of them was still in use, open that screen once in development and it comes back.

This is a command rather than something the dev server does on its own. A screen opened twice a year is still a screen, and dropping its icons quietly would put them back on the network for the one person who opens it.

Upgrading a file written before names carried their own timestamps removes nothing. When each was last rendered was never recorded, so they are all stamped as seen at the upgrade โ€” the clock starts there and tells the truth from there on.

In CIโ€‹

- name: Check icon coverage
run: npx rn-iconify doctor --strict

Fixing what it reportsโ€‹

Most of what appears there is a name the source cannot tie to an icon set:

// Nothing says 'hanger' is an Mdi icon
const CATEGORY_ICON: Record<string, string> = { OUTFIT: 'hanger' };

Typing it is usually all it takes. The build follows an icon set type wherever you use it, so each of these is found without anything else:

// A record whose values are icons
const CATEGORY_ICON: Record<string, MdiIconName> = { OUTFIT: 'hanger' };

// A field, and the table that fills it
interface TabConfig { icon: IonIconName; route: string }
const TABS: TabConfig[] = [{ icon: 'home', route: 'Home' }];

// The type written out rather than imported
type IoniconName = ComponentProps<typeof Ion>['name'];

// An icon that depends on state โ€” both names are read
<Ion name={paused ? 'play' : 'pause'} />

Names handed to your own components need nothing either โ€” the prop type is enough.

defineIcons is for what is left: a name assembled at runtime, or one that genuinely cannot carry a type.

const CATEGORY_ICON = defineIcons<MdiIconName>({ OUTFIT: 'hanger' });
note

.rn-iconify/usage.json collects icons the app fetched during development and is read by the next build, which is why a project can look healthy while depending on it. Doctor deliberately does not count those as resolved.

Integration with package.jsonโ€‹

Add scripts for common operations:

{
"scripts": {
"icons:analyze": "rn-iconify analyze --src ./src",
"icons:bundle": "rn-iconify bundle --auto --output ./assets/icons.bundle.json",
"icons:bundle:verbose": "rn-iconify bundle --auto --verbose --pretty"
}
}

CI/CD Integrationโ€‹

GitHub Actionsโ€‹

# .github/workflows/icons.yml
name: Icon Analysis

on: [push, pull_request]

jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install
- name: Analyze Icons
run: npx rn-iconify analyze --format json > icon-report.json
- name: Upload Report
uses: actions/upload-artifact@v4
with:
name: icon-report
path: icon-report.json

Pre-commit Hookโ€‹

Add icon analysis to pre-commit:

# .husky/pre-commit
npx rn-iconify analyze --src ./src

Loading Generated Bundleโ€‹

Use the generated bundle in your app:

import { loadOfflineBundle } from 'rn-iconify';
import iconBundle from './assets/icons.bundle.json';

// Load at app startup
loadOfflineBundle(iconBundle);

// Icons are now available offline
<Mdi name="home" /> // Renders instantly

Troubleshootingโ€‹

Command Not Foundโ€‹

Ensure rn-iconify is installed:

npm install rn-iconify

Network Errorsโ€‹

The CLI fetches icon data from Iconify API. If you have network issues:

# Check connectivity
curl https://api.iconify.design/mdi.json?icons=home

Permission Errorsโ€‹

If output directory is protected:

# Check directory permissions
ls -la ./assets

# Or use a different directory
npx rn-iconify bundle --output ./generated/icons.bundle.json

Next Stepsโ€‹