iconsmaker 0.1.2

Generate platform icon bundles (macOS, Windows, Linux) from a single SVG
iconsmaker-0.1.2 is not a library.

iconsmaker

One SVG in. Every platform icon bundle out.

iconsmaker reads a single source SVG and a small TOML config file and generates deployment-ready icon assets for macOS, Windows, and Linux — including packaging variants for Snap, Flatpak, and AppImage — in a single command.


Why iconsmaker

Most icon generators target macOS, Windows, and web favicons — and they almost always start from a raster (PNG) image. You can press them into service for Linux, but that's where it falls apart: you're left manually producing a spread of exact sizes, applying strict reverse-DNS file names, reorganizing everything into the freedesktop hicolor directory tree, and then hand-writing the .desktop entry, the AppStream metainfo.xml, and a separate icon variant for each packaging format (Snap, Flatpak, AppImage). The requirements are finite but scattered across specs, and looking them all up and assembling them by hand for every project is a slow, error-prone chore.

iconsmaker automates the whole thing from a single 1024 × 1024 SVG. One command renders every required size, applies the platform shaping (like the macOS squircle) automatically, names and files each asset exactly where each platform expects it, and generates the accompanying metadata — producing every permutation for macOS, Windows, and Linux (including Snap/Flatpak/AppImage) with no manual resizing, renaming, or reorganizing. And because the source is vector rather than a raster image, small sizes stay crisp instead of turning to mush.


What it generates

Platform Output Notes
macOS dist/macos/AppName.icns 7 ICNS elements (16 – 1024 px), Apple squircle mask applied
Windows dist/windows/AppName.ico 7 sizes (16 – 256 px), PNG + BMP per ICO spec
Linux dist/linux/hicolor/ 9 PNG sizes + scalable SVG + optional symbolic SVG
Linux dist/linux/<id>.desktop freedesktop Desktop Entry
Linux dist/linux/<id>.metainfo.xml AppStream MetaInfo for GNOME Software / Discover
Snap dist/snap/snap/gui/ 256 × 256 store icon + desktop file
Flatpak dist/flatpak/app/share/ Full hicolor tree + metadata under the Flatpak prefix
AppImage dist/appimage/<Name>.AppDir/ Top-level icon, .DirIcon, inner hicolor tree

Installation

Prebuilt native installers are published to GitHub Releases for each tagged version.

macOS

brew tap ideocentric/tap
brew install iconsmaker

Or download iconsmaker-<version>-universal-apple-darwin.tar.gz from the release and place iconsmaker on your PATH — it's a universal binary that runs natively on both Apple Silicon and Intel Macs.

Linux

x86_64 (amd64) and arm64 (aarch64) packages are published — pick the one matching uname -m.

# Debian / Ubuntu
sudo dpkg -i iconsmaker_<version>_amd64.deb      # or _arm64.deb

# Fedora / RHEL / openSUSE
sudo rpm -i iconsmaker-<version>.x86_64.rpm      # or .aarch64.rpm

Both packages install the binary to /usr/bin/iconsmaker and the man page to /usr/share/man/man1.

Windows

winget install ideocentric.iconsmaker

winget picks the right build for your CPU automatically. To install by hand, download and run iconsmaker-<version>-x86_64.msi or iconsmaker-<version>-arm64.msi (installs to Program Files and adds itself to PATH).

From source

cargo install --path .        # or: cargo build --release

Requires a Rust 1.85+ toolchain. For full prerequisites, per-platform notes, and how to build a universal macOS binary or the installers, see BUILDING.md.

Documentation / man page

On macOS and Linux the package installs a man page:

man iconsmaker

On Windows the MSI installs iconsmaker.html alongside the binary. On any platform you can also print the man page directly:

iconsmaker --print-man-page | sudo tee /usr/share/man/man1/iconsmaker.1

See packaging/ for how the installers are built.


Prerequisites

Choose one:

Docker (recommended — no Rust toolchain needed)

Docker 20.10+

Cargo (native build)

Rust 1.85+ (edition 2024)

Full build instructions and per-platform prerequisites are in BUILDING.md.


Quick start

Via Docker

# 1. Clone and build the image once
git clone https://github.com/yourname/iconsmaker
cd iconsmaker
docker build -t iconsmaker:latest .

# 2. Run against any project
docker run --rm \
  -v "/path/to/myproject:/workspace" \
  iconsmaker:latest \
  --config icons/icons.toml

Via Cargo

# From your project directory
cargo run --manifest-path /path/to/iconsmaker/Cargo.toml -- \
  --config icons/icons.toml

Two ways to run

iconsmaker can be driven by a config file or entirely by flags, and the two compose — flags override the config file.

Config mode (IDE / toolchain): keep an icons.toml in your project and run it as part of your build. If --config is omitted, ./icons.toml is used when present.

iconsmaker --config icons/icons.toml

Flag mode (web / CI backend): pass everything on the command line — ideal when a UI collects the parameters and forwards them. Select platforms with --macos --windows --linux (or --all):

iconsmaker -i logo.svg --all \
  --id com.example.MyApp --name "My App" --exec "myapp %F" \
  --comment "One-line summary" --description "Longer store paragraph." \
  --categories Utility --license MIT --metadata-license CC0-1.0 \
  --developer-name "Me"

Passing any platform/packaging flag switches selection to the CLI, so a lone --macos builds only macOS (it does not also pick up platforms from the config).

Required fields depend on the platforms you select

Requirements form a grid. iconsmaker reports every missing field at once, naming the selected target that needs it, why, and how to supply it (both flag and config form). Hard = blocks; Soft = warns (and becomes an error under --strict).

Field macOS Windows Linux Packaging*
input SVG (-i / [input] svg) Hard Hard Hard Hard
--name Hard Hard Hard Hard
--id (reverse-DNS) Hard Hard Hard
--exec Hard Hard
--comment, --description, --categories, --metadata-license, --license, --developer-name Soft Soft

* Packaging (--snap / --flatpak / --appimage) requires --linux and inherits all Linux requirements.

Format lints (Soft): a non-reverse-DNS --id and unregistered --categories values are flagged as warnings.

Every flag mirrors a config key (e.g. --metadata-license[app] metadata_license); run iconsmaker --help for the full list.


Recommended project layout

Place your icon assets in an icons/ subdirectory of your project:

myproject/
├── icons/
│   ├── master.svg          ← your 1024 × 1024 source artwork  (required)
│   ├── symbolic.svg        ← monochrome tray/panel variant     (optional)
│   └── icons.toml          ← configuration
├── dist/                   ← generated output (add to .gitignore)
└── ... (project source)

The dist/ directory is entirely generated — never commit it.


Preparing your artwork

Base SVG (master.svg)

Property Requirement
Format SVG 1.1
Viewbox Square — 1024 1024 strongly recommended
Text Must be converted to outlines. The renderer has no font loader; text elements that reference font families will not render. Export "text as paths" / "outline text" from your vector editor.
Embedded images Self-contained raster elements (base64 <image>) are supported. External file references (xlink:href="file.png") are not.
Filters The resvg engine supports a useful subset of SVG filters: feGaussianBlur, feOffset, feFlood, feComposite, feMerge, feBlend, feColorMatrix, and feSpecularLighting. Complex filter chains (e.g. feConvolveMatrix) may be ignored.
Size Keep under 2 MB. Highly complex paths slow down rasterization.

What NOT to include in the master SVG

  • Drop shadows — macOS and Linux add their own at the system level.
  • Rounded corners / squircle clipping — the tool applies Apple's squircle mask automatically for macOS.
  • Platform-specific layering or gloss — the [effects] section handles depth shading.

Design the artwork as a flat square. The tool handles all platform shaping.

Symbolic SVG (symbolic.svg)

Used on Linux for system trays, notification areas, and high-contrast modes.

  • Single colour — use #363636 or currentColor
  • Designed on a 16 × 16 grid (simplified silhouette of the full icon)
  • No fills outside the silhouette; no gradients
  • Place in hicolor/symbolic/apps/ automatically when symbolic_svg is set

Apple squircle shape

The macOS squircle mask is generated analytically at every icon size — there is no shape file to supply or reference. Its roundness is controlled by the squircle_power value in the [effects] section (default 5.0, macOS-like). See the [effects] reference below.


icons.toml reference

Create this file in your icons/ directory. All fields in [app] are used for metadata generation (.desktop, metainfo.xml).

# ── Application identity ───────────────────────────────────────────────────────
[app]
# Reverse-DNS identifier — used as the filename stem for every asset and as the
# Flatpak / Snap / D-Bus application ID. Must be consistent across all files.
id            = "com.example.MyApp"

name          = "My App"
generic_name  = "My Application Type"   # e.g. "Audio Editor", "Image Viewer"
comment       = "One-line summary"       # .desktop Comment=, AppStream <summary>
exec          = "myapp %F"              # .desktop Exec= — shell command to launch

# freedesktop.org menu categories:
# https://specifications.freedesktop.org/menu-spec/latest/apa.html
categories    = ["Category", "SubCategory"]
keywords      = ["keyword1", "keyword2"]

# Must match your window's WM_CLASS so docks/taskbars group windows correctly.
startup_wm_class = "myapp"

mime_types    = ["application/x-myapp"]  # Leave empty if no file associations

license          = "GPL-3.0-or-later"   # SPDX identifier for your app
metadata_license = "CC0-1.0"            # License for the metadata itself

description   = "Longer paragraph for store listings."
homepage_url  = "https://example.com"
developer_name = "Your Name or Studio"

# ── Input assets ──────────────────────────────────────────────────────────────
[input]
svg          = "icons/master.svg"      # Path relative to the working directory

# The macOS squircle mask is generated analytically — no shape file needed.
# Tune its roundness via [effects] squircle_power below.

# Monochrome SVG for Linux trays (optional):
# symbolic_svg = "icons/symbolic.svg"

# ── Output location ───────────────────────────────────────────────────────────
[output]
dir = "dist"

# ── Platform targets ──────────────────────────────────────────────────────────
[platforms]
macos   = true
windows = true
linux   = true

# ── Linux PNG sizes ───────────────────────────────────────────────────────────
[linux]
# Standard freedesktop hicolor sizes. 48 is the minimum required; keep all of
# these for full desktop-environment compatibility.
hicolor_sizes = [16, 22, 24, 32, 48, 64, 128, 256, 512]

# ── Visual effects (macOS) ────────────────────────────────────────────────────
[effects]
# SDF bevel: simulates overhead lighting on the squircle boundary.
# Rim highlight on top, subtle shadow on bottom. Applied before masking.
squircle_depth = true
gloss_strength = 0.35   # 0.0 = flat, 1.0 = maximum. 0.35 is a natural default.
depth_blur     = 0.12   # Gaussian blur on the lighting maps.
                         # 0.00 = no smoothing (may show staircase artifacts)
                         # 0.12 = default (smooth without losing edge definition)
                         # 0.30 = very soft

# ── Packaging formats ─────────────────────────────────────────────────────────
[packaging]
snap     = false   # Generates dist/snap/snap/gui/
flatpak  = false   # Generates dist/flatpak/app/share/
appimage = false   # Generates dist/appimage/<Name>.AppDir/
deb      = false   # (reserved — not yet implemented)

Running

Docker

# Run from your project root, mounting it as /workspace:
docker run --rm \
  -v "$(pwd):/workspace" \
  iconsmaker:latest \
  --config icons/icons.toml

# With verbose output:
docker run --rm \
  -v "$(pwd):/workspace" \
  iconsmaker:latest \
  --config icons/icons.toml --verbose

# Using the included docker-compose.yml (from the iconsmaker directory):
PROJECT_DIR=/path/to/myproject \
  docker compose run --rm iconsmaker --config icons/icons.toml

Cargo

# From your project directory:
cargo run \
  --manifest-path /path/to/iconsmaker/Cargo.toml \
  -- --config icons/icons.toml

# Or if iconsmaker is installed on PATH:
iconsmaker --config icons/icons.toml

Output reference

After a successful run with all platforms enabled:

dist/
├── macos/
│   └── MyApp.icns                     macOS icon bundle
├── windows/
│   └── MyApp.ico                      Windows icon (multi-size)
├── linux/
│   ├── com.example.MyApp.desktop      freedesktop Desktop Entry
│   ├── com.example.MyApp.metainfo.xml AppStream MetaInfo
│   └── hicolor/
│       ├── 16x16/apps/com.example.MyApp.png
│       ├── 22x22/apps/ ...
│       ├── 24x24/apps/ ...
│       ├── 32x32/apps/ ...
│       ├── 48x48/apps/ ...
│       ├── 64x64/apps/ ...
│       ├── 128x128/apps/ ...
│       ├── 256x256/apps/ ...
│       ├── 512x512/apps/ ...
│       └── scalable/apps/com.example.MyApp.svg
├── snap/
│   └── snap/gui/
│       ├── icon.png                   256 × 256 Snap Store icon
│       └── com.example.MyApp.desktop
├── flatpak/
│   └── app/share/
│       ├── applications/com.example.MyApp.desktop
│       ├── metainfo/com.example.MyApp.metainfo.xml
│       └── icons/hicolor/ ...         (full hicolor tree)
└── appimage/
    └── MyApp.AppDir/
        ├── com.example.MyApp.png      top-level icon
        ├── .DirIcon -> ...            symlink (Linux only)
        ├── com.example.MyApp.desktop
        └── usr/share/ ...

Installing Linux assets (tarball / manual)

# Icons
rsync -a dist/linux/hicolor/ /usr/share/icons/hicolor/
gtk-update-icon-cache -f -t /usr/share/icons/hicolor

# Desktop integration
install -Dm644 dist/linux/com.example.MyApp.desktop \
  /usr/share/applications/com.example.MyApp.desktop
install -Dm644 dist/linux/com.example.MyApp.metainfo.xml \
  /usr/share/metainfo/com.example.MyApp.metainfo.xml

# Validate
desktop-file-validate /usr/share/applications/com.example.MyApp.desktop
appstreamcli validate /usr/share/metainfo/com.example.MyApp.metainfo.xml

Visual effects

The [effects] section applies a depth treatment to macOS icons only, simulating overhead lighting on the squircle boundary.

gloss_strength  controls how strong the lighting contrast is
depth_blur      controls how smoothly the lighting fades across the edge band

The bevel band is fixed at 7 % of the icon's shorter dimension — about 72 px at 1024 px, 18 px at 256 px. Edge pixels facing the light source (upper-left) are brightened via Screen blend; pixels facing away are darkened via Multiply.

Tuning guide:

gloss_strength Effect
0.15 Barely perceptible — suitable for very dark or very light icons
0.35 Default — natural overhead light on a physical surface
0.55 Dramatic — similar to an app icon under strong directional lighting
depth_blur Effect
0.00 Raw edge sampling — may show subtle pixel-level staircase
0.12 Default — artifacts smoothed, edge still defined
0.25 Soft — good for icons with gradients near the squircle boundary

Set squircle_depth = false for a completely flat icon (no lighting).


Build system integration

CMake

Add icon generation as a custom target that runs before the app bundle step.

# Find the tool (adjust if using Docker or a specific install path)
find_program(ICONSMAKER_BIN iconsmaker
    HINTS "$ENV{HOME}/.cargo/bin" "/usr/local/bin"
)

set(ICON_CONFIG  "${CMAKE_SOURCE_DIR}/icons/icons.toml")
set(ICON_SVG     "${CMAKE_SOURCE_DIR}/icons/master.svg")
set(ICON_ICNS    "${CMAKE_SOURCE_DIR}/dist/macos/${PROJECT_NAME}.icns")
set(ICON_ICO     "${CMAKE_SOURCE_DIR}/dist/windows/${PROJECT_NAME}.ico")

if(ICONSMAKER_BIN)
    add_custom_command(
        OUTPUT  "${ICON_ICNS}" "${ICON_ICO}"
        COMMAND "${ICONSMAKER_BIN}" --config "${ICON_CONFIG}"
        WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
        DEPENDS "${ICON_SVG}" "${ICON_CONFIG}"
        COMMENT "Generating platform icon bundles"
        VERBATIM
    )
    add_custom_target(icons DEPENDS "${ICON_ICNS}" "${ICON_ICO}")
else()
    message(STATUS "iconsmaker not found — skipping icon generation")
endif()

Via Docker (no local install needed)

add_custom_command(
    OUTPUT  "${ICON_ICNS}" "${ICON_ICO}"
    COMMAND docker run --rm
            -v "${CMAKE_SOURCE_DIR}:/workspace"
            iconsmaker:latest
            --config icons/icons.toml
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
    DEPENDS "${ICON_SVG}" "${ICON_CONFIG}"
    COMMENT "Generating platform icon bundles via Docker"
    VERBATIM
)
add_custom_target(icons DEPENDS "${ICON_ICNS}" "${ICON_ICO}")

Then in your app bundle target:

add_dependencies(MyApp icons)

Makefile

ICONSMAKER ?= iconsmaker

.PHONY: icons
icons:
	$(ICONSMAKER) --config icons/icons.toml

dist/macos/MyApp.icns: icons/master.svg icons/icons.toml
	$(ICONSMAKER) --config icons/icons.toml

Adding iconsmaker to a new project

Follow these steps for each new application:

1 — Prepare artwork

  • Design your icon in a vector editor (Figma, Affinity Designer, Inkscape, Sketch).
  • Canvas size: 1024 × 1024 px square.
  • Export as SVG with text converted to outlines (no font dependencies).
  • Do not add rounded corners, drop shadows, or gloss — the tool handles these.
  • Save as icons/master.svg in your project.

2 — Create icons/icons.toml

Start from the template in the icons.toml reference section above. At minimum, fill in:

[app]
id             = "com.yourname.YourApp"   # unique reverse-DNS ID
name           = "Your App"
comment        = "One-line description"
exec           = "yourapp"

[input]
svg       = "icons/master.svg"

3 — Run and inspect

docker run --rm -v "$(pwd):/workspace" iconsmaker:latest --config icons/icons.toml --verbose

Open dist/macos/YourApp.icns in Preview (macOS) and dist/linux/hicolor/256x256/apps/ in your file manager to visually check the output.

4 — Tune effects

If the depth bevel is too strong or too subtle, adjust in icons.toml:

[effects]
gloss_strength = 0.35   # reduce for subtle, increase for dramatic
depth_blur     = 0.12

Re-run to see the change immediately.

5 — Validate Linux metadata

desktop-file-validate dist/linux/com.yourname.YourApp.desktop
appstreamcli validate dist/linux/com.yourname.YourApp.metainfo.xml

Fix any validation errors before shipping.

6 — Wire into your build system

See Build system integration above. Add dist/ to your project's .gitignore.

7 — Per-packaging-format setup

Enable packaging formats in icons.toml as needed and follow the platform's own guide for referencing the generated assets:

Format Generated assets location Reference
Snap dist/snap/snap/gui/ Copy to your snap source tree
Flatpak dist/flatpak/app/share/ Copy under your Flatpak module prefix
AppImage dist/appimage/YourApp.AppDir/ Merge into your AppDir before appimagetool
.deb dist/linux/hicolor/ + .desktop List in debian/<pkg>.install

SVG design reference

Colour palette guidance

Element Use
Background fill Avoid pure black (#000) — use near-black like #1a1a1a for depth
Primary colour Should read clearly at 16 × 16 px — test at small sizes
High-contrast content Avoid very similar colours next to each other; they merge at small sizes

Testing at small sizes

The most common mistake in icon design is content that looks fine at 512 px but is unreadable at 16 px. Check your 16 × 16 and 22 × 22 PNG outputs. Simplify the SVG or increase contrast if small sizes look muddy.

resvg filter support

The following SVG filter primitives are supported: feBlend, feColorMatrix, feComposite, feFlood, feGaussianBlur, feImage, feMerge, feOffset, feSpecularLighting, feTurbulence (basic).

Not supported: feConvolveMatrix, feDiffuseLighting (partial), feMorphology, feDisplacementMap. Unsupported primitives are silently ignored.

Further reading

  • Linux Application Icon Asset Guide — freedesktop hicolor layout, per-desktop styling (GNOME/KDE/Xfce/…), and the Snap / Flatpak / AppImage / .deb icon requirements.

Bundled assets

iconsmaker ships as a single self-contained binary with no external asset files. The macOS squircle mask is generated analytically at runtime from the [effects] squircle_power value — there is no bundled shape SVG to install or reference.

A sample source icon is included at icons/master.svg so you can try a build immediately after cloning:

cargo run --release -- --config icons.toml
# assets appear under dist/

License

iconsmaker is free software licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).

Acknowledgments

Claude (Anthropic) was used extensively in the design and implementation of this package — architecture, the Rust code, the packaging/installer pipeline, and this documentation.