iconmate 1.2.1

CLI to fetch icons and save them into your Vite, NextJS, or similar TypeScript project
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
<p align="center">
  <img src="./_docs/iconmate_logo.png" alt="iconmate logo" width="180" />
</p>

<h1 align="center">iconmate</h1>

<p align="center"><strong>Add SVG icons to your JS apps without icon libraries.</strong></p>

<p align="center">
  <img src="./_docs/iconmate_banner.jpg" alt="iconmate banner" width="100%" />
</p>

<p align="center">
  <a href="#quick-start">Quick Start</a>
  ·
  <a href="#installation">Install</a>
  ·
  <a href="#framework-presets">Presets</a>
  ·
  <a href="#command-line">CLI Commands</a>
  ·
  <a href="#ai-ready-workflows">AI Ready</a>
  ·
  <a href="#configuration">Configuration</a>
</p>

Built from my blog post on [Why you might not need an icon library](https://carlotaleon.net/blog/why-you-dont-need-an-icon-library), `iconmate` is a Rust-powered CLI for developers who want the speed and control of plain files without icon-package bloat.

Use [icones.js.org](https://icones.js.org), a direct SVG URL, or raw SVG markup. `iconmate` drops the icon straight into your project and keeps your exports tidy.

## Why iconmate?

- **Made with Rust🦀**: Fast TUI that you can use on any IDE (powered by ratatui, nucleo).
- **AI-ready automation** 🤖: Let your coding agents get icons and add it to your project! A CLI is basically an MCP, just let AI use `iconmate --help` and it should be able to get everything running!
- **Zero dependencies** 📦: No icon library runtime added to your app
- **Framework-native output** 🧩: Generate files for React, Vue, Svelte, Solid, or plain SVG
- **Interactive by default** 🎮: Run `iconmate` and have a pleasant interactive TUI
- **Multiple sources** 🌐: Pull icons from Iconify names, URLs, or even raw SVG (which means it works with your private icon packs i.e. Anron)
- **Fast workflow** ⚡: Generate file + export line in one step
- **Prototype-friendly** 🏗️: Create empty SVG placeholders when needed

## Quick Start

```bash
# Install
brew install blankeos/tap/iconmate # Homebrew (macOS/Linux)
npm install -g iconmate

# Run the TUI in your project 🚀
iconmate
```

✨ That's it. The interactive TUI guides you through adding icons to your project.

```tsx
// 👇 Then, you can just easily use any icon on your project like this!

import { IconHeart } from "@/assets/icons";

function MyApp() {
  return <IconHeart />;
}
```

## Configuration

You can also add sensible defaults by passing flags as configs:

```bash
iconmate --folder src/components/Icons/ --folder src/components/icons
iconmate --folder src/components/Icons/ --icon heroicons:heart --name Heart
```

Iconmate now includes config schemas + TS type definitions in the repo:

- Local config schema (repo): [`iconmatelocal.schema.json`]https://github.com/Blankeos/iconmate/blob/main/iconmatelocal.schema.json
- Global config schema (repo): [`iconmateglobal.schema.json`]https://github.com/Blankeos/iconmate/blob/main/iconmateglobal.schema.json
- Local config schema (raw): `https://raw.githubusercontent.com/Blankeos/iconmate/main/iconmatelocal.schema.json`
- Global config schema (raw): `https://raw.githubusercontent.com/Blankeos/iconmate/main/iconmateglobal.schema.json`
- Schema source: `config-gen/src/schema.ts`
- TS type definitions: `config-gen/src/types.ts`

Regenerate schemas from project root:

```bash
just config-schema
```

`just config-schema` installs `config-gen` deps and generates both schema files.

### Local Config (`iconmate.config.json`)

```json
{
  "$schema": "https://raw.githubusercontent.com/Blankeos/iconmate/main/iconmatelocal.schema.json",
  "folder": "src/assets/icons",
  "preset": "normal",
  "svg_view_cmd": "zed %filename%",
  "flutter_barrel_file": "lib/icons.dart",
  "flutter_barrel_class": "AppIcons"
}
```

Use the raw URL for `$schema` so editors can fetch JSON directly.

Local config keys:

- `folder` (default: `src/assets/icons`, or `assets/icons` when `preset` is `flutter`)
- `preset` (default: `normal`, meaning plain `.svg` mode; auto-switches to `flutter` in detected Flutter projects)
- `svg_view_cmd` (supports `%filename%` token)
- `flutter_barrel_file` (Flutter preset only; default: `lib/icons.dart`)
- `flutter_barrel_class` (Flutter preset only; default: `AppIcons`)

Allowed `preset` values:

- `normal` (plain SVG mode)
- `react`
- `svelte`
- `solid`
- `vue`
- `emptysvg`
- `flutter` (SVGs + Dart barrel at `lib/icons.dart`)

### Global Config (user-level)

Global config is for user-wide defaults and currently documents `svg_view_cmd`.

Suggested paths:

- macOS: `~/Library/Application Support/iconmate/config.json`
- Linux: `~/.config/iconmate/config.json`
- Windows: `%APPDATA%\\iconmate\\config.json`

Example global config:

```json
{
  "$schema": "https://raw.githubusercontent.com/Blankeos/iconmate/main/iconmatelocal.schema.json",
  "svg_view_cmd": "code %filename%"
}
```

> [!NOTE]
> This release adds config schemas and generated docs/types. Runtime loading/precedence wiring in the CLI/TUI is tracked in `folder-system-plan.md`.

## Installation

```sh
brew install blankeos/tap/iconmate # Homebrew (macOS/Linux)
npm install -g iconmate            # or npm
bun install -g iconmate            # or bun
cargo binstall iconmate            # or cargo-binstall (prebuilt binary, faster)
cargo install iconmate             # or cargo (build from source)
curl -sSL https://raw.githubusercontent.com/Blankeos/iconmate/main/install.sh | sh # or linux/macos (via curl)
```

## Framework Presets

Determines the output filetype and the contents inside that file type.

| Preset     | File Type | Framework                                     |
| ---------- | --------- | --------------------------------------------- |
| `normal`   | `.svg`    | Vanilla HTML/CSS                              |
| `react`    | `.tsx`    | React Components                              |
| `svelte`   | `.svelte` | Svelte Components                             |
| `solid`    | `.tsx`    | Solid Components                              |
| `vue`      | `.vue`    | Vue Components                                |
| `emptysvg` | `.svg`    | Placeholder                                   |
| `flutter`  | `.svg`    | Dart barrel (`lib/icons.dart` / `AppIcons.*`) |

> [!IMPORTANT]
> If you want to use `.svg` file types, make sure to setup [svgr]https://github.com/gregberge/svgr for your js apps. I covered how to do this in:
>
> - [SolidJS (Vite)]https://carlotaleon.net/blog/why-you-dont-need-an-icon-library#use-svg-only-with-solidjs
> - [React (Vite)]https://carlotaleon.net/blog/why-you-dont-need-an-icon-library#use-svg-only-with-react-vite
> - [React (NextJS)]https://carlotaleon.net/blog/why-you-dont-need-an-icon-library#use-svg-only-with-react-nextjs
> - Vue - contribution welcome!
> - Svelte - couldn't find an svgr integration. Just use the svg preset.

### Flutter preset

Run `iconmate add --preset flutter --icon heroicons:heart` and you'll get:

- `assets/icons/heart.svg` on disk (default folder for Flutter projects).
- `lib/icons.dart` created or updated, with a generated `AppIcons` class:

```dart
// GENERATED by iconmate — do not edit by hand.
class AppIcons {
  AppIcons._();

  static const String heart = 'assets/icons/heart.svg';
}
```

Use it at call sites:

```dart
import 'package:my_app/icons.dart';
import 'package:flutter_svg/flutter_svg.dart';

SvgPicture.asset(AppIcons.heart, width: 24);
```

One-time setup in `pubspec.yaml`:

```yaml
dependencies:
  flutter_svg: ^2.0.0

flutter:
  assets:
    - assets/icons/
```

Notes:

- Dart identifiers are always lowerCamelCase (`constant_identifier_names` lint). iconmate normalizes whatever you pass.
- iconmate fully owns `lib/icons.dart` — don't hand-edit inside the class body; changes get overwritten on the next add/delete/rename.

## Command Line

### Interactive TUI Mode (Recommended)

```bash
iconmate
```

This section is helpful for AI:

### Add Specific Icon

```bash
iconmate add --folder src/assets/icons --icon heroicons:heart --name Heart
```

### With URL

```bash
iconmate add --folder src/assets/icons --icon https://api.iconify.design/mdi:heart.svg --name Heart
```

### Raw SVG Content

```bash
iconmate add --folder src/assets/icons --icon '<svg>...</svg>' --name Heart
```

You can also pull raw SVG directly from the Iconify API:

```bash
iconmate add --folder src/assets/icons --icon "$(curl -fsSL https://api.iconify.design/mdi:heart.svg)" --name Heart
```

### Delete icons

```bash
iconmate delete --folder src/assets/icons
```

### Rename icons

Rename an icon from the TUI (`iconmate` → select an icon → press `r`).

> [!NOTE]
> iconmate only renames the **SVG file on disk** and updates the path reference in the export line / barrel. To rename the **exported alias** (e.g. `IconHeart` → `IconFavorite`, or `AppIcons.heart` → `AppIcons.favorite`), use your IDE's LSP rename so every call site updates in one shot.

### Sync icons

Reconciles the barrel (`index.ts` / `lib/icons.dart`) with the SVGs on disk — useful if someone dropped an SVG in manually or deleted one without iconmate.

```bash
iconmate sync                       # dry-run: print the plan
iconmate sync --apply               # add orphan files to the barrel
iconmate sync --apply --prune       # also remove entries whose SVG is gone
```

Dry-run by default. Never touches SVG files — only the barrel. From the TUI, press `Shift+S` for a read-only view of the current drift.

### List current icons

```bash
iconmate list --folder src/assets/icons
# or use the default folder (src/assets/icons)
iconmate list
```

### Iconify API Commands

```bash
# Search by keyword (text: one prefix:icon per line)
iconmate iconify search heart

# Search with pagination and JSON output
iconmate iconify search heart --limit 20 --start 0 --format json

# Include collection metadata in JSON search output
iconmate iconify search heart --format json --include-collections

# List all available collections
iconmate iconify collections

# List icons from one collection prefix
iconmate iconify collection mdi

# Get one icon as raw SVG (default)
iconmate iconify get mdi:heart

# Get one icon as raw Iconify JSON
iconmate iconify get mdi:heart --format json
```

`iconmate iconify get <prefix:icon> --format json` uses Iconify's JSON endpoint format,
for example `https://api.iconify.design/mdi.json?icons=heart`.

### AI-Ready Workflows

`iconmate` is designed to be easy for AI agents and scripts to drive end-to-end.

```bash
# 1) Search in machine-readable JSON
iconmate iconify search heart --format json --limit 20 --include-collections

# 2) Add an icon non-interactively from prefix:name
iconmate add --folder src/assets/icons --icon mdi:heart --name Heart

# 3) Or fetch raw SVG from Iconify API and add directly
iconmate add --folder src/assets/icons --icon "$(curl -fsSL https://api.iconify.design/mdi:heart.svg)" --name Heart
```

This means an AI can search, choose, and add icons without opening a browser.

#### Agent Skill

For the best AI experience, install the [iconmate skill](https://github.com/Blankeos/iconmate/tree/main/skills/iconmate) so your agent knows all the commands automatically:

```bash
npx skills add Blankeos/iconmate
```

### Package.json Scripts

Best practice: Add sensible defaults to your script runner.

```jsonc
"scripts": {
  // Usage: npm run iconmate (usually this is the only command you need)!
  "iconmate": "iconmate --folder src/assets/icons/"
}
```

## Supported Platforms

- macOS (Intel & Apple Silicon) 🍎
- Linux (x64 & ARM64) 🐧
- Windows (x64) 🪟

## How It Works

1. **Find your icon**: Use https://icones.js.org _or_ `iconmate iconify search <query>`.
2. **Pick the icon id**: For example `heroicons:heart`.
3. **Add with iconmate**: Interactive (`iconmate`) or direct (`iconmate add ...`).

![illustration](https://raw.githubusercontent.com/Blankeos/iconmate/refs/heads/main/_docs/icones-cli-illustration.png)

## Why this structure?

1. **Copy-paste workflow**: Find icon on icones.js.org → copy name → paste into iconmate
2. **Organized by default**: Everything goes into `index.ts` exports automatically and just typing `<Icon` will autosuggest from your current collection. Just regular TS behavior.
3. **TypeScript ready**: Generated code is fully typed. Pass custom width, height, fills, you name it.
4. **Customizable** 🎨: Want to add a default Tailwind class on every icon? custom props? Just add it to the file!
5. **Git-friendly**: Plain SVG files, no binary assets
6. **Lightning fast**: Native Rust binary, no Node.js startup time

## Contributing

Contributions are welcome—pull requests for bug fixes, new framework presets, or improvements are appreciated.

🐱 Repo: [github.com/Blankeos/iconmate](https://github.com/Blankeos/iconmate) - Star it if you love it ⭐

## What's Completed from the Roadmap

- ✅ Interactive prompt mode
- ✅ Framework presets (React, Vue, Svelte, Solid)
- ✅ URL and raw SVG support
- ✅ Custom export templates
- ✅ Zero-config installation

### Roadmap & Out-of-scoped

- [x] An empty command. Creates an .svg, adds it to the index.ts with a name you can specify.
- [x] Paste an actual svg instead of an icon `name`.
- [x] Presets (`normal`, `react`, `solid`, `svelte`, `vue`, `emptysvg`) override output templates and file types.
- [x] Prompt Mode via `iconmate` - Interactive mode so you won't need to pass arguments.
- [x] Delete an icon using `iconmate delete`
- [x] An interactive TUI instead of prompt-mode.
  - [x] Rename in the TUI (but recommended for you to just use the LSP to do it)
  - [x] A lot of TUI functionalities wokr
- [x] `iconmate iconify --help` commands for AI to easily look for icons itself.
- [x] Search and add Iconify icons directly inside the TUI (no need to open https://icones.js.org).
- [x] `--preset=flutter` (SVGs + generated Dart barrel).
- [ ] Other frameworks i.e. Go/Rust GUI apps? (Not sure how they work yet though).
- [ ] ~Zed or VSCode Extension~ (seems unnecessary now, it's just a CLI)

### Near-Term Roadmap

---

Made with Rust 🦀 | Based on [my blog post][my_blog]

[my_blog]: https://carlotaleon.net/blog/why-you-dont-need-an-icon-library
[my_blog#svgr]: https://carlotaleon.net/blog/why-you-dont-need-an-icon-library#bonus-just-save-them-as-svg-files