Hide background check-ins
Collapses the trailing status message a session posts when its own background job wakes it back up — a build, a test run, a Monitor watch, a scheduled wake-up — into a single quiet one-line marker you can click to expand. Covers which turns fold, which never do, the setting that controls it, and the rules that decide.
What it is
When a Claude Code session kicks off a background job — a Bash command with run_in_background: true, a --cloud test or build, a Monitor watch, a scheduled wake-up — and that job finishes, the Claude Code harness wakes the agent back up and it posts a short trailing message. That message is almost always a status/progress report of the background work, not an answer to you: "Tests green (exit 0). Build still running on the VM.", "Typecheck passed — 2 of 3. Lint still running."
Omniscio already handled most of this: it hides the wake-up prompt, it gives the reply its own visual turn so it can't bury your previous answer, and it suppresses the Needs You inbox flip (that's the separate waiting detector). The one remaining bit of noise was that the trailing status line still showed in the transcript. Hide background check-ins collapses it: a confirmed background acknowledgment turn renders as a single, quiet one-line marker — just the label and a timestamp, with no preview of the status text —
› 🤖 Background check-in 10:27 PM
— that you can click to expand into the full turn. The marker hugs its text (it doesn't stretch across the chat), matching the Auto-waited notice right beside it. It's also deliberately label-only: the status reply often carries colored emoji (e.g. ✅) that paint their own bright color regardless of the muted row, so a preview was visually noisy — it's dropped, and you expand to read it. Nothing is deleted. Turning on Show system messages for a session reveals these turns whole, for auditing.
On by default. Turn it off at Settings → Sessions → "Hide background check-ins".
One special case — the "nothing to do" wake-up. When a background event wakes a finished session that genuinely has nothing left to do, it posts a short no-op sign-off ("Nothing to do here…", "Nothing further to do.", "…nothing further needed."). For Claude sessions Omniscio already removes the exact instructed sentence automatically (a separate, always-on tidy). This feature additionally collapses the natural rewordings — and is the one path that reaches Codex / non-Claude sessions, which never emit Omniscio's exact wording. And when that no-op comes from a mechanical resume — a rate-limit-recovery or lb-rebalance "Please continue" that fired on its own, not something you asked for — it now collapses by default, no setting needed: a re-verification like "Everything was already complete… nothing further needed." shouldn't take over your screen or push your real answer out of view. Progress reports ("tests green") on such a resume still honor the opt-in setting.
And the "verify, then sign off" wake-up (2026-08-05). A very common shape: a background job finishes, the session wakes, runs a quick check or two to be sure, writes a sentence or two about what it found, and then ends with Omniscio's exact "Nothing to do here. Everything was already finished before this background wake-up." Because a short preamble comes before the sign-off, the always-on tidy (which only removes a message that is nothing but the sentence) correctly leaves it visible. This feature now collapses that whole turn to the one-line marker by default — one click still shows the check it ran — so a double-check that changed nothing doesn't sit between you and the real answer above it. It stays strictly scoped to a short, plain sign-off: a turn that carries a real answer (a heading, a bullet list, code, or a question) is never folded, and the permanent (un-expandable) tidy is untouched — this is only the reversible, one-click collapse.
Reworded no-ops — "nothing left to run" (2026-08-05). The "nothing to do" family now also recognizes the run phrasing — "nothing further/more/left to run" — and it takes priority over a progress phrase in the same sentence. So a wake-up note that says both "the deploy finished" and "there's nothing left to run" is treated as the terminal no-op it is, and the real answer above it stays in view instead of being folded away. (Previously that combination was read as a plain progress report, so the one-line answer in a "Push to Remote" session could end up tucked behind the activity pill while the wake-up note became the visible final message — the reported bug.)
Two more paraphrases — "nothing left to check" and "no wait needed" (2026-09-27). A session answering Omniscio's own auto-nudge check-in closed with "…the fix is finished and tagged, and the land is the auto-lander's job … No wait needed, nothing left to check." Because the nudge row is dropped from render, that reply stood alone in the transcript as a green bubble with no context — machine traffic you had no reason to read. The turn was ack-eligible (the dropped nudge opens it, so the detector did run); it simply matched no rule, because the agent had paraphrased Omniscio's instructed sentence into its own words. Two additions close that: the check phrasing joins the same nothing <further/more/left> to <verb> shape ("nothing further/more/left/… to check"), and a new no-wait-needed rule catches the terminal "you can stop waiting" sign-off ("no wait needed" / "no … waiting needed") — a cue the family had never covered, since it is anchored on "nothing", "no further action" and "no longer". Both sit in the nothing-to-do category, so they default-fold (isAutoResumeNoOpAck) rather than waiting on the opt-in setting.
Where to find it
How to use it
- Turn it off: Settings → Sessions → Hide background check-ins (on by default). The change is live — already-open conversations collapse/reveal immediately, no restart.
- Expand one: click the marker. The full turn appears and the marker becomes a collapse control; click again to re-collapse.
- Consecutive check-ins batch automatically. When two or more collapsible check-ins appear in a row (common with parallel background jobs — builds, tests, lints finishing one after another), they collapse into a single grouped marker — "5 background check-ins" — instead of five separate one-liners. Click the batch marker to expand all of them, then click any individual marker to see that turn's full content. Two-level collapse: batch → individual markers → full turns.
- See them all (audit): the per-session Show system messages toggle (session ⋯ menu) reveals every background check-in turn in full, regardless of this setting.
How it behaves
What it does NOT do
- It never hides a turn that asks you a question. Any
?(or a multiple-choice-widget shape) in the reply means the turn is addressing you — it always renders in full. The same "question always wins" rule the waiting detector uses. - It never hides real work. A reply with a heading, a bullet list, a long answer, or a code block is a deliverable, not an acknowledgment — it's never collapsed. (This reuses the same backtested "is this a real message?" heuristic that decides what to promote out of the activity pill.)
- It only acts on genuine self-resumes. A turn is eligible only when it was opened by a resume the agent did not author — EITHER the harness re-invoking the agent after its own background work (a durable
turnBoundarymarker Omniscio stamps) OR a dropped, system-injected auto-response resume (a rate-limit-recovery / lb-rebalance "Please continue" that carries no stamp — added 2026-06-30) — AND the reply matches an acknowledgment pattern. A normal reply that merely happens to say "tests green (exit 0)" in answer to you is never collapsed — both halves must agree. - It never collapses a turn that is still running. A live, in-flight status update stays fully visible; only a settled turn can collapse.
- It always keeps the most recent check-in visible. Only older check-ins of a run fold; the newest one of each run stays fully expanded. So when a waiting session times out and surfaces to your inbox, opening it always shows the last thing it said — the reason it pinged you — never a content-less marker. This mirrors how the Auto-waited notice keeps its newest entry of each run visible.
- It never stacks two collapsed rows for one message. A background self-resume whose reply also declares a wait ("…Waiting on the build to finish.") trips both this feature and the Auto-waited collapse. With both settings on it would have folded into two stacked markers ("Background check-in", then "Auto-waited") that took two clicks to get past; instead the turn collapses to a single ⏱ Auto-waited marker — the wait label wins — so it's one click to the message, which still carries its inline ⏱ badge.
- It never hides a turn that ends the session. When a session archives itself (its agent decides its work is done) or is auto-archived, that turn carries a "Self-archived — the agent ended its own session." / "Automatically archived — …" note — a terminal event you asked to see. Even when the sign-off reads like a routine "nothing to do" check-in, the turn is treated as a first-class landmark and always renders in full, never folded into a background check-in batch. This is why a self-archive that lands at the end of an auto-continue run stays visible instead of being buried in the collapsed group (the 2026-08-18 report).
- It doesn't delete or alter any data. The full turn is still in the conversation and the database; this is purely a display collapse, reversible by a click or by "Show system messages".
- It does not change which sessions land in your inbox. That's the waiting detector's job; this feature only changes how an already-settled turn renders.
For agents
How it works (technical)
Two halves, AND-gated — either alone is not enough:
- Structural half — the reply turn must have been opened by a self-resume the agent did not author: EITHER a
metadata.turnBoundarystamp (the durable mark Omniscio writes when the harness re-invokes the agent after background work / a wake-up) OR a turn split off at a dropped, system-injected auto-response resume (a rate-limit-recovery / lb-rebalance "Please continue", which carries no stamp — the builder tracks this asopenedByResumeoffcurrentTurnOpenedByAutoResume, added 2026-06-30 so a no-op reply on that stampless path is eligible too). This is what distinguishes a genuine background acknowledgment from a normal reply that happens to use status vocabulary. - Content half — a small regex library (
BACKGROUND_ACK_PATTERNSinsrc/shared/background-ack/patterns.ts, categories exit-code / check-result / progress-tally / still-running / nothing-to-do) matched against the turn's reply prose bydetectBackgroundAck(src/shared/background-ack/detect.ts). Before the pattern match, three guards reject non-acks in order: a 500-character length cap, a question veto, and a deliverable veto (heading / list / long prose / code fence). Deliberately distinct vocabulary from the waiting detector — that one matches the hold ("standing by"), this one matches the completion/progress report ("exit 0", "tests green", "0 errors", "N of M", "build still running", "merge/install still running") that precedes it, plus the woken no-op sign-off ("nothing to do here", "nothing further to do", "no further action needed", "no longer needed / already worked around", "nothing left to check", "no wait needed").
The turn builder (src/shared/real-conversation-turns.ts) AND-gates the two halves and stamps turn.isBackgroundAck. The actual hide is a live render decision in the shared computeTurnFoldState predicate (src/renderer/src/lib/turn-fold-state.ts, read by both TurnGroup and the scroll index) — the on/off setting is read fresh at render, never baked into the cached turn — so toggling the setting flips the view instantly. The render gate also requires nextTurnIsContinuation (more agent activity follows this turn before your next message), which keeps the newest check-in of each run visible — the same newest-of-run carve-out the auto-wait marker uses. One exception (2026-06-30): a woken no-op ack (turn.isWokenNoOpAck — the reply is Omniscio's exact instructed "Nothing to do here…" sentinel) folds even when it is the newest of its run AND folds regardless of the opt-in setting, because the exact sentinel is unambiguous and a no-op never re-pings — mirroring how isCanonicalSentinelWait default-folds. This is what keeps a rate-limit-recovery no-op from standing between you and the real answer above it (the buried-final-answer fix). A second default-fold (2026-07-03, extended 2026-08-12): turn.isAutoResumeNoOpAck — a nothing-to-do ack (the exact sentinel OR a natural reword like "…nothing further needed", "…no further action needed", "…no longer needed / already worked around", "…nothing left to check", or "…no wait needed") whose turn was opened by a mechanical auto-resume (rate-limit-recovery / lb-rebalance, or a spontaneous background wake) OR a Claude turnBoundary self-resume split that follows a real answer — also folds by default and even as the newest of its run, and (per the same scroll-skip rule) the picker skips its ref-less marker so the view rests on the real answer above. It is scoped to the nothing-to-do category, so a progress ack on a mechanical resume still honors the opt-in setting. Since 2026-08-15 the backend also suppresses the redundant re-ping for such a reworded no-op on an already-waiting session (previously only the exact sentinel was), so a leftover-task wake like "…no longer needed" neither re-chimes nor sits between you and the real answer above it — the live 314c48ac leak. A third default-fold (2026-08-05): turn.isTrailingWokenNoOpAck — a background-wake self-resume whose reply ends with Omniscio's exact "Nothing to do here…" sentence after a short verify/preamble (the "woke, ran a quick check, then signed off" shape that the whole-message hard-hide and isWokenNoOpAck both miss, since a preamble precedes the sentence). Detected by detectTrailingWokenNoOpSentinel (a strict complement of detectWokenNoOpSentinel — the no-preamble whole-message case returns false, so the irreversible hard-hide stays whole-message-exact) and AND-gated on isBackgroundAck, so the same substantive veto (≤500 chars / no heading / list / code fence / question) has already spared any real deliverable. It folds by default and even as the newest of its run, to the same reversible one-line marker — never the irreversible hide. When a turn is flagged BOTH a background-ack and an auto-wait, that same predicate suppresses the background-ack collapse so the turn folds as one Auto-waited marker (the auto-wait fold wins) — see waiting-detector.md. Audit mode (Show system messages) makes the builder leave the flag false, so those turns always render whole.
Batch grouping (display-only, 2026-07-29). When two or more consecutive turns are all ackCollapsible, the renderer groups them into a single batch marker ("N background check-ins") instead of N separate one-line markers. The grouping is computed by computeAckBatchGroups (src/renderer/src/features/sessions/ack-batch-groups.ts) — a pure function that scans the turns array for consecutive runs and returns a lead-count map (first turn of each run → count + last turn) and a follower-to-lead map (every other turn → its lead's key). RealConversationList runs this in a useMemo pre-pass, owns the expand/collapse state in a useState<Set<string>>, and passes batch info as props to TurnGroup. When collapsed, follower TurnGroups return null and the lead renders a BackgroundAckBatchMarker; when expanded, each individual turn renders its own BackgroundAckMarker. Two-level collapse: batch → individual markers → full turns.
Archive-note landmark veto (2026-08-18). A turn carrying a self-archive / auto-archive note ("Self-archived — …" / "Automatically archived — …", recognized by isArchiveNote in src/shared/archive-note.ts on the turn's system rows) is a first-class terminal landmark: computeTurnFoldState computes hasArchiveNote once and refuses every whole-turn fold for it — the background-ack collapse, the woken-no-op hard-hide, and the auto-wait fold — exactly as it already protects a compaction divider. Without it, a self-archive reply — which naturally reads as a "nothing to do" sign-off ("…nothing left to receive or decide, so I'll close this session out.") and rides an auto-continue "Please continue" resume — set both isBackgroundAck and isAutoResumeNoOpAck, so it default-folded into the "N background check-ins" batch and hid the session's own ending two clicks deep (the reported bug). Detection is content-based and system-rows-only, so a normal agent reply can never trip it, and it reads only existing render-time fields, so no turns-cache version bump is needed. See background-ack-detector-contract.md (archive-note-landmark-veto).
Like the waiting detector, the pattern library is proven against your real history by a read-only live-DB backtest (scripts/background-ack-backtest.mjs) that must show zero false positives in the would-hide sample before any pattern change ships. On the build's first run it flagged 870 would-hide turns across the corpus with 0 false positives; the 2026-06-11 broadening (background-operation jobs like "merge/install running", plus clean-count results like "0 errors") took the corpus figure to 1,557, still with 0 false positives; the 2026-07-03 addition (the nothing-further-needed reword family + the mechanical-resume default-fold) matched exactly 1 corpus row — the target rate-limit-recovery reply — with 0 false positives; the 2026-08-12 addition (the no-further-action-needed rule + the turnBoundary reword-fold) held 0 false positives across 73 would-fold rows; the 2026-08-15 addition (the no-longer-needed leftover-task rule + backend re-ping suppression for reworded no-ops) matched exactly 1 corpus row — the target 314c48ac leak — with 0 false positives; and the 2026-09-27 addition (nothing <left/more> to check + the no-wait-needed rule) matched exactly 1 corpus row — the target auto-nudge leak — with 0 false positives across all 60,269 agent rows scanned, and 12/12 adversarial inline cases clear.
Related
- waiting-detector.md — the sibling system that suppresses the Needs You inbox flip for the same self-resume turns (the hold; this page is the acknowledgment). Same design: regex rules + a mandatory live-DB backtest.
Last verified 2026-10-06