# Agent Instructions

## Project layout

- `app.py` — FastAPI server (writable)
- `frontend/` — Preact + TypeScript UI built with Vite
- `voice_rtc.py`, `supertonic_gateway.py`, `wisper.py` — read-only; do not modify
- `start.sh` — read-only startup script
- `.env.voice` — local env overrides (writable); sourced before `start.sh` defaults

## Toolchain

All frontend commands run from `frontend/` using `~/.bun/bin/bun`.

| Task | Command |
|---|---|
| Lint + format check | `~/.bun/bin/bun run check` |
| Build | `~/.bun/bin/bun run build` |
| Dead code | `~/.bun/bin/bunx knip` |
| Format a file | `~/.bun/bin/bun run biome format --write <file>` |
| Aggregate frontend checks | `./scripts/check_frontend_quality.sh` |
| Install git hooks | `~/.bun/bin/bun run hooks:install` |

Always run `check` and `build` after making frontend changes. `check` must pass with no Biome warnings or errors before finishing.

## Backend Python Checks

Backend Python checks run from the repo root using `uv`.

| Task | Command |
|---|---|
| Aggregate backend checks | `./scripts/check_python_quality.sh` |
| Format check | `uv run --with "ruff>=0.15.0,<1.0.0" ruff format --check app.py` |
| Lint | `uv run --with "ruff>=0.15.0,<1.0.0" ruff check app.py` |
| Dependency check | `uv run --with "deptry>=0.24.0,<1.0.0" deptry . --requirements-files requirements.txt --known-first-party app,supertonic_gateway,voice_rtc,wisper --per-rule-ignores DEP002=uvicorn --extend-exclude ".*/frontend/.*" --extend-exclude ".*/\\.venv/.*" --extend-exclude ".*/__pycache__/.*"` |
| Dead code | `uv run --with "vulture>=2.15,<3.0.0" vulture app.py --min-confidence 80` |

Always run `./scripts/check_python_quality.sh` after making backend Python changes.

## Git Hooks

- Versioned hooks live in `.githooks/`
- `bun install` in `frontend/` auto-installs them via `postinstall`
- Manual install is `~/.bun/bin/bun run hooks:install` from `frontend/` or `./scripts/install_git_hooks.sh` from the repo root
- The `pre-commit` hook runs `./scripts/check_python_quality.sh` for staged backend changes and `./scripts/check_frontend_quality.sh` for staged frontend changes

## CI

- Forgejo CI lives in `.forgejo/workflows/ci.yml`
- Pushes and pull requests run the same backend and frontend check scripts used locally

## Linting rules

- Linter: Biome (config at `frontend/biome.json`)
- No `biome-ignore` suppressions — fix the code or disable the rule in `biome.json`
- `bun run check` is warning-failing and should block commits on any Biome warning
- All font sizes in CSS must use `rem`, not `px`

## Dead code

Run `~/.bun/bin/bunx knip` from `frontend/` to find unused files, exports, and types. The only expected false positive is `dist/assets/` build output.

## Backend

- Card instances are file-backed in `NANOBOT_WORKSPACE/cards/instances/<card-id>/card.json`
- Card HTML snapshots are stored beside metadata in `NANOBOT_WORKSPACE/cards/instances/<card-id>/render.html`
- Templates live in `NANOBOT_WORKSPACE/cards/templates/<template-key>/template.html` with `manifest.json`
- `GET /cards` returns all non-archived cards ordered by lane, state, priority, then update time
- `DELETE /cards/{id}` removes a card on dismiss
