CLI
The optical-center binary. Asset-level batch processing — point it at a folder of SVGs and it rewrites their viewBoxes on disk. JSON-able output, clean stream contracts, composes inside CI pipelines.
When to use the CLI
The CLI operates on SVG files directly — it has no view of CSS rules or JSX wrappers. Reach for it when you want to:
- Pre-process an icon set once and check the corrected files into a repo.
- Inspect a single icon to see what the pipeline computes for it.
- Aggregate a library to find which icons need the largest correction.
- Run in CI as a check (with
--strict) that no icon trips a warning.
For runtime use inside a build, prefer the Vite or PostCSS plugin — the CLI is for batch operations, not per-build wiring.
Interactive wizard
Run the binary with no arguments in a real terminal and it opens a
menu instead of printing the help page: pick a command with the
arrow keys, fill in the inputs (paths are validated against the
filesystem before anything runs), and the wizard prints the
equivalent one-shot invocation before dispatching — so it doubles
as a flag tutorial. After each command the menu returns; run
several in one session and leave with exit or esc.
npx optical-center
The wizard only ever appears on a TTY. Pipes, CI logs,
--json, and --silent always get the
stable plain-text contract, so nothing scripted ever blocks on a
prompt. A session closed normally exits 0 regardless
of per-command warnings — the codes below are the contract for the
non-interactive surface.
Commands
init
Wires optical-center into a project. Detects the framework
(Vite, Astro, Tailwind, PostCSS, Babel) from
package.json and existing config files, detects the
package manager from the lockfile, installs the dependency, and
patches the config — opticalCenter() first in Vite's
plugins array, after Tailwind in PostCSS's,
and so on. Creates a minimal config when none exists.
npx optical-center init # interactive: select + confirm
npx optical-center init --integration vite --yes # non-interactive
npx optical-center init ./my-app --dry-run # report, write nothing
Flags: --integration=<vite|astro|postcss|tailwind|babel>,
--yes, --no-install,
--pm=<npm|pnpm|yarn|bun>, --dry-run.
When a config file's shape can't be edited confidently, init prints
a paste-ready snippet and exits 1 instead of guessing —
it never rewrites code it doesn't recognise, and re-running it is
always safe (already-wired files are left untouched).
transform
Rewrites every SVG in <input> and writes results to [output]. Folder in, folder out.
npx optical-center transform <input> [output] info
Inspects a single SVG. Returns the original viewBox, the corrected viewBox, and the offset in both pixels and percent.
npx optical-center info <svg> [--json] analyze
Aggregates a folder of SVGs. Returns a top-N report sorted by offset magnitude — useful for finding which icons in a library need the largest corrections.
npx optical-center analyze <folder> [--json] clear-cache
Drops the content-addressable cache. The cache is normally self-managing (keyed by SVG bytes + algorithm version) so manual clears are rarely needed.
npx optical-center clear-cache [--all] version
Prints the package version and algorithm version. Useful inside CI logs.
npx optical-center version Common flags
| Flag | Effect |
|---|---|
--json | Emits machine-readable JSON on stdout. Progress and warnings still go to stderr. |
--strict | Promotes warnings to a non-zero exit code so CI fails on (for example) OPTICAL_CLIP_DETECTED. |
--no-cache | Skips the disk cache; recomputes every icon from scratch. |
--cache-dir=<path> | Overrides the cache directory. Defaults to the OS cache location. |
--emit-metadata |
Adds data-optical-original-viewbox and
data-optical-offset attributes for DevTools
inspection. On for info, off for production
transform.
|
--silent | Suppresses progress logs on stderr. Errors still surface. |
--quiet | Suppresses warnings on stderr. Stronger than --silent. |
Exit codes
The exit code is the contract between the CLI and your CI script. Every command follows the same scheme:
| Code | Meaning |
|---|---|
0 | Success. |
1 | Success with warnings (or --strict tripped on a warning). |
2 | Recoverable error — one or more files failed but the run continued. |
3 | Fatal — the run aborted (invalid args, IO failure, etc). |
Heads-up for script runners: exit code 1 means
success with warnings (clip detection, derived viewBox),
but yarn and npm print a "command failed" banner for any non-zero
exit. That banner is the runner talking, not a crash — the actual
warning is on stderr. Use --strict when you
want warnings to fail CI; otherwise treat 1
as a soft pass.
JSON output
With --json, stdout is data only — pipe it into jq or read from a CI job.
$ optical-center info ./icons/play.svg --json {
"schemaVersion": 1,
"command": "info",
"result": {
"file": ".../play.svg",
"originalViewBox": { "x": 0, "y": 0, "w": 24, "h": 24, "source": "attribute" },
"newViewBox": "-0.3239 -0.6226 24 24",
"offset": {
"dxPercent": 1.3497,
"dyPercent": 2.5944,
"dx": 1.62,
"dy": 3.11
},
"clipDetected": false,
"breadcrumb": {
"data-optical-center": "",
"data-optical-original-viewbox": "0 0 24 24",
"data-optical-offset": "1.3497% 2.5944%"
}
},
"version": {
"package": "0.2.0-alpha.0",
"algorithm": "1.0.0-v2",
"schema": 1
}
}