Overview
Three commands cover the full development lifecycle in Spraxium: spraxium dev for local iteration, spraxium build for producing a production artifact, and spraxium start for running that artifact. This page covers all three so you never need to jump between pages to understand how they connect.
spraxium dev
spraxium dev starts a file-watching development server that restarts the application automatically when source files change. It uses SWC for loading TypeScript without a separate compile step, keeping restart times short even in large projects. The watcher fires based on the include and exclude glob patterns in your configuration, and applies a configurable debounce to batch rapid file saves into a single restart.
spraxium devDev configuration
export default {
dev: {
entrypoint: 'src/main.ts',
include: ['src/**'],
exclude: ['src/**/*.spec.ts'],
debounce: 300,
},
};Default excludes are always on
Even with no config block, the watcher ignores node_modules, .git, and .spraxium to prevent restart loops from dependency installs or build output.
Crash recovery
If the bot process crashes, the dev server does not exit. It applies an exponential backoff delay before relaunching, calculated as Math.min(1000 * 2 ** crashCount, maxBackoff). This prevents a tight relaunch loop when the crash is reproducible. Fix the error, save the file, and the watcher triggers a normal restart.
spraxium build
spraxium build validates types and produces a production-ready bundle. It runs in two sequential steps: first a type-check pass and then the bundler. If the type-check fails, the bundler never runs, so you get a clean exit code that CI pipelines can rely on.
spraxium buildWhat happens
Type-check
Runs tsc --noEmit against your project. Any type error fails the command
immediately. Fix all TypeScript errors before the bundler can proceed.
Bundle
Runs tsdown with your project's configuration. If a tsdown.config.* file
exists in the project root, the CLI uses it. Otherwise it applies these
defaults: entry points src/main.ts and spraxium.config.ts, output
directory .spraxium/dist, format ESM, platform Node, --clean, and
--no-dts.
The compiled output lands in .spraxium/dist/ by default. This directory is the artifact that spraxium start looks for.
Build does not run tests
Running spraxium build does not execute your test suite. Run your tests separately before or after, and treat the build as a type and bundle gate only.
spraxium start
spraxium start runs the compiled artifact produced by spraxium build. It sets NODE_ENV=production before launching and inherits the current process stdio so application logs stream directly to the terminal.
spraxium startEntrypoint resolution
The CLI checks the following paths in order and runs the first one it finds:
.spraxium/dist/src/main.js.spraxium/dist/main.jsdist/src/main.jsdist/main.jsbuild/src/main.jsbuild/main.js
No build means no start
If none of the candidate paths exist, the command fails and prints a message telling you to run spraxium build first. Ensure your environment variables such as DISCORD_TOKEN are loaded before running this command.
Typical workflow
A complete iteration from development to production follows this order: run spraxium dev during active work, then switch to spraxium build when preparing a release, and finally run spraxium start to verify or deploy the compiled artifact. In CI, skip the dev step entirely and run build then start in sequence as your validation pipeline.
Process lock
Spraxium writes a per-project lock file at .spraxium/spraxium.lock on startup and removes it on clean shutdown. If a second instance detects the lock, it exits with a conflict warning instead of silently duplicating listeners and command registrations.
Flags
Both spraxium dev and spraxium start support two lock-related flags:
| Flag | Env var | Description |
|---|---|---|
| --force-unlock | SPRAXIUM_FORCE_UNLOCK=1 | Kills the existing bot process (and its dev-watcher launcher to prevent auto-respawn) then takes over. Terminal is released immediately after the kill. |
| --no-lock | SPRAXIUM_NO_LOCK=1 | Skips the lock check entirely. Use this only in setups that intentionally run concurrent instances (e.g. a testing environment running alongside production). |
# Kill the running instance and take over
spraxium dev --force-unlock
# Skip the lock check (concurrent instances allowed)
spraxium dev --no-lockStale locks from crashed processes are detected automatically via process.kill(pid, 0) and cleaned before startup, so you only see conflict warnings for genuinely running instances.
Upgrade notifier
At startup, Spraxium scans node_modules/@spraxium/* to find every framework package installed in the project, queries the npm registry for the latest versions, and prints a notice if any packages are behind. The check runs in the background and never delays startup.
Results are cached at ~/.spraxium/upgrade-check.json with a 24-hour TTL shared across all projects on the machine. If a package was recently installed that is not yet in the cache, only that package is fetched, while the rest use the cached data.
Set SPRAXIUM_NO_UPGRADE_NOTIFIER=1 (or the environment variable of the same name) to disable the check entirely. This is useful in CI environments where the notice is noise rather than signal.