Follow-up to #1530, which was closed on 2026-07-18 without the guard landing in the repo. Re-opening the topic as a fresh issue because the original framing turned out to be too narrow in a way that matters: implementing it literally would still let captures through.
What ships today
LifeOS/install/hooks/ContextReduction.hook.sh already knows about this hazard and mitigates it (lines ~187-193): it rewrites a matching command into a subshell that cds into /tmp/pai-screenshots first, so the capture doesn't land in the cwd.
elif echo "$MATCH_CMD" | grep -qE '^interceptor[[:space:]]+screenshot([[:space:]]|$)' && echo "$MATCH_CMD" | grep -qE -- '--save'; then
REWRITTEN="${ENV_PREFIX}mkdir -p /tmp/pai-screenshots && ( cd /tmp/pai-screenshots && $CMD_BODY )"
The hook's own comment states the goal: "Prevents stray interceptor-screenshot-*.jpg files from landing in the cwd (typically ~/.claude) when a subagent calls the command without the skill's cd /tmp/pai-screenshots prefix."
The gap
That rewrite is a command-pattern match, so it is best-effort by construction. It only fires for a command whose text matches that regex at position 0. It does not fire when the binary is reached some other way — a wrapper script, an alias, a different tool invoking it, a shape the regex doesn't anticipate.
When it doesn't fire, the capture lands in the cwd, which for LifeOS work is typically ~/.claude. There the file is untracked but not ignored, and nothing shipped upstream makes it ignored: the repo-root .gitignore governs the LifeOS repo itself, and the installer does not materialize a .gitignore for the installed ~/.claude.
That matters because keeping ~/.claude under git with a private remote is a common and reasonable backup practice for an install. A routine git add -A then sweeps the captures into a commit and pushes them. On one install, 21 stray captures (~9 MB) accumulated in the repo root before anyone noticed.
Why this is worth a guard rather than a shrug: these are screenshots of pages taken during verification. They can contain authenticated sessions, customer data, anything that was on the page. A file that silently rides into a backup commit is a privacy failure mode, not a housekeeping annoyance.
The part that makes #1530's framing unsafe
#1530 is titled for interceptor-screenshot-*.png. The hook's own comment says .jpg.
Anyone implementing the closed issue literally would anchor the ignore rule on .png — and miss the extension that upstream's own code comments document. This is not hypothetical: on an install running the .png-anchored rule, four stray .jpg captures appeared in the repo root on 2026-07-21 and went straight past it. The rule had to be widened the same day.
The general lesson: anchor the guard on the name, never on an extension. A tool can change output format without announcing it, and the guard should not care.
Proposed fix
Ship a name-anchored ignore rule for the installed ~/.claude — as part of whatever the installer writes, or as a documented snippet the installer appends:
# Interceptor verification captures — never commit these.
# Anchored on the NAME, not an extension: the capture format is not guaranteed
# (both .png and .jpg have been observed) and a format change must not silently
# reopen the hole.
interceptor-screenshot-*
interceptor-capture-*
Two notes on the shape of the fix:
- Keep the ContextReduction rewrite. This is defense in depth, not a replacement. The rewrite keeps the working tree clean in the common case; the ignore rule is the durable backstop for the cases the pattern cannot catch.
- Pair it with housekeeping if you want the tmp dir bounded — a short-TTL prune of
/tmp/pai-screenshots (trash, not delete) keeps the redirect target from growing without bound. Optional; the ignore rule is the part that closes the privacy hole.
Verified against the repository as it stands today: LifeOS/install/hooks/ContextReduction.hook.sh contains the rewrite quoted above, and a search for interceptor-screenshot across the repo returns only that hook and SystemUserBoundary.md — no ignore rule anywhere.
Follow-up to #1530, which was closed on 2026-07-18 without the guard landing in the repo. Re-opening the topic as a fresh issue because the original framing turned out to be too narrow in a way that matters: implementing it literally would still let captures through.
What ships today
LifeOS/install/hooks/ContextReduction.hook.shalready knows about this hazard and mitigates it (lines ~187-193): it rewrites a matching command into a subshell thatcds into/tmp/pai-screenshotsfirst, so the capture doesn't land in the cwd.The hook's own comment states the goal: "Prevents stray
interceptor-screenshot-*.jpgfiles from landing in the cwd (typically~/.claude) when a subagent calls the command without the skill'scd /tmp/pai-screenshotsprefix."The gap
That rewrite is a command-pattern match, so it is best-effort by construction. It only fires for a command whose text matches that regex at position 0. It does not fire when the binary is reached some other way — a wrapper script, an alias, a different tool invoking it, a shape the regex doesn't anticipate.
When it doesn't fire, the capture lands in the cwd, which for LifeOS work is typically
~/.claude. There the file is untracked but not ignored, and nothing shipped upstream makes it ignored: the repo-root.gitignoregoverns the LifeOS repo itself, and the installer does not materialize a.gitignorefor the installed~/.claude.That matters because keeping
~/.claudeunder git with a private remote is a common and reasonable backup practice for an install. A routinegit add -Athen sweeps the captures into a commit and pushes them. On one install, 21 stray captures (~9 MB) accumulated in the repo root before anyone noticed.Why this is worth a guard rather than a shrug: these are screenshots of pages taken during verification. They can contain authenticated sessions, customer data, anything that was on the page. A file that silently rides into a backup commit is a privacy failure mode, not a housekeeping annoyance.
The part that makes #1530's framing unsafe
#1530 is titled for
interceptor-screenshot-*.png. The hook's own comment says.jpg.Anyone implementing the closed issue literally would anchor the ignore rule on
.png— and miss the extension that upstream's own code comments document. This is not hypothetical: on an install running the.png-anchored rule, four stray.jpgcaptures appeared in the repo root on 2026-07-21 and went straight past it. The rule had to be widened the same day.The general lesson: anchor the guard on the name, never on an extension. A tool can change output format without announcing it, and the guard should not care.
Proposed fix
Ship a name-anchored ignore rule for the installed
~/.claude— as part of whatever the installer writes, or as a documented snippet the installer appends:Two notes on the shape of the fix:
/tmp/pai-screenshots(trash, not delete) keeps the redirect target from growing without bound. Optional; the ignore rule is the part that closes the privacy hole.Verified against the repository as it stands today:
LifeOS/install/hooks/ContextReduction.hook.shcontains the rewrite quoted above, and a search forinterceptor-screenshotacross the repo returns only that hook andSystemUserBoundary.md— no ignore rule anywhere.