IsaacCapture
AGENTS.md438 starsChanged 31 days agoApache-2.0View on GitHub
Before modifying OR creating ANY file under this repository, you MUST use your file-reading tools to load EVERY AGENTS.md on the directory paths you will touch (see "CRITICAL — mandatory preflight" below). This is NON-OPTIONAL. Skipping it, or relying only on chat context without reading those files, is incorrect. Before you treat work as finished, you MUST run pre-commit as in "Pre-commit — match CI before you stop" and fix all failures. Declaring the task done without that run is…
1 other project uses a version of this.
Adopted by
Most recently taken up by
- NVIDIA/IsaacTeleopword for word, first seen Oct 14, 2026
Other versions1 project uses a version of this.
Word for word · 1
- NVIDIA/IsaacTeleop★ 438100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository28 other files it gives its agents.
- deps/cloudxr/webxr_client/AGENTS.mdAGENTS.md
- docs/AGENTS.mdAGENTS.md
- examples/camera_streamer/AGENTS.mdAGENTS.md
- examples/egocap/AGENTS.mdAGENTS.md
- examples/teleop_ros2/AGENTS.mdAGENTS.md
- src/core/AGENTS.mdAGENTS.md
- src/core/codegen/AGENTS.mdAGENTS.md
- src/core/deviceio_base/AGENTS.mdAGENTS.md
- src/core/deviceio_session/AGENTS.mdAGENTS.md
- src/core/deviceio_trackers/AGENTS.mdAGENTS.md
- src/core/live_trackers/AGENTS.mdAGENTS.md
- src/core/log_bridge/AGENTS.mdAGENTS.md
- src/core/replay_trackers/AGENTS.mdAGENTS.md
- src/core/schema/AGENTS.mdAGENTS.md
- src/plugins/sensing/AGENTS.mdAGENTS.md
- src/plugins/sharpa_avatar/AGENTS.mdAGENTS.md
- src/python/isaaccapture/cts/common/AGENTS.mdAGENTS.md
- src/python/isaaccapture/cts/full_body/checker/AGENTS.mdAGENTS.md
- src/python/isaaccapture/cts/full_body/oracle/AGENTS.mdAGENTS.md
- src/python/isaaccapture/cts/hand/AGENTS.mdAGENTS.md
- src/python/isaaccapture/cts/hand/checker/AGENTS.mdAGENTS.md
- src/python/isaaccapture/logging_config/AGENTS.mdAGENTS.md
- src/viz/AGENTS.mdAGENTS.md
- tests/AGENTS.mdAGENTS.md
- .cursor/rules/cmake-structure.mdcCursor rule
- cmake-structureSkill
- rebot-orin-setupSkill
- rebot-orin-setupSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
22 rules. About 0 are common, 12 are distinctive, and 10 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈12
Distinctive · estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 9
Before modifying OR creating ANY file under this repository, you MUST use your file-reading tools to load EVERY AGENTS.md on the directory …
- Distinctive: line 14
Before you treat work as finished, you MUST run pre-commit as in "Pre-commit — match CI before you stop" and fix all failures.
- Distinctive: line 18
If pre-commit/CI fails, or the user corrects you, or you repeat the same class of mistake, you MUST record the lesson in AGENTS.md or …
- Very specific: line 51
If you cannot run a shell, use your search/glob tools on the pattern /AGENTS.md from the same root.
- Distinctive: line 61
Keep licensing summaries brief in README and CONTRIBUTING.
- Distinctive: line 67
Keep license-boundary changes separate from copyright-template and year-policy changes.
- Very specific: line 68
Keep canonical texts in LICENSES/ unmodified, including template placeholders.
- Very specific: line 75
When you create or edit a CMakeLists.txt, add or move a target, place a header, write #include directives, or restructure directories, …
- Distinctive: line 78
Read that file before touching build files, header placement, or include paths.
- Very specific: line 99
Every process in this repo, Python and C++, feeds a single logger tree rooted at isaaccapture.
- Very specific: line 142
A log message some machine greps for is an interface: Before rewording or re-homing one, grep -rF the phrase over .github/, docs/, scripts/ …
- Distinctive: line 215
One statement of a fact, in one place: If a constraint is already in the code, the test name, or an adjacent doc, do not restate it.
- Distinctive: line 243
When moving a focused fix from a release branch onto main, identify its original base and replay only the fix commits.
- Very specific: line 246
Before pushing, compare every URL from git remote get-url --push --all <remote> with the user-specified owner and repository.
- Distinctive: line 250
Before updating an existing pull request, verify its exact head owner, repository, and ref.
- Very specific: line 273
Keep local dependency or toolchain trees outside the repository or ignored: the REUSE --fix hook enumerates non-ignored files and can …
- Very specific: line 291
When the SBOM step stops the Release build, fix the cause.
- Distinctive: line 307
When a fact is stated in more than one place — a predicate in several modules, a claim in both the code and the docs, a heading over the …
- Very specific: line 314
Grep for the claim, not the line you edited: Search the phrase, the predicate, the constant — across docs/, scripts/, tests/ and the code — …
- Distinctive: line 317
Prefer one authority to a swept duplicate: If the same rule has to hold in several places, give it one definition and call it.
- Distinctive: line 325
Hard requirement: When any of the following happens, you must complete steps 1–3 before you end the session or move on as if the work were …
- Very specific: line 348
Put that in comments in the source files where the behavior lives (short // notes: intent, invariants, or “do not X because …”).
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!--
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0
--><!--
MANDATORY FOR ALL AUTOMATED CODING AGENTS (Cursor, Copilot, etc.):
Before modifying OR creating ANY file under this repository, you MUST use your
file-reading tools to load EVERY AGENTS.md on the directory paths you will touch
(see "CRITICAL — mandatory preflight" below). This is NON-OPTIONAL. Skipping it,
or relying only on chat context without reading those files, is incorrect.
Before you treat work as finished, you MUST run pre-commit as in
"Pre-commit — match CI before you stop" and fix all failures. Declaring the task
done without that run is incorrect.
If pre-commit/CI fails, or the user corrects you, or you repeat the same class of
mistake, you MUST record the lesson in AGENTS.md or source comments per
"Mandatory learning loop" in the same session—not only when the user asks.
Repository owners: keep this block at the top of this file; do not delete it.
-->Isaac Capture — agent notes
Product naming
Isaac Capture names the overall library and repository. Isaac Teleop remains its teleoperation component; preserve that brand and existing technical identifiers.
CRITICAL — mandatory preflight (do not skip)
Hard requirement: Do not edit or add code under IsaacCapture/ until you have read (e.g. with the Read tool) every relevant AGENTS.md file as defined below. This is not optional, not "only for large tasks," and not satisfiable by inferring from prior conversation. If you have not read those files in this session for this task, stop and read them first.
You must:
- List the directories you expect to edit or create files under (e.g.
src/core/live_trackers/cpp/,src/core/deviceio_base/cpp/inc/…). - For each such directory, read
AGENTS.mdin that directory if it exists. - Walk up toward the IsaacCapture repo root and read
AGENTS.mdin every ancestor directory that has one (e.g.live_trackers/→src/core/→IsaacCapture/AGENTS.md(this file)).
You must not assume that reading the single "closest" AGENTS.md is enough. Multiple AGENTS.md files can apply to one change (e.g. both live_trackers and deviceio_base).
Listing every AGENTS.md in this repo (no curated table here—add new files under the tree without editing this document):
# Run from the IsaacCapture repository root (the directory that contains this file):
find . -name AGENTS.md ! -path '*/.git/*' | sortIf you cannot run a shell, use your search/glob tools on the pattern **/AGENTS.md from the same root. That inventory is for orientation; you must still read every file that applies to the directories you will touch (steps 1–3 above).
Optional context index: src/core/AGENTS.md (also on the ancestor walk—read it when working under src/core/).
Product naming
- Spell the product name “Isaac Capture” in prose; avoid the ambiguous shorthand “Capture”.
Component licensing
- Keep licensing summaries brief in README and CONTRIBUTING; automate routine checks and updates rather than documenting manual header maintenance.
- Preserve root
LICENSE.mdverbatim as Apache-2.0; explain component exceptions in README/CONTRIBUTING and local license files, so GitHub can recognize the default. - EgoPost uses
LicenseRef-OpenMDW-1.1; preserve upstream exceptions and notices. Keep license-boundary changes separate from copyright-template and year-policy changes. - Keep canonical texts in
LICENSES/unmodified, including template placeholders; do not prepend project copyright or SPDX headers or include them in header repair. - Source hosting does not authorize wheel inclusion. Keep package discovery explicit and verify license metadata/notices in each artifact before shipping a new component.
CMake & include structure
When you create or edit a CMakeLists.txt, add or move a target, place a header,
write #include directives, or restructure directories, follow the repo's
canonical CMake/include rules in cmake/cmake-structure.md.
Read that file before touching build files, header placement, or include paths.
Per-tool shims auto-load the same doc for Claude Code, Cursor, Copilot, and
CodeRabbit (.claude/skills/cmake-structure/, .cursor/rules/cmake-structure.mdc,
.github/instructions/cmake-structure.instructions.md, .coderabbit.yaml); they
only point here — edit the rules in the doc, not the shims.
Shell scripts
- In bash scripts (
#!/bin/bash,#!/usr/bin/env bash, or filessourced only by bash), use[[ ... ]]for conditional tests, never the POSIX single-bracket[ ... ].[[is safer (no word-splitting or glob expansion on unquoted operands) and more feature-rich; SonarQube/ShellCheck (SC2292) flag the single-bracket form. - Caveat:
[[is a bash builtin and is not POSIX. Before converting, confirm the script's interpreter is bash — a genuine#!/bin/sh(dash) script must keep[ ... ]. Check the shebang (and, for sourced files, who sources them) first.
Logging — one tree, one place to configure it
Every process in this repo, Python and C++, feeds a single logger tree rooted
at isaaccapture. These rules apply wherever you emit output, not only inside
the logging packages.
- Name every logger under
isaaccapture.In Python that meanslogging.getLogger(__name__)insidesrc/python/isaaccapture/(where__name__already starts withisaaccapture.) and an explicitlogging.getLogger("isaaccapture.<area>.<module>")anywhere else, includingexamples/. In C++ it meansisaaccapture::Logger::get("isaaccapture.<module>.<ClassName>"). Dotted names are the hierarchy: a bare name like"robot_viz"is a sibling ofisaaccapture, not a descendant, so the console and file handlers attached to the root of this tree can never see its records. - Never call
logging.basicConfig(), and never attach your own handler to theisaaccapturelogger or to the Python root logger.basicConfig()installs a handler on the root logger, and nothing here setspropagate = False, so from that call onward everyisaaccapturerecord is emitted twice — once in the shared line format and once in yours. The one exception is a program that imports noisaaccaptureat all, and is meant to keep it that way: there are no handlers of ours for it to duplicate, and reaching forlogging_configwould add the dependency the program exists without. The camera_viz streamer,examples/camera_viz/python/isaaccapture_examples/camera_viz/camera_streamer.py, is the case — a sender-only camera box runs it with no CUDA/Vulkan/OpenXR runtime installed, soimport isaaccapturewould fail outright. Keep the logger names underisaaccapture.anyway; the naming rule above is a convention, not a runtime coupling. - Configure through the public API instead:
logging_config.set_console_level(),set_console_logger_name_filter(),set_console_content_filter(),set_console_format(),set_logger_colors(). A--verboseflag should callset_console_level("debug"), not build a handler. print()/std::coutare for deliberate terminal UX only — CLI usage text, interactive prompts, operator banners, progress lines a log file would ruin. Diagnostics go to a logger. Existing raw-output sites that survive insrc/plugins/*/main.cpp,cloudxr/oob_teleop_*.pyand similar are that deliberate kind; do not "migrate" them, and do not add new ones for diagnostics.- One operator message, one channel. The line rejecting an argument and
the usage block printed straight after it are one message; splitting them
between a logger and
std::coutshows the operator half of it, and underISAACCAPTURE_LOG_SOCKET— wherelocal_sinks()gives a forwarding sink and no console sink — none of the logged half. Judge such a site by the message it belongs to, not by the call on its own line. - A log message some machine greps for is an interface. Before rewording
or re-homing one,
grep -rFthe phrase over.github/,docs/,scripts/andtests/..github/workflows/build-ubuntu.ymlalone waits on three literals and fails fast on eight more, and a miss there does not look like a broken marker — the job waits out its timeout and blames the wrong thing. Note what moving a class name from the message into the logger name costs: the two halves are then separated by the level and pid columns, so no fixed string spans them any more. - Evaluate timed operator reminders on every status snapshot. Gate transition messages on state entry, but do not gate elapsed-time reminders on a transition; repeated snapshots are what advance those timers.
- Six environment variables are the whole external contract. The first
four are read identically by both halves — change one and change both, or
the two stop agreeing:
ISAACCAPTURE_LOGGING(see the next rule),ISAACCAPTURE_LOG_DIR(where log files land),ISAACCAPTURE_LOG_LEVEL(the console threshold every process starts at, the Python leader's included; the six level names and the numeric form, nothing else — spdlog'swarn/errspellings are deliberately not accepted, because Python has no entry for them) andISAACCAPTURE_LOG_SOCKET(set by the session leader; its presence is what makes a process forward instead of owning handlers). The last two belong to the Python half alone:ISAACCAPTURE_NATIVE_CAPTURE=offswitches offcapture_native_output()'s rebinding of the host's fd 1 and fd 2 (a process isaaccapture launches still gets the capture file — its descriptors are not the host's), andISAACCAPTURE_NATIVE_CAPTURE_FILEis written by the leader and read by processes with no interpreter so they can point their own stdio at the same file. Do not invent a seventh. ISAACCAPTURE_LOGGING=offswitches this whole system off; unset or any other value leaves it on. Off means none of it runs — no handler, log file, socket, native capture or thread of its own — and C++ loggers write every level to stderr. A call site whose output would otherwise vanish keeps its pre-system code (print(),basicConfig(), its own handler) behind the check; only that off-path code is exempt from the rules above, since nothing of ours is attached for it to duplicate.- Never rebind the host process's fd 1 or fd 2 outside a scope. This is a
library its host imports; its descriptors are not ours. Output that no logger
can reach — vendor code that formats its own lines onto a descriptor — is
captured either inside
logging_config.capture_native_output(), which restores what it found, or in a process this library launched, whose descriptors are ours to set. There is deliberately no process-wide mode and no import-timedup2(); do not add either back.
Subsystem-internal rules live with the code:
src/python/isaaccapture/logging_config/AGENTS.md
and src/core/log_bridge/AGENTS.md. Read the
relevant one before changing either half.
Comments and docstrings — say it once, briefly
Comments earn their place by recording what the code cannot: a constraint, a measurement, a trap someone already paid for. They are not a place to narrate.
- Default to a few lines. A block comment over ~8 lines, or a docstring
over ~6, needs a reason. If the explanation is genuinely long, it belongs in
a
README.md/ design doc that a reader can skip, not inline where they cannot. - State the fact, drop the argument. "MuJoCo rewrites meshes into their
inertial frame, so STL axes need
mesh_pos/mesh_quat" beats three paragraphs re-deriving why. Keep measured numbers and file/line references; cut the prose around them. - No counts that drift. A comment must not state how many files, rows, components or call sites something currently has. The number is true the day it is written and wrong after the next build or refactor, and nothing fails when it goes stale. State the property instead — "these SDKs share build-ids", not "they share five". A measured number earns its place only when it is a fixed fact about the world (a protocol limit, a benchmark with its date).
- Do not narrate history. "An earlier revision did X and it was wrong" is
what
git logis for. If the wrong approach is tempting enough to warn about, write the warning as a rule — "do not derive this from the mesh" — not as a changelog. - No emphasis-by-shouting. Occasional caps for a single load-bearing word is fine; whole sentences in caps are noise once every third comment has them.
- One statement of a fact, in one place. If a constraint is already in the code, the test name, or an adjacent doc, do not restate it.
This applies to #/// comments, docstrings, and comment blocks in
CMakeLists.txt, pyproject.toml, YAML data files and scene XML.
Commits — DCO sign-off for AI-drafted commits
Any commit whose message is drafted or edited by an AI agent must include
a Signed-off-by: line (Developer Certificate of Origin). Pass -s /
--signoff to git commit, or add the line manually:
Signed-off-by: Your Name <your@email.com>The name and e-mail must match the committer's git identity
(git config user.name / git config user.email).
A commit-msg pre-commit hook enforces this. Install it once per clone
(in addition to the usual pre-commit install):
pre-commit install --hook-type commit-msgRemote pushes
- When moving a focused fix from a release branch onto
main, identify its original base and replay only the fix commits. Do not carry release-only CI changes or duplicate upstream features into the new branch. - Before pushing, compare every URL from
git remote get-url --push --all <remote>with the user-specified owner and repository. Do not infer the destination from the account, remote alias, or branch name. - Before updating an existing pull request, verify its exact head owner, repository, and ref. A similarly named branch does not update that pull request.
Pre-commit — match CI before you stop
- From the IsaacCapture repo root (this directory), run pre-commit and fix all failures before you treat a change as finished (do not only rely on “should pass” reasoning).
Use the same hook set as GitHub Actions:
.github/workflows/pre-commit.yamlruns pre-commit withSKIP=check-copyright-year. Mirror that locally:SKIP=check-copyright-year pre-commit run --all-files- Finish a rebase before the full hook run. While rebase metadata exists,
check-merge-conflictcan mistake an RST heading underline (=======) for an unresolved conflict. --all-filesmeans all tracked files. pre-commit enumerates throughgit ls-files, so a file you have created but not yetgit added is skipped and the run passes for the wrong reason — REUSE andruff formatalike. Stage first (git add -A), then run the hooks.- Format touched Python source with
ruff formatbefore staging. If the pre-commit hook rewrites a file, restage it and rerun the hooks. - REUSE: files covered by the REUSE hook need
SPDX-FileCopyrightTextandSPDX-License-Identifierin the form the repo already uses (for example the HTML comment block at the top ofREADME.mdalso applies toAGENTS.mdand similar docs). - Keep local dependency or toolchain trees outside the repository or ignored:
the REUSE
--fixhook enumerates non-ignored files and can rewrite them. C++ formatting is enforced by CI, not pre-commit. The hook set runs
rufffor Python but does not runclang-format; CI (build-ubuntu.yml) installsclang-format-14and rejects unformatted C++ as-Wclang-format-violations. Before pushing, format touched C++ with the systemclang-format(match CI's version 14) and verify:clang-format -i $(git diff --name-only main -- '*.cpp' '*.hpp' '*.h' '*.cc') clang-format --dry-run --Werror $(git diff --name-only main -- '*.cpp' '*.hpp' '*.h' '*.cc')- If a hook failure shows missing or non-obvious repo policy (not a one-off typo), you must add a short reminder under Mandatory learning loop rules to the right
AGENTS.mdor adjacent//comments so the next run does not repeat it—unless it is already documented.
The wheel SBOM
Published wheels carry a contents SBOM and license evidence derived from the build itself. There is no checked-in dependency registry and adding one would be a second source of truth — declare a dependency the way you already would and it appears in the next wheel's inventory.
When the SBOM step stops the Release build, fix the cause; never exclude a file or
record an assumed license. Remedies: scripts/sbom/README.md ('What stops the Release
build').
The collector is a project of its own: uv run --project scripts/sbom
isaaccapture-sbom .... Its dependency pins live in scripts/sbom/pyproject.toml
and nowhere else — never restate them as --with flags in a workflow or a doc.
Its tests run the same way, through uv; do not register them with the product's
CMake or CTest.
Read scripts/sbom/README.md first if you are
changing anything under scripts/sbom/, changing how a dependency reaches a
wheel, or touching the wheel-packaging steps in build-ubuntu.yml.
A rule changed in one place is changed in none
When a fact is stated in more than one place — a predicate in several modules, a claim in both the code and the docs, a heading over the rows it describes — fixing one instance and leaving the rest is the most common way a correction fails to stick here. It has happened repeatedly: a licence rule enforced in four modules, a design doc contradicting its own collector, a per-row reason corrected under a heading that still said the opposite.
- Grep for the claim, not the line you edited. Search the phrase, the
predicate, the constant — across
docs/,scripts/,tests/and the code — and fix every hit in the same pass. - Prefer one authority to a swept duplicate. If the same rule has to hold in several places, give it one definition and call it; the sweep is what you do when you cannot.
- Verify against output, not against the test suite. Several of these passed every test while producing wrong artifacts. Regenerate and look.
Mandatory learning loop (AGENTS.md and comments)
Hard requirement: When any of the following happens, you must complete steps 1–3 before you end the session or move on as if the work were complete:
- The user is dissatisfied or corrects your approach (wrong layer, scope, style, or a fix that does not stick).
- Pre-commit or CI fails on something you or another agent could hit again (linters, REUSE/SPDX, formatting, policy hooks, etc.).
- You repeat the same category of error after a correction.
You must:
- Distill what went wrong into a short, reusable pattern (a rule or boundary, not a chat transcript).
- Update the right artifact in the same working pass as the fix: prefer the most local
AGENTS.mdfor package- or subtree-level rules; use the repo rootAGENTS.mdonly for expectations that span the whole tree; put volatile or line-specific detail in//comments next to the code. - Respect scope vs
main(below): only addAGENTS.mdbullets for this branch’s delta tomain(or the agreed base), not for behavior that already exists on the base branch.
You must not skip documentation updates because the user did not say “update AGENTS.md”—failed checks and repeated mistakes trigger this loop automatically.
What belongs in AGENTS.md
- High-level expectations: boundaries between layers, what to avoid, naming or structural conventions, CMake/include policy at a glance, “always / never” rules that stay true across refactors.
- Style of work: how minimal to keep diffs, when to ask for clarification, how this subsystem should relate to OpenXR/schema/deviceio, etc.
- For build-only requests, use the documented CMake flags and environment first (for example
-DISAAC_TELEOP_PYTHON_VERSION=...) rather than patching build files to select options.
What does not belong in AGENTS.md
- Low-level or volatile detail: exact call sequences, field-by-field semantics, long checklists tied to one function, anything that will go stale the next time the code moves.
- Put that in comments in the source files where the behavior lives (short
//notes: intent, invariants, or “do not X because …”).
Scope — document what this branch changes, not main
- New or updated bullets should capture learnings from the delta between this branch (or commit) and
main(or whatever long-lived base you are targeting—release branch, parent MR, etc.). - Do not restate facts that already hold on
mainjust because this branch touches nearby files. If behavior landed in the base history, it belongs in code comments next to that code or in main’s docs—not as “new” guidance in anAGENTS.mdintroduced only to support a smaller follow-up change. - Example: schema- or API-level choices that merged before this branch are out of scope for
AGENTS.mdedits tied to this branch; they add churn and read like stale noise after merge.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

