agileflow 2.99.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/lib/cache-provider.js +155 -0
  3. package/lib/codebase-indexer.js +1 -1
  4. package/lib/content-sanitizer.js +1 -0
  5. package/lib/dashboard-protocol.js +25 -0
  6. package/lib/dashboard-server.js +184 -133
  7. package/lib/errors.js +18 -0
  8. package/lib/file-cache.js +1 -1
  9. package/lib/flag-detection.js +11 -20
  10. package/lib/git-operations.js +15 -33
  11. package/lib/merge-operations.js +40 -34
  12. package/lib/process-executor.js +199 -0
  13. package/lib/registry-cache.js +13 -47
  14. package/lib/skill-loader.js +206 -0
  15. package/lib/smart-json-file.js +2 -4
  16. package/package.json +1 -1
  17. package/scripts/agileflow-configure.js +13 -12
  18. package/scripts/agileflow-statusline.sh +30 -0
  19. package/scripts/agileflow-welcome.js +181 -212
  20. package/scripts/auto-self-improve.js +3 -3
  21. package/scripts/claude-smart.sh +67 -0
  22. package/scripts/claude-tmux.sh +248 -161
  23. package/scripts/damage-control-multi-agent.js +227 -0
  24. package/scripts/lib/bus-utils.js +471 -0
  25. package/scripts/lib/configure-detect.js +5 -6
  26. package/scripts/lib/configure-features.js +44 -0
  27. package/scripts/lib/configure-repair.js +5 -6
  28. package/scripts/lib/configure-utils.js +2 -3
  29. package/scripts/lib/context-formatter.js +87 -8
  30. package/scripts/lib/damage-control-utils.js +37 -3
  31. package/scripts/lib/file-lock.js +392 -0
  32. package/scripts/lib/ideation-index.js +2 -5
  33. package/scripts/lib/lifecycle-detector.js +123 -0
  34. package/scripts/lib/process-cleanup.js +55 -81
  35. package/scripts/lib/scale-detector.js +357 -0
  36. package/scripts/lib/signal-detectors.js +779 -0
  37. package/scripts/lib/story-state-machine.js +1 -1
  38. package/scripts/lib/sync-ideation-status.js +2 -3
  39. package/scripts/lib/task-registry.js +7 -1
  40. package/scripts/lib/team-events.js +357 -0
  41. package/scripts/messaging-bridge.js +79 -36
  42. package/scripts/migrate-ideation-index.js +37 -14
  43. package/scripts/obtain-context.js +37 -19
  44. package/scripts/ralph-loop.js +3 -4
  45. package/scripts/smart-detect.js +390 -0
  46. package/scripts/team-manager.js +174 -30
  47. package/src/core/commands/audit.md +13 -11
  48. package/src/core/commands/babysit.md +162 -115
  49. package/src/core/commands/changelog.md +21 -4
  50. package/src/core/commands/configure.md +105 -2
  51. package/src/core/commands/debt.md +12 -2
  52. package/src/core/commands/feedback.md +7 -6
  53. package/src/core/commands/ideate/history.md +1 -1
  54. package/src/core/commands/ideate/new.md +5 -5
  55. package/src/core/commands/logic/audit.md +2 -2
  56. package/src/core/commands/pr.md +7 -6
  57. package/src/core/commands/research/analyze.md +28 -20
  58. package/src/core/commands/research/ask.md +43 -0
  59. package/src/core/commands/research/import.md +29 -21
  60. package/src/core/commands/research/list.md +8 -7
  61. package/src/core/commands/research/synthesize.md +356 -20
  62. package/src/core/commands/research/view.md +8 -5
  63. package/src/core/commands/review.md +24 -6
  64. package/src/core/commands/skill/create.md +34 -0
  65. package/tools/cli/lib/docs-setup.js +4 -0
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # claude-smart.sh - Smart resume wrapper for Claude in tmux
3
+ #
4
+ # Uses per-pane tmux option @claude_uuid to track conversation identity.
5
+ # New windows start fresh; re-running in the same pane resumes the conversation.
6
+ #
7
+ # Usage:
8
+ # claude-smart.sh # Resume if UUID stored, else fresh
9
+ # claude-smart.sh --fresh # Force fresh start (ignore stored UUID)
10
+ # claude-smart.sh [flags...] # Pass-through flags to claude
11
+ #
12
+ # NO set -e: UUID capture must run even after Ctrl+C / non-zero exit
13
+
14
+ FRESH=false
15
+ ARGS=()
16
+
17
+ for arg in "$@"; do
18
+ case $arg in
19
+ --fresh)
20
+ FRESH=true
21
+ ;;
22
+ *)
23
+ ARGS+=("$arg")
24
+ ;;
25
+ esac
26
+ done
27
+
28
+ # ── Resolve conversation UUID ──────────────────────────────────────────────
29
+ STORED_UUID=""
30
+ if [ "$FRESH" = false ] && [ -n "$TMUX" ]; then
31
+ STORED_UUID=$(tmux show-options -pqv @claude_uuid 2>/dev/null || true)
32
+ fi
33
+
34
+ # Validate: the .jsonl file must still exist
35
+ if [ -n "$STORED_UUID" ]; then
36
+ PROJ_DIR=$(pwd | sed 's|/|-|g' | sed 's|^-||')
37
+ SESSIONS_DIR="$HOME/.claude/projects/-$PROJ_DIR"
38
+ if [ ! -f "$SESSIONS_DIR/$STORED_UUID.jsonl" ]; then
39
+ STORED_UUID="" # File gone, start fresh
40
+ fi
41
+ fi
42
+
43
+ # ── Build and run Claude command ───────────────────────────────────────────
44
+ CMD=(claude)
45
+ if [ -n "$STORED_UUID" ]; then
46
+ CMD+=(--resume "$STORED_UUID")
47
+ fi
48
+ CMD+=("${ARGS[@]}")
49
+
50
+ "${CMD[@]}"
51
+ EXIT_CODE=$?
52
+
53
+ # ── Capture UUID after exit ────────────────────────────────────────────────
54
+ # Store the most recent non-agent .jsonl as the pane's conversation UUID
55
+ if [ -n "$TMUX" ]; then
56
+ PROJ_DIR=${PROJ_DIR:-$(pwd | sed 's|/|-|g' | sed 's|^-||')}
57
+ SESSIONS_DIR=${SESSIONS_DIR:-"$HOME/.claude/projects/-$PROJ_DIR"}
58
+ if [ -d "$SESSIONS_DIR" ]; then
59
+ NEWEST=$(ls -t "$SESSIONS_DIR"/*.jsonl 2>/dev/null | grep -v "agent-" | head -1)
60
+ if [ -n "$NEWEST" ]; then
61
+ NEW_UUID=$(basename "$NEWEST" .jsonl)
62
+ tmux set-option -p @claude_uuid "$NEW_UUID" 2>/dev/null || true
63
+ fi
64
+ fi
65
+ fi
66
+
67
+ exit $EXIT_CODE
@@ -2,8 +2,9 @@
2
2
  # claude-tmux.sh - Wrapper script that auto-starts Claude Code in a tmux session
3
3
  #
4
4
  # Usage:
5
- # ./claude-tmux.sh # Create new tmux session (supports multiple from same dir)
6
- # ./claude-tmux.sh --attach # Reattach to most recent session
5
+ # ./claude-tmux.sh # Reattach to detached session, or create new
6
+ # ./claude-tmux.sh --new # Force create a new session
7
+ # ./claude-tmux.sh --attach # Reattach to most recent session (any state)
7
8
  # ./claude-tmux.sh --no-tmux # Start without tmux (regular claude)
8
9
  # ./claude-tmux.sh -n # Same as --no-tmux
9
10
  # ./claude-tmux.sh --kill # Kill ALL sessions for this directory
@@ -11,11 +12,12 @@
11
12
  # ./claude-tmux.sh --help # Show help with keybinds
12
13
  #
13
14
  # When already in tmux: Just runs claude normally
14
- # When not in tmux: Creates a tmux session and runs claude inside it
15
+ # When not in tmux: Reattaches to a detached session if one exists, otherwise
16
+ # creates a new tmux session. Use --new to always create a fresh session.
15
17
  #
16
18
  # Multiple terminals can run `af` from the same directory simultaneously.
17
19
  # Sessions are named: claude-<dir>, claude-<dir>-2, claude-<dir>-3, etc.
18
- # Your Claude conversation is preserved via --resume regardless of tmux state.
20
+ # Your Claude conversation is preserved via smart resume (per-pane UUID tracking).
19
21
  #
20
22
  # SESSION CREATION (while inside tmux):
21
23
  # - Alt+N New worktree session (isolated branch + directory)
@@ -29,11 +31,15 @@
29
31
 
30
32
  set -e
31
33
 
34
+ # Resolve script directory (used for claude-smart.sh and other helpers)
35
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
36
+
32
37
  # Parse arguments
33
38
  NO_TMUX=false
34
39
  KILL_SESSION=false
35
40
  SHOW_HELP=false
36
41
  ATTACH_ONLY=false
42
+ FORCE_NEW=false
37
43
  REFRESH_CONFIG=false
38
44
  USE_RESUME=false
39
45
  RESUME_SESSION_ID=""
@@ -48,6 +54,10 @@ for arg in "$@"; do
48
54
  ATTACH_ONLY=true
49
55
  shift
50
56
  ;;
57
+ --new)
58
+ FORCE_NEW=true
59
+ shift
60
+ ;;
51
61
  --fresh|-f)
52
62
  # Kept for backwards compat, but this is now the default behavior
53
63
  shift
@@ -81,38 +91,38 @@ USAGE:
81
91
  agileflow [options] [claude-args...]
82
92
 
83
93
  OPTIONS:
84
- --attach, -a Reattach to most recent session for this directory
94
+ --attach, -a Reattach to most recent session (attached or detached)
95
+ --new Force create a new session (skip auto-reattach)
85
96
  --no-tmux, -n Run claude without tmux
86
97
  --kill Kill ALL sessions for this directory
87
98
  --refresh Refresh tmux config on all existing sessions
88
99
  --help, -h Show this help
89
100
 
90
- By default, af creates a new tmux session. Multiple terminals can run
91
- af from the same directory simultaneously (sessions: claude-dir,
92
- claude-dir-2, claude-dir-3, etc.).
101
+ By default, af reattaches to a detached session if one exists (so Alt+Q
102
+ then af gets you right back). Use --new to force a new session.
103
+
104
+ SESSIONS:
105
+ Alt+s New Claude window
106
+ Alt+l Switch between sessions (picker)
107
+ Alt+q Detach (run af to reattach)
93
108
 
94
- TMUX KEYBINDS:
109
+ WINDOWS:
95
110
  Alt+1-9 Switch to window N
96
- Alt+c Create new window
111
+ Alt+c Create empty window
97
112
  Alt+n/p Next/previous window
98
- Alt+d Split horizontally
99
- Alt+s Split vertically
100
- Alt+arrows Navigate panes
101
- Alt+z Zoom/unzoom pane
102
- Alt+[ Enter copy mode (scroll)
103
113
  Alt+r Rename window
104
- Alt+x Close pane
105
114
  Alt+w Close window
106
- Alt+q Detach from tmux
107
115
 
108
- SESSION CREATION:
109
- Alt+N New worktree session (isolated branch + directory)
110
- Alt+S Same-directory session (quick, no worktree)
116
+ PANES:
117
+ Alt+d Split side by side
118
+ Alt+v Split top/bottom
119
+ Alt+arrows Navigate panes
120
+ Alt+z Zoom/unzoom pane
121
+ Alt+x Close pane
111
122
 
112
- FREEZE RECOVERY:
113
- Alt+k Send Ctrl+C twice (soft interrupt)
114
- Alt+K Force kill pane immediately
115
- Alt+R Respawn pane with fresh shell
123
+ OTHER:
124
+ Alt+[ Scroll mode
125
+ Alt+k Send Ctrl+C twice (unfreeze)
116
126
  EOF
117
127
  exit 0
118
128
  fi
@@ -145,6 +155,156 @@ if command -v tmux &> /dev/null; then
145
155
  unset _TMUX_BASE _TMUX_SOCK_DIR
146
156
  fi
147
157
 
158
+ # ══════════════════════════════════════════════════════════════════════════════
159
+ # TMUX CONFIGURATION FUNCTION — applies theme, keybinds, and status bar
160
+ # Defined early so --refresh can use it before any session logic
161
+ # ══════════════════════════════════════════════════════════════════════════════
162
+ configure_tmux_session() {
163
+ local target_session="$1"
164
+
165
+ # Enable mouse support
166
+ tmux set-option -t "$target_session" mouse on
167
+
168
+ # Fix colors - proper terminal support
169
+ tmux set-option -t "$target_session" default-terminal "xterm-256color"
170
+ tmux set-option -t "$target_session" -ga terminal-overrides ",xterm-256color:Tc"
171
+
172
+ # ─── Status Bar Styling (2-line) ────────────────────────────────────────────
173
+
174
+ # Status bar position and refresh
175
+ tmux set-option -t "$target_session" status-position bottom
176
+ # Reduce refresh rate to prevent CPU overhead and freezes (was 5s, now 30s)
177
+ tmux set-option -t "$target_session" status-interval 30
178
+
179
+ # Enable 2-line status bar
180
+ tmux set-option -t "$target_session" status 2
181
+
182
+ # Base styling - Tokyo Night inspired dark theme
183
+ tmux set-option -t "$target_session" status-style "bg=#1a1b26,fg=#a9b1d6"
184
+
185
+ # Line 0 (top): Session name + live git branch + keybind hints
186
+ # Uses #() for live branch updates (runs on status-interval, every 30s)
187
+ tmux set-option -t "$target_session" status-format[0] "#[bg=#1a1b26] #[fg=#e8683a bold]#{s/claude-//:session_name} #[fg=#3b4261]· #[fg=#7aa2f7]󰘬 #(git -C #{pane_current_path} branch --show-current 2>/dev/null || echo '-')#[align=right]#[fg=#565a6e]Alt+h help "
188
+
189
+ # Line 1 (bottom): Window tabs with smart truncation and brand color
190
+ tmux set-option -t "$target_session" status-format[1] "#[bg=#1a1b26]#{W:#{?window_active,#[fg=#1a1b26 bg=#e8683a bold] #I #[fg=#e8683a bg=#2d2f3a]#[fg=#e0e0e0] #{=15:window_name} #[bg=#1a1b26 fg=#2d2f3a],#[fg=#8a8a8a] #I:#{=|8|...:window_name} }}"
191
+
192
+ # Pane border styling - blue inactive, orange active
193
+ tmux set-option -t "$target_session" pane-border-style "fg=#3d59a1"
194
+ tmux set-option -t "$target_session" pane-active-border-style "fg=#e8683a"
195
+
196
+ # Message styling - orange highlight
197
+ tmux set-option -t "$target_session" message-style "bg=#e8683a,fg=#1a1b26,bold"
198
+
199
+ # ─── Keybindings ────────────────────────────────────────────────────────────
200
+
201
+ # Alt+number to switch windows (1-9)
202
+ for i in 1 2 3 4 5 6 7 8 9; do
203
+ tmux bind-key -n "M-$i" select-window -t ":$i"
204
+ done
205
+
206
+ # Alt+c to create new window
207
+ tmux bind-key -n M-c new-window -c "#{pane_current_path}"
208
+
209
+ # Alt+q to detach
210
+ tmux bind-key -n M-q detach-client
211
+
212
+ # Alt+l to list and switch between sessions (interactive picker)
213
+ tmux bind-key -n M-l choose-tree -s -Z
214
+
215
+ # Alt+d to split horizontally (side by side)
216
+ tmux bind-key -n M-d split-window -h -c "#{pane_current_path}"
217
+
218
+ # Alt+v to split vertically (top/bottom)
219
+ tmux bind-key -n M-v split-window -v -c "#{pane_current_path}"
220
+
221
+ # Alt+arrow to navigate panes
222
+ tmux bind-key -n M-Left select-pane -L
223
+ tmux bind-key -n M-Right select-pane -R
224
+ tmux bind-key -n M-Up select-pane -U
225
+ tmux bind-key -n M-Down select-pane -D
226
+
227
+ # Alt+x to close current pane (with confirmation)
228
+ tmux bind-key -n M-x confirm-before -p "Close pane? (y/n)" kill-pane
229
+
230
+ # Alt+w to close current window (with confirmation)
231
+ tmux bind-key -n M-w confirm-before -p "Close window? (y/n)" kill-window
232
+
233
+ # Alt+n/p for next/previous window
234
+ tmux bind-key -n M-n next-window
235
+ tmux bind-key -n M-p previous-window
236
+
237
+ # Alt+r to rename window
238
+ tmux bind-key -n M-r command-prompt -I "#W" "rename-window '%%'"
239
+
240
+ # Alt+z to zoom/unzoom pane (fullscreen toggle)
241
+ tmux bind-key -n M-z resize-pane -Z
242
+
243
+ # Alt+[ to enter copy mode (for scrolling)
244
+ tmux bind-key -n M-[ copy-mode
245
+
246
+ # ─── Session Creation Keybindings ──────────────────────────────────────────
247
+ # Alt+s to create a new Claude window (starts fresh, future re-runs in same pane resume)
248
+ tmux bind-key -n M-s run-shell "tmux new-window -n claude -c '#{pane_current_path}' && tmux send-keys '\"\$AGILEFLOW_SCRIPTS/claude-smart.sh\" --fresh \$CLAUDE_SESSION_FLAGS' Enter"
249
+
250
+ # ─── Freeze Recovery Keybindings ───────────────────────────────────────────
251
+ # Alt+k to send Ctrl+C twice (soft interrupt for frozen processes)
252
+ tmux bind-key -n M-k run-shell "tmux send-keys C-c; sleep 0.5; tmux send-keys C-c"
253
+
254
+ # ─── Help Panel ──────────────────────────────────────────────────────────
255
+ # Alt+h to show keybind cheat sheet in a popup
256
+ tmux bind-key -n M-h display-popup -E -w 52 -h 24 "\
257
+ printf '\\n';\
258
+ printf ' \\033[1;38;5;208mSESSIONS\\033[0m\\n';\
259
+ printf ' Alt+s New Claude window\\n';\
260
+ printf ' Alt+l Switch session\\n';\
261
+ printf ' Alt+q Detach (af to resume)\\n';\
262
+ printf '\\n';\
263
+ printf ' \\033[1;38;5;208mWINDOWS\\033[0m\\n';\
264
+ printf ' Alt+1-9 Switch to window\\n';\
265
+ printf ' Alt+c New empty window\\n';\
266
+ printf ' Alt+n/p Next / previous\\n';\
267
+ printf ' Alt+r Rename window\\n';\
268
+ printf ' Alt+w Close window\\n';\
269
+ printf '\\n';\
270
+ printf ' \\033[1;38;5;208mPANES\\033[0m\\n';\
271
+ printf ' Alt+d Split side by side\\n';\
272
+ printf ' Alt+v Split top / bottom\\n';\
273
+ printf ' Alt+←→↑↓ Navigate\\n';\
274
+ printf ' Alt+z Zoom / unzoom\\n';\
275
+ printf ' Alt+x Close pane\\n';\
276
+ printf '\\n';\
277
+ printf ' \\033[1;38;5;208mOTHER\\033[0m\\n';\
278
+ printf ' Alt+[ Scroll mode\\n';\
279
+ printf ' Alt+k Unfreeze (Ctrl+C×2)\\n';\
280
+ printf ' Alt+h This help\\n';\
281
+ printf '\\n';\
282
+ read -n 1 -s -r -p ' Press any key to close'"
283
+ }
284
+
285
+ # Handle --refresh flag — re-apply config to all existing claude-* sessions
286
+ if [ "$REFRESH_CONFIG" = true ]; then
287
+ REFRESHED=0
288
+ for sid in $(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep "^claude-"); do
289
+ configure_tmux_session "$sid"
290
+ # Ensure AGILEFLOW_SCRIPTS is set (needed by Alt+S keybind)
291
+ tmux set-environment -t "$sid" AGILEFLOW_SCRIPTS "$SCRIPT_DIR" 2>/dev/null || true
292
+ REFRESHED=$((REFRESHED + 1))
293
+ done
294
+ if [ "$REFRESHED" -gt 0 ]; then
295
+ echo "Refreshed config on $REFRESHED session(s)."
296
+ else
297
+ echo "No claude-* sessions found to refresh."
298
+ fi
299
+ exit 0
300
+ fi
301
+
302
+ # Check if we're already inside tmux — use smart wrapper instead of session management
303
+ if [ -n "$TMUX" ]; then
304
+ # shellcheck disable=SC2086
305
+ exec "$SCRIPT_DIR/claude-smart.sh" $CLAUDE_SESSION_FLAGS "$@"
306
+ fi
307
+
148
308
  # Generate directory name (used for session name patterns)
149
309
  DIR_NAME=$(basename "$(pwd)")
150
310
 
@@ -190,8 +350,59 @@ if [ "$ATTACH_ONLY" = true ]; then
190
350
  fi
191
351
  fi
192
352
 
193
- # Find next available session name (supports multiple from same directory)
353
+ # ── Auto-cleanup dead sessions ────────────────────────────────────────────
354
+ # Silently remove sessions where all panes have exited (dead/empty shells).
355
+ # This prevents accumulation of orphan sessions over time.
194
356
  SESSION_BASE="claude-${DIR_NAME}"
357
+ for sid in $(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep "^${SESSION_BASE}\(\$\|-[0-9]*\$\)"); do
358
+ # Count alive panes (pane_dead=0 means alive)
359
+ ALIVE=$(tmux list-panes -t "$sid" -F '#{pane_dead}' 2>/dev/null | grep -c '^0$' || true)
360
+ if [ "$ALIVE" = "0" ]; then
361
+ tmux kill-session -t "$sid" 2>/dev/null || true
362
+ fi
363
+ done
364
+
365
+ # ── Auto-reattach to detached session ──────────────────────────────────────
366
+ # When user does Alt+Q (detach) and then runs `af` again, reattach to the
367
+ # existing session instead of creating a new one. This preserves tmux windows,
368
+ # pane layout, and the live Claude chat session.
369
+ # If multiple detached sessions exist, show a picker so user can choose.
370
+ if [ "$FORCE_NEW" = false ]; then
371
+ DETACHED=()
372
+ while IFS= read -r sid; do
373
+ [ -n "$sid" ] && DETACHED+=("$sid")
374
+ done < <(tmux list-sessions -F '#{session_name} #{session_attached}' 2>/dev/null | awk '$2 == "0" {print $1}' | grep "^${SESSION_BASE}\(\$\|-[0-9]*\$\)")
375
+
376
+ if [ "${#DETACHED[@]}" -eq 1 ]; then
377
+ # Single detached session — just reattach
378
+ echo "Reattaching to: ${DETACHED[0]}"
379
+ exec tmux attach-session -t "${DETACHED[0]}"
380
+ elif [ "${#DETACHED[@]}" -gt 1 ]; then
381
+ # Multiple detached sessions — let user pick
382
+ echo ""
383
+ echo " Multiple detached sessions found:"
384
+ echo ""
385
+ i=1
386
+ for sid in "${DETACHED[@]}"; do
387
+ WINS=$(tmux list-windows -t "$sid" -F '#{window_name}' 2>/dev/null | tr '\n' ',' | sed 's/,$//')
388
+ printf " %d) %s (%s)\n" "$i" "$sid" "$WINS"
389
+ i=$((i + 1))
390
+ done
391
+ printf " %d) Create new session\n" "$i"
392
+ echo ""
393
+ printf " Pick [1]: "
394
+ read -r CHOICE
395
+ CHOICE=${CHOICE:-1}
396
+ if [ "$CHOICE" -ge 1 ] 2>/dev/null && [ "$CHOICE" -lt "$i" ] 2>/dev/null; then
397
+ IDX=$((CHOICE - 1))
398
+ echo "Reattaching to: ${DETACHED[$IDX]}"
399
+ exec tmux attach-session -t "${DETACHED[$IDX]}"
400
+ fi
401
+ # Fall through to create new session
402
+ fi
403
+ fi
404
+
405
+ # No detached session found — create a new one
195
406
  SESSION_NAME="$SESSION_BASE"
196
407
  SESSION_NUM=1
197
408
  while tmux has-session -t "$SESSION_NAME" 2>/dev/null; do
@@ -265,12 +476,6 @@ if [ -f "$METADATA_FILE" ]; then
265
476
  fi
266
477
  fi
267
478
 
268
- # Check if we're already inside tmux
269
- if [ -n "$TMUX" ]; then
270
- # Already in tmux, just run claude
271
- exec claude "$@"
272
- fi
273
-
274
479
  # Check if tmux is available
275
480
  if ! command -v tmux &> /dev/null; then
276
481
  echo "tmux not found. Running claude without tmux."
@@ -281,118 +486,6 @@ if ! command -v tmux &> /dev/null; then
281
486
  exec claude "$@"
282
487
  fi
283
488
 
284
- # ══════════════════════════════════════════════════════════════════════════════
285
- # TMUX CONFIGURATION FUNCTION — applies theme, keybinds, and status bar
286
- # Extracted so --refresh can re-apply to existing sessions
287
- # ══════════════════════════════════════════════════════════════════════════════
288
- configure_tmux_session() {
289
- local target_session="$1"
290
-
291
- # Enable mouse support
292
- tmux set-option -t "$target_session" mouse on
293
-
294
- # Fix colors - proper terminal support
295
- tmux set-option -t "$target_session" default-terminal "xterm-256color"
296
- tmux set-option -t "$target_session" -ga terminal-overrides ",xterm-256color:Tc"
297
-
298
- # ─── Status Bar Styling (2-line) ────────────────────────────────────────────
299
-
300
- # Status bar position and refresh
301
- tmux set-option -t "$target_session" status-position bottom
302
- # Reduce refresh rate to prevent CPU overhead and freezes (was 5s, now 30s)
303
- tmux set-option -t "$target_session" status-interval 30
304
-
305
- # Enable 2-line status bar
306
- tmux set-option -t "$target_session" status 2
307
-
308
- # Base styling - Tokyo Night inspired dark theme
309
- tmux set-option -t "$target_session" status-style "bg=#1a1b26,fg=#a9b1d6"
310
-
311
- # Capture git branch once (avoids spawning process every refresh)
312
- local git_branch
313
- git_branch=$(git branch --show-current 2>/dev/null || echo '-')
314
-
315
- # Line 0 (top): Session name (stripped of claude- prefix) + Keybinds + Git branch
316
- tmux set-option -t "$target_session" status-format[0] "#[bg=#1a1b26] #[fg=#e8683a bold]#{s/claude-//:session_name} #[fg=#3b4261]· #[fg=#7aa2f7]󰘬 ${git_branch} #[align=right]#[fg=#7a7e8a]Alt+1-9 windows Alt+s new session Alt+q detach "
317
-
318
- # Line 1 (bottom): Window tabs with smart truncation and brand color
319
- tmux set-option -t "$target_session" status-format[1] "#[bg=#1a1b26]#{W:#{?window_active,#[fg=#1a1b26 bg=#e8683a bold] #I #[fg=#e8683a bg=#2d2f3a]#[fg=#e0e0e0] #{=15:window_name} #[bg=#1a1b26 fg=#2d2f3a],#[fg=#8a8a8a] #I:#{=|8|...:window_name} }}"
320
-
321
- # Pane border styling - blue inactive, orange active
322
- tmux set-option -t "$target_session" pane-border-style "fg=#3d59a1"
323
- tmux set-option -t "$target_session" pane-active-border-style "fg=#e8683a"
324
-
325
- # Message styling - orange highlight
326
- tmux set-option -t "$target_session" message-style "bg=#e8683a,fg=#1a1b26,bold"
327
-
328
- # ─── Keybindings ────────────────────────────────────────────────────────────
329
-
330
- # Alt+number to switch windows (1-9)
331
- for i in 1 2 3 4 5 6 7 8 9; do
332
- tmux bind-key -n "M-$i" select-window -t ":$i"
333
- done
334
-
335
- # Alt+c to create new window
336
- tmux bind-key -n M-c new-window -c "#{pane_current_path}"
337
-
338
- # Alt+q to detach
339
- tmux bind-key -n M-q detach-client
340
-
341
- # Alt+d to split horizontally (side by side)
342
- tmux bind-key -n M-d split-window -h -c "#{pane_current_path}"
343
-
344
- # Alt+v to split vertically (top/bottom)
345
- tmux bind-key -n M-v split-window -v -c "#{pane_current_path}"
346
-
347
- # Alt+arrow to navigate panes
348
- tmux bind-key -n M-Left select-pane -L
349
- tmux bind-key -n M-Right select-pane -R
350
- tmux bind-key -n M-Up select-pane -U
351
- tmux bind-key -n M-Down select-pane -D
352
-
353
- # Alt+x to close current pane (with confirmation)
354
- tmux bind-key -n M-x confirm-before -p "Close pane? (y/n)" kill-pane
355
-
356
- # Alt+w to close current window (with confirmation)
357
- tmux bind-key -n M-w confirm-before -p "Close window? (y/n)" kill-window
358
-
359
- # Alt+n/p for next/previous window
360
- tmux bind-key -n M-n next-window
361
- tmux bind-key -n M-p previous-window
362
-
363
- # Alt+r to rename window
364
- tmux bind-key -n M-r command-prompt -I "#W" "rename-window '%%'"
365
-
366
- # Alt+z to zoom/unzoom pane (fullscreen toggle)
367
- tmux bind-key -n M-z resize-pane -Z
368
-
369
- # Alt+[ to enter copy mode (for scrolling)
370
- tmux bind-key -n M-[ copy-mode
371
-
372
- # ─── Session Creation Keybindings ──────────────────────────────────────────
373
- # Alt+s to create a same-directory Claude window
374
- tmux bind-key -n M-s run-shell "tmux new-window -c '#{pane_current_path}' && tmux send-keys 'claude \$CLAUDE_SESSION_FLAGS' Enter && tmux display-message 'New Claude session created'"
375
-
376
- # ─── Freeze Recovery Keybindings ───────────────────────────────────────────
377
- # Alt+k to send Ctrl+C twice (soft interrupt for frozen processes)
378
- tmux bind-key -n M-k run-shell "tmux send-keys C-c; sleep 0.5; tmux send-keys C-c"
379
- }
380
-
381
- # Handle --refresh flag — re-apply config to all existing claude-* sessions
382
- if [ "$REFRESH_CONFIG" = true ]; then
383
- REFRESHED=0
384
- for sid in $(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep "^claude-"); do
385
- configure_tmux_session "$sid"
386
- REFRESHED=$((REFRESHED + 1))
387
- done
388
- if [ "$REFRESHED" -gt 0 ]; then
389
- echo "Refreshed config on $REFRESHED session(s)."
390
- else
391
- echo "No claude-* sessions found to refresh."
392
- fi
393
- exit 0
394
- fi
395
-
396
489
  # Create new tmux session with Claude
397
490
  echo "Starting Claude in tmux session: $SESSION_NAME"
398
491
 
@@ -408,33 +501,27 @@ tmux move-window -t "$SESSION_NAME":1 >/dev/null 2>&1 || true
408
501
  # Apply tmux configuration
409
502
  configure_tmux_session "$SESSION_NAME"
410
503
 
411
- # Send the claude command to the first window
412
- CLAUDE_CMD="claude"
413
-
414
- # Check for inherited session flags (set by parent Claude session)
415
- INHERITED_FLAGS=""
504
+ # Export scripts directory to tmux session environment (used by keybinds)
505
+ tmux set-environment -t "$SESSION_NAME" AGILEFLOW_SCRIPTS "$SCRIPT_DIR"
416
506
  if [ -n "$CLAUDE_SESSION_FLAGS" ]; then
417
- INHERITED_FLAGS="$CLAUDE_SESSION_FLAGS"
507
+ tmux set-environment -t "$SESSION_NAME" CLAUDE_SESSION_FLAGS "$CLAUDE_SESSION_FLAGS"
418
508
  fi
419
509
 
510
+ # Pre-seed @claude_uuid on initial pane if we found a recent conversation
420
511
  if [ "$USE_RESUME" = true ] && [ -n "$RESUME_SESSION_ID" ]; then
421
- # Fresh restart with specific conversation resume (skips picker)
422
- CLAUDE_CMD="claude --resume $RESUME_SESSION_ID"
423
- elif [ "$USE_RESUME" = true ]; then
424
- # Fresh restart with conversation picker
425
- CLAUDE_CMD="claude --resume"
512
+ tmux set-option -p -t "$SESSION_NAME" @claude_uuid "$RESUME_SESSION_ID" 2>/dev/null || true
426
513
  fi
427
514
 
428
- # Add inherited flags if present (e.g., --dangerously-skip-permissions)
429
- if [ -n "$INHERITED_FLAGS" ]; then
430
- CLAUDE_CMD="$CLAUDE_CMD $INHERITED_FLAGS"
515
+ # Launch Claude via smart wrapper (handles resume from @claude_uuid)
516
+ SMART_CMD="\"$SCRIPT_DIR/claude-smart.sh\""
517
+ if [ -n "$CLAUDE_SESSION_FLAGS" ]; then
518
+ SMART_CMD="$SMART_CMD $CLAUDE_SESSION_FLAGS"
431
519
  fi
432
-
433
520
  if [ $# -gt 0 ]; then
434
- # Pass any remaining arguments to claude
435
- CLAUDE_CMD="$CLAUDE_CMD $*"
521
+ SMART_CMD="$SMART_CMD $*"
436
522
  fi
437
- tmux send-keys -t "$SESSION_NAME" "$CLAUDE_CMD" Enter
523
+
524
+ tmux send-keys -t "$SESSION_NAME" "$SMART_CMD" Enter
438
525
 
439
526
  # Attach to the session
440
527
  exec tmux attach-session -t "$SESSION_NAME"