Development
Build, link, restart, and read the logs.
Day to day, one command covers the loop:
pnpm devThe rest of this page is what that command does on your behalf, and what to reach for when you need to step outside it.
How the loop works
pnpm dev starts two watchers — one for the background process, one for the
editor — and each rebuilds into dist/<your-plugin-id>/. That folder is the
plugin: manifest, code, and editor assets in the shape Fluxta loads.
After every successful background-process build, the watcher runs
fluxta restart, which does two things:
- Points Fluxta at
dist/<your-plugin-id>/with a development link, so the app loads that build instead of any installed copy of the same plugin. - Restarts the plugin's process and waits for it to come back up.
Saving a .ts file in the background process is therefore enough: Fluxta is
already running the new code.
Editors do not restart the process
The editor is static files. When it rebuilds, nothing needs restarting — Fluxta picks up the new assets the next time it opens that iframe. An editor left open while it rebuilds keeps showing the old bundle until it is closed and reopened.
Reading the logs
The background process has no console of its own, so console.log and
console.error are how to see what it is doing. Both are captured to a file
inside the plugin folder:
tail -f dist/<your-plugin-id>/logs/<your-plugin-id>.logstdout is recorded as info, stderr as errors.
A full build deletes the logs
pnpm build clears dist/ before rebuilding, and the log file lives inside
it. pnpm dev does not, so a running loop keeps its log.
Plugin status
Fluxta reports one status per plugin:
| Status | What it means |
|---|---|
Available | The plugin loaded. It either needs no background process, or one has not started yet. |
Starting | The process was launched and has not connected yet. |
Running | The process is up and connected. This is the normal state. |
Disconnected | The process is alive but its connection to Fluxta dropped. |
Stopped | The process exited normally. |
Error | The plugin failed to load, or the process exited with an error. |
A crashed process is not restarted automatically. A dead plugin stays dead until it is rebuilt or restarted, so that a crash loop cannot hide.
Commands
| Command | What it does |
|---|---|
pnpm build | A clean, full build of dist/<your-plugin-id>/. Owned by your project, not the CLI. |
pnpm typecheck | Type-checks both halves without building. |
pnpm lint | Runs ESLint. fluxta publish runs this too and stops if it fails. |
pnpm format | Rewrites files with Prettier. publish runs format:check and stops if it fails. |
fluxta link | Registers an existing build folder as a development link, without building. |
fluxta restart | Refreshes the link and restarts the process. What the dev loop calls. |
fluxta start | Starts a stopped plugin. |
fluxta stop | Stops a running plugin. |
fluxta unlink | Removes the development link and restores the installed copy, if there is one. |
fluxta validate | Checks the project and build output against everything publishing requires. |
The CLI never builds. If a command needs a build folder and cannot find a valid
one, fix the build and run pnpm build again.
Fluxta has to be running
Anything that touches the app — link, restart, start, stop, unlink —
needs Fluxta already running; the CLI does not launch it. If it is not
running, the command says so. A build still succeeds; only the restart step is
skipped.
Several plugins at once
A development link is per plugin, and links persist across restarts of Fluxta.
Several plugins can be linked at once — run pnpm dev in each project.
If a link's build folder goes missing or becomes invalid, Fluxta reports the
link as broken and refuses to fall back to the installed copy of that
plugin. Silently running installed code while you believe you are testing your
own is the worse outcome. Fix the build folder, or run fluxta unlink to hand
the plugin back to its installed version.
Build output rules
Two rules catch most people:
- Bundle everything. Fluxta runs the background process with its own Node
runtime and does not install
node_modulesin the plugin folder. The entry file must be a self-contained ES module. The generated project already does this. - Keep editor paths relative. The editor is served from a nested path, so
its bundle must not reference assets with absolute
/paths. With Vite that meansbase: "./", which the generated project already sets.
Get either wrong and the plugin loads but does nothing visible — see Troubleshooting.