Skip to main content

Develop locally

This page provides an overview of getting your development environment ready for building Reboot applications. Once your development environment is ready you can then start to define and implement your API.

New to Reboot? Build with Claude Code or Codex gets you a running app in minutes; this page is the reference behind what they set up.

Set up your environment

You can use one of Reboot's GitHub Codespaces or set up your environment manually by installing the prerequisites listed below.

Prerequisites

OS
Linuxx86_64 or arm64, glibc>=2.35 (Ubuntu Jammy and other equivalent-generation distributions)
macOSarm64, macOS >= 14.0 and Xcode >= 15.2
  • Python >= 3.10 and < 3.13 is required for Python backends, and fetched automatically for Node.js backends
  • Node.js >= 20.10 is required for Node.js backends only
  • Docker
note

Python 3.13 support is coming soon.

note

Your applications don't need to run "inside of" Docker, but Docker is used to host a service required for local development.

The rbt CLI

The rbt command line tool doesn't have a separate installation; it comes with the Reboot library.

For Python, installing the reboot package provides rbt:

uv add reboot

Then run it as uv run rbt ..., or as plain rbt ... in an activated virtual environment (e.g. .venv).

Directory layout

You can lay out your directories however you like, as long as you pass them correctly to rbt.

Here is a suggested file layout:

FilesDirectory
API definitions (*.py, *.ts)api/
Backend source *.py, *.ts/jsbackend/src
Tests: feature files and *.pytests
Backend tests *.ts/jsbackend/tests
Generated React clientfrontend/api
Browser appfrontend/web
React Native appfrontend/mobile
UI method apps, one per methodfrontend/mcp/<name>

Putting the generated client in frontend/api lets every frontend of your application share one copy of it. See One backend, many frontends.

.rbtrc and flags

rbt loads its flags from an .rbtrc file, if present. This is a convenient way of keeping the options you have to type and remember to a minimum.

An .rbtrc file might look like:

# Watch if any generated or source files are modified.
dev run --watch=backend/**/*.py

# Tell `rbt` that this is a Python application.
dev run --python

# Save state between chaos restarts.
dev run --application-name=bank

# Run the application!
dev run --application=backend/src/main.py

# When expunging, expunge that state we've saved.
dev expunge --application-name=bank

Syntax

Global options

Global options like the --state-directory flag can be specified in .rbtrc by prefixing with ...:

... --state-directory=non/default

Passthrough options

Commands like generate use the -- separator to accept arguments to pass directly to an underlying tool:

In a terminal:

rbt generate --python=backend/api/ api/ -- --mypy_out=backend/api/

In .rbtrc:

# Find API definitions in 'api/'.
generate api/

# Generate Python code into 'backend/api/'.
generate --python=backend/api/

# Generate 'mypy' stubs into 'backend/api/mypy/'.
generate -- --mypy_out=backend/api/mypy/

In these examples, the order of the flags is crucial. All flags that appear after -- are passed directly to the underlying code generator.

Frontend flags

When your application has a React frontend — a web app, a React Native app, or UI methods — add these to your .rbtrc:

# Generate typed React hooks, shared by every frontend.
generate --react=frontend/api

# Proxy the frontend through Vite for hot module replacement.
dev run --frontend-root-path=frontend

dev run:hmr --frontend-host=http://localhost:4444

# Default to HMR mode when --config is not specified.
dev run --default-config=hmr
FlagDescription
dev run --frontend-root-path=<dir>Names the frontend root (e.g. frontend). Set once on the base dev run line so the :hmr and :dist configs inherit it.
dev run --frontend-host=<url>HMR: point at the Vite dev server URL (e.g. http://localhost:4444); Envoy proxies /__/frontend/** to it.
dev run --frontend-dist-path=<dir>Dist: serve pre-built frontend assets from <dir> (e.g. frontend/dist) on disk; mutually exclusive with --frontend-host.
dev run --default-config=<name>Sets the default configuration profile when --config is not specified.
dev run:hmr / dev run:distNamed configurations. Flags prefixed with dev run:<name> only apply when --config=<name> is used.

Running your app for development

Once you've set up your environment as outlined above, all you'll need to run to start live developing your app is:

$ rbt dev run
...

Or if you're building a Node.js backend with npm (after installing @reboot-dev/reboot):

$ npx rbt dev run
...

Inspecting state

While doing local development you can inspect your application state by pointing your browser at http://localhost:9991/__/inspect (assuming you aren't using TLS and haven't changed the default port from 9991).

Persisting state during development

By default your application state will not be persisted across restarts. To persist state, you can pass an --application-name=... flag to rbt dev run.

When state is persisted, backwards incompatible changes to your API definitions are detected, and will trigger errors to encourage resolving them before they reach production. The --on-backwards-incompatibility flag allows you to control what happens when backwards incompatibility is encountered:

  • ask: (default) Asks whether you would like to expunge the stored state to ignore the backwards incompatibility.
  • expunge: Automatically expunges stored state after rendering a backwards compatibility error.
  • fail: Waits for a code change that resolves the backwards incompatibility.

During early development of your application, either ask or expunge are reasonable choices. Once you have deployed to production, the fail option can encourage more caution while adjusting schemas.

You can also use rbt dev expunge --application-name=... to manually expunge data (where --application-name=... is the same value you're using for rbt dev run).