@humanu/orchestra 0.5.73 → 0.5.75
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.
- package/package.json +1 -1
- package/resources/api/tmux.sh +81 -31
- package/resources/prebuilt/linux-x64/orchestra +0 -0
- package/resources/prebuilt/macos-arm64/orchestra +0 -0
- package/resources/prebuilt/macos-intel/orchestra +0 -0
- package/resources/scripts/gw-bridge.sh +7 -1
- package/resources/scripts/shell/bridge/tmux.sh +20 -0
package/package.json
CHANGED
package/resources/api/tmux.sh
CHANGED
|
@@ -434,7 +434,7 @@ with open(active_path, "r", encoding="utf-8") as handle:
|
|
|
434
434
|
line = raw_line.rstrip("\n")
|
|
435
435
|
if not line:
|
|
436
436
|
continue
|
|
437
|
-
parts = line.split("\t"
|
|
437
|
+
parts = line.split("\t")
|
|
438
438
|
name = parts[0].strip()
|
|
439
439
|
display_name = parts[1].strip() if len(parts) > 1 else ""
|
|
440
440
|
if not name:
|
|
@@ -506,14 +506,6 @@ _tmux_truncate_tab_label() {
|
|
|
506
506
|
fi
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
-
_tmux_pad_tab_label() {
|
|
510
|
-
local label="$1"
|
|
511
|
-
local width="${2:-14}"
|
|
512
|
-
|
|
513
|
-
label="$(_tmux_truncate_tab_label "$label" "$width")"
|
|
514
|
-
printf '%-*s' "$width" "$label"
|
|
515
|
-
}
|
|
516
|
-
|
|
517
509
|
_tmux_workspace_session_rows() {
|
|
518
510
|
local current_session="$1"
|
|
519
511
|
local repo_root="$2"
|
|
@@ -589,8 +581,8 @@ _tmux_workspace_session_tabs() {
|
|
|
589
581
|
local current_session="$1"
|
|
590
582
|
local fallback_display_name="$2"
|
|
591
583
|
local session_dir repo_root rows tabs name display_name tab_label escaped_tab_label divider active_style inactive_style muted_style reset_style
|
|
592
|
-
local
|
|
593
|
-
local
|
|
584
|
+
local tab_max_width=24
|
|
585
|
+
local active_label_max_width=22
|
|
594
586
|
|
|
595
587
|
session_dir="$(tmux display-message -t "$current_session" -p '#{pane_current_path}' 2>/dev/null || echo "")"
|
|
596
588
|
repo_root="$(_tmux_shared_root_for_path "$session_dir" 2>/dev/null || true)"
|
|
@@ -602,7 +594,7 @@ _tmux_workspace_session_tabs() {
|
|
|
602
594
|
fi
|
|
603
595
|
|
|
604
596
|
if [[ -z "$rows" ]]; then
|
|
605
|
-
tab_label="$(
|
|
597
|
+
tab_label="$(_tmux_truncate_tab_label "$fallback_display_name" "$active_label_max_width")"
|
|
606
598
|
escaped_tab_label="$(_tmux_status_escape_text "$tab_label")"
|
|
607
599
|
printf '#[bg=#414868] #[fg=#ff9e64,bg=#414868,bold]● #[fg=#c0caf5,bg=#414868,bold]%s #[default]' "$escaped_tab_label"
|
|
608
600
|
return
|
|
@@ -621,7 +613,7 @@ _tmux_workspace_session_tabs() {
|
|
|
621
613
|
tabs+="$divider"
|
|
622
614
|
fi
|
|
623
615
|
if [[ "$name" == "__ellipsis__" ]]; then
|
|
624
|
-
tab_label="
|
|
616
|
+
tab_label="⋯"
|
|
625
617
|
escaped_tab_label="$(_tmux_status_escape_text "$tab_label")"
|
|
626
618
|
tabs+="${muted_style} ${escaped_tab_label} ${reset_style}"
|
|
627
619
|
continue
|
|
@@ -631,11 +623,11 @@ _tmux_workspace_session_tabs() {
|
|
|
631
623
|
display_name="$(tmux_format_session_display "$name" without-timestamp)"
|
|
632
624
|
fi
|
|
633
625
|
if [[ "$name" == "$current_session" ]]; then
|
|
634
|
-
tab_label="$(
|
|
626
|
+
tab_label="$(_tmux_truncate_tab_label "$display_name" "$active_label_max_width")"
|
|
635
627
|
escaped_tab_label="$(_tmux_status_escape_text "$tab_label")"
|
|
636
628
|
tabs+="#[bg=#414868] #[fg=#ff9e64,bg=#414868,bold]● ${active_style}${escaped_tab_label} ${reset_style}"
|
|
637
629
|
else
|
|
638
|
-
tab_label="$(
|
|
630
|
+
tab_label="$(_tmux_truncate_tab_label "$display_name" "$tab_max_width")"
|
|
639
631
|
escaped_tab_label="$(_tmux_status_escape_text "$tab_label")"
|
|
640
632
|
tabs+="${inactive_style} ${escaped_tab_label} ${reset_style}"
|
|
641
633
|
fi
|
|
@@ -651,7 +643,7 @@ _tmux_orchestra_status_left() {
|
|
|
651
643
|
}
|
|
652
644
|
|
|
653
645
|
_tmux_orchestra_status_right() {
|
|
654
|
-
printf ''
|
|
646
|
+
printf '#[fg=#565f89,bg=#1a1b26]Ctrl+b,h for help#[default]'
|
|
655
647
|
}
|
|
656
648
|
|
|
657
649
|
_tmux_configure_orchestra_bindings() {
|
|
@@ -659,16 +651,21 @@ _tmux_configure_orchestra_bindings() {
|
|
|
659
651
|
bridge="$(_orchestra_bridge_script)"
|
|
660
652
|
[[ -f "$bridge" ]] || return
|
|
661
653
|
|
|
662
|
-
local quoted_bridge rename_command prompt_command next_command previous_command help_command
|
|
654
|
+
local quoted_bridge rename_command prompt_command next_command previous_command new_session_command help_command
|
|
663
655
|
printf -v quoted_bridge '%q' "$bridge"
|
|
664
656
|
rename_command="$quoted_bridge manual-rename-session \\\"#{session_name}\\\" \\\"%%\\\" >/dev/null 2>&1"
|
|
665
657
|
prompt_command="command-prompt -p 'Rename Orchestra session:' 'run-shell -b \"$rename_command\"'"
|
|
666
658
|
next_command="$quoted_bridge cycle-workspace-session \\\"#{session_name}\\\" next \\\"#{client_tty}\\\" >/dev/null 2>&1"
|
|
667
659
|
previous_command="$quoted_bridge cycle-workspace-session \\\"#{session_name}\\\" previous \\\"#{client_tty}\\\" >/dev/null 2>&1"
|
|
660
|
+
new_session_command="$quoted_bridge create-workspace-session \\\"#{session_name}\\\" \\\"#{client_tty}\\\" >/dev/null 2>&1"
|
|
668
661
|
help_command="$quoted_bridge tmux-help-popup \\\"#{client_tty}\\\" >/dev/null 2>&1"
|
|
669
662
|
|
|
670
663
|
tmux bind-key -T prefix '?' if-shell -F '#{@orchestra_display_name}' \
|
|
671
664
|
"run-shell -b \"$help_command\"" 'list-keys -N' >/dev/null 2>&1 || true
|
|
665
|
+
tmux bind-key -T prefix h if-shell -F '#{@orchestra_display_name}' \
|
|
666
|
+
"run-shell -b \"$help_command\"" 'refresh-client -S' >/dev/null 2>&1 || true
|
|
667
|
+
tmux bind-key -T prefix n if-shell -F '#{@orchestra_display_name}' \
|
|
668
|
+
"run-shell -b \"$new_session_command\"" 'next-window' >/dev/null 2>&1 || true
|
|
672
669
|
tmux bind-key -T prefix r if-shell -F '#{@orchestra_display_name}' \
|
|
673
670
|
"$prompt_command" 'refresh-client -S' >/dev/null 2>&1 || true
|
|
674
671
|
tmux bind-key -T prefix '>' if-shell -F '#{@orchestra_display_name}' \
|
|
@@ -700,7 +697,7 @@ _tmux_configure_orchestra_status() {
|
|
|
700
697
|
tmux set-option -t "$session_name" status-left "$status_left" >/dev/null 2>&1 || true
|
|
701
698
|
tmux set-option -t "$session_name" status-left-length 1000 >/dev/null 2>&1 || true
|
|
702
699
|
tmux set-option -t "$session_name" status-right "$status_right" >/dev/null 2>&1 || true
|
|
703
|
-
tmux set-option -t "$session_name" status-right-length
|
|
700
|
+
tmux set-option -t "$session_name" status-right-length 40 >/dev/null 2>&1 || true
|
|
704
701
|
tmux set-option -t "$session_name" window-status-format "" >/dev/null 2>&1 || true
|
|
705
702
|
tmux set-option -t "$session_name" window-status-current-format "" >/dev/null 2>&1 || true
|
|
706
703
|
tmux set-option -t "$session_name" window-status-separator "" >/dev/null 2>&1 || true
|
|
@@ -906,6 +903,47 @@ tmux_ensure_session() {
|
|
|
906
903
|
_tmux_source_command_hook "$sess"
|
|
907
904
|
}
|
|
908
905
|
|
|
906
|
+
# Create a new auto-named Orchestra session in the current session's worktree and switch to it.
|
|
907
|
+
# Uses the same tmux_ensure_session path as the TUI tree view create action.
|
|
908
|
+
# Usage: tmux_create_workspace_session <current_session> [client_tty]
|
|
909
|
+
tmux_create_workspace_session() {
|
|
910
|
+
local current_session="$1"
|
|
911
|
+
local target_client="${2:-}"
|
|
912
|
+
local session_dir branch slug new_session
|
|
913
|
+
|
|
914
|
+
if ! tmux_available; then
|
|
915
|
+
err "tmux not installed"
|
|
916
|
+
return 1
|
|
917
|
+
fi
|
|
918
|
+
if [[ -z "$current_session" ]]; then
|
|
919
|
+
err "tmux_create_workspace_session: current session required"
|
|
920
|
+
return 1
|
|
921
|
+
fi
|
|
922
|
+
|
|
923
|
+
session_dir="$(tmux display-message -t "$current_session" -p '#{pane_current_path}' 2>/dev/null || echo "")"
|
|
924
|
+
if [[ -z "$session_dir" || ! -d "$session_dir" ]]; then
|
|
925
|
+
err "Unable to determine current worktree path"
|
|
926
|
+
return 1
|
|
927
|
+
fi
|
|
928
|
+
|
|
929
|
+
branch="$(_tmux_branch_for_path "$session_dir" 2>/dev/null || true)"
|
|
930
|
+
if [[ -z "$branch" || "$branch" == "detached" ]]; then
|
|
931
|
+
err "Unable to determine current worktree branch"
|
|
932
|
+
return 1
|
|
933
|
+
fi
|
|
934
|
+
|
|
935
|
+
slug="$(git_branch_to_slug "$branch")"
|
|
936
|
+
new_session="$(tmux_ensure_session "$slug" "" "$session_dir")" || return 1
|
|
937
|
+
|
|
938
|
+
if [[ -n "$target_client" ]]; then
|
|
939
|
+
tmux switch-client -c "$target_client" -t "$new_session" >/dev/null 2>&1 || return 1
|
|
940
|
+
else
|
|
941
|
+
tmux switch-client -t "$new_session" >/dev/null 2>&1 || return 1
|
|
942
|
+
fi
|
|
943
|
+
|
|
944
|
+
printf '%s\n' "$new_session"
|
|
945
|
+
}
|
|
946
|
+
|
|
909
947
|
# Check if a session exists
|
|
910
948
|
# Usage: tmux_session_exists <session_name>
|
|
911
949
|
tmux_session_exists() {
|
|
@@ -1083,7 +1121,7 @@ tmux_rename_session() {
|
|
|
1083
1121
|
|
|
1084
1122
|
# --------------------------- Session Discovery ------------------------------
|
|
1085
1123
|
|
|
1086
|
-
# Get tmux sessions for a slug prefix; prints session names sorted by
|
|
1124
|
+
# Get tmux sessions for a slug prefix; prints session names sorted by creation time, oldest first
|
|
1087
1125
|
# Expected session format: [worktreename]_[worktreehash]_[datetime]_[readable_name]
|
|
1088
1126
|
# Usage: tmux_list_sessions_for_slug <slug> [worktree_path]
|
|
1089
1127
|
tmux_list_sessions_for_slug() {
|
|
@@ -1114,19 +1152,19 @@ tmux_list_sessions_for_slug() {
|
|
|
1114
1152
|
fi
|
|
1115
1153
|
|
|
1116
1154
|
# List sessions with any known prefix variant
|
|
1117
|
-
tmux list-sessions -F '#{session_name}|||#{
|
|
1155
|
+
tmux list-sessions -F '#{session_name}|||#{session_created}' 2>/dev/null \
|
|
1118
1156
|
| sed 's/|||/\t/g' \
|
|
1119
|
-
| awk -v a="$p1_new" -v b="$p2_new" -v c="$p1_old" -v d="$p2_old" -v e="$p1_branch_hash" -v f="$p2_branch_hash" 'BEGIN{FS="\t"} (length(a)>0 && index($1, a)==1) || (length(b)>0 && index($1, b)==1) || (length(c)>0 && index($1, c)==1) || (length(d)>0 && index($1, d)==1) || (length(e)>0 && index($1, e)==1) || (length(f)>0 && index($1, f)==1) {print $1"\t"$2
|
|
1120
|
-
| sort -t $'\t' -k2,
|
|
1157
|
+
| awk -v a="$p1_new" -v b="$p2_new" -v c="$p1_old" -v d="$p2_old" -v e="$p1_branch_hash" -v f="$p2_branch_hash" 'BEGIN{FS="\t"} (length(a)>0 && index($1, a)==1) || (length(b)>0 && index($1, b)==1) || (length(c)>0 && index($1, c)==1) || (length(d)>0 && index($1, d)==1) || (length(e)>0 && index($1, e)==1) || (length(f)>0 && index($1, f)==1) {print $1"\t"$2}' \
|
|
1158
|
+
| sort -t $'\t' -k2,2n -k1,1f \
|
|
1121
1159
|
| awk -F '\t' '{print $1}' | awk '!seen[$0]++' || true
|
|
1122
1160
|
else
|
|
1123
1161
|
# New-format prefix matching without hash: orchestra__slug__... or slug__...
|
|
1124
1162
|
local prefix1="${ORCH_PREFIX}${slug}${d}"
|
|
1125
1163
|
local prefix2="${slug}${d}"
|
|
1126
|
-
tmux list-sessions -F '#{session_name}|||#{
|
|
1164
|
+
tmux list-sessions -F '#{session_name}|||#{session_created}' 2>/dev/null \
|
|
1127
1165
|
| sed 's/|||/\t/g' \
|
|
1128
|
-
| awk -v p1="$prefix1" -v p2="$prefix2" 'BEGIN{FS="\t"} index($1, p1)==1 || index($1, p2)==1 {print $1"\t"$2
|
|
1129
|
-
| sort -t $'\t' -k2,
|
|
1166
|
+
| awk -v p1="$prefix1" -v p2="$prefix2" 'BEGIN{FS="\t"} index($1, p1)==1 || index($1, p2)==1 {print $1"\t"$2}' \
|
|
1167
|
+
| sort -t $'\t' -k2,2n -k1,1f \
|
|
1130
1168
|
| awk -F '\t' '{print $1}' || true
|
|
1131
1169
|
fi
|
|
1132
1170
|
}
|
|
@@ -1509,21 +1547,33 @@ tmux_show_orchestra_help_popup() {
|
|
|
1509
1547
|
fi
|
|
1510
1548
|
|
|
1511
1549
|
local popup_command
|
|
1512
|
-
popup_command=
|
|
1550
|
+
popup_command="$(cat <<'EOF'
|
|
1551
|
+
bash -lc '
|
|
1552
|
+
trap "exit 0" INT TERM
|
|
1553
|
+
printf "%s\n" \
|
|
1513
1554
|
"Orchestra tmux shortcuts" \
|
|
1514
1555
|
"" \
|
|
1556
|
+
"Ctrl+b, d Detach and return to Orchestra" \
|
|
1557
|
+
"Ctrl+b, r Rename the current Orchestra session" \
|
|
1558
|
+
"Ctrl+b, n New Orchestra session in this worktree" \
|
|
1559
|
+
"" \
|
|
1515
1560
|
"Ctrl+b, Left Previous Orchestra session in this workspace" \
|
|
1516
1561
|
"Ctrl+b, Right Next Orchestra session in this workspace" \
|
|
1517
1562
|
"Ctrl+b, < Previous Orchestra session in this workspace" \
|
|
1518
1563
|
"Ctrl+b, > Next Orchestra session in this workspace" \
|
|
1519
|
-
"
|
|
1520
|
-
"Ctrl+b, d Detach and return to Orchestra" \
|
|
1564
|
+
"" \
|
|
1521
1565
|
"Ctrl+b, [ Copy/scroll mode" \
|
|
1566
|
+
"Ctrl+b, h Show this help" \
|
|
1522
1567
|
"Ctrl+b, ? Show this help" \
|
|
1523
1568
|
"" \
|
|
1524
|
-
"Press
|
|
1569
|
+
"Press any key to close..."
|
|
1570
|
+
IFS= read -rsn1 _ || true
|
|
1571
|
+
exit 0
|
|
1572
|
+
'
|
|
1573
|
+
EOF
|
|
1574
|
+
)"
|
|
1525
1575
|
|
|
1526
|
-
tmux display-popup "${target_args[@]}" -E -w 78 -h
|
|
1576
|
+
tmux display-popup "${target_args[@]}" -E -w 78 -h 18 -T "Orchestra shortcuts" "$popup_command" >/dev/null 2>&1 || true
|
|
1527
1577
|
}
|
|
1528
1578
|
|
|
1529
1579
|
# Find the adjacent active Orchestra session registered for the current repo.
|
|
@@ -1556,7 +1606,7 @@ tmux_workspace_cycle_target() {
|
|
|
1556
1606
|
}
|
|
1557
1607
|
|
|
1558
1608
|
active_file="$(mktemp)"
|
|
1559
|
-
tmux list-sessions -F $'#{session_name}\t#{@orchestra_display_name}' > "$active_file" 2>/dev/null || {
|
|
1609
|
+
tmux list-sessions -F $'#{session_name}\t#{@orchestra_display_name}\t#{session_last_attached}\t#{session_activity}' > "$active_file" 2>/dev/null || {
|
|
1560
1610
|
rm -f "$active_file"
|
|
1561
1611
|
err "Unable to list tmux sessions"
|
|
1562
1612
|
return 1
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -97,7 +97,11 @@ case "${1:-}" in
|
|
|
97
97
|
"create-session-exact")
|
|
98
98
|
bridge_create_session_exact "${2:-}" "${3:-}"
|
|
99
99
|
;;
|
|
100
|
-
|
|
100
|
+
|
|
101
|
+
"create-workspace-session")
|
|
102
|
+
bridge_create_workspace_session "${2:-}" "${3:-}"
|
|
103
|
+
;;
|
|
104
|
+
|
|
101
105
|
"kill-session")
|
|
102
106
|
bridge_kill_session "${2:-}"
|
|
103
107
|
;;
|
|
@@ -243,6 +247,8 @@ Commands:
|
|
|
243
247
|
copy-env-files <source> <target> Copy .env files between directories
|
|
244
248
|
cycle-workspace-session <session> <next|previous> [client]
|
|
245
249
|
Switch within registered Orchestra sessions for this repo
|
|
250
|
+
create-workspace-session <session> [client]
|
|
251
|
+
Create a new session in the current worktree and switch to it
|
|
246
252
|
tmux-help-popup [client] Show Orchestra tmux shortcut popup
|
|
247
253
|
repo-info Get repository information
|
|
248
254
|
git-status Get git status --porcelain
|
|
@@ -62,6 +62,26 @@ bridge_create_session_exact() {
|
|
|
62
62
|
fi
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
# Create a new tmux session in the current session's worktree and switch to it.
|
|
66
|
+
bridge_create_workspace_session() {
|
|
67
|
+
if [[ -z "${1:-}" ]]; then
|
|
68
|
+
json_error "Current session name required"
|
|
69
|
+
return 1
|
|
70
|
+
fi
|
|
71
|
+
session_name="$1"
|
|
72
|
+
target_client="${2:-}"
|
|
73
|
+
|
|
74
|
+
if tmux_available; then
|
|
75
|
+
created_session="$(tmux_create_workspace_session "$session_name" "$target_client")" || {
|
|
76
|
+
json_error "Failed to create workspace session"
|
|
77
|
+
return 1
|
|
78
|
+
}
|
|
79
|
+
json_object "ok:b=true" "session:s=$created_session"
|
|
80
|
+
else
|
|
81
|
+
json_error "tmux not available"
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
|
|
65
85
|
# Kill tmux session
|
|
66
86
|
bridge_kill_session() {
|
|
67
87
|
if [[ -z "${1:-}" ]]; then
|