# nixie-fx CLI reference

> Documentation · Updated August 2026 · https://nixiefx.com/cli-reference/

The `nixie-fx` package installs a command-line tool for headless and
agent-driven workflows: create effects, validate a project, and export the
game bundle — no browser required.

## TL;DR — three commands

Run from a folder containing `vfx-editor.prj` (or point at one):
`npx nixie-fx effect create --project . --name "Fire Burst" --profile three-world-3d`
scaffolds an effect JSON file, `npx nixie-fx validate .` checks every effect
read-only and exits non-zero on errors, and `npx nixie-fx export .` writes
the `out/vfx` bundle games load. Effects are plain JSON — the intended loop
is **create → edit JSON → validate → export**, which is exactly what the
NixieFX agent skills (https://nixiefx.com/skills/) drive.

## Overview & installation

The CLI ships inside the `nixie-fx` npm package
(https://www.npmjs.com/package/nixie-fx) as the `nixie-fx` binary (Node ≥
20). Run it ad hoc with `npx nixie-fx`, or install the package in your
project and call it from scripts. `--help`, `-h`, `help`, or no arguments
print the synopsis:

```text
$ npx nixie-fx --help
NixieFX runtime and authoring tools

Usage:
  nixie-fx effect create --project <folder> --name <name> [--profile <profile>]
  nixie-fx validate [project-folder]
  nixie-fx export [project-folder]

Profiles:
  pixi-ui-2d (default), three-world-3d, portable
```

Those three commands are the complete surface. There are no separate asset or
material commands — assets are files under the project's asset root, managed
by the editor or your filesystem — and no project scaffolding command (see
the next section for the one file a project needs). Every command prints
`Error: …` to stderr and exits `1` on unknown commands, unknown or repeated
options, and missing values.

## Project layout & vfx-editor.prj

All commands operate on a NixieFX project: any folder containing a
`vfx-editor.prj` settings file. You can pass the folder (or the `.prj` file
path itself) as `--project` / a positional argument; the default is the
current directory. Projects are normally created in the editor
(https://nixiefx.com/editor-manual/), but the file is plain JSON, so headless
setups (CI, agents) can write it by hand:

```json
{
  "app": "vfx-editor",
  "kind": "project",
  "version": 1,
  "id": "my-game-vfx",
  "name": "My Game VFX",
  "settings": {
    "effectDataPath": "particle-data/effects",
    "assetRootPath": "assets",
    "outputPath": "out/vfx",
    "materialsFolder": "materials",
    "allowExternalOutput": false
  },
  "createdAt": "2026-08-16T00:00:00.000Z",
  "updatedAt": "2026-08-16T00:00:00.000Z"
}
```

| Setting | Default | Meaning |
| --- | --- | --- |
| `effectDataPath` | `"."` | Folder (relative to the project root) holding authoring effect JSON. Required in the file; the editor uses `particle-data/effects`. |
| `assetRootPath` | `"."` | Root that authored texture/mesh paths resolve against and that export copies assets from. |
| `outputPath` | `"out/vfx"` | Where `export` writes the game bundle. |
| `materialsFolder` | `"materials"` | Folder holding `.material` graph assets. |
| `allowExternalOutput` | `false` | Permits an `outputPath` outside the project root. |

## nixie-fx effect create

```text
nixie-fx effect create --project <folder> --name <name> [--profile <profile>]
```

Creates a new starter effect as a JSON file under the project's effect data
folder. The file name is the kebab-cased effect id derived from the name
(`"Impact Burst"` → `impact-burst.json`). The command **refuses to
overwrite** an existing file. With `--profile portable`, the starter
emitter's depth flags (`depthTest`, `depthWrite`, `depthInk`) are switched
off so the new effect validates cleanly against both backends.

| Flag | Required | Default | Description |
| --- | --- | --- | --- |
| `--project <folder>` | no | `.` | Project folder (or a direct path to `vfx-editor.prj`). |
| `--name <name>` | yes | — | Display name; also the source of the effect id and file name. |
| `--profile <profile>` | no | `pixi-ui-2d` | Target profile: `pixi-ui-2d`, `three-world-3d`, or `portable`. |

```text
$ npx nixie-fx effect create --project ./my-vfx --name "Impact Burst" --profile three-world-3d
Created /work/my-vfx/particle-data/effects/impact-burst.json

$ npx nixie-fx effect create --project ./my-vfx --name "Impact Burst" --profile three-world-3d
Error: Effect file already exists: /work/my-vfx/particle-data/effects/impact-burst.json
# exit code 1

$ npx nixie-fx effect create --project ./my-vfx --name X --profile webgl
Error: Unknown profile "webgl". Expected pixi-ui-2d, three-world-3d, portable
# exit code 1
```

The created file is a complete, valid effect (one billboard emitter using the
procedural shape, no file assets) — the intended starting point for editing
the JSON directly or opening it in the editor.

## nixie-fx validate

```text
nixie-fx validate [project-folder]
nixie-fx validate --project <folder>
```

Read-only validation of every effect in the project. The command walks the
effect data folder recursively, skips dot-files, parses every `*.json`, and
validates each file that carries the effect envelope
(`app: "vfx-editor"`, `kind: "particle-effect"` — or, for legacy files, an
`emitters` array with no `kind`). Other JSON files are silently ignored. Pass
the project as a positional path or `--project`, not both.

### Output semantics

Each diagnostic is one line — `severity [code] file:path: message` — where
`path` is the JSON path inside the effect. Warnings print to stdout, errors
(including export blockers not already reported as errors) to stderr,
followed by a one-line summary:

```text
$ npx nixie-fx validate ./my-vfx
warning [clamped-value] broken-burst.json:emitters.0.maxParticles: Numeric authoring value will be clamped to 1..4096.
error [duplicate-id] impact-burst.json:emitters.1.id: Emitter id duplicates emitters.0.id.
Validated 2 effects: 1 error, 1 warning.
# exit code 1 — errors present

$ npx nixie-fx validate ./my-vfx     # after fixing
Validated 2 effects: 0 errors, 0 warnings.
# exit code 0 — warnings alone never fail validate
```

| Severity | Stream | Meaning |
| --- | --- | --- |
| `error` | stderr | The effect cannot be represented safely; export will be blocked. Fails the command. |
| `warning` | stdout | Exportable, but a module or value is approximated or will be adjusted (these become the `partial` entries of the support report). Never fails the command. |
| `note` | stdout | Informational backend-semantics notes, printed as `note [code] (backend note) …` — for example how the *other* backend renders authored depth flags. Notes are scoped by the effect's target profile: diagnostics about a backend outside the profile are demoted to notes, never counted, and a clean effect still summarizes as `0 errors, 0 warnings`. |

Diagnostic codes are stable and grep-friendly: `bad-kind`, `bad-version`,
`missing-id`, `duplicate-id`, `invalid-asset-ref`, `unsupported-module`,
`clamped-value`, and the material-graph family (`missing-material`,
`material-sampler-cap`, `material-variant-cap`, `material-banned-node`,
`material-channel-conflict`, `material-runtime-noise`).

> `validate` checks schema and runtime semantics only — it does not touch the
> filesystem beyond reading effect JSON. Asset *existence* (a texture path
> that resolves to no file under the asset root) is verified at export time,
> which is why a clean `validate` can still produce a blocked export.

## nixie-fx export

```text
nixie-fx export [project-folder]
nixie-fx export --project <folder>
```

Compiles every effect and writes the game bundle to the project's configured
`outputPath` (default `out/vfx`). A successful export writes:

- `manifest.json` — effect and asset index, validation result, and source
  hashes for cache invalidation;
- `effects/*.json` — compiled effects with editor-only fields stripped and a
  per-backend `support` report embedded;
- byte-copies of every referenced asset (textures, `.material` graphs,
  prepared meshes), preserving their asset-root-relative paths.

Validation runs first and prints exactly like `validate`. If any error or
blocker exists, no game-loadable bundle is written — the command writes
`export-diagnostics.json` (the full validation result plus resolved project
paths) into the output folder instead and exits `1`. Runtime loaders refuse
blocked bundles, so a failed export cannot be shipped by accident.

```text
$ npx nixie-fx export ./my-vfx
Exported 1 effect to out/vfx.

$ find my-vfx/out/vfx -type f
my-vfx/out/vfx/manifest.json
my-vfx/out/vfx/effects/impact-burst.json

# With a texture reference that resolves to no file under assets/:
$ npx nixie-fx export ./my-vfx
error [invalid-asset-ref] broken-burst.json.assets.0.path: Missing raw texture asset "textures/missing-spark.png" in asset root "assets".
Export blocked with 1 error(s). Diagnostics: out/vfx/export-diagnostics.json
# exit code 1
```

Exports are deterministic for unchanged sources: effect and manifest
`sourceHash` values only change when authoring content changes, so bundle
diffs in version control stay meaningful.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success — including `validate` with warnings or notes only. |
| `1` | Any failure: validation errors or blockers, a blocked export, an existing effect file on `effect create`, a missing `vfx-editor.prj`, or a usage error (unknown command/option/profile, repeated or valueless options). |

## Typical workflows

### Agent-driven authoring loop

Effects are plain JSON, which makes the CLI the natural authoring backend for
AI coding agents — this is exactly the loop the official nixie-fx-authoring
skill (https://nixiefx.com/skills/) drives:

```sh
# 1. Scaffold a valid starting effect
npx nixie-fx effect create --project . --name "Muzzle Flash" --profile three-world-3d

# 2. Edit particle-data/effects/muzzle-flash.json directly:
#    emission bursts, shape, color gradients, size curves, blend mode...

# 3. Validate after every edit — cheap, read-only, machine-parseable
npx nixie-fx validate .

# 4. Export the bundle the game loads
npx nixie-fx export .

# 5. Integrate: load out/vfx with the Three.js or PixiJS runtime
#    (https://nixiefx.com/threejs-runtime/), or review visually in the editor.
```

### CI validation

Because `validate` is read-only and exits non-zero on errors, it slots
straight into CI to keep unreviewable effect regressions out of main:

```jsonc
// package.json
"scripts": {
  "vfx:check": "nixie-fx validate ./vfx-project",
  "vfx:build": "nixie-fx export ./vfx-project"
}
```

```sh
# CI step
npm run vfx:check          # fails the build on any validation error
npm run vfx:build          # refreshes out/vfx for deployment
```

Committing the exported `out/vfx` bundle or rebuilding it in CI are both
fine — hashes make stale-bundle drift detectable, and the runtime loader
re-verifies everything at load time.

## Resources

- **Three.js runtime guide & API reference** — https://nixiefx.com/threejs-runtime/ (loading the exported bundle in a game)
- **Agent skills** — https://nixiefx.com/skills/ (nixie-fx-authoring wraps this CLI for AI coding agents)
- **Editor & runtime feature reference** — https://nixiefx.com/vfx-runtime-docs/ (what the effect JSON can express)
- **Runtime repository** — https://github.com/azakhary/nixie-fx (runtime, CLI, and skills, MIT)
- **npm package** — https://www.npmjs.com/package/nixie-fx

---

*This reference is maintained by the team behind NixieFX
(https://nixiefx.com/), the browser-based particle editor for PixiJS and
Three.js. The HTML version lives at https://nixiefx.com/cli-reference/, and a
site index for LLMs at https://nixiefx.com/llms.txt.*
