1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#+TITLE: Proposal — wrap-it-up teardown + "wrap it up and shutdown" variant
* Source
Raised by Craig in a home-project session, 2026-06-23, after talking the
design through. Two related additions to =wrap-it-up.org=. Both touch the
Claude-session lifecycle (workflow + hook + the =ai-term= buffer/tmux pair),
so they're rulesets — with one companion piece that has to live in
=.emacs.d/modules/ai-term.el= (flagged below). Originally floated as an
archsetup task; archsetup owns the Hyprland/waybar layer, not the
Claude-session lifecycle, so it was re-routed here.
* Architecture this depends on (so the design is grounded)
- =ai-term.el= (=.emacs.d=) is the in-Emacs launcher: a vertical-split vterm
buffer running a tmux session named =aiv-<project-basename>= (prefix
=aiv-=). Layering: =claude= process → tmux session =aiv-<proj>= → Emacs
vterm buffer.
- Killing the tmux session takes the =claude= process with it, so "quit
Claude Code" is a *consequence* of killing =aiv-<proj>=, not a separate
step.
- Hooks already exist under =~/.claude/hooks/= (e.g. =session-clear-resume.sh=,
=precompact-priorities.sh=) — the teardown trigger fits that pattern.
- =sudo= is =NOPASSWD: ALL= on Craig's machines, so =sudo shutdown now= runs
unattended.
* Item 1 — wrap-up also removes the buffer, quits Claude, removes the tmux session
Recommend: yes, with one structural rule — the wrap-up runs *inside* the
things it tears down, so teardown is self-terminating and must be the last,
decoupled action, or the valediction may not flush before the session dies.
Design:
1. *Teardown lives in =ai-term.el=* (companion, see below): one function
=cj/ai-term-quit= that kills the =aiv-<proj>= tmux session (takes =claude=
with it), kills the vterm buffer, and restores the saved window geometry —
=ai-term.el= already owns the buffer↔session pair and the geometry logic.
2. *Trigger from a Stop / SessionEnd hook, not inline.* Wrap-up does all its
git/archive work, delivers the valediction, then drops a sentinel (flag
file, e.g. =/tmp/ai-wrap-teardown-<session>=). The hook fires when Claude
finishes, sees the sentinel, and runs =cj/ai-term-quit= via =emacsclient=.
Decoupling guarantees the valediction lands before the session dies.
3. *Gate on commit+push verified* — never tear down before the session record
is pushed (wrap-up's existing Step 4 / validation checklist already
enforces push; teardown is strictly after it).
4. *Phrase split — teardown IS the default* (Craig's decision 2026-06-23).
Bare "wrap it up" does the full wrap AND removes the buffer/session/quits —
that's his typical case. The non-destructive variant gets the explicit
qualifier: "wrap it up with summary" summarizes + commits + pushes +
archives but keeps the buffer (no teardown), so the summary stays readable.
So: "wrap it up" → teardown; "wrap it up with summary" → no teardown;
"wrap it up and shutdown" → wrap + poweroff (supersedes teardown, Item 2).
* Item 2 — "wrap it up and shutdown": 10-count then =sudo shutdown now=
Recommend: yes, but the safety gate is load-bearing and the countdown has a
rendering gotcha.
Design:
1. *"Only ai-term left" = hard blocking precondition*, evaluated BEFORE the
countdown. Count live sessions (=tmux ls | grep '^aiv-'= or
=pgrep -fc claude=). If more than this one is alive, ABORT the shutdown,
list what's running, and fall back to a normal wrap. Never power the box
off out from under another active Claude session. This is the most
important part of the item.
2. *The live countdown can't run through Claude's tool output.* The Bash tool
buffers stdout until the command returns, so a =for i in $(seq 10 -1 1);
sleep 1= prints all ten at once at the end, not one per second. It has to
run detached or in Emacs:
- tty writer: =for i in $(seq 10 -1 1); do printf '\rShutting down in %2d…'
"$i" > /dev/tty; sleep 1; done; sudo shutdown now= (backgrounded), or
- an Emacs =run-at-time= timer printing 10→1 in the echo area, then
=(shell-command "sudo shutdown now")=.
3. *Make it abort-able* (Ctrl-C / keypress cancels). A 10-second countdown's
whole purpose is a last-chance window; a non-cancellable one is just a
delay.
4. *Sequencing.* "...and shutdown" supersedes Item 1's teardown — if the box
is powering off, killing the buffer/session first is moot. Wrap (commit +
push + archive) → session-count gate → countdown → =shutdown=.
Packaging: a small rulesets bin script (e.g. =ai-wrap-shutdown=) doing the
gate → abort-able countdown → shutdown, invoked by the workflow after the wrap
commit/push. Countdown either in that script (tty) or handed to Emacs.
* Companion — required change in =.emacs.d/modules/ai-term.el=
Item 1's teardown function =cj/ai-term-quit= must live in =ai-term.el= (it
owns =aiv-<proj>= session naming, the vterm buffer, and geometry restore).
rulesets owns the workflow + hook + bin script that *call* it; =.emacs.d= owns
the function itself. Spec for the =.emacs.d= side:
- =cj/ai-term-quit (&optional project)= — resolve the =aiv-<basename>= session
for the current/!named project, =tmux kill-session= it, =kill-buffer= the
associated vterm buffer, restore saved geometry. Idempotent / no-op if the
session or buffer is already gone. Callable from =emacsclient -e= so the
Stop hook can invoke it headlessly.
- (Optional) a count helper =cj/ai-term-live-count= so the Item-2 gate can ask
Emacs how many ai-term sessions are live, as an alternative to =tmux ls= /
=pgrep=.
When rulesets builds the workflow/hook side, route this companion to
=.emacs.d= (inbox-send) so the two land together.
* Open decisions for Craig
- Phrase set: DECIDED (2026-06-23) — "wrap it up" tears down (default);
"wrap it up with summary" wraps without teardown; "wrap it up and shutdown"
is the poweroff variant. Remaining nuance: confirm the exact non-destructive
qualifier wording is "with summary" (vs e.g. "and summarize").
- Countdown home: tty-writer bin script vs Emacs timer. (Emacs timer reads
cleaner inside the vterm and is trivially abort-able.)
- Session-count mechanism for the gate: =tmux ls=, =pgrep claude=, or
=cj/ai-term-live-count=.
* Verify
- Item 1: bare "wrap it up" → valediction renders fully, THEN buffer +
=aiv-<proj>= session + claude all gone, geometry restored; "wrap it up with
summary" → wrap completes but the buffer stays intact (no teardown).
- Item 2 gate: with a second =aiv-*= session alive, "wrap it up and shutdown"
refuses, lists the other session, and does a normal wrap (no poweroff).
- Item 2 happy path: sole session → 10→1 renders one-per-second, is
cancellable, then =shutdown= fires.
- Teardown never runs before commit+push is verified.
|