Nothing links or dlopens libvlc any more, so the dev package is no longer a build requirement anywhere: the debian, beowulf, ubuntu and split-package control files, the podman Containerfile, the redhat and opensuse specs, the centos CI image, and the five workflows that installed libvlc-dev. The redhat spec also required vlc-core at runtime, which was the dlopen target. Documentation follows: the libVLC source tab section, the macos note about libVLC not being found, and the WEB_FILTER_SOURCE source-type list. Two stale statements nearby are corrected while the files are open. The Remote source tab still said its RTSP method "may be removed in the future"; it was removed earlier on this branch. AGENTS.md still listed RemoteCameraRTSP and LibVLCCamera among the camera classes, both of which are now gone. All workflow yaml parses, the three edited rst files render, and the debian control field structure is unchanged apart from the removed entries. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Y6FieTwEXuLhhR4e2yiax
13 KiB
AI Agent Development Guide for ZoneMinder
Note
: This file guides AI coding agents (Claude Code, GitHub Copilot, Cursor, etc.) working on ZoneMinder. CLAUDE.md is a symlink to this file.
Quick Reference (MANDATORY RULES)
- Testing First: Write tests BEFORE/DURING implementation - NEVER skip. Tests written "later" never get written.
- Build System: CMake with C++17, out-of-source builds in
build/. In-source builds pollute the repo. - Feature Workflow: GitHub Issue -> Feature Branch -> Implement FULLY -> Tests Pass -> Get Approval -> Merge to master. Feature branches keep master stable.
- Commits: Conventional format (
feat:/fix:/test:), reference issues (refs #norfixes #n). Enables automated changelog. - Pre-Commit: Tests pass, build succeeds, linting clean, no warnings.
- Never merge without user approval. Never leave features half-implemented.
What is ZoneMinder?
Linux-based CCTV surveillance system: capture, analysis, recording, and monitoring of video cameras.
- C++ daemons (
src/) - Capture (zmc), analysis (zma), streaming (zms), utility (zmu) - PHP web interface (
web/) - Bootstrap + jQuery UI, AJAX endpoints inweb/ajax/, views inweb/views/ - REST API (
web/api/) - CakePHP 2.x, controllers inweb/api/app/Controller/, JWT auth - Perl scripts (
scripts/) - Daemon control (zmdc.pl), migrations (zmupdate.pl), filtering (zmfilter.pl) - MySQL database (
db/) - Schema indb/zm_create.sql.in, migrations indb/zm_update-*.sql(60+ versions)
Architecture
Data Flow
Camera -> zmc (capture) -> Shared Memory -> zma (analysis) -> Event Recording
| |
zms (streaming) Database + Disk
| |
Web Browsers <- Web Interface/API <- MySQL Storage
Key Patterns
- Shared Memory:
zmcwrites frames to/dev/shm;zmaandzmsread from same buffers. Zero-copy for performance — this is why ZM can handle many cameras on modest hardware. - Monitor-Centric:
Monitorclass (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. - Pluggable Cameras: Abstract
Camerabase with:LocalCamera(V4L2),RemoteCameraHTTP,FFmpegCamera,LibVNCCamera. Add new camera types by subclassing Camera. - Event-Driven Recording: Motion detection triggers
Eventobjects with pre/post alarm buffers. Lifecycle: Create -> Record -> Close -> Archive/Delete. Events are the core unit of recorded footage. - Multi-Server Clustering: Database-coordinated distributed architecture with shared monitors and storage.
Directory Structure (Key Paths)
src/ C++ core (86+ source files): zm_monitor.*, zm_camera.*, zm_event.*, zm_zone.*, zm_image.*, zm_ffmpeg*.*
web/ PHP web interface
ajax/ AJAX handlers
includes/ PHP libraries and functions
views/ UI templates
skins/ Themes (classic skin)
js/, css/ Frontend assets
api/app/Controller/ CakePHP REST API controllers
api/app/Model/ CakePHP REST API models
scripts/ Perl system management (.in templates)
db/ Schema (zm_create.sql.in) and migrations (zm_update-*.sql)
tests/ Catch2 unit tests + test data
misc/ Server configs (apache, nginx, systemd)
dep/ Vendored deps (catch2, jwt-cpp)
.github/workflows/ CI/CD pipelines
Development Workflow (MANDATORY)
For every feature or bug fix:
- Create GitHub Issue:
gh issue create --title "..." --label enhancement|bug - Create Feature Branch:
git checkout -b <issue>-<description>from master - Write failing test first (TDD)
- Implement - follow existing patterns, keep changes minimal
- Build & test - must all pass (see Build and Testing sections)
- Commit in logical chunks with conventional messages
- Request user approval - never merge without it
- After approval: merge to master, delete branch, push, verify issue closes
Technology-Specific Notes
- C++ changes (
src/): Rebuild required, run ctest. Daemons must be restarted to pick up changes. - PHP/JS changes (
web/): No rebuild needed — PHP is interpreted, changes are live immediately. Test in browser + ESLint. - Database schema (
db/): Create migration filezm_update-X.X.X.sqlfor existing installs, also updatedb/zm_create.sql.infor fresh installs. Both must result in the same schema. - Perl scripts (
scripts/): Edit.intemplate 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 - API changes (
web/api/): Clear CakePHP cache (tmp/cache/) if you change models or routes. Test endpoints with curl.
Example Workflow
gh issue create --title "Add event favorites" --label enhancement
# Note issue number, e.g. #42
git checkout master && git pull && git checkout -b 42-event-favorites
# Write test first, implement, build & test
cd build && cmake --build . && ctest
npx eslint .
# Commit
git add <files>
git commit -m "feat: add favorites toggle to event view refs #42"
# Ask user for approval, then after approval:
git checkout master && git merge 42-event-favorites
git push origin master
git branch -d 42-event-favorites && git push origin --delete 42-event-favorites
Build System
# Standard build (out-of-source required)
mkdir build && cd build
cmake ..
cmake --build .
# Debug build with tests
cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TEST_SUITE=ON ..
cmake --build .
# Build specific target
cmake --build . --target zmc
Key CMake Options
| Option | Values | Default | Notes |
|---|---|---|---|
CMAKE_BUILD_TYPE |
Release/Debug/Optimised/Profile | Release | Profile = -O2 -g -fno-omit-frame-pointer for perf/flamegraph |
BUILD_TEST_SUITE |
ON/OFF | OFF | Enables Catch2 tests |
ENABLE_WERROR |
ON/OFF | OFF | Warnings as errors (CI uses ON) |
ASAN |
ON/OFF | OFF | AddressSanitizer |
TSAN |
ON/OFF | OFF | ThreadSanitizer (mutually exclusive with ASAN) |
ZM_CRYPTO_BACKEND |
openssl/gnutls | ||
ZM_JWT_BACKEND |
libjwt/jwt_cpp | ||
ZM_TARGET_DISTRO |
FreeBSD/fc/el/OS13 | (Debian) | Platform-specific paths |
ZM_ONVIF |
ON/OFF | ON | ONVIF camera support |
Testing Requirements (MANDATORY)
Workflow
- Write a failing test that reproduces the issue or validates the feature
- Implement the fix/feature
- Run tests - verify they PASS
- Run full test suite for regressions
- Only then commit
C++ Unit Tests (Catch2)
# Build with tests
cmake -DBUILD_TEST_SUITE=ON .. && cmake --build .
# Run all tests
ctest
# Or directly with more output
./tests/tests
# Run specific test / list tests
./tests/tests "[Box]"
./tests/tests --list-tests
./tests/tests "~[notCI]"
Test location: tests/ directory
Existing modules: zm_box.cpp, zm_comms.cpp, zm_crypt.cpp, zm_font.cpp, zm_poly.cpp, zm_utils.cpp, zm_vector2.cpp
Framework: Catch2 with custom header tests/zm_catch2.h, main in tests/main.cpp
Test data: tests/data/fonts/
JavaScript Linting
npx eslint . # Lint all
npx eslint --fix web/js/ # Auto-fix
ESLint config: eslint.config.js (ESLint 9 flat config, Google style guide). Runs in CI via .github/workflows/ci-eslint.yml.
PHP/API Testing
Manual testing required. Test endpoints with curl/browser. Verify JSON responses, auth (session + JWT), error handling, DB persistence.
Database Migration Testing
sudo zmupdate.pl --check # Check for updates
sudo zmupdate.pl # Apply migrations
When creating migrations: test upgrade path AND verify fresh install matches migrated schema.
CI Notes
- 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. - CI does: multi-platform builds (Debian/Ubuntu/CentOS with GnuTLS/OpenSSL + libjwt/jwt_cpp matrix), ESLint, CodeQL security scanning
Code Standards
C++ (src/)
- C++17 standard, follow existing patterns in file/module
- Memory: RAII, smart pointers where appropriate
- Error handling: Exceptions for exceptional cases, return codes for expected errors
- 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).
PHP (web/, web/api/)
- PSR-12 where practical, follow existing conventions
- 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
- CakePHP 2.x framework in
web/api/— we're stuck on 2.x due to migration cost, don't try to upgrade it
JavaScript (web/js/, inline in PHP)
- Google JavaScript Style Guide (ESLint configured)
- jQuery + Bootstrap (legacy codebase), ES6+ where browser support allows
Perl (scripts/)
- Edit
.intemplate files, NOT generated scripts — cmake substitutes variables like@ZM_LOGDIR@to produce the final scripts - Use
ZoneMinder::modules,ZoneMinder::Loggerfor logging - Rerun cmake after editing
.infiles to regenerate the actual scripts
Commit Standards
Conventional format with issue references:
feat|fix|test|docs|chore|refactor|perf|style: description refs #N
refs #Nreferences issue;fixes #Ncloses it- Imperative mood ("add feature" not "added feature")
- Be detailed and descriptive, no vague summaries
- One logical change per commit
- No superlative language ("comprehensive", "critical", "major", "massive") — AI agents tend to use these; they make commit logs unreadable
- Split unrelated changes into separate commits — makes bisecting and reverting possible
Pre-Commit Checklist (Single Source of Truth)
Before committing or claiming complete:
- Tests written/updated BEFORE or DURING implementation
- Build succeeds:
cmake --build .(C++ changes) - C++ tests pass:
ctestor./tests/tests - JavaScript linting passes:
npx eslint . - Manual testing done (PHP/web changes)
- No compiler warnings or linter errors
- Code follows existing patterns
- Commit messages follow conventional format with issue reference
- Feature is COMPLETE (not half-implemented)
- State which tests were run and their results
NEVER commit if: tests failing, tests missing for new code, build fails, warnings exist, feature incomplete.
Debugging Quick Reference
# Debug build
cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .
# AddressSanitizer
cmake -DCMAKE_BUILD_TYPE=Debug -DASAN=ON .. && cmake --build .
# Debug logging
export ZM_DBG_LEVEL=9 ZM_DBG_LOG=/tmp/debug.log
./src/zmc -m 1
# Log locations: /var/log/zm/ (zmc_m1.log, zma_m2.log, etc.)
# Runtime log level: kill -USR1 <pid> (increase) / kill -USR2 <pid> (decrease)
Contributing (For Humans)
- Bug reports & features: GitHub Issues (read posting rules first)
- Support: Forums, Slack, Discord
- PRs: Fork -> feature branch -> implement + test -> PR. Maintainers merge after review.
- Docs: https://zoneminder.readthedocs.org (source in
docs/)
grepai - Semantic Code Search
Use grepai as PRIMARY tool for code exploration and search.
When to Use grepai (REQUIRED)
Use grepai search INSTEAD OF Grep/Glob for:
- Understanding what code does or where functionality lives
- Finding implementations by intent ("authentication logic", "error handling")
- Exploring unfamiliar parts of the codebase
Only use Grep/Glob for exact text matching (variable names, imports, specific strings) or file path patterns.
If grepai fails (not running, index unavailable), fall back to Grep/Glob.
Usage
grepai search "user authentication flow" --json --compact
grepai search "JWT token validation" --json --compact
Call Graph Tracing
grepai trace callers "HandleRequest" --json
grepai trace callees "ProcessOrder" --json
grepai trace graph "ValidateToken" --depth 3 --json
Workflow
grepai searchto find relevant codegrepai traceto understand function relationshipsReadtool to examine files from results- Grep only for exact string searches if needed