These instructions apply to all directories in this repository.
NestedAGENTS.mdfiles (if added later) override rules for their subtrees.
-
Use Python 3.11 (or the version configured in
pyproject.toml). -
Install
uv(safe to rerun even if present):pip install uv
-
Install dependencies using the existing workflow:
uv sync --all-extras --all-groups
-
uvwill create a.venvin the project root. Prefer running everything throughuvso you don’t have to manage activation manually:# Generic command wrapper uv run <command> [args...]
Always run Python entry points as modules from the repo root, not as loose scripts, so that from boxmot... imports work correctly:
# ✅ Good – uses package context
uv run python -m boxmot.engine.cli --help
# ❌ Avoid – can break imports (e.g., ModuleNotFoundError: boxmot)
python boxmot/engine/cli.py --help
PYTHONPATH=. python boxmot/engine/cli.py --helpIf you really need to use the virtualenv directly:
source .venv/bin/activate
python -m boxmot.engine.cli --help-
Create short, lowercase branches with hyphens between words.
git checkout -b <type>/<short-description>
-
Branch name examples:
feature/add-login-pagefix/handle-null-userrefactor/simplify-auth-flowdocs/update-readme
-
Recommended branch types:
feature/– New features or user-facing additionsfix/– Bug fixeshotfix/– Urgent production fixesrefactor/– Code restructuring without changing behaviorperf/– Performance improvementsdocs/– Documentation-only changestest/– Adding or updating testschore/– Maintenance tasks that do not affect runtime behaviorci/– CI/CD pipeline changesbuild/– Build system, dependency, packaging, or tooling changesdeps/– Dependency updatesstyle/– Formatting, linting, or non-functional style changesrelease/– Release preparationrevert/– Reverting a previous changesecurity/– Security-related fixes or hardeningexperiment/– Experimental work that may not be mergedspike/– Research or investigation branchesmigration/– Database, schema, or data migration workinfra/– Infrastructure, deployment, or cloud configuration changes
-
Avoid vague branch names such as
update,changes,stuff,fixes, orwip. -
Prefer descriptive branch names such as:
fix/user-session-timeoutfeature/export-results-csvrefactor/split-training-pipelinedocs/add-agent-instructions
-
Keep changes focused: one logical change per PR / task.
-
Follow the existing structure and conventions of the modules you touch.
-
Do not add backwards compatibility layers, legacy aliases, migration shims, compatibility wrappers, or deprecated paths unless explicitly requested. Prefer updating callers, tests, docs, and examples to the new canonical structure.
-
Architecture rule:
boxmot.engineowns command entrypoints and orchestration. Domain packages such asboxmot.reidshould keep reusable model, backend, dataset, training, exporter, and algorithm code; CLI/API workflow adapters for those domains belong underboxmot.engine.
- Prefer Python type hints and docstrings for any new or modified functions/classes.
- Keep imports:
- Sorted.
- Minimal (remove unused).
- Do not wrap imports in
try/exceptunless there is a very specific reason and it’s clearly documented.
Logging
- Use the existing logger (e.g.,
LOGGER) rather thanprintin library code. - It’s fine to
printin CLI entry points when it improves UX, but prefer consistent logging style.
Match the surrounding style
- Naming, spacing, line wrapping, click option style, etc.
- Reuse helper patterns (e.g., decorators like
core_options, shared parsing helpers).
When editing boxmot/engine/cli.py or other CLIs:
- Group options logically (e.g., input, inference, output, display). Use the new canonical option names and defaults; do not preserve legacy options solely for backwards compatibility unless explicitly requested.
- Prefer reusable decorators for option groups (
core_options,plural_model_options, etc.). - Use parsing helpers (e.g.,
parse_tuple,parse_hw_tuple) rather than ad-hoc parsing in every command. - Keep help text accurate and concise; if you change behavior, update:
- The option help strings.
- Any CLI examples in
README.md,docs/, orexamples/.
When adding a new command:
- Reuse
make_argsto build argparse-like namespaces. - Align with existing subcommands’ style (
track,generate,eval,tune,export).
Commit messages should start with one of:
feat:– new featurefix:– bug fixrefactor:– internal-only changes / cleanupdocs:– documentation onlyci:– CI / tooling changesperf:– performance improvements
Each commit should represent a coherent change; avoid mixing unrelated edits.
PR / task descriptions should include:
- A short summary of user-facing changes.
- A Testing section (see below).
- Any follow-up work or known limitations.
What to run
-
Default: run the pytest suite from the repo root:
uv run pytest
-
If the full suite is too heavy, at least run the tests relevant to your change, e.g.:
uv run pytest tests/test_cli.py uv run pytest tests/path/to/affected_module_tests.py
-
When touching CLI / engine entry points, it’s useful to smoke-test common commands:
uv run python -m boxmot.engine.cli --help # Example invocations (adjust source/paths as available in your env) uv run python -m boxmot.engine.cli track --source <path-or-url> ... uv run python -m boxmot.engine.cli generate --source <path-or-url> ... uv run python -m boxmot.engine.cli eval --source <path-or-url> ... uv run python -m boxmot.engine.cli tune --source <path-or-url> ...
If tests or commands cannot be run
Sometimes the provided environment is missing GPUs, large datasets, or external services. In that case:
-
Try the following first:
uv sync --all-extras --all-groups uv run python -m boxmot.engine.cli --help uv run pytest
-
If something still fails for reasons outside your control (e.g., missing CUDA runtime, no network for model downloads, etc.), do not fake test results. Instead, document clearly in your Testing section, for example:
Testing - uv run python -m boxmot.engine.cli --help ✅ - uv run pytest ❌ (not run) Reason: pytest requires GPU / CUDA dependencies that are not available in the current container. Please run `uv sync --all-extras --all-groups` and `uv run pytest` in a fully configured environment.
- Include the exact commands you ran and a brief reason why anything couldn’t be completed.
- Update docs or examples when behavior or interfaces change, especially:
- CLI options or defaults.
- New or removed commands.
- Keep README snippets and CLI help text in sync with code updates.
- When changing data formats or output directories, update any references in:
docs/examples/tests/
- Be mindful of model weights and large assets:
- Do not commit generated artifacts or large binaries.
- Prefer referencing weights via URLs or documented download steps.
- Where practical:
- Use deterministic or seeded behavior for tests/examples.
- Avoid unnecessary heavy computation in unit tests.
- Implement the tracker
- Add a new module under the appropriate modality folder, such as
boxmot/trackers/bbox/<name>.py,boxmot/trackers/mask/<name>/, orboxmot/trackers/hybrid/<name>/. - Implement a tracker class that subclasses
BaseTrackerand definesupdate().
- Register the tracker
- Add the tracker to
TRACKER_MAPPINGinboxmot/trackers/registry.py. - Export it in
boxmot/trackers/__init__.pyandboxmot/__init__.py. - Add the tracker name to the
TRACKERSlist inboxmot/__init__.py.
- Add default configuration
- Create
boxmot/configs/trackers/<name>.yamlwith default parameters and tuning ranges.
- Update docs
- Add a tracker doc page in
docs/trackers/<name>.md. - Add the tracker to
mkdocs.ymlnav. - Mention it in
docs/index.mdandREADME.mdwhere trackers are listed.
- Update tests
- Register the tracker in
tests/test_config.pylists so it’s covered by unit tests.
- Update CI/benchmarks
- Add the tracker name to workflow matrices/lists in
.github/workflows/.
- Commit new files
- Ensure new tracker code, config, and docs are staged and pushed.
When adding oriented bounding box (OBB) support, follow this generic implementation guide.
- Set
supports_obb = Trueon the tracker class. - Keep
@BaseTracker.setup_decoratorenabled so detection shape can trigger OBB mode automatically. - Reuse shared detection plumbing from:
boxmot/trackers/base.pyboxmot/trackers/common/detections/layout.py
- Do not hardcode column indices if layout helpers already provide them:
self.detection_layout.boxes(...)self.detection_layout.confidences(...)self.detection_layout.classes(...)self.detection_layout.with_detection_indices(...)
- Input detections:
- AABB:
(x1, y1, x2, y2, conf, cls)(6 columns) - OBB:
(cx, cy, w, h, angle, conf, cls)(7 columns)
- AABB:
- Output tracks:
- AABB: 8 columns
- OBB: 9 columns
(cx, cy, w, h, angle, id, conf, cls, det_ind)
- Split AABB and OBB parsing paths
- Add explicit detection parsing/init branches for each mode.
- Preserve
conf,cls, anddet_indin both paths.
- Use a motion model that supports OBB state
- Keep AABB and OBB state/measurement handling explicit.
- If OBB adds dimensions (for example angle), ensure
initiate,predict, andupdateall use matching state sizes. - For KF-based trackers, keep angle dynamics explicit (
theta,v_theta/omega) and prefer damping over hard resets. - For non-KF trackers, maintain per-track angular velocity state and apply damping during OBB updates.
- Keep mode-dependent predict/update logic
- If velocity/state reset behavior differs between AABB and OBB, implement separate branches.
- Avoid combining incompatible state assumptions in one path.
- Do not hard-zero OBB angular velocity after every update unless there is a tracker-specific reason.
- Preferred default: damp angular velocity each update (for example
omega *= 0.8or equivalent blend).
- Wire OBB-aware association
- Ensure association uses OBB geometry in OBB mode.
- For IoU distance matching, pass
is_obb=self.is_obbwhere applicable. - If using
self.asso_func, verify the OBB association mode is selected in OBB mode.
- Preserve geometry accessors for downstream consumers
- Expose
xywhain OBB mode. - Keep
xyxyavailable as enclosing AABB for compatibility where needed. - Maintain
history_observationsandidfor plotting and lifecycle logic.
- Keep OBB plotting/history stable
- Append post-update OBB geometry to
history_observations. - If angles are used for plotting, add angle continuity handling to avoid wrap/flip artifacts.
- Before OBB update, resolve equivalent rectangle forms relative to current state:
(w, h, theta)(w, h, theta + pi)(h, w, theta + pi/2)(h, w, theta - pi/2)
- Choose the candidate closest to the reference state, then apply damped angular update.
- Emit schema-correct outputs
- AABB outputs must remain 8 columns.
- OBB outputs must remain 9 columns in the exact order:
(cx, cy, w, h, angle, id, conf, cls, det_ind).
At minimum, add or update tests to cover:
- tracker accepts OBB detections
- tracker returns 9-column OBB outputs
- OBB association path uses oriented geometry
- OBB plotting/history path remains stable across frames
- OBB angle update is smooth:
- track angle moves toward the new detection
- track angle does not jump the full detection delta when damping is enabled
If shared OBB plumbing changes, also consider extending:
tests/unit/test_inference.pytests/unit/test_base_backend.py
Use shared OBB plumbing for detection mode/layout and keep tracker-specific OBB internals limited to algorithm-specific motion and association details.