Constrain agents to read files only through notevi — enforcement comes from harness config; AGENTS.md is navigation guidance only, never the constraint. ── files here ────────────────────────────────────────────────────────────── claude-settings.json project install: /.claude/settings.json (hook path uses $CLAUDE_PROJECT_DIR) claude-headless-settings.json no-install variant for `claude -p --settings` (hook path is absolute into this dir) notevi-only-guard.sh PreToolUse hook: blocks cat/rg/sed/... and jj/git content reads; its error message points the agent at `notevi -doc`, so agents converge even with zero instructions notevi-only.rules codex execpolicy rules (allow notevi, forbid readers) AGENTS.md how-to-navigate-with-notevi guidance for the repo ── one-time setup ────────────────────────────────────────────────────────── put it on PATH: go build -o ~/.local/bin/notevi . (repo root) one binary now: agents call `notevi read/grep/note`, and you read the trace back with `notevi web` ── running a constrained CLAUDE investigation ────────────────────────────── From the target jj repo dir: claude -p --settings /constrain/claude-headless-settings.json \ --allowedTools 'Bash(notevi)' 'Bash(notevi:*)' \ < prompt.txt > report.md ( is wherever this repo lives; the settings file's hook path is absolute into this directory, so it must be spelled out in full) - --allowedTools on the CLI is required headless: allow rules inside settings are IGNORED until the workspace is trusted (deny rules and the hook always apply). Interactive use instead: install claude-settings.json + hook into the repo's .claude/, open once, accept the trust dialog. - put the prompt on stdin; a positional prompt after --allowedTools gets eaten by the flag's list parsing. ── running a constrained CODEX investigation ─────────────────────────────── cp notevi-only.rules ~/.codex/rules/ # activate (GLOBAL: constrains # every codex session while there) codex exec -s danger-full-access "$(cat prompt.txt)" > report.md rm ~/.codex/rules/notevi-only.rules # deactivate when done - danger-full-access is required: workspace-write blocks jj metadata writes, including the sidecar rewrite and `notevi read`'s working-copy snapshot. - enforcement is pre-exec by codex's execpolicy engine, even through `zsh -lc` wrappers; validate rules with: codex execpolicy check --rules notevi-only.rules -- cat foo.txt ── shared trace + rendering ──────────────────────────────────────────────── - notevi creates one anonymous sidecar change directly under jj's root() on the first append. The repo-local alias notevi_log names it; git.private-commits protects it from accidental pushes. No path or environment setup exists. - A repository last written by the older `vr` tool is renamed in place the first time notevi touches it; `notevi migrate ...` does it up front. - Multiple agents in the repo share that sidecar. Rewrites are serialized, note ids are assigned under the same lock, and the project @ is untouched. - The sidecar has no bookmark and is local-only. It does not survive a fresh clone; include the jj repository in backups when the trace matters. - In the prompt, tell the agent to leave pinned notes (notevi note -f FILE:START-END -t kind "...") — that is the payload. - Read traces afterwards from one process. Bare `notevi web` scans below ~ at startup and when Refresh is pressed, then offers every repo with a sidecar: notevi web Its explicit buttons can start an empty private sidecar in a discovered jj repo or initialize colocated jj in a discovered Git repo. The project index is only in memory; those two requested metadata changes are the only writes. - To bypass the dashboard and serve one repository directly: notevi web -repo -title "..." or take a static copy to hand around (one change, no server features): notevi web -repo -out site -title "..." `notevi web -h` explains both, and what a log needs to be worth reading. ── known holes (accepted) ────────────────────────────────────────────────── Scripting runtimes (python/node/perl) can still open files — uncomment their rules in notevi-only.rules / extend the hook to close, at the cost of breaking legitimate scripts. Neither harness constrains its own non-shell internals beyond what the deny rules cover. Codex's rules file is global-only; there is no per-project rules mechanism (probed, none exists as of codex 0.145).