Spraxium logoSpraxium

Development Lifecycle

How spraxium dev, build, and start work together to drive your development flow. Understand hot reload, type-check, bundling, and production startup in one place.

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.

terminal
spraxium dev

Dev configuration

spraxium.config.ts
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.

terminal
spraxium build

What 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.

terminal
spraxium start

Entrypoint resolution

The CLI checks the following paths in order and runs the first one it finds:

  1. .spraxium/dist/src/main.js
  2. .spraxium/dist/main.js
  3. dist/src/main.js
  4. dist/main.js
  5. build/src/main.js
  6. build/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:

FlagEnv varDescription
--force-unlockSPRAXIUM_FORCE_UNLOCK=1Kills the existing bot process (and its dev-watcher launcher to prevent auto-respawn) then takes over. Terminal is released immediately after the kill.
--no-lockSPRAXIUM_NO_LOCK=1Skips the lock check entirely. Use this only in setups that intentionally run concurrent instances (e.g. a testing environment running alongside production).
terminal
# Kill the running instance and take over
spraxium dev --force-unlock

# Skip the lock check (concurrent instances allowed)
spraxium dev --no-lock

Stale 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.