Contributing
Development Setup
Section titled “Development Setup”Prerequisites
Section titled “Prerequisites”- Nix (with flakes enabled) — recommended
- Or manually: Go 1.26+,
templ,golangci-lint,v4l-utils
Enter Dev Shell
Section titled “Enter Dev Shell”nix developThis provides Go, golangci-lint, templ, and all other tools.
nix build # Production build (preferred)go build -o emeet-pixyd . # Manual build (needs `templ generate` first)# Full test suite with race detector (CI runs this)GOEXPERIMENT=jsonv2 GOWORK=off go test -race -count=1 ./...
# Without race detectorGOEXPERIMENT=jsonv2 GOWORK=off go test ./...
# Single testGOEXPERIMENT=jsonv2 GOWORK=off go test -run TestName ./...GOEXPERIMENT=jsonv2 GOWORK=off golangci-lint run --timeout 2m ./...All golangci-lint v2 linters are enabled. Lint is expected to be clean (0 issues).
Templates
Section titled “Templates”templ generate # Required after editing .templ filesgo generate ./... # AlternativeGenerated _templ.go files are gitignored. CI runs templ generate before lint/test.
Format
Section titled “Format”nix fmt # Alejandra for .nix filesCode Style
Section titled “Code Style”- Standard
testingpackage only (no testify) fmt.Errorf("label: %w", err)for error wrapping- Named constants for all command strings, response strings, and binary names
//nolintdirectives at call sites for intentional suppressions- All source files use
//go:build linux - No
init()functions — metrics registration is lazy viasync.Once
Testing Patterns
Section titled “Testing Patterns”newTestDaemon(t, camera, videoDev, hidrawDev, opts...)is the canonical test builder- Uses
t.TempDir()forStateDirso parallel tests never race on state files t.Parallel()used consistently- Predefined test options:
withInCall(),withAutoOff(),withCameraInUse(), etc. - Fuzz tests:
FuzzExtractJPEGFrame,FuzzParseHIDResponse,FuzzParsePTZValue - Integration tests:
//go:build integrationtag
Pull Request Checklist
Section titled “Pull Request Checklist”-
GOWORK=off go test -race -count=1 ./...passes -
GOWORK=off golangci-lint run --timeout 2m ./...passes with 0 issues -
templ generatehas been run (if templates changed) - No hardcoded strings for command names or binary names
- Tests use
t.Parallel()andt.TempDir()
GitHub Actions runs: go vet, templ generate, golangci-lint run --timeout 2m, govulncheck, go test -race -count=1 -coverprofile=coverage.out, nix flake check, and fuzz targets.
Where to go next
Section titled “Where to go next”- Architecture Overview — understand the codebase before changing it
- HID Protocol — device communication internals
- Call Detection — core automation logic
- CLI Reference — the user-facing surface
- Troubleshooting — common issues to watch for