> ## Documentation Index
> Fetch the complete documentation index at: https://docs.druks.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Develop Druks

> Set up the repository, understand its architecture, change the database, and run verification.

This guide is for changes to Druks itself. The backend and Vite development
server operate on the host. Compose supplies isolated Postgres and Redis.

## Set up

From the repository root:

```bash theme={null}
docker compose -f deploy/compose.dev.yaml up -d
uv sync --locked --dev
cp druks.toml.example druks.toml
cp .env.example .env
python3 -c 'import base64, os; print(base64.b64encode(os.urandom(32)).decode())'
```

Paste the generated value into `secrets.secrets_key` in `druks.toml`, then
initialize the development database:

```bash theme={null}
uv run druks init-db
```

Settings reads `./druks.toml` from the current directory. The example uses
`[identity].mode = "none"`. The loopback dashboard has no authentication and
exactly one operator account. Your first harness connection creates this
account.

To use `header` mode with the development server, set
`identity.mode = "header"` in `druks.toml`. Set `identity.header` in the same
file. Then send the header with a browser add-on or
`curl -H 'X-Edge-Email: you@example.com'`.

The dev Compose project creates two databases:

* **Development:** `druks_dev` for the host-run server.
* **Tests:** `druks_test` for pytest. The suite rebuilds this schema.

`.env.example` points the server at `druks_dev`. The suite reaches
`druks_test` and Redis index 15 through `DRUKS_TEST_DATABASE_URL` and
`DRUKS_TEST_REDIS_URL`. It does not use the server settings. Thus, the two
databases cannot be confused.

Start the backend:

```bash theme={null}
uv run uvicorn druks.api.server:app --host 127.0.0.1 --port 8001
```

In another terminal:

```bash theme={null}
npm --prefix frontend ci
npm --prefix frontend run dev
```

Vite proxies API traffic to the backend. The production backend image instead
contains the built SPA and serves it from FastAPI.

## Architecture map

| Path                                                      | Responsibility                                             |
| --------------------------------------------------------- | ---------------------------------------------------------- |
| `backend/druks/workflows.py`                              | Public workflow, step, gate, scheduling, and start API     |
| `backend/druks/agents.py`                                 | Public agent descriptor and output contract                |
| `backend/druks/durable/`                                  | DBOS integration, run projection, lifecycle internals      |
| `backend/druks/apps/`                                     | Entry-point loading, discovery, author settings            |
| `backend/druks/events/`, `signals.py`                     | Event log, feed, and reactions                             |
| `backend/druks/webhooks/`                                 | Authenticated delivery framework and deduplication         |
| `backend/druks/harnesses/`                                | Claude/Codex invocation, auth, usage, capability manifests |
| `backend/druks/sandbox/`                                  | Drukbox lifecycle, SSH execution, workspace delivery       |
| `backend/druks/api/`                                      | FastAPI composition and platform routes                    |
| `backend/druks/{mcp,skills,notifications,user_settings}/` | Shared operator services                                   |
| `backend/druks/contrib/software_factory/`                 | Bundled reference app, not framework core                  |
| `frontend/src/`                                           | Shared dashboard shell and bundled app UI                  |
| `backend/migrations/`                                     | Core/bundled schema history                                |
| `deploy/`, `scripts/`                                     | Images, Compose, Caddy, setup, and deployment              |

The API process embeds DBOS and executes workflows. App modules register
capabilities during boot, after DBOS initialization and before launch.

## App test surface

The main package registers bundled apps through `pyproject.toml`. CI also
installs `backend/tests/druks-field_notes` as a real editable distribution and
runs the proof-app tests. Those tests are the executable contract for:

* Headless and boot-time entry-point loading
* Role-module discovery
* Route and subject read-side mounting
* Independent migrations and table-prefix enforcement
* Workflow start, settings, and feed formatting.

If you change the author API, update the scaffold, proof app, author guide, and
tests together.

## Database changes

Core and bundled historical tables use the core Alembic history:

```bash theme={null}
uv run alembic -c backend/alembic.ini revision --autogenerate -m "describe change"
uv run druks init-db
```

For an independently packaged app:

```bash theme={null}
uv run druks makemigrations <app-name> -m "describe change"
uv run druks init-db
```

The app owns its migration directory and version table. Review every
autogenerated revision before applying it.

## Verification

Backend checks:

```bash theme={null}
uv pip install -e backend/tests/druks-field_notes   # once per environment
uv run ruff check backend
uv run ruff format --check backend
uv run pytest backend/
```

The suite builds its subjects from `field_notes`, the proof app. This standalone
distribution depends on Druks. It installs like an author app, not as a Druks
dependency. Install it one time for the full suite.

The pull-request backend
workflow does the same. Pyright is available for local and editor use. It is not
a CI gate.

Frontend checks:

```bash theme={null}
npm --prefix frontend run lint
npm --prefix frontend test
npm --prefix frontend run build
```

The frontend CI workflow runs those three commands on Node 22.

For documentation-only changes, also run these commands:

```bash theme={null}
git diff --check
cd docs
mint validate
mint broken-links --check-anchors --check-redirects
```

Mintlify builds `docs/` directly. Its GitHub App owns deployments and
pull-request previews. The repository does not require a documentation-specific
GitHub Actions workflow.

## Working with sandboxes

Backend tests mock most provider boundaries. For a real local sandbox, run
Drukbox on the host from its own checkout
(`DOCKER_SSH_USERNAME=druks make dev` in
[czpython/drukbox](https://github.com/czpython/drukbox)) and set:

```toml theme={null}
[sandbox]
service_url = "http://127.0.0.1:8000"
service_token = "dev-token"
image = "ghcr.io/czpython/druks/sandbox:latest"
```

`uv run druks doctor --sandbox` creates a real host. If you require a real
sandbox test, run this command. It is not part of the normal test suite.

## Frontend ownership

Backend app entry points and shared-shell React routes have different
delivery mechanisms. Python discovery can load an installed app at
runtime. An app can ship a standalone static frontend in its package's
`dist/`, served at `/app/<name>`. React code that joins the bundled dashboard
shell must already be in the SPA and register through
`frontend/src/apps/index.ts`. A wheel cannot put routes into that
existing JavaScript bundle.

See the [frontend guide](https://github.com/czpython/druks/blob/main/frontend/README.md)
before adding dashboard pages.
