@humanu/orchestra 0.5.29 → 0.5.30

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 (78) hide show
  1. package/install.js +27 -3
  2. package/package.json +1 -1
  3. package/resources/prebuilt/linux-x64/orchestra +0 -0
  4. package/resources/prebuilt/macos-arm64/orchestra +0 -0
  5. package/resources/prebuilt/macos-intel/orchestra +0 -0
  6. package/resources/scripts/gw-bridge.sh +50 -1024
  7. package/resources/scripts/gw.sh +25 -19
  8. package/resources/scripts/gwr.sh +41 -139
  9. package/resources/scripts/shell/bridge/ai.sh +175 -0
  10. package/resources/scripts/shell/bridge/copy_env.sh +84 -0
  11. package/resources/scripts/shell/bridge/tmux.sh +162 -0
  12. package/resources/scripts/shell/bridge/utils.sh +449 -0
  13. package/resources/scripts/shell/build/build_bridge.sh +17 -0
  14. package/resources/scripts/shell/build/build_dependencies.sh +23 -0
  15. package/resources/scripts/shell/build/build_install.sh +7 -0
  16. package/resources/scripts/shell/build/build_load.sh +10 -0
  17. package/resources/scripts/shell/build/build_logging.sh +6 -0
  18. package/resources/scripts/shell/build/build_rust.sh +18 -0
  19. package/resources/scripts/shell/build/build_usage.sh +27 -0
  20. package/resources/scripts/shell/env/copy_env_command.sh +27 -0
  21. package/resources/scripts/shell/env/copy_env_constants.sh +3 -0
  22. package/resources/scripts/shell/env/copy_env_core.sh +171 -0
  23. package/resources/scripts/shell/env/copy_env_debug_parse.sh +14 -0
  24. package/resources/scripts/shell/env/copy_env_load.sh +9 -0
  25. package/resources/scripts/shell/env/copy_env_locations.sh +34 -0
  26. package/resources/scripts/shell/env/copy_env_logging.sh +17 -0
  27. package/resources/scripts/shell/env/copy_env_state.sh +5 -0
  28. package/resources/scripts/shell/fix_hanging_colors.sh +9 -0
  29. package/resources/scripts/shell/fix_hanging_load.sh +9 -0
  30. package/resources/scripts/shell/fix_hanging_logging.sh +6 -0
  31. package/resources/scripts/shell/fix_hanging_script.sh +19 -0
  32. package/resources/scripts/shell/fix_hanging_steps.sh +81 -0
  33. package/resources/scripts/shell/git/bridge_check_branch.sh +53 -0
  34. package/resources/scripts/shell/git/bridge_create_worktree.sh +35 -0
  35. package/resources/scripts/shell/git/bridge_create_worktree_from_existing.sh +32 -0
  36. package/resources/scripts/shell/git/bridge_create_worktree_from_remote.sh +28 -0
  37. package/resources/scripts/shell/git/bridge_delete_branch_only.sh +25 -0
  38. package/resources/scripts/shell/git/bridge_delete_worktree.sh +26 -0
  39. package/resources/scripts/shell/git/bridge_delete_worktree_only.sh +28 -0
  40. package/resources/scripts/shell/git/bridge_enhanced_git_status.sh +106 -0
  41. package/resources/scripts/shell/git/bridge_git_status.sh +13 -0
  42. package/resources/scripts/shell/git/bridge_list_worktrees.sh +12 -0
  43. package/resources/scripts/shell/git/bridge_merge.sh +12 -0
  44. package/resources/scripts/shell/git/bridge_merge_from_primary.sh +112 -0
  45. package/resources/scripts/shell/git/bridge_merge_into_primary.sh +116 -0
  46. package/resources/scripts/shell/git/bridge_primary_branch.sh +15 -0
  47. package/resources/scripts/shell/git/bridge_rebase_from_primary.sh +72 -0
  48. package/resources/scripts/shell/git/bridge_repo.sh +12 -0
  49. package/resources/scripts/shell/git/bridge_repo_info.sh +23 -0
  50. package/resources/scripts/shell/git/bridge_squash_into_primary.sh +144 -0
  51. package/resources/scripts/shell/git/bridge_switch_worktree.sh +23 -0
  52. package/resources/scripts/shell/git/bridge_worktree.sh +17 -0
  53. package/resources/scripts/shell/git/checkout_worktree.sh +68 -0
  54. package/resources/scripts/shell/git/create_worktree.sh +23 -0
  55. package/resources/scripts/shell/git/delete_worktree.sh +27 -0
  56. package/resources/scripts/shell/git/gwr_worktree_title.sh +29 -0
  57. package/resources/scripts/shell/git/list_worktrees.sh +22 -0
  58. package/resources/scripts/shell/git/merge.sh +12 -0
  59. package/resources/scripts/shell/git/repo.sh +12 -0
  60. package/resources/scripts/shell/git/status.sh +21 -0
  61. package/resources/scripts/shell/git/worktree.sh +17 -0
  62. package/resources/scripts/shell/gw_debug.sh +3 -0
  63. package/resources/scripts/shell/gw_err.sh +3 -0
  64. package/resources/scripts/shell/gw_have_cmd.sh +3 -0
  65. package/resources/scripts/shell/gw_info.sh +3 -0
  66. package/resources/scripts/shell/gw_legacy_wrappers.sh +7 -0
  67. package/resources/scripts/shell/gw_load.sh +9 -0
  68. package/resources/scripts/shell/gwr_binary.sh +25 -0
  69. package/resources/scripts/shell/gwr_bridge.sh +10 -0
  70. package/resources/scripts/shell/gwr_colors.sh +7 -0
  71. package/resources/scripts/shell/gwr_git.sh +8 -0
  72. package/resources/scripts/shell/gwr_load.sh +12 -0
  73. package/resources/scripts/shell/gwr_logging.sh +6 -0
  74. package/resources/scripts/shell/gwr_terminal.sh +13 -0
  75. package/resources/scripts/shell/gwr_usage.sh +49 -0
  76. package/resources/scripts/shell/orchestra-command-hook.sh +109 -0
  77. package/resources/scripts/shell/orchestra-local.sh +87 -0
  78. package/resources/scripts/commands.sh +0 -208
@@ -0,0 +1,68 @@
1
+ # shellcheck shell=bash
2
+
3
+ cmd_checkout_worktree() {
4
+ local create_new=false
5
+ local branch_name=""
6
+ local root; root="$(git_require_repo_root)" || return 1
7
+ local shared_root; shared_root="$(git_shared_root 2>/dev/null)"
8
+ [[ -z "$shared_root" ]] && shared_root="$root"
9
+ local source_root="$(git_current_path)"
10
+
11
+ if [[ "${1-}" == "-b" ]]; then
12
+ [[ -z "${2-}" ]] && { err "Branch name required for -b"; echo "Usage: gw checkout -b <branch>"; return 1; }
13
+ create_new=true
14
+ branch_name="$2"
15
+ [[ "$#" -gt 2 ]] && { err "Too many args"; return 1; }
16
+ else
17
+ [[ -z "${1-}" ]] && { err "Branch name required"; echo "Usage: gw checkout <branch>"; return 1; }
18
+ branch_name="$1"
19
+ [[ "$#" -gt 1 ]] && { err "Too many args"; return 1; }
20
+ fi
21
+
22
+ if $create_new; then
23
+ if git_branch_exists "$branch_name"; then
24
+ # Branch exists, ensure worktree exists
25
+ local wt; wt="$(git_branch_to_worktree_path "$branch_name")"
26
+ if [[ -n "$wt" ]]; then
27
+ info "✅ Worktree exists at '$wt'"
28
+ echo "cd \"$wt\""
29
+ else
30
+ # Create worktree for existing branch
31
+ info "🌳 Creating worktree for existing branch '$branch_name'..."
32
+ wt="$(git_ensure_worktree_for_branch "$branch_name")"
33
+ copy_env_files "$source_root" "$wt" "$shared_root"
34
+ echo "cd \"$wt\""
35
+ fi
36
+ return 0
37
+ else
38
+ # Create new branch and worktree
39
+ cmd_create_worktree "$branch_name" || return $?
40
+ local wt; wt="$(git_branch_to_worktree_path "$branch_name")"
41
+ [[ -n "$wt" ]] && {
42
+ echo "cd \"$wt\""
43
+ return 0
44
+ }
45
+ err "Worktree created but not found"
46
+ return 1
47
+ fi
48
+ else
49
+ # Switch to existing branch
50
+ local wt; wt="$(git_branch_to_worktree_path "$branch_name")"
51
+ if [[ -n "$wt" ]]; then
52
+ echo "cd \"$wt\""
53
+ return 0
54
+ fi
55
+
56
+ # Try to create worktree for existing branch
57
+ if git_branch_exists "$branch_name"; then
58
+ info "🌳 Creating worktree for existing branch '$branch_name'..."
59
+ wt="$(git_ensure_worktree_for_branch "$branch_name")"
60
+ copy_env_files "$source_root" "$wt" "$shared_root"
61
+ echo "cd \"$wt\""
62
+ return 0
63
+ else
64
+ err "Branch '$branch_name' does not exist"
65
+ return 1
66
+ fi
67
+ fi
68
+ }
@@ -0,0 +1,23 @@
1
+ # shellcheck shell=bash
2
+
3
+ cmd_create_worktree() {
4
+ if [ -z "${1-}" ]; then
5
+ err "Branch name required"
6
+ echo "Usage: gw create <branch>"
7
+ return 1
8
+ fi
9
+ local branch_name="$1"
10
+ local root; root="$(git_require_repo_root)" || return 1
11
+ local shared_root; shared_root="$(git_shared_root 2>/dev/null)"
12
+ [[ -z "$shared_root" ]] && shared_root="$root"
13
+ local source_root="$(git_current_path)"
14
+
15
+ local dir; dir="$(git_build_worktree_path "$branch_name")"
16
+
17
+ info "🌳 Creating branch '$branch_name' and worktree at '$dir'..."
18
+ dir="$(git_create_branch_and_worktree "$branch_name")"
19
+ copy_env_files "$source_root" "$dir" "$shared_root"
20
+ info "✅ Success! Worktree created at '$dir'."
21
+ echo "cd \"$dir\""
22
+ (cd "$dir" && git_status_short)
23
+ }
@@ -0,0 +1,27 @@
1
+ # shellcheck shell=bash
2
+
3
+ cmd_delete_worktree() {
4
+ if [ -z "${1-}" ]; then
5
+ err "Branch name required"
6
+ echo "Usage: gw delete <branch>"
7
+ return 1
8
+ fi
9
+ local branch_name="$1"
10
+ git_require_repo || return 1
11
+
12
+ local worktree_path; worktree_path="$(git_branch_to_worktree_path "$branch_name")"
13
+
14
+ info "🗑️ Removing worktree and deleting branch '$branch_name'..."
15
+
16
+ # Remove worktree if it exists
17
+ if [[ -n "$worktree_path" ]] && [[ -d "$worktree_path" ]]; then
18
+ git_remove_worktree "$worktree_path"
19
+ fi
20
+
21
+ # Delete branch if it exists
22
+ if git_branch_exists "$branch_name"; then
23
+ git_delete_branch "$branch_name"
24
+ fi
25
+
26
+ info "🧹 Done."
27
+ }
@@ -0,0 +1,29 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_get_current_worktree_title() {
4
+ local branch=""
5
+ local worktree=""
6
+
7
+ if command -v git >/dev/null 2>&1 && git rev-parse --git-dir >/dev/null 2>&1; then
8
+ branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
9
+ if [[ -n "$branch" && "$branch" != "HEAD" ]]; then
10
+ worktree="$branch"
11
+ else
12
+ worktree="$(git rev-parse --short HEAD 2>/dev/null || echo "")"
13
+ fi
14
+ fi
15
+
16
+ if [[ -z "$worktree" ]]; then
17
+ worktree="$(pwd -P)"
18
+ worktree="$(basename "$worktree")"
19
+ fi
20
+
21
+ worktree="${worktree//\//-}"
22
+ worktree="${worktree// /-}"
23
+
24
+ if [[ -z "$worktree" ]]; then
25
+ worktree="unknown"
26
+ fi
27
+
28
+ printf 'orchestra [orchestra/%s]' "$worktree"
29
+ }
@@ -0,0 +1,22 @@
1
+ # shellcheck shell=bash
2
+
3
+ cmd_list_worktrees() {
4
+ local root; root="$(git_require_repo_root)" || return 1
5
+
6
+ local here; here="$(git_current_path)"
7
+ info "🌳 Listing Git Worktrees (repo: $root)"
8
+ echo ""
9
+ printf ' %-35s %-12s %s\n' "BRANCH" "HEAD" "PATH"
10
+ printf ' %s\n' "------------------------------------------------------------------------------------------"
11
+
12
+ while IFS=$'\t' read -r path branch sha; do
13
+ local rel="$path"
14
+ [[ "$path" == "$root" ]] && rel="."
15
+ [[ "$path" == "$root"/* ]] && rel="${path#$root/}"
16
+ local indicator=" "
17
+ [[ "$path" == "$here" ]] && indicator="◉ "
18
+ printf '%s🌿 %-35s %-12s %s\n' "$indicator" "$branch" "$sha" "$rel"
19
+ done < <(git_list_worktrees)
20
+
21
+ printf ' %s\n' "------------------------------------------------------------------------------------------"
22
+ }
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ # shellcheck shell=bash
4
+
5
+ # Master file that sources all individual bridge functions for merge operations
6
+ # This maintains the same interface while using modular files
7
+
8
+ # Source individual merge functions
9
+ source "$(dirname "${BASH_SOURCE[0]}")/merge_from_primary.sh"
10
+ source "$(dirname "${BASH_SOURCE[0]}")/rebase_from_primary.sh"
11
+ source "$(dirname "${BASH_SOURCE[0]}")/merge_into_primary.sh"
12
+ source "$(dirname "${BASH_SOURCE[0]}")/squash_into_primary.sh"
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ # shellcheck shell=bash
4
+
5
+ # Master file that sources all individual bridge functions for repository operations
6
+ # This maintains the same interface while using modular files
7
+
8
+ # Source individual repo functions
9
+ source "$(dirname "${BASH_SOURCE[0]}")/repo_info.sh"
10
+ source "$(dirname "${BASH_SOURCE[0]}")/git_status.sh"
11
+ source "$(dirname "${BASH_SOURCE[0]}")/enhanced_git_status.sh"
12
+ source "$(dirname "${BASH_SOURCE[0]}")/primary_branch.sh"
@@ -0,0 +1,21 @@
1
+ # shellcheck shell=bash
2
+
3
+ cmd_status() {
4
+ local root; root="$(git_require_repo_root)" || return 1
5
+
6
+ local here; here="$(git_current_path)"
7
+ local rel="$here"
8
+ [[ "$here" == "$root" ]] && rel="."
9
+ [[ "$here" == "$root"/* ]] && rel="${here#$root/}"
10
+
11
+ local branch; branch="$(git_current_branch)"
12
+ if [[ -z "$branch" ]]; then
13
+ branch="$(git_current_commit_short)"
14
+ [[ -z "$branch" ]] && { err "Cannot determine branch/commit"; return 1; }
15
+ info "🌳 In worktree '$rel' (Detached HEAD: $branch)"
16
+ else
17
+ info "🌳 In worktree '$rel' on branch '$branch'"
18
+ fi
19
+ echo ""
20
+ git_status "$@"
21
+ }
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ # shellcheck shell=bash
4
+
5
+ # Master file that sources all individual bridge functions for worktree operations
6
+ # This maintains the same interface while using modular files
7
+
8
+ # Source individual worktree functions
9
+ source "$(dirname "${BASH_SOURCE[0]}")/list_worktrees.sh"
10
+ source "$(dirname "${BASH_SOURCE[0]}")/check_branch.sh"
11
+ source "$(dirname "${BASH_SOURCE[0]}")/create_worktree.sh"
12
+ source "$(dirname "${BASH_SOURCE[0]}")/create_worktree_from_existing.sh"
13
+ source "$(dirname "${BASH_SOURCE[0]}")/create_worktree_from_remote.sh"
14
+ source "$(dirname "${BASH_SOURCE[0]}")/delete_worktree.sh"
15
+ source "$(dirname "${BASH_SOURCE[0]}")/delete_worktree_only.sh"
16
+ source "$(dirname "${BASH_SOURCE[0]}")/delete_branch_only.sh"
17
+ source "$(dirname "${BASH_SOURCE[0]}")/switch_worktree.sh"
@@ -0,0 +1,3 @@
1
+ # shellcheck shell=bash
2
+
3
+ debug() { :; }
@@ -0,0 +1,3 @@
1
+ # shellcheck shell=bash
2
+
3
+ err() { printf '❌ %s\n' "$*" 1>&2; }
@@ -0,0 +1,3 @@
1
+ # shellcheck shell=bash
2
+
3
+ have_cmd() { command -v "$1" >/dev/null 2>&1; }
@@ -0,0 +1,3 @@
1
+ # shellcheck shell=bash
2
+
3
+ info() { printf '%s\n' "$*"; }
@@ -0,0 +1,7 @@
1
+ # shellcheck shell=bash
2
+
3
+ repo_root() { git_repo_root; }
4
+ current_abs_path() { git_current_path; }
5
+ branch_to_slug() { git_branch_to_slug "$1"; }
6
+ worktree_path_to_branch() { git_worktree_path_to_branch "$1"; }
7
+ list_worktrees() { git_list_worktrees; }
@@ -0,0 +1,9 @@
1
+ # shellcheck shell=bash
2
+
3
+ gw_load_core() {
4
+ source "$SCRIPT_DIR/shell/gw_err.sh"
5
+ source "$SCRIPT_DIR/shell/gw_info.sh"
6
+ source "$SCRIPT_DIR/shell/gw_debug.sh"
7
+ source "$SCRIPT_DIR/shell/gw_have_cmd.sh"
8
+ source "$SCRIPT_DIR/shell/gw_legacy_wrappers.sh"
9
+ }
@@ -0,0 +1,25 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_find_binary() {
4
+ if [[ -n "${GW_TUI_BIN:-}" && -x "$GW_TUI_BIN" ]]; then
5
+ echo "$GW_TUI_BIN"
6
+ return 0
7
+ fi
8
+
9
+ local binary_paths=(
10
+ "$SCRIPT_DIR/orchestra"
11
+ "$SCRIPT_DIR/gw-tui"
12
+ "$SCRIPT_DIR/gw-tui/target/release/gw-tui"
13
+ "$SCRIPT_DIR/gw-tui/target/debug/gw-tui"
14
+ "$(command -v gw-tui 2>/dev/null || true)"
15
+ )
16
+
17
+ for path in "${binary_paths[@]}"; do
18
+ if [[ -n "$path" && -f "$path" && -x "$path" ]]; then
19
+ echo "$path"
20
+ return 0
21
+ fi
22
+ done
23
+
24
+ return 1
25
+ }
@@ -0,0 +1,10 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_check_bridge_script() {
4
+ local bridge_path="$SCRIPT_DIR/gw-bridge.sh"
5
+ if [[ ! -x "$bridge_path" ]]; then
6
+ gwr_error "gw-bridge.sh not found or not executable at: $bridge_path"
7
+ gwr_error "Please ensure the bridge script exists and is executable."
8
+ exit 1
9
+ fi
10
+ }
@@ -0,0 +1,7 @@
1
+ # shellcheck shell=bash
2
+
3
+ GW_COLOR_RED='\033[0;31m'
4
+ GW_COLOR_GREEN='\033[0;32m'
5
+ GW_COLOR_YELLOW='\033[1;33m'
6
+ GW_COLOR_BLUE='\033[0;34m'
7
+ GW_COLOR_RESET='\033[0m'
@@ -0,0 +1,8 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_check_git_repo() {
4
+ if ! git rev-parse --git-dir >/dev/null 2>&1; then
5
+ gwr_error "Not a git repository or git command not found."
6
+ exit 1
7
+ fi
8
+ }
@@ -0,0 +1,12 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_load_core() {
4
+ source "$SCRIPT_DIR/shell/gwr_colors.sh"
5
+ source "$SCRIPT_DIR/shell/gwr_logging.sh"
6
+ source "$SCRIPT_DIR/shell/gwr_git.sh"
7
+ source "$SCRIPT_DIR/shell/gwr_bridge.sh"
8
+ source "$SCRIPT_DIR/shell/gwr_binary.sh"
9
+ source "$SCRIPT_DIR/shell/git/gwr_worktree_title.sh"
10
+ source "$SCRIPT_DIR/shell/gwr_terminal.sh"
11
+ source "$SCRIPT_DIR/shell/gwr_usage.sh"
12
+ }
@@ -0,0 +1,6 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_info() { printf "${GW_COLOR_BLUE:-}[INFO]${GW_COLOR_RESET:-} %s\n" "$*" >&2; }
4
+ gwr_success() { printf "${GW_COLOR_GREEN:-}[SUCCESS]${GW_COLOR_RESET:-} %s\n" "$*" >&2; }
5
+ gwr_warn() { printf "${GW_COLOR_YELLOW:-}[WARN]${GW_COLOR_RESET:-} %s\n" "$*" >&2; }
6
+ gwr_error() { printf "${GW_COLOR_RED:-}[ERROR]${GW_COLOR_RESET:-} %s\n" "$*" >&2; }
@@ -0,0 +1,13 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_set_terminal_title() {
4
+ local tty_device
5
+ tty_device="$(tty 2>/dev/null || true)"
6
+ if [[ -z "$tty_device" || ! -w "$tty_device" ]]; then
7
+ return 0
8
+ fi
9
+
10
+ local title
11
+ title="$(gwr_get_current_worktree_title)"
12
+ printf '\033]0;%s\007' "$title" >"$tty_device" 2>/dev/null || true
13
+ }
@@ -0,0 +1,49 @@
1
+ # shellcheck shell=bash
2
+
3
+ gwr_show_usage() {
4
+ cat << EOF
5
+ gwr - Git Worktree Rust TUI
6
+
7
+ Usage: gwr [options]
8
+
9
+ A terminal user interface for managing git worktrees and tmux sessions.
10
+
11
+ Options:
12
+ -d, --debug Enable debug mode
13
+ -h, --help Show this help
14
+
15
+ Features:
16
+ • Interactive worktree and session management
17
+ • Visual tree display of worktrees and their tmux sessions
18
+ • Real-time session previews and git status
19
+ • Keyboard navigation with vim-like bindings
20
+ • Session creation, deletion, and renaming
21
+ • AI-powered session naming (when configured)
22
+
23
+ Navigation:
24
+ ↑/↓ Navigate items
25
+ Enter Select worktree or attach to session
26
+ s Auth menu (if enabled)
27
+ Space Expand/collapse worktree sessions
28
+ d Delete worktree or kill session
29
+ r Rename session (AI-powered)
30
+ c Create new worktree
31
+ o Configure Anthropic API key
32
+ Ctrl+R Refresh data
33
+ q/Esc Quit
34
+
35
+ Requirements:
36
+ • Git repository
37
+ • Rust TUI binary (built with build.sh)
38
+ • gw-bridge.sh script
39
+ • tmux (optional, for session management)
40
+
41
+ For the original shell-based interface, use: gw
42
+
43
+ Examples:
44
+ gwr # Launch interactive TUI
45
+ gwr --debug # Launch with debug information
46
+ gwr --help # Show this help
47
+
48
+ EOF
49
+ }
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Orchestra command history hook
4
+ #
5
+ # Source this file from your shell profile to log each executed command to a
6
+ # per-tmux-session history file. The auto-rename pipeline can then use the
7
+ # captured history as the primary signal for determining app prefixes.
8
+ #
9
+ # source /path/to/orchestrator/shell/orchestra-command-hook.sh
10
+ #
11
+ # On Bash we automatically append the hook to PROMPT_COMMAND; on Zsh we add a
12
+ # precmd hook (requires add-zsh-hook). Other shells can invoke
13
+ # `orchestra_log_command` manually from their prompt hooks.
14
+
15
+ if [[ -n "${ORCHESTRA_PROMPT_HOOK_INSTALLED-}" ]]; then
16
+ return 0 2>/dev/null || exit 0
17
+ fi
18
+
19
+ ORCHESTRA_HISTORY_DIR="${ORCHESTRA_HISTORY_DIR:-$HOME/.orchestra/history}"
20
+ ORCHESTRA_PROMPT_HOOK_INSTALLED=1
21
+
22
+ _orchestra_history_key() {
23
+ local key="$1"
24
+ key="${key//\//_}"
25
+ key=$(echo "$key" | tr '[:space:]' '_')
26
+ key=$(echo "$key" | tr -c '[:alnum:]_-' '_')
27
+ while [[ "$key" == *"__"* ]]; do
28
+ key="${key//__/_}"
29
+ done
30
+ key="${key##_}"
31
+ key="${key%%_}"
32
+ echo "$key"
33
+ }
34
+
35
+ _orchestra_capture_command() {
36
+ local cmd=""
37
+ if [[ -n "${ZSH_VERSION-}" ]]; then
38
+ # fc -ln -1 returns the most recent command without line numbers
39
+ cmd="$(fc -ln -1 2>/dev/null)"
40
+ else
41
+ cmd="$(history 1 2>/dev/null)"
42
+ cmd="${cmd#*[0-9] }"
43
+ fi
44
+ printf '%s' "$cmd"
45
+ }
46
+
47
+ orchestra_log_command() {
48
+ local command=$(_orchestra_capture_command)
49
+ command="${command## }"
50
+ if [[ -z "$command" ]]; then
51
+ return
52
+ fi
53
+
54
+ # Avoid logging duplicate consecutive commands within the same shell
55
+ if [[ "$command" == "${ORCHESTRA_LAST_COMMAND-}" ]]; then
56
+ return
57
+ fi
58
+ ORCHESTRA_LAST_COMMAND="$command"
59
+
60
+ local session_name=""
61
+ if command -v tmux >/dev/null 2>&1 && [[ -n "${TMUX-}" ]]; then
62
+ session_name="$(tmux display-message -p '#{session_name}' 2>/dev/null || echo "")"
63
+ fi
64
+ session_name="${session_name:-shell}"
65
+
66
+ local key
67
+ key=$(_orchestra_history_key "$session_name")
68
+ if [[ -z "$key" ]]; then
69
+ key="shell"
70
+ fi
71
+
72
+ mkdir -p "$ORCHESTRA_HISTORY_DIR"
73
+
74
+ local timestamp
75
+ timestamp=$(date '+%Y-%m-%dT%H:%M:%S%z')
76
+ printf '%s\t%s\n' "$timestamp" "$command" >> "$ORCHESTRA_HISTORY_DIR/$key.log"
77
+ }
78
+
79
+ _orchestra_install_hook_bash() {
80
+ if [[ "${PROMPT_COMMAND-}" == *orchestra_log_command* ]]; then
81
+ return
82
+ fi
83
+ if [[ -n "${PROMPT_COMMAND-}" ]]; then
84
+ PROMPT_COMMAND="orchestra_log_command; ${PROMPT_COMMAND}"
85
+ else
86
+ PROMPT_COMMAND="orchestra_log_command"
87
+ fi
88
+ }
89
+
90
+ _orchestra_install_hook_zsh() {
91
+ if command -v add-zsh-hook >/dev/null 2>&1; then
92
+ add-zsh-hook precmd orchestra_log_command
93
+ else
94
+ # Fallback: append to precmd_functions manually
95
+ if [[ -z "${precmd_functions[(r)orchestra_log_command]}" ]]; then
96
+ precmd_functions+=(orchestra_log_command)
97
+ fi
98
+ fi
99
+ }
100
+
101
+ _orchestra_install_hook() {
102
+ if [[ -n "${ZSH_VERSION-}" ]]; then
103
+ _orchestra_install_hook_zsh
104
+ else
105
+ _orchestra_install_hook_bash
106
+ fi
107
+ }
108
+
109
+ _orchestra_install_hook
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+
3
+ # Orchestra local development command.
4
+ # Usage: orchestra-local [--root <path>] [--worktree <name>] [extra args]
5
+ #
6
+ # - Default root is $HOME/repos/orchestrator (override via ORCHESTRA_LOCAL_ROOT
7
+ # or --root).
8
+ # - Worktree flag resolves to <root>/worktrees/<name>/gwr.sh for convenience.
9
+
10
+ set -euo pipefail
11
+
12
+ print_usage() {
13
+ cat <<'EOF'
14
+ Usage: orchestra-local [--root <path>] [--worktree <name>] [args...]
15
+
16
+ Launch the local Orchestra TUI directly from your cloned repository.
17
+
18
+ Options:
19
+ --root <path> Path to the orchestrator repo (default: $HOME/repos/orchestrator)
20
+ or the value of $ORCHESTRA_LOCAL_ROOT if set.
21
+ -w, --worktree <n> Use the worktree wrapper at <root>/worktrees/<n>/gwr.sh
22
+ -h, --help Show this help and exit.
23
+
24
+ Any remaining arguments are forwarded to the local gwr.sh script.
25
+
26
+ Environment:
27
+ ORCHESTRA_LOCAL_ROOT Overrides the default repo path.
28
+ EOF
29
+ }
30
+
31
+ main() {
32
+ local root="${ORCHESTRA_LOCAL_ROOT:-$HOME/repos/orchestrator}"
33
+ local worktree=""
34
+ local args=()
35
+
36
+ while [[ $# -gt 0 ]]; do
37
+ case $1 in
38
+ --root)
39
+ [[ $# -lt 2 ]] && { echo "--root requires a value" >&2; exit 1; }
40
+ root="$2"
41
+ shift 2
42
+ ;;
43
+ -w|--worktree)
44
+ [[ $# -lt 2 ]] && { echo "--worktree requires a value" >&2; exit 1; }
45
+ worktree="$2"
46
+ shift 2
47
+ ;;
48
+ -h|--help)
49
+ print_usage
50
+ return 0
51
+ ;;
52
+ --)
53
+ shift
54
+ args+=("$@")
55
+ break
56
+ ;;
57
+ *)
58
+ args+=("$1")
59
+ shift
60
+ ;;
61
+ esac
62
+ done
63
+
64
+ if [[ ! -d "$root" ]]; then
65
+ echo "orchestra-local: repository not found at $root" >&2
66
+ echo "Set ORCHESTRA_LOCAL_ROOT or use --root <path> to point to your clone." >&2
67
+ exit 1
68
+ fi
69
+
70
+ local script_path="$root/gwr.sh"
71
+ if [[ -n "$worktree" ]]; then
72
+ script_path="$root/worktrees/$worktree/gwr.sh"
73
+ fi
74
+
75
+ if [[ ! -f "$script_path" ]]; then
76
+ echo "orchestra-local: unable to locate $script_path" >&2
77
+ exit 1
78
+ fi
79
+
80
+ if [[ ${#args[@]} -gt 0 ]]; then
81
+ exec bash "$script_path" "${args[@]}"
82
+ else
83
+ exec bash "$script_path"
84
+ fi
85
+ }
86
+
87
+ main "$@"