# Contributing (/docs/contributing)



Read this page before you change warden itself: it covers the repo layout, conventions and commands. warden is a Bun + Turborepo monorepo with strict TypeScript, Biome for lint and format, and prek git hooks (biome on commit, typecheck on push).

<Files>
  <Folder name="apps">
    <File name="cli — @delacour/warden, the warden binary (commands, hooks)" />

    <File name="docs — @delacour/warden-docs, this site (Fumadocs + TanStack Start)" />

    <File name="example — @delacour/warden-example, Expo + Delacour UI demo app for warden e2e example" />
  </Folder>

  <Folder name="packages">
    <File name="core — lease store, allocation, device providers, build cache" />

    <File name="e2e — @delacour/warden-e2e, spec runner, iOS/Android driver, warden-simd helper" />

    <File name="e2e-bench — private benchmark of warden against other e2e tools (bun run bench)" />

    <File name="types — Result / AsyncResult" />

    <File name="biome-config, tsconfig — shared config" />
  </Folder>

  <Folder name="skills/warden">
    <File name="SKILL.md — embedded in the binary" />

    <Folder name="references">
      <File name="ui.md, specs.md, suites.md, troubleshooting.md" />
    </Folder>

    <Folder name="rules">
      <File name="warden.md — installed as ~/.claude/rules/warden.md" />
    </Folder>
  </Folder>
</Files>

## Commands [#commands]

`bun install` needs no token. `@delacournz/otel*` (GitHub Packages, see `bunfig.toml`) is an optional dependency of the docs site: without a classic `read:packages` PAT in `NPM_TOKEN` it is skipped with a `401` warning, and the site builds and runs untraced. Export the token only to trace the docs locally; the Railway deploy has its own.

```bash
bun run test        # turbo: every package with tests (incl. cross-process race tests)
bun run typecheck
bun run check       # biome
bun run --cwd apps/docs dev   # this site on :3210 (PORT overrides)
```

## Conventions [#conventions]

* sqlite `BEGIN IMMEDIATE` (`store.transaction`) is the cross-process mutex — no lockfiles.
* Never shut down / erase / install on a device warden didn't create or lease. Foreign devices are read-only.
* Side effects (`exec`, clock, pid liveness, stdin, spawn) are injected; tests use a temp `WARDEN_HOME`.
* Errors are `Result` / `AsyncResult` discriminated unions from `@delacour/warden-types/result`. No `any`, no barrel exports.
* TDD: failing test first, colocated `{name}.test.ts`, `bun test <path>`.

## Pull requests and changesets [#pull-requests-and-changesets]

Open PRs against `develop`; they squash-merge and need the `signoff` status (`bun run signoff`). `main` is a release pointer that only `promote.yml` moves.

A PR that changes what `@delacour/warden` or `@delacour/warden-e2e` ship needs a changeset. Run `bun changeset`, pick `@delacour/warden` only (e2e follows in lock-step), choose patch, minor or major, and write a one-line summary for the changelog. Docs-only and internal-only PRs need none. changeset-bot comments on PRs that lack one. Never edit `version` by hand; see [releasing](/docs/updating#releasing).

## Editing these docs [#editing-these-docs]

Pages are MDX under `apps/docs/content/docs`; sidebar order lives in each folder's `meta.json`. Every page is also served as Markdown at `<url>.md`, and the whole site at `/llms.txt` and `/llms-full.txt`.

The charts on the benchmark comparison page read `apps/docs/content/docs/bench/data/<platform>-<date>.json`. Regenerate one with `bun run bench summary packages/e2e-bench/.bench/<run> --out apps/docs/content/docs/bench/data/<platform>-<date>.json`.
