Skip to content

Say the kitty caveat once per session - #4

Merged
guohai merged 1 commit into
mainfrom
fix/hint-once
Sep 11, 2026
Merged

guohai merged 1 commit into
mainfrom
fix/hint-once

Conversation

@guohai

@guohai guohai commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

The approximate-capture hint fired on every kitty capture, four lines at a time,
because kitty is always approximate. A warning that is true 100% of the time
carries no information and buries the specific ones. It interrupted tcap | llm
worst.

One line, once per session, pointing at tcap doctor. The caveat still appears
in the # note: header, "approximate": true, doctor and both READMEs.

Verified live: three piped captures, one line on the first, silence after.

Generated with SMT smt@agora.build

The approximate-capture hint fired on every kitty capture, four lines at a time,
because kitty is *always* approximate. A warning that is true 100% of the time
carries no information — it just trains the reader to skip it, and it buried the
hints that are specific. It interrupted `tcap | llm` worst, which is the workflow
the README leads with.

Now one line, once per session, pointing at `tcap doctor` for the detail. The
caveat still appears where it is read deliberately: the `# note:` header line,
`"approximate": true` in --json, doctor, and both READMEs. `--quiet` still
silences everything.

Note the captured text itself was never printed when piping — it goes to the
pipe, as expected. Only this hint reached the terminal.

🤖 Built with SMT <smt@agora.build>
@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Reviewed the merge ref (ce21615, diff vs 0df4659). The change is small and the security posture is fine — the new marker file contains no captured text, goes through secure_write (0600, O_NOFOLLOW, owner-checked dir), and the key is sanitized. src/backend/tmux.rs and shell/ are untouched, so the coordinate arithmetic and $?/argv invariants are unaffected.

Three issues, one of which I'd call a bug.

src/state.rs:77 — the failure mode is inverted relative to its own comment.

// If the note cannot be recorded, saying it again is the safer failure.
secure_write(&path, b"1").is_ok()

is_ok() returns false when the write fails, and false means don't say it. So when the note can't be recorded, the caveat is suppressed entirely rather than repeated — the opposite of the stated intent. This bites exactly where it matters: a read-only or full $TMPDIR, or a state dir ensure_state_dir rejects because another uid owns it. In that state load() also returns empty, so there's no shell metadata either — the user gets an unannotated, unattributable kitty capture with no warning at all. What the comment describes is:

let _ = secure_write(&path, b"1");
true

src/main.rs:257 — "see tcap doctor" points at output that doesn't cover this. I read doctor::run and Kitty::diagnose: doctor reports the kitty binary, remote-control reachability, window match, "shell integration: last_non_empty_output resolves", and history depth (-c 2 needs tmux). Nothing there says output may belong to an earlier command. The old message carried the two concrete causes and the fix (tmux records exact boundaries); the new one drops both and redirects to a page that never explains it. Since this line now fires only once per session, and in --output/--raw it's the only signal (the # note: header exists only in annotated mode), it's worth keeping the one actionable word — tmux — rather than the doctor pointer, or adding a line to doctor's kitty diagnostics.

src/state.rs:72 — "once per session" is really "once per $TMPDIR lifetime". Nothing ever removes <session_key>.said-approximate, and session keys are reused: KITTY_WINDOW_ID restarts at 1 for each new kitty process, TMUX_PANE at %0 for each new server. Quit kitty and reopen it and the first window inherits the previous run's marker, so the caveat is never shown again until /tmp is cleared — while the message asserts "Shown once per session". The stale-.jsonl equivalent is pre-existing, but a suppression marker is more consequential than a stale log. Keying off something that dies with the session (e.g. requiring the log to be non-empty, or writing the marker alongside a session-start sentinel) would make the promise true.

Minor: first_time has no test, in a module where capture_marker_round_trips_and_is_consumed_once exists precisely because the marker file was otherwise unexercised. A three-line test (first_time("x") true, then false) would have caught the is_ok() inversion if it stubbed a failing write.

Version bump is consistent across Cargo.toml, Cargo.lock and npm/package.json (0.1.2). I wasn't able to run cargo test here — the command needed approval — so this is a static review.

@guohai
guohai merged commit f6343bb into main Sep 11, 2026
4 of 5 checks passed
@guohai
guohai deleted the fix/hint-once branch September 11, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant