feat(settings): configurable close-confirmation policy for tab and quit#142
Merged
Conversation
abe7dc5 to
4486df7
Compare
This was referenced Jul 5, 2026
4486df7 to
e88a9bf
Compare
Collaborator
Author
|
Applied the code-review findings (all five) in
|
Add a `close` block to settings.json letting the user choose, per action,
whether closing prompts first:
"close": { "tab": "confirmWhenActive", "app": "confirmWhenActive" }
Each of `tab` (tab close) and `app` (app quit) takes one of alwaysConfirm /
confirmWhenActive / noConfirmation. One pure decision seam,
ConfirmClose::confirms(active), backs both paths.
confirmWhenActive reuses the running-process predicate from #140: a tab keys
off App::tab_has_running_process, a quit off the new App::any_running_process
(both over LiveSession::has_running_process, single-sourced in core), so an
idle shell closes/quits silently while a working shell or a live Claude
confirms.
Both actions default to confirmWhenActive, which preserves #140's shipped
tab-close behaviour and extends the same predicate to the quit path — so an
all-idle app now quits without a prompt. alwaysConfirm / noConfirmation are the
new opt-in overrides. The quit prompt now counts open sessions honestly ("N
open session(s) will be force-stopped — any running work is lost") instead of
claiming Claude is always the victim.
Known gap: the predicate reads a plain shell running a non-Claude foreground
program (vim, a long make) as idle, so it can be closed/quit silently —
better foreground-process detection is tracked in #143.
Closes #80.
e88a9bf to
52b6e24
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Make close confirmation configurable, per action, via
settings.json:tab(tab close) andapp(app quit) each take one of:alwaysConfirm— always promptconfirmWhenActive— prompt only while a session is running a foregroundprocess (a working shell or any live Claude); an idle shell closes/quits
silently
noConfirmation— close immediatelyBoth default to
confirmWhenActive. Either field may be omitted.Relationship to #140 / #79 / #80
A config layer over #140 (which landed the running-process predicate in core and
closed #79):
confirmWhenActivereuses feat(shell): confirm tab close only when a process is running #140's predicate — a tab keys offApp::tab_has_running_process, a quit off the newApp::any_running_process(both over
LiveSession::has_running_process, single-sourced in core).predicate to quit — an all-idle app now quits without a prompt. Closes Confirm app quit when a process is running #80.
alwaysConfirm/noConfirmationare the opt-in overrides.How
ConfirmCloseenum (camelCase serde) +CloseSettings { tab, app }insettings.rs, defaultconfirmWhenActivefor both.ConfirmClose::confirms(active) -> bool; the callersupplies the predicate.
App::any_running_processadded incorenext totab_has_running_process(so close and quit never re-derive "is something running?" in two places).
request_close/request_quitconsult the policy; feat(shell): confirm tab close only when a process is running #140's"pending-confirmation owns the interaction" guard is preserved.
force-stopped — any running work is lost") rather than always naming Claude;
quit_prompt(0)degrades to a plain "Quit TermHerd?".Known gap (tracked)
The predicate reads a plain shell running a non-Claude foreground program
(vim, a long
make) as idle, so it can be closed/quit silently. Betterforeground-process detection is filed as #143; users who want the safe
behaviour today can set
"close": { "app": "alwaysConfirm" }.Tests
core—any_running_processspans tabs (idle → false, one Busy anywhere →true).
settings.rs— defaults, camelCase round-trip,confirmstruth table,partial-block fill.
shell.rs—noConfirmationcloses without arming;confirmWhenActiveprompts while running then skips once exited; an idle-but-live session quits
silently under the default (the Confirm app quit when a process is running #80 headline);
alwaysConfirmprompts withnothing running;
noConfirmationquits past a running session.Full workspace green;
fmt+clippy -D warningsclean.Closes #80. Built on #79/#140. Known gap: #143.