Files
usb-camera-webui/AGENTS.md
T

92 lines
4.5 KiB
Markdown
Raw Normal View History

# Working in this repo
Project instructions for Codex on `pi5`. The client-wide prompt lives in `~/.codex/AGENTS.md`; this
file is the project-specific part.
## Where you are
**You are on the target hardware.** `pi5` is the Raspberry Pi 5 this runs on, with the webcam
physically attached. You can test everything for real — there is no deploy step and no emulation.
Use that: prefer running the thing over reasoning about whether it would run.
`platform_info` confirms which machine you are on if you need it.
**Do not copy code or assumptions from the sibling `camera-webui` repo.** That one targets a Jetson
Orin Nano with a CSI IMX219 and uses a different capture stack entirely. Here it is plain **V4L2 /
UVC** — no libcamera, no `picamera2`, no Argus, no device-tree overlays.
## The camera
**Logitech C505 HD Webcam at `/dev/video0`**, offering `MJPG` and `YUYV`. A 1280x720 MJPG capture is
verified working.
**Never select a video node by index.** This board exposes `/dev/video19``/dev/video35` for its
ISP and codec blocks with no camera involved, and `/dev/video1` is the webcam's *metadata* interface,
not a capture device. Resolve the device with `v4l2-ctl --list-devices`, or by matching the USB ID
`046d:08e3` — never by assuming `video0` is stable across reboots or a second camera being plugged in.
**Prefer `MJPG` for streaming.** The camera compresses in hardware; `YUYV` is uncompressed and makes
the Pi's CPU do encoding work that is already done for you.
## ⚠ Writing files, and not looping
**Write files with `apply_patch`**, or a heredoc through the shell. **Never** use `write_stdin` to
create file contents — it writes to the stdin of an already-running process and will not create
anything. `write_stdin` takes a session id that an actual `exec_command` returned; never invent one
and never increment one.
**If the same tool call fails twice with the same error, STOP and report it.** Do not retry, and do
not vary an identifier hoping one works. A repeated identical failure means the assumption is wrong,
not that the call needs another attempt.
This is from life, in the sibling repo: an agent tried to write a file with `write_stdin`, was told
`Unknown process id 45`, and answered by incrementing the id — 46, 47, 48 — for **27 attempts over
nine minutes** until a human killed it.
**Emit tool calls as the API's JSON arguments only.** Markup like `<parameter=...>` inside a string
argument means you are mixing in a different tool-calling format, and the call will not do what you
mean.
## ⚠ Read the working tree with the shell, not over MCP
The `gitea__*` tools read the **Gitea server's** copy of a repo over its API. They do not see this
machine's files. Anything uncommitted or unpushed is invisible to them, so a file fetched that way
can be silently stale.
**Use the shell for files in front of you.** Use the MCP tools only for repo state you have not
cloned — history, issues, another repository.
## Constraints
- **Power is tight.** The Pi is on a 3 A supply with a restricted USB budget
(`usb_max_current_enable=0`). The webcam fits; a second USB device may not. Do not add powered
peripherals, and do not assume headroom.
- **Install from system packages where possible** (`apt`), not pip, for anything binding to system
libraries. Keep dependencies few — they all have to build on aarch64.
- **Do not commit captured images or video.** Frames of a real room are not test fixtures. Generate a
synthetic one if a fixture is genuinely needed.
- This is a **4-core Pi 5 with no GPU acceleration for inference.** Anything per-frame must be cheap,
and must run off the capture thread.
## Verifying your work
Claims about the camera or the stream need a command that ran:
```bash
v4l2-ctl --list-devices # which node is really the webcam
v4l2-ctl -d /dev/video0 --list-formats # what it can actually produce
curl -sI http://localhost:<port>/ # is the server responding
```
**The absence of an error is not evidence that something works.** A stream endpoint returning 200
with no frames is indistinguishable from a working one unless you look at what came back. A capture
that writes a file proves nothing until the file is checked — `file frame.jpg` must say
`JPEG image data`, not merely exist with a non-zero size.
## Git
The remote is Gitea at `192.168.2.199:3005`, over SSH on port 2222.
**`tea` (the Gitea CLI) is denied by policy.** Ordinary `git` is fine. **Do not push** unless the
operator asks — commit locally and say what is ready.