aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-14 18:02:41 -0500
committerCraig Jennings <c@cjennings.net>2026-06-14 18:02:41 -0500
commitdedbca326fe0337ae9c678a8579810a6c475a256 (patch)
tree4f436ab42f596d2a21fb99d8e3d72631952d1faf
parentbbd07b6611fcb9bb5ea962adb02cea53a509c780 (diff)
downloadrulesets-dedbca326fe0337ae9c678a8579810a6c475a256.tar.gz
rulesets-dedbca326fe0337ae9c678a8579810a6c475a256.zip
feat(ai): disable C-z suspend in launched Claude panes
An accidental C-z suspended Claude to the shell mid-session. C-z isn't a Claude Code keybinding. It's the tty's SIGTSTP char, delivered below the app, so the only place to clear it is the tty. The launcher now runs stty susp undef in each pane right before claude starts, so it's scoped to ai-launched panes. C-z keeps working as job control in every other terminal, shell, and program.
-rwxr-xr-xclaude-templates/bin/ai13
1 files changed, 10 insertions, 3 deletions
diff --git a/claude-templates/bin/ai b/claude-templates/bin/ai
index 63dc2e9..5a806ec 100755
--- a/claude-templates/bin/ai
+++ b/claude-templates/bin/ai
@@ -27,6 +27,13 @@
SESSION="ai"
CLAUDE_CMD="claude"
+# Run in the pane's shell just before Claude launches. `stty susp undef` clears
+# the tty's SIGTSTP (C-z) character for this pane only, so an accidental C-z is
+# passed through to Claude as input rather than suspending the session to the
+# shell. Scoped here so C-z keeps working as job control in every other
+# terminal, shell, and program.
+LAUNCH_PREFIX="stty susp undef; "
+
# Format the per-project opening line passed to claude. Takes the project
# directory's basename; returns a string of the form
# "This is <host> <name> project. Follow all instructions in .ai/protocols.org."
@@ -66,7 +73,7 @@ create_window() {
wid=$(tmux new-window -a -t "$SESSION:{end}" -n "$name" -c "$dir" -P -F '#{window_id}')
sleep 0.1
instructions=$(build_instructions "$name")
- tmux send-keys -t "$wid" "$CLAUDE_CMD \"$instructions\"" Enter
+ tmux send-keys -t "$wid" "${LAUNCH_PREFIX}$CLAUDE_CMD \"$instructions\"" Enter
echo "$wid"
}
@@ -311,7 +318,7 @@ single_mode() {
local instructions
wid=$(tmux new-session -d -s "$SESSION" -n "$name" -c "$dir" -P -F '#{window_id}')
instructions=$(build_instructions "$name")
- tmux send-keys -t "$wid" "$CLAUDE_CMD \"$instructions\"" Enter
+ tmux send-keys -t "$wid" "${LAUNCH_PREFIX}$CLAUDE_CMD \"$instructions\"" Enter
fi
sort_windows
@@ -371,7 +378,7 @@ multi_mode() {
local instructions
first_wid=$(tmux new-session -d -s "$SESSION" -n "$name" -c "$dir" -P -F '#{window_id}')
instructions=$(build_instructions "$name")
- tmux send-keys -t "$first_wid" "$CLAUDE_CMD \"$instructions\"" Enter
+ tmux send-keys -t "$first_wid" "${LAUNCH_PREFIX}$CLAUDE_CMD \"$instructions\"" Enter
for entry in "${selected[@]:1}"; do
dir="${entry/#\~/$HOME}"
name="$(basename "$dir")"