{"owner":"ZoneMinder","repo":"zoneminder","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AI Agent Development Guide for ZoneMinder\n\n> **Note**: This file guides AI coding agents (Claude Code, GitHub Copilot, Cursor, etc.) working on ZoneMinder.\n> CLAUDE.md is a symlink to this file.\n\n## Quick Reference (MANDATORY RULES)\n\n1. **Testing First**: Write tests BEFORE/DURING implementation - NEVER skip. Tests written \"later\" never get written.\n2. **Build System**: CMake with C++17, out-of-source builds in `build/`. In-source builds pollute the repo.\n3. **Feature Workflow**: GitHub Issue -> Feature Branch -> Implement FULLY -> Tests Pass -> Get Approval -> Merge to master. Feature branches keep master stable.\n4. **Commits**: Conventional format (`feat:`/`fix:`/`test:`), reference issues (`refs #n` or `fixes #n`). Enables automated changelog.\n5. **Pre-Commit**: Tests pass, build succeeds, linting clean, no warnings.\n6. **Never merge without user approval. Never leave features half-implemented.**\n\n---\n\n## What is ZoneMinder?\n\nLinux-based CCTV surveillance system: capture, analysis, recording, and monitoring of video cameras.\n\n- **C++ daemons** (`src/`) - Capture (`zmc`), analysis (`zma`), streaming (`zms`), utility (`zmu`)\n- **PHP web interface** (`web/`) - Bootstrap + jQuery UI, AJAX endpoints in `web/ajax/`, views in `web/views/`\n- **REST API** (`web/api/`) - CakePHP 2.x, controllers in `web/api/app/Controller/`, JWT auth\n- **Perl scripts** (`scripts/`) - Daemon control (`zmdc.pl`), migrations (`zmupdate.pl`), filtering (`zmfilter.pl`)\n- **MySQL database** (`db/`) - Schema in `db/zm_create.sql.in`, migrations in `db/zm_update-*.sql` (60+ versions)\n\n---\n\n## Architecture\n\n### Data Flow\n\n```\nCamera -> zmc (capture) -> Shared Memory -> zma (analysis) -> Event Recording\n                              |                                    |\n                           zms (streaming)                   Database + Disk\n                              |                                    |\n                        Web Browsers <- Web Interface/API <- MySQL Storage\n```\n\n### Key Patterns\n\n- **Shared Memory**: `zmc` writes frames to `/dev/shm`; `zma` and `zms` read from same buffers. Zero-copy for performance — this is why ZM can handle many cameras on modest hardware.\n- **Monitor-Centric**: `Monitor` class (`src/zm_monitor.cpp/h`) is the central orchestrator. One monitor = one DB row = one set of daemons. Most changes to camera handling flow through this class.\n- **Pluggable Cameras**: Abstract `Camera` base with: `LocalCamera` (V4L2), `RemoteCameraRTSP`, `RemoteCameraHTTP`, `FFmpegCamera`, `LibVLCCamera`, `LibVNCCamera`. Add new camera types by subclassing Camera.\n- **Event-Driven Recording**: Motion detection triggers `Event` objects with pre/post alarm buffers. Lifecycle: Create -> Record -> Close -> Archive/Delete. Events are the core unit of recorded footage.\n- **Multi-Server Clustering**: Database-coordinated distributed architecture with shared monitors and storage.\n\n### Directory Structure (Key Paths)\n\n```\nsrc/                      C++ core (86+ source files): zm_monitor.*, zm_camera.*, zm_event.*, zm_zone.*, zm_image.*, zm_ffmpeg*.*\nweb/                      PHP web interface\n  ajax/                   AJAX handlers\n  includes/               PHP libraries and functions\n  views/                  UI templates\n  skins/                  Themes (classic skin)\n  js/, css/               Frontend assets\n  api/app/Controller/     CakePHP REST API controllers\n  api/app/Model/          CakePHP REST API models\nscripts/                  Perl system management (.in templates)\ndb/                       Schema (zm_create.sql.in) and migrations (zm_update-*.sql)\ntests/                    Catch2 unit tests + test data\nmisc/                     Server configs (apache, nginx, systemd)\ndep/                      Vendored deps (catch2, jwt-cpp)\n.github/workflows/        CI/CD pipelines\n```\n\n---\n\n## Development Workflow (MANDATORY)\n\n### For every feature or bug fix:\n\n1. **Create GitHub Issue**: `gh issue create --title \"...\" --label enhancement|bug`\n2. **Create Feature Branch**: `git checkout -b <issue>-<description>` from master\n3. **Write failing test first** (TDD)\n4. **Implement** - follow existing patterns, keep changes minimal\n5. **Build & test** - must all pass (see Build and Testing sections)\n6. **Commit** in logical chunks with conventional messages\n7. **Request user approval** - never merge without it\n8. **After approval**: merge to master, delete branch, push, verify issue closes\n\n### Technology-Specific Notes\n\n- **C++ changes** (`src/`): Rebuild required, run ctest. Daemons must be restarted to pick up changes.\n- **PHP/JS changes** (`web/`): No rebuild needed — PHP is interpreted, changes are live immediately. Test in browser + ESLint.\n- **Database schema** (`db/`): Create migration file `zm_update-X.X.X.sql` for existing installs, also update `db/zm_create.sql.in` for fresh installs. Both must result in the same schema.\n- **Perl scripts** (`scripts/`): Edit `.in` template files (NOT generated scripts). cmake substitutes `@ZM_*@` variables to produce the final scripts. When testing perl changes, any perl script will try to read /etc/zm/zm.conf and needs to be run as a user with permission to read it. Best to run with sudo -u www-data\n- **API changes** (`web/api/`): Clear CakePHP cache (`tmp/cache/`) if you change models or routes. Test endpoints with curl.\n\n### Example Workflow\n\n```bash\ngh issue create --title \"Add event favorites\" --label enhancement\n# Note issue number, e.g. #42\ngit checkout master && git pull && git checkout -b 42-event-favorites\n\n# Write test first, implement, build & test\ncd build && cmake --build . && ctest\nnpx eslint .\n\n# Commit\ngit add <files>\ngit commit -m \"feat: add favorites toggle to event view refs #42\"\n\n# Ask user for approval, then after approval:\ngit checkout master && git merge 42-event-favorites\ngit push origin master\ngit branch -d 42-event-favorites && git push origin --delete 42-event-favorites\n```\n\n---\n\n## Build System\n\n```bash\n# Standard build (out-of-source required)\nmkdir build && cd build\ncmake ..\ncmake --build .\n\n# Debug build with tests\ncmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TEST_SUITE=ON ..\ncmake --build .\n\n# Build specific target\ncmake --build . --target zmc\n```\n\n### Key CMake Options\n\n| Option | Values | Default | Notes |\n|--------|--------|---------|-------|\n| `CMAKE_BUILD_TYPE` | Release/Debug/Optimised/Profile | Release | `Profile` = `-O2 -g -fno-omit-frame-pointer` for perf/flamegraph |\n| `BUILD_TEST_SUITE` | ON/OFF | OFF | Enables Catch2 tests |\n| `ENABLE_WERROR` | ON/OFF | OFF | Warnings as errors (CI uses ON) |\n| `ASAN` | ON/OFF | OFF | AddressSanitizer |\n| `TSAN` | ON/OFF | OFF | ThreadSanitizer (mutually exclusive with ASAN) |\n| `ZM_CRYPTO_BACKEND` | openssl/gnutls | | |\n| `ZM_JWT_BACKEND` | libjwt/jwt_cpp | | |\n| `ZM_TARGET_DISTRO` | FreeBSD/fc/el/OS13 | (Debian) | Platform-specific paths |\n| `ZM_ONVIF` | ON/OFF | ON | ONVIF camera support |\n\n---\n\n## Testing Requirements (MANDATORY)\n\n### Workflow\n\n1. Write a failing test that reproduces the issue or validates the feature\n2. Implement the fix/feature\n3. Run tests - verify they PASS\n4. Run full test suite for regressions\n5. Only then commit\n\n### C++ Unit Tests (Catch2)\n\n```bash\n# Build with tests\ncmake -DBUILD_TEST_SUITE=ON .. && cmake --build .\n\n# Run all tests\nctest\n# Or directly with more output\n./tests/tests\n\n# Run specific test / list tests\n./tests/tests \"[Box]\"\n./tests/tests --list-tests\n./tests/tests \"~[notCI]\"\n```\n\n**Test location**: `tests/` directory\n**Existing modules**: `zm_box.cpp`, `zm_comms.cpp`, `zm_crypt.cpp`, `zm_font.cpp`, `zm_poly.cpp`, `zm_utils.cpp`, `zm_vector2.cpp`\n**Framework**: Catch2 with custom header `tests/zm_catch2.h`, main in `tests/main.cpp`\n**Test data**: `tests/data/fonts/`\n\n### JavaScript Linting\n\n```bash\nnpx eslint .        # Lint all\nnpx eslint --fix web/js/              # Auto-fix\n```\n\nESLint config: `eslint.config.js` (ESLint 9 flat config, Google style guide). Runs in CI via `.github/workflows/ci-eslint.yml`.\n\n### PHP/API Testing\n\nManual testing required. Test endpoints with curl/browser. Verify JSON responses, auth (session + JWT), error handling, DB persistence.\n\n### Database Migration Testing\n\n```bash\nsudo zmupdate.pl --check              # Check for updates\nsudo zmupdate.pl                      # Apply migrations\n```\n\nWhen creating migrations: test upgrade path AND verify fresh install matches migrated schema.\n\n### CI Notes\n\n- Unit tests are **DISABLED** in CI (`BUILD_TEST_SUITE=0`) — some tests need hardware/network access. Running locally goes beyond CI requirements but is still expected for local development.\n- CI does: multi-platform builds (Debian/Ubuntu/CentOS with GnuTLS/OpenSSL + libjwt/jwt_cpp matrix), ESLint, CodeQL security scanning\n\n---\n\n## Code Standards\n\n### C++ (`src/`)\n\n- **C++17** standard, follow existing patterns in file/module\n- **Memory**: RAII, smart pointers where appropriate\n- **Error handling**: Exceptions for exceptional cases, return codes for expected errors\n- **Logging**: Use printf-style `Debug(1, \"msg %s\", val)`, `Info(...)`, `Warning(...)`, `Error(...)`, `Fatal(...)` — NOT iostream style. The number in Debug() is verbosity level (1-9).\n\n### PHP (`web/`, `web/api/`)\n\n- PSR-12 where practical, follow existing conventions\n- **Security**: Validate ALL user input, use prepared statements (NOT string interpolation — legacy code has SQL injection bugs we're fixing), sanitize output with htmlspecialchars/json_encode, CSRF protection on forms\n- CakePHP 2.x framework in `web/api/` — we're stuck on 2.x due to migration cost, don't try to upgrade it\n\n### JavaScript (`web/js/`, inline in PHP)\n\n- Google JavaScript Style Guide (ESLint configured)\n- jQuery + Bootstrap (legacy codebase), ES6+ where browser support allows\n\n### Perl (`scripts/`)\n\n- Edit `.in` template files, NOT generated scripts — cmake substitutes variables like `@ZM_LOGDIR@` to produce the final scripts\n- Use `ZoneMinder::` modules, `ZoneMinder::Logger` for logging\n- Rerun cmake after editing `.in` files to regenerate the actual scripts\n\n---\n\n## Commit Standards\n\n**Conventional format** with issue references:\n\n```\nfeat|fix|test|docs|chore|refactor|perf|style: description refs #N\n```\n\n- `refs #N` references issue; `fixes #N` closes it\n- Imperative mood (\"add feature\" not \"added feature\")\n- Be detailed and descriptive, no vague summaries\n- One logical change per commit\n- **No superlative language** (\"comprehensive\", \"critical\", \"major\", \"massive\") — AI agents tend to use these; they make commit logs unreadable\n- Split unrelated changes into separate commits — makes bisecting and reverting possible\n\n---\n\n## Pre-Commit Checklist (Single Source of Truth)\n\nBefore committing or claiming complete:\n\n- [ ] Tests written/updated BEFORE or DURING implementation\n- [ ] Build succeeds: `cmake --build .` (C++ changes)\n- [ ] C++ tests pass: `ctest` or `./tests/tests`\n- [ ] JavaScript linting passes: `npx eslint .`\n- [ ] Manual testing done (PHP/web changes)\n- [ ] No compiler warnings or linter errors\n- [ ] Code follows existing patterns\n- [ ] Commit messages follow conventional format with issue reference\n- [ ] Feature is COMPLETE (not half-implemented)\n- [ ] State which tests were run and their results\n\n**NEVER commit if**: tests failing, tests missing for new code, build fails, warnings exist, feature incomplete.\n\n---\n\n## Debugging Quick Reference\n\n```bash\n# Debug build\ncmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .\n\n# AddressSanitizer\ncmake -DCMAKE_BUILD_TYPE=Debug -DASAN=ON .. && cmake --build .\n\n# Debug logging\nexport ZM_DBG_LEVEL=9 ZM_DBG_LOG=/tmp/debug.log\n./src/zmc -m 1\n\n# Log locations: /var/log/zm/ (zmc_m1.log, zma_m2.log, etc.)\n# Runtime log level: kill -USR1 <pid> (increase) / kill -USR2 <pid> (decrease)\n```\n\n---\n\n## Contributing (For Humans)\n\n- **Bug reports & features**: [GitHub Issues](https://github.com/ZoneMinder/zoneminder/issues) (read [posting rules](https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules) first)\n- **Support**: [Forums](https://forums.zoneminder.com), [Slack](https://zoneminder-chat.slack.com), [Discord](https://discord.gg/tHYyP9k66q)\n- **PRs**: Fork -> feature branch -> implement + test -> PR. Maintainers merge after review.\n- **Docs**: https://zoneminder.readthedocs.org (source in `docs/`)\n\n---\n\n## grepai - Semantic Code Search\n\n**Use grepai as PRIMARY tool for code exploration and search.**\n\n### When to Use grepai (REQUIRED)\n\nUse `grepai search` INSTEAD OF Grep/Glob for:\n- Understanding what code does or where functionality lives\n- Finding implementations by intent (\"authentication logic\", \"error handling\")\n- Exploring unfamiliar parts of the codebase\n\nOnly use Grep/Glob for exact text matching (variable names, imports, specific strings) or file path patterns.\n\nIf grepai fails (not running, index unavailable), fall back to Grep/Glob.\n\n### Usage\n\n```bash\ngrepai search \"user authentication flow\" --json --compact\ngrepai search \"JWT token validation\" --json --compact\n```\n\n### Call Graph Tracing\n\n```bash\ngrepai trace callers \"HandleRequest\" --json\ngrepai trace callees \"ProcessOrder\" --json\ngrepai trace graph \"ValidateToken\" --depth 3 --json\n```\n\n### Workflow\n\n1. `grepai search` to find relevant code\n2. `grepai trace` to understand function relationships\n3. `Read` tool to examine files from results\n4. Grep only for exact string searches if needed\n"},"files":{"AGENTS.md":"# AI Agent Development Guide for ZoneMinder\n\n> **Note**: This file guides AI coding agents (Claude Code, GitHub Copilot, Cursor, etc.) working on ZoneMinder.\n> CLAUDE.md is a symlink to this file.\n\n## Quick Reference (MANDATORY RULES)\n\n1. **Testing First**: Write tests BEFORE/DURING implementation - NEVER skip. Tests written \"later\" never get written.\n2. **Build System**: CMake with C++17, out-of-source builds in `build/`. In-source builds pollute the repo.\n3. **Feature Workflow**: GitHub Issue -> Feature Branch -> Implement FULLY -> Tests Pass -> Get Approval -> Merge to master. Feature branches keep master stable.\n4. **Commits**: Conventional format (`feat:`/`fix:`/`test:`), reference issues (`refs #n` or `fixes #n`). Enables automated changelog.\n5. **Pre-Commit**: Tests pass, build succeeds, linting clean, no warnings.\n6. **Never merge without user approval. Never leave features half-implemented.**\n\n---\n\n## What is ZoneMinder?\n\nLinux-based CCTV surveillance system: capture, analysis, recording, and monitoring of video cameras.\n\n- **C++ daemons** (`src/`) - Capture (`zmc`), analysis (`zma`), streaming (`zms`), utility (`zmu`)\n- **PHP web interface** (`web/`) - Bootstrap + jQuery UI, AJAX endpoints in `web/ajax/`, views in `web/views/`\n- **REST API** (`web/api/`) - CakePHP 2.x, controllers in `web/api/app/Controller/`, JWT auth\n- **Perl scripts** (`scripts/`) - Daemon control (`zmdc.pl`), migrations (`zmupdate.pl`), filtering (`zmfilter.pl`)\n- **MySQL database** (`db/`) - Schema in `db/zm_create.sql.in`, migrations in `db/zm_update-*.sql` (60+ versions)\n\n---\n\n## Architecture\n\n### Data Flow\n\n```\nCamera -> zmc (capture) -> Shared Memory -> zma (analysis) -> Event Recording\n                              |                                    |\n                           zms (streaming)                   Database + Disk\n                              |                                    |\n                        Web Browsers <- Web Interface/API <- MySQL Storage\n```\n\n### Key Patterns\n\n- **Shared Memory**: `zmc` writes frames to `/dev/shm`; `zma` and `zms` read from same buffers. Zero-copy for performance — this is why ZM can handle many cameras on modest hardware.\n- **Monitor-Centric**: `Monitor` class (`src/zm_monitor.cpp/h`) is the central orchestrator. One monitor = one DB row = one set of daemons. Most changes to camera handling flow through this class.\n- **Pluggable Cameras**: Abstract `Camera` base with: `LocalCamera` (V4L2), `RemoteCameraRTSP`, `RemoteCameraHTTP`, `FFmpegCamera`, `LibVLCCamera`, `LibVNCCamera`. Add new camera types by subclassing Camera.\n- **Event-Driven Recording**: Motion detection triggers `Event` objects with pre/post alarm buffers. Lifecycle: Create -> Record -> Close -> Archive/Delete. Events are the core unit of recorded footage.\n- **Multi-Server Clustering**: Database-coordinated distributed architecture with shared monitors and storage.\n\n### Directory Structure (Key Paths)\n\n```\nsrc/                      C++ core (86+ source files): zm_monitor.*, zm_camera.*, zm_event.*, zm_zone.*, zm_image.*, zm_ffmpeg*.*\nweb/                      PHP web interface\n  ajax/                   AJAX handlers\n  includes/               PHP libraries and functions\n  views/                  UI templates\n  skins/                  Themes (classic skin)\n  js/, css/               Frontend assets\n  api/app/Controller/     CakePHP REST API controllers\n  api/app/Model/          CakePHP REST API models\nscripts/                  Perl system management (.in templates)\ndb/                       Schema (zm_create.sql.in) and migrations (zm_update-*.sql)\ntests/                    Catch2 unit tests + test data\nmisc/                     Server configs (apache, nginx, systemd)\ndep/                      Vendored deps (catch2, jwt-cpp)\n.github/workflows/        CI/CD pipelines\n```\n\n---\n\n## Development Workflow (MANDATORY)\n\n### For every feature or bug fix:\n\n1. **Create GitHub Issue**: `gh issue create --title \"...\" --label enhancement|bug`\n2. **Create Feature Branch**: `git checkout -b <issue>-<description>` from master\n3. **Write failing test first** (TDD)\n4. **Implement** - follow existing patterns, keep changes minimal\n5. **Build & test** - must all pass (see Build and Testing sections)\n6. **Commit** in logical chunks with conventional messages\n7. **Request user approval** - never merge without it\n8. **After approval**: merge to master, delete branch, push, verify issue closes\n\n### Technology-Specific Notes\n\n- **C++ changes** (`src/`): Rebuild required, run ctest. Daemons must be restarted to pick up changes.\n- **PHP/JS changes** (`web/`): No rebuild needed — PHP is interpreted, changes are live immediately. Test in browser + ESLint.\n- **Database schema** (`db/`): Create migration file `zm_update-X.X.X.sql` for existing installs, also update `db/zm_create.sql.in` for fresh installs. Both must result in the same schema.\n- **Perl scripts** (`scripts/`): Edit `.in` template files (NOT generated scripts). cmake substitutes `@ZM_*@` variables to produce the final scripts. When testing perl changes, any perl script will try to read /etc/zm/zm.conf and needs to be run as a user with permission to read it. Best to run with sudo -u www-data\n- **API changes** (`web/api/`): Clear CakePHP cache (`tmp/cache/`) if you change models or routes. Test endpoints with curl.\n\n### Example Workflow\n\n```bash\ngh issue create --title \"Add event favorites\" --label enhancement\n# Note issue number, e.g. #42\ngit checkout master && git pull && git checkout -b 42-event-favorites\n\n# Write test first, implement, build & test\ncd build && cmake --build . && ctest\nnpx eslint .\n\n# Commit\ngit add <files>\ngit commit -m \"feat: add favorites toggle to event view refs #42\"\n\n# Ask user for approval, then after approval:\ngit checkout master && git merge 42-event-favorites\ngit push origin master\ngit branch -d 42-event-favorites && git push origin --delete 42-event-favorites\n```\n\n---\n\n## Build System\n\n```bash\n# Standard build (out-of-source required)\nmkdir build && cd build\ncmake ..\ncmake --build .\n\n# Debug build with tests\ncmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TEST_SUITE=ON ..\ncmake --build .\n\n# Build specific target\ncmake --build . --target zmc\n```\n\n### Key CMake Options\n\n| Option | Values | Default | Notes |\n|--------|--------|---------|-------|\n| `CMAKE_BUILD_TYPE` | Release/Debug/Optimised/Profile | Release | `Profile` = `-O2 -g -fno-omit-frame-pointer` for perf/flamegraph |\n| `BUILD_TEST_SUITE` | ON/OFF | OFF | Enables Catch2 tests |\n| `ENABLE_WERROR` | ON/OFF | OFF | Warnings as errors (CI uses ON) |\n| `ASAN` | ON/OFF | OFF | AddressSanitizer |\n| `TSAN` | ON/OFF | OFF | ThreadSanitizer (mutually exclusive with ASAN) |\n| `ZM_CRYPTO_BACKEND` | openssl/gnutls | | |\n| `ZM_JWT_BACKEND` | libjwt/jwt_cpp | | |\n| `ZM_TARGET_DISTRO` | FreeBSD/fc/el/OS13 | (Debian) | Platform-specific paths |\n| `ZM_ONVIF` | ON/OFF | ON | ONVIF camera support |\n\n---\n\n## Testing Requirements (MANDATORY)\n\n### Workflow\n\n1. Write a failing test that reproduces the issue or validates the feature\n2. Implement the fix/feature\n3. Run tests - verify they PASS\n4. Run full test suite for regressions\n5. Only then commit\n\n### C++ Unit Tests (Catch2)\n\n```bash\n# Build with tests\ncmake -DBUILD_TEST_SUITE=ON .. && cmake --build .\n\n# Run all tests\nctest\n# Or directly with more output\n./tests/tests\n\n# Run specific test / list tests\n./tests/tests \"[Box]\"\n./tests/tests --list-tests\n./tests/tests \"~[notCI]\"\n```\n\n**Test location**: `tests/` directory\n**Existing modules**: `zm_box.cpp`, `zm_comms.cpp`, `zm_crypt.cpp`, `zm_font.cpp`, `zm_poly.cpp`, `zm_utils.cpp`, `zm_vector2.cpp`\n**Framework**: Catch2 with custom header `tests/zm_catch2.h`, main in `tests/main.cpp`\n**Test data**: `tests/data/fonts/`\n\n### JavaScript Linting\n\n```bash\nnpx eslint .        # Lint all\nnpx eslint --fix web/js/              # Auto-fix\n```\n\nESLint config: `eslint.config.js` (ESLint 9 flat config, Google style guide). Runs in CI via `.github/workflows/ci-eslint.yml`.\n\n### PHP/API Testing\n\nManual testing required. Test endpoints with curl/browser. Verify JSON responses, auth (session + JWT), error handling, DB persistence.\n\n### Database Migration Testing\n\n```bash\nsudo zmupdate.pl --check              # Check for updates\nsudo zmupdate.pl                      # Apply migrations\n```\n\nWhen creating migrations: test upgrade path AND verify fresh install matches migrated schema.\n\n### CI Notes\n\n- Unit tests are **DISABLED** in CI (`BUILD_TEST_SUITE=0`) — some tests need hardware/network access. Running locally goes beyond CI requirements but is still expected for local development.\n- CI does: multi-platform builds (Debian/Ubuntu/CentOS with GnuTLS/OpenSSL + libjwt/jwt_cpp matrix), ESLint, CodeQL security scanning\n\n---\n\n## Code Standards\n\n### C++ (`src/`)\n\n- **C++17** standard, follow existing patterns in file/module\n- **Memory**: RAII, smart pointers where appropriate\n- **Error handling**: Exceptions for exceptional cases, return codes for expected errors\n- **Logging**: Use printf-style `Debug(1, \"msg %s\", val)`, `Info(...)`, `Warning(...)`, `Error(...)`, `Fatal(...)` — NOT iostream style. The number in Debug() is verbosity level (1-9).\n\n### PHP (`web/`, `web/api/`)\n\n- PSR-12 where practical, follow existing conventions\n- **Security**: Validate ALL user input, use prepared statements (NOT string interpolation — legacy code has SQL injection bugs we're fixing), sanitize output with htmlspecialchars/json_encode, CSRF protection on forms\n- CakePHP 2.x framework in `web/api/` — we're stuck on 2.x due to migration cost, don't try to upgrade it\n\n### JavaScript (`web/js/`, inline in PHP)\n\n- Google JavaScript Style Guide (ESLint configured)\n- jQuery + Bootstrap (legacy codebase), ES6+ where browser support allows\n\n### Perl (`scripts/`)\n\n- Edit `.in` template files, NOT generated scripts — cmake substitutes variables like `@ZM_LOGDIR@` to produce the final scripts\n- Use `ZoneMinder::` modules, `ZoneMinder::Logger` for logging\n- Rerun cmake after editing `.in` files to regenerate the actual scripts\n\n---\n\n## Commit Standards\n\n**Conventional format** with issue references:\n\n```\nfeat|fix|test|docs|chore|refactor|perf|style: description refs #N\n```\n\n- `refs #N` references issue; `fixes #N` closes it\n- Imperative mood (\"add feature\" not \"added feature\")\n- Be detailed and descriptive, no vague summaries\n- One logical change per commit\n- **No superlative language** (\"comprehensive\", \"critical\", \"major\", \"massive\") — AI agents tend to use these; they make commit logs unreadable\n- Split unrelated changes into separate commits — makes bisecting and reverting possible\n\n---\n\n## Pre-Commit Checklist (Single Source of Truth)\n\nBefore committing or claiming complete:\n\n- [ ] Tests written/updated BEFORE or DURING implementation\n- [ ] Build succeeds: `cmake --build .` (C++ changes)\n- [ ] C++ tests pass: `ctest` or `./tests/tests`\n- [ ] JavaScript linting passes: `npx eslint .`\n- [ ] Manual testing done (PHP/web changes)\n- [ ] No compiler warnings or linter errors\n- [ ] Code follows existing patterns\n- [ ] Commit messages follow conventional format with issue reference\n- [ ] Feature is COMPLETE (not half-implemented)\n- [ ] State which tests were run and their results\n\n**NEVER commit if**: tests failing, tests missing for new code, build fails, warnings exist, feature incomplete.\n\n---\n\n## Debugging Quick Reference\n\n```bash\n# Debug build\ncmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .\n\n# AddressSanitizer\ncmake -DCMAKE_BUILD_TYPE=Debug -DASAN=ON .. && cmake --build .\n\n# Debug logging\nexport ZM_DBG_LEVEL=9 ZM_DBG_LOG=/tmp/debug.log\n./src/zmc -m 1\n\n# Log locations: /var/log/zm/ (zmc_m1.log, zma_m2.log, etc.)\n# Runtime log level: kill -USR1 <pid> (increase) / kill -USR2 <pid> (decrease)\n```\n\n---\n\n## Contributing (For Humans)\n\n- **Bug reports & features**: [GitHub Issues](https://github.com/ZoneMinder/zoneminder/issues) (read [posting rules](https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules) first)\n- **Support**: [Forums](https://forums.zoneminder.com), [Slack](https://zoneminder-chat.slack.com), [Discord](https://discord.gg/tHYyP9k66q)\n- **PRs**: Fork -> feature branch -> implement + test -> PR. Maintainers merge after review.\n- **Docs**: https://zoneminder.readthedocs.org (source in `docs/`)\n\n---\n\n## grepai - Semantic Code Search\n\n**Use grepai as PRIMARY tool for code exploration and search.**\n\n### When to Use grepai (REQUIRED)\n\nUse `grepai search` INSTEAD OF Grep/Glob for:\n- Understanding what code does or where functionality lives\n- Finding implementations by intent (\"authentication logic\", \"error handling\")\n- Exploring unfamiliar parts of the codebase\n\nOnly use Grep/Glob for exact text matching (variable names, imports, specific strings) or file path patterns.\n\nIf grepai fails (not running, index unavailable), fall back to Grep/Glob.\n\n### Usage\n\n```bash\ngrepai search \"user authentication flow\" --json --compact\ngrepai search \"JWT token validation\" --json --compact\n```\n\n### Call Graph Tracing\n\n```bash\ngrepai trace callers \"HandleRequest\" --json\ngrepai trace callees \"ProcessOrder\" --json\ngrepai trace graph \"ValidateToken\" --depth 3 --json\n```\n\n### Workflow\n\n1. `grepai search` to find relevant code\n2. `grepai trace` to understand function relationships\n3. `Read` tool to examine files from results\n4. Grep only for exact string searches if needed\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AI Agent Development Guide for ZoneMinder\n\n> **Note**: This file guides AI coding agents (Claude Code, GitHub Copilot, Cursor, etc.) working on ZoneMinder.\n> CLAUDE.md is a symlink to this file.\n\n## Quick Reference (MANDATORY RULES)\n\n1. **Testing First**: Write tests BEFORE/DURING implementation - NEVER skip. Tests written \"later\" never get written.\n2. **Build System**: CMake with C++17, out-of-source builds in `build/`. In-source builds pollute the repo.\n3. **Feature Workflow**: GitHub Issue -> Feature Branch -> Implement FULLY -> Tests Pass -> Get Approval -> Merge to master. Feature branches keep master stable.\n4. **Commits**: Conventional format (`feat:`/`fix:`/`test:`), reference issues (`refs #n` or `fixes #n`). Enables automated changelog.\n5. **Pre-Commit**: Tests pass, build succeeds, linting clean, no warnings.\n6. **Never merge without user approval. Never leave features half-implemented.**\n\n---\n\n## What is ZoneMinder?\n\nLinux-based CCTV surveillance system: capture, analysis, recording, and monitoring of video cameras.\n\n- **C++ daemons** (`src/`) - Capture (`zmc`), analysis (`zma`), streaming (`zms`), utility (`zmu`)\n- **PHP web interface** (`web/`) - Bootstrap + jQuery UI, AJAX endpoints in `web/ajax/`, views in `web/views/`\n- **REST API** (`web/api/`) - CakePHP 2.x, controllers in `web/api/app/Controller/`, JWT auth\n- **Perl scripts** (`scripts/`) - Daemon control (`zmdc.pl`), migrations (`zmupdate.pl`), filtering (`zmfilter.pl`)\n- **MySQL database** (`db/`) - Schema in `db/zm_create.sql.in`, migrations in `db/zm_update-*.sql` (60+ versions)\n\n---\n\n## Architecture\n\n### Data Flow\n\n```\nCamera -> zmc (capture) -> Shared Memory -> zma (analysis) -> Event Recording\n                              |                                    |\n                           zms (streaming)                   Database + Disk\n                              |                                    |\n                        Web Browsers <- Web Interface/API <- MySQL Storage\n```\n\n### Key Patterns\n\n- **Shared Memory**: `zmc` writes frames to `/dev/shm`; `zma` and `zms` read from same buffers. Zero-copy for performance — this is why ZM can handle many cameras on modest hardware.\n- **Monitor-Centric**: `Monitor` class (`src/zm_monitor.cpp/h`) is the central orchestrator. One monitor = one DB row = one set of daemons. Most changes to camera handling flow through this class.\n- **Pluggable Cameras**: Abstract `Camera` base with: `LocalCamera` (V4L2), `RemoteCameraRTSP`, `RemoteCameraHTTP`, `FFmpegCamera`, `LibVLCCamera`, `LibVNCCamera`. Add new camera types by subclassing Camera.\n- **Event-Driven Recording**: Motion detection triggers `Event` objects with pre/post alarm buffers. Lifecycle: Create -> Record -> Close -> Archive/Delete. Events are the core unit of recorded footage.\n- **Multi-Server Clustering**: Database-coordinated distributed architecture with shared monitors and storage.\n\n### Directory Structure (Key Paths)\n\n```\nsrc/                      C++ core (86+ source files): zm_monitor.*, zm_camera.*, zm_event.*, zm_zone.*, zm_image.*, zm_ffmpeg*.*\nweb/                      PHP web interface\n  ajax/                   AJAX handlers\n  includes/               PHP libraries and functions\n  views/                  UI templates\n  skins/                  Themes (classic skin)\n  js/, css/               Frontend assets\n  api/app/Controller/     CakePHP REST API controllers\n  api/app/Model/          CakePHP REST API models\nscripts/                  Perl system management (.in templates)\ndb/                       Schema (zm_create.sql.in) and migrations (zm_update-*.sql)\ntests/                    Catch2 unit tests + test data\nmisc/                     Server configs (apache, nginx, systemd)\ndep/                      Vendored deps (catch2, jwt-cpp)\n.github/workflows/        CI/CD pipelines\n```\n\n---\n\n## Development Workflow (MANDATORY)\n\n### For every feature or bug fix:\n\n1. **Create GitHub Issue**: `gh issue create --title \"...\" --label enhancement|bug`\n2. **Create Feature Branch**: `git checkout -b <issue>-<description>` from master\n3. **Write failing test first** (TDD)\n4. **Implement** - follow existing patterns, keep changes minimal\n5. **Build & test** - must all pass (see Build and Testing sections)\n6. **Commit** in logical chunks with conventional messages\n7. **Request user approval** - never merge without it\n8. **After approval**: merge to master, delete branch, push, verify issue closes\n\n### Technology-Specific Notes\n\n- **C++ changes** (`src/`): Rebuild required, run ctest. Daemons must be restarted to pick up changes.\n- **PHP/JS changes** (`web/`): No rebuild needed — PHP is interpreted, changes are live immediately. Test in browser + ESLint.\n- **Database schema** (`db/`): Create migration file `zm_update-X.X.X.sql` for existing installs, also update `db/zm_create.sql.in` for fresh installs. Both must result in the same schema.\n- **Perl scripts** (`scripts/`): Edit `.in` template files (NOT generated scripts). cmake substitutes `@ZM_*@` variables to produce the final scripts. When testing perl changes, any perl script will try to read /etc/zm/zm.conf and needs to be run as a user with permission to read it. Best to run with sudo -u www-data\n- **API changes** (`web/api/`): Clear CakePHP cache (`tmp/cache/`) if you change models or routes. Test endpoints with curl.\n\n### Example Workflow\n\n```bash\ngh issue create --title \"Add event favorites\" --label enhancement\n# Note issue number, e.g. #42\ngit checkout master && git pull && git checkout -b 42-event-favorites\n\n# Write test first, implement, build & test\ncd build && cmake --build . && ctest\nnpx eslint .\n\n# Commit\ngit add <files>\ngit commit -m \"feat: add favorites toggle to event view refs #42\"\n\n# Ask user for approval, then after approval:\ngit checkout master && git merge 42-event-favorites\ngit push origin master\ngit branch -d 42-event-favorites && git push origin --delete 42-event-favorites\n```\n\n---\n\n## Build System\n\n```bash\n# Standard build (out-of-source required)\nmkdir build && cd build\ncmake ..\ncmake --build .\n\n# Debug build with tests\ncmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TEST_SUITE=ON ..\ncmake --build .\n\n# Build specific target\ncmake --build . --target zmc\n```\n\n### Key CMake Options\n\n| Option | Values | Default | Notes |\n|--------|--------|---------|-------|\n| `CMAKE_BUILD_TYPE` | Release/Debug/Optimised/Profile | Release | `Profile` = `-O2 -g -fno-omit-frame-pointer` for perf/flamegraph |\n| `BUILD_TEST_SUITE` | ON/OFF | OFF | Enables Catch2 tests |\n| `ENABLE_WERROR` | ON/OFF | OFF | Warnings as errors (CI uses ON) |\n| `ASAN` | ON/OFF | OFF | AddressSanitizer |\n| `TSAN` | ON/OFF | OFF | ThreadSanitizer (mutually exclusive with ASAN) |\n| `ZM_CRYPTO_BACKEND` | openssl/gnutls | | |\n| `ZM_JWT_BACKEND` | libjwt/jwt_cpp | | |\n| `ZM_TARGET_DISTRO` | FreeBSD/fc/el/OS13 | (Debian) | Platform-specific paths |\n| `ZM_ONVIF` | ON/OFF | ON | ONVIF camera support |\n\n---\n\n## Testing Requirements (MANDATORY)\n\n### Workflow\n\n1. Write a failing test that reproduces the issue or validates the feature\n2. Implement the fix/feature\n3. Run tests - verify they PASS\n4. Run full test suite for regressions\n5. Only then commit\n\n### C++ Unit Tests (Catch2)\n\n```bash\n# Build with tests\ncmake -DBUILD_TEST_SUITE=ON .. && cmake --build .\n\n# Run all tests\nctest\n# Or directly with more output\n./tests/tests\n\n# Run specific test / list tests\n./tests/tests \"[Box]\"\n./tests/tests --list-tests\n./tests/tests \"~[notCI]\"\n```\n\n**Test location**: `tests/` directory\n**Existing modules**: `zm_box.cpp`, `zm_comms.cpp`, `zm_crypt.cpp`, `zm_font.cpp`, `zm_poly.cpp`, `zm_utils.cpp`, `zm_vector2.cpp`\n**Framework**: Catch2 with custom header `tests/zm_catch2.h`, main in `tests/main.cpp`\n**Test data**: `tests/data/fonts/`\n\n### JavaScript Linting\n\n```bash\nnpx eslint .        # Lint all\nnpx eslint --fix web/js/              # Auto-fix\n```\n\nESLint config: `eslint.config.js` (ESLint 9 flat config, Google style guide). Runs in CI via `.github/workflows/ci-eslint.yml`.\n\n### PHP/API Testing\n\nManual testing required. Test endpoints with curl/browser. Verify JSON responses, auth (session + JWT), error handling, DB persistence.\n\n### Database Migration Testing\n\n```bash\nsudo zmupdate.pl --check              # Check for updates\nsudo zmupdate.pl                      # Apply migrations\n```\n\nWhen creating migrations: test upgrade path AND verify fresh install matches migrated schema.\n\n### CI Notes\n\n- Unit tests are **DISABLED** in CI (`BUILD_TEST_SUITE=0`) — some tests need hardware/network access. Running locally goes beyond CI requirements but is still expected for local development.\n- CI does: multi-platform builds (Debian/Ubuntu/CentOS with GnuTLS/OpenSSL + libjwt/jwt_cpp matrix), ESLint, CodeQL security scanning\n\n---\n\n## Code Standards\n\n### C++ (`src/`)\n\n- **C++17** standard, follow existing patterns in file/module\n- **Memory**: RAII, smart pointers where appropriate\n- **Error handling**: Exceptions for exceptional cases, return codes for expected errors\n- **Logging**: Use printf-style `Debug(1, \"msg %s\", val)`, `Info(...)`, `Warning(...)`, `Error(...)`, `Fatal(...)` — NOT iostream style. The number in Debug() is verbosity level (1-9).\n\n### PHP (`web/`, `web/api/`)\n\n- PSR-12 where practical, follow existing conventions\n- **Security**: Validate ALL user input, use prepared statements (NOT string interpolation — legacy code has SQL injection bugs we're fixing), sanitize output with htmlspecialchars/json_encode, CSRF protection on forms\n- CakePHP 2.x framework in `web/api/` — we're stuck on 2.x due to migration cost, don't try to upgrade it\n\n### JavaScript (`web/js/`, inline in PHP)\n\n- Google JavaScript Style Guide (ESLint configured)\n- jQuery + Bootstrap (legacy codebase), ES6+ where browser support allows\n\n### Perl (`scripts/`)\n\n- Edit `.in` template files, NOT generated scripts — cmake substitutes variables like `@ZM_LOGDIR@` to produce the final scripts\n- Use `ZoneMinder::` modules, `ZoneMinder::Logger` for logging\n- Rerun cmake after editing `.in` files to regenerate the actual scripts\n\n---\n\n## Commit Standards\n\n**Conventional format** with issue references:\n\n```\nfeat|fix|test|docs|chore|refactor|perf|style: description refs #N\n```\n\n- `refs #N` references issue; `fixes #N` closes it\n- Imperative mood (\"add feature\" not \"added feature\")\n- Be detailed and descriptive, no vague summaries\n- One logical change per commit\n- **No superlative language** (\"comprehensive\", \"critical\", \"major\", \"massive\") — AI agents tend to use these; they make commit logs unreadable\n- Split unrelated changes into separate commits — makes bisecting and reverting possible\n\n---\n\n## Pre-Commit Checklist (Single Source of Truth)\n\nBefore committing or claiming complete:\n\n- [ ] Tests written/updated BEFORE or DURING implementation\n- [ ] Build succeeds: `cmake --build .` (C++ changes)\n- [ ] C++ tests pass: `ctest` or `./tests/tests`\n- [ ] JavaScript linting passes: `npx eslint .`\n- [ ] Manual testing done (PHP/web changes)\n- [ ] No compiler warnings or linter errors\n- [ ] Code follows existing patterns\n- [ ] Commit messages follow conventional format with issue reference\n- [ ] Feature is COMPLETE (not half-implemented)\n- [ ] State which tests were run and their results\n\n**NEVER commit if**: tests failing, tests missing for new code, build fails, warnings exist, feature incomplete.\n\n---\n\n## Debugging Quick Reference\n\n```bash\n# Debug build\ncmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .\n\n# AddressSanitizer\ncmake -DCMAKE_BUILD_TYPE=Debug -DASAN=ON .. && cmake --build .\n\n# Debug logging\nexport ZM_DBG_LEVEL=9 ZM_DBG_LOG=/tmp/debug.log\n./src/zmc -m 1\n\n# Log locations: /var/log/zm/ (zmc_m1.log, zma_m2.log, etc.)\n# Runtime log level: kill -USR1 <pid> (increase) / kill -USR2 <pid> (decrease)\n```\n\n---\n\n## Contributing (For Humans)\n\n- **Bug reports & features**: [GitHub Issues](https://github.com/ZoneMinder/zoneminder/issues) (read [posting rules](https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules) first)\n- **Support**: [Forums](https://forums.zoneminder.com), [Slack](https://zoneminder-chat.slack.com), [Discord](https://discord.gg/tHYyP9k66q)\n- **PRs**: Fork -> feature branch -> implement + test -> PR. Maintainers merge after review.\n- **Docs**: https://zoneminder.readthedocs.org (source in `docs/`)\n\n---\n\n## grepai - Semantic Code Search\n\n**Use grepai as PRIMARY tool for code exploration and search.**\n\n### When to Use grepai (REQUIRED)\n\nUse `grepai search` INSTEAD OF Grep/Glob for:\n- Understanding what code does or where functionality lives\n- Finding implementations by intent (\"authentication logic\", \"error handling\")\n- Exploring unfamiliar parts of the codebase\n\nOnly use Grep/Glob for exact text matching (variable names, imports, specific strings) or file path patterns.\n\nIf grepai fails (not running, index unavailable), fall back to Grep/Glob.\n\n### Usage\n\n```bash\ngrepai search \"user authentication flow\" --json --compact\ngrepai search \"JWT token validation\" --json --compact\n```\n\n### Call Graph Tracing\n\n```bash\ngrepai trace callers \"HandleRequest\" --json\ngrepai trace callees \"ProcessOrder\" --json\ngrepai trace graph \"ValidateToken\" --depth 3 --json\n```\n\n### Workflow\n\n1. `grepai search` to find relevant code\n2. `grepai trace` to understand function relationships\n3. `Read` tool to examine files from results\n4. Grep only for exact string searches if needed\n","category":"root","tokens":3339}]}