Skip to main content

nested_instructions

Function nested_instructions 

Source
pub fn nested_instructions(worktree: &Path) -> Option<String>
Expand description

Nested CLAUDE.md / AGENTS.md files — scoped rules that apply to one subtree (car#1071).

§Why git ls-files rather than a directory walk

Tracked-ness is doing two jobs at once here, and both matter.

It is the relevance filter. A plain recursive walk of CAR’s own checkout finds 16 instruction files; git ls-files finds 2. The other 14 are five nested .claude/worktrees/ checkouts of this same repository and four extracted bench/coder-ab fixtures — copies and test data, none of them guidance about the code under work. A skip-list would have to grow a new entry every time someone adds a build or scratch directory, and would be wrong until they did.

It is also the trust filter, which is the more important half. This text lands in a system prompt. A tracked file is one a maintainer committed and review saw; an untracked one is anything that happens to be sitting in the worktree — including a file the model itself just wrote. Reading untracked instruction files would let a session author its own rules mid-run and have them injected as maintainer intent on the next iteration.

§Inlined, not merely indexed

available_skills indexes rather than inlines, because five skill bodies would swamp the prompt and a skill is opt-in by nature. Nested instruction files are the opposite case: they are small (CAR’s is 1.2KB), they are not optional, and the failure they prevent is silent. car-ffi-napi/CLAUDE.md opens with “These bugs cost many hours. Do not reintroduce them.” — a pointer to that is a rule the model has to choose to follow, and this module’s header already names “loading the pointer, not the rule” as a known way this goes wrong.

Budgets keep that honest for a repo unlike this one: at most [MAX_NESTED_FILES] files, [MAX_NESTED_FILE_BYTES] each and [MAX_NESTED_INSTRUCTIONS_BYTES] combined. Anything past a budget is listed as a path the model can read_file, so a monorepo degrades to pointers instead of blowing the context — and is told that is what happened.

Each block is labelled with the directory it governs, because a scoped rule presented without its scope reads as a global one.