---
title: Developing
description: Build, run, and test System Bridge from source.
---

This guide covers the contributor workflow for building and running System Bridge locally. End-user install steps are on the [Install](/install/) page.

## Prerequisites

1. Install [`mise`](https://mise.jdx.dev/installing-mise.html) (recommended). `mise.toml` pins the Go, Bun, and Node versions used by local development and CI.

2. Clone the [repository](https://github.com/timmo001/system-bridge) and install toolchains:

   ```bash
   git clone https://github.com/timmo001/system-bridge.git
   cd system-bridge
   mise install
   ```

3. Install dependencies:

   ```bash
   mise run deps
   ```

:::note
**Building without mise:** `mise run` tasks require `mise`. If you cannot install it, put compatible versions of `go`, `bun`, and `node` (see `mise.toml`) on your `PATH` and run the underlying commands from the `[tasks]` section directly.
:::

## Build

Build everything (web client and backend binary):

```bash
mise run build:all
```

On Linux this produces `system-bridge-linux` in the repo root. On Windows it produces `system-bridge.exe`.

Common component tasks:

| Task | Purpose |
| --- | --- |
| `mise run build:client:web` | Build the Lit + Vite web client into `client/web/dist/` |
| `mise run generate:schemas` | Regenerate Zod schemas after changing Go types in `types/` |

List every task with `mise tasks`.

## Run during development

### Foreground (all platforms)

`mise run run` builds the project and starts the Vite dev server and backend together in the foreground. Use this when you want live reload and logs in one terminal.

| Task | What it starts |
| --- | --- |
| `mise run run` | Vite dev server + backend (via `concurrently`) |
| `mise run run:client:web` | Vite dev server only (default port `5173`) |
| `mise run run:backend` | Backend only on port `9170` |
| `mise run run:backend-dev` | Build and run the backend with console output |

When using the Vite dev server, open `http://localhost:5173` and connect to the backend at port `9170`. Get your token with [`system-bridge client token`](/using/cli/#token).

### Background with pitchfork (Linux)

On Linux, [pitchfork](https://pitchfork.jdx.dev) can supervise dev servers in the background. Install it once:

```bash
mise use -g pitchfork
```

Then use the `serve:*` tasks (defined in `pitchfork.toml`):

| Task | Purpose |
| --- | --- |
| `mise run serve:all` | Start backend and web dev servers |
| `mise run serve:backend` | Start the backend dev server only |
| `mise run serve:web` | Start the Vite dev server only |
| `mise run serve:status` | Show daemon PIDs, ports, and state |
| `mise run serve:logs` | Follow backend logs |
| `mise run serve:restart` | Restart backend and web daemons |
| `mise run serve:stop` | Stop backend and web daemons |

:::caution
The backend daemon owns port `9170` and is also at `https://backend.system-bridge.localhost`. On start, `.scripts/linux/pitchfork-backend-prep.sh` stops any production `system-bridge` process using that port (systemd user service, compositor autostart, or a manual shell process). When the dev backend stops, `.scripts/linux/pitchfork-backend-restore.sh` brings it back. Plan for a brief interruption to your running instance while developing.
:::

Prefer `serve:*` for long-running background work (agents, repeated UI checks). Use `run:*` for foreground debugging or on platforms where pitchfork is not set up.

## Test data modules locally

Data modules live under `data/module/`. After building, exercise a module without starting the full backend:

```bash
mise run cli -- client data list
mise run cli -- client data run --module cpu --pretty
```

Or with `go run` before a full build:

```bash
go run . client data run --module cpu --pretty
```

OS-specific module code belongs in build-tagged files inside subpackages (for example `data/module/system/system_linux.go`). See `.agents/architecture.md` in the repository for the required pattern.

## Schema and type changes

When you change Go types under `types/`, regenerate the TypeScript connector's Effect schemas:

```bash
mise run generate:schemas
```

Do not hand-edit `connector/typescript/src/generated/modules.ts`; it is generated output.

## Quality checks

| Task | Purpose |
| --- | --- |
| `mise run test` | Build the web client if needed, then run Go tests (`go test ./...`) |
| `mise run lint:all` | Go format check and vet, web client Oxlint and typecheck |
| `mise run check` | `lint:all` plus tests, run in parallel |
| `mise run format:go` | Format Go code |

`lint:go` checks formatting without changing files. After editing Go code, run `mise run format:go`.

Pass several tasks to one run to execute them in parallel, for example `mise run check ::: build:all`. The schema and web client builds are skipped when their sources haven't changed.

## Documentation site

Docs live in `docs/`, built with [Blume](https://github.com/haydenbleasel/blume) and [`@timmo001/docs-kit`](https://github.com/timmo001/docs-kit). From the repo root:

```bash
mise run docs:dev       # dev server
mise run docs:build     # production build, failing on content errors
mise run docs:validate  # check every link and anchor
mise run docs:lint      # lint the Markdown
```

See `docs/AGENTS.md` for authoring conventions.

## Configuration paths

During development, settings and tokens use the same per-user locations as a normal install:

| Platform | Settings / token | Logs |
| --- | --- | --- |
| Linux | `~/.local/share/system-bridge/v5/` | `~/.local/state/system-bridge/YYYY-MM-DD.log` |
| Windows | `%LOCALAPPDATA%\system-bridge\v5\` | `%LOCALAPPDATA%\system-bridge\logs\YYYY-MM-DD.log` |
| macOS | `~/Library/Application Support/system-bridge/v5/` | `~/Library/Logs/system-bridge/YYYY-MM-DD.log` |

The backend port defaults to `9170` and can be overridden with `SYSTEM_BRIDGE_PORT`. Override the settings and log directories with `SYSTEM_BRIDGE_CONFIG_DIR` and `SYSTEM_BRIDGE_LOG_DIR` (both must be absolute paths). See [Running → Configuration](/running/#configuration) for the full list of environment variables.

## Next steps

- Read the [API overview](/api/) and [MCP server](/api/mcp/) docs for integration work.
- Use the [CLI](/using/cli/) reference for token, data, and completion commands.
- Open the [web client](/using/web-client/) against your dev backend once it is running.
