From 7773ae68cf716f0da9db6e89052ff9f9429b5649 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 15:55:32 -0800 Subject: [PATCH 1/6] Refactor README and gtr script for improved configuration commands. Update README to replace 'git config' with 'gtr config' for clarity and consistency. Enhance gtr script to support 'add' action in config management, allowing multi-valued configurations. Update error messages and documentation for better user guidance. --- README.md | 64 +++++++++++++++++++++++++++---------------------------- bin/gtr | 57 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 77 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 775df6c..3b8a470 100644 --- a/README.md +++ b/README.md @@ -324,13 +324,13 @@ Copy files to new worktrees using glob patterns: ```bash # Add patterns to copy (multi-valued) -git config --add gtr.copy.include "**/.env.example" -git config --add gtr.copy.include "**/CLAUDE.md" -git config --add gtr.copy.include "*.config.js" +gtr config add gtr.copy.include "**/.env.example" +gtr config add gtr.copy.include "**/CLAUDE.md" +gtr config add gtr.copy.include "*.config.js" # Exclude patterns (multi-valued) -git config --add gtr.copy.exclude "**/.env" -git config --add gtr.copy.exclude "**/secrets.*" +gtr config add gtr.copy.exclude "**/.env" +gtr config add gtr.copy.exclude "**/secrets.*" ``` **⚠️ Security Note:** Be careful not to copy sensitive files. Use `.env.example` instead of `.env`. @@ -341,11 +341,11 @@ Run custom commands after worktree operations: ```bash # Post-create hooks (multi-valued, run in order) -git config --add gtr.hook.postCreate "npm install" -git config --add gtr.hook.postCreate "npm run build" +gtr config add gtr.hook.postCreate "npm install" +gtr config add gtr.hook.postCreate "npm run build" # Post-remove hooks -git config --add gtr.hook.postRemove "echo 'Cleaned up!'" +gtr config add gtr.hook.postRemove "echo 'Cleaned up!'" ``` **Environment variables available in hooks:** @@ -358,19 +358,19 @@ git config --add gtr.hook.postRemove "echo 'Cleaned up!'" ```bash # Node.js (npm) -git config --add gtr.hook.postCreate "npm install" +gtr config add gtr.hook.postCreate "npm install" # Node.js (pnpm) -git config --add gtr.hook.postCreate "pnpm install" +gtr config add gtr.hook.postCreate "pnpm install" # Python -git config --add gtr.hook.postCreate "pip install -r requirements.txt" +gtr config add gtr.hook.postCreate "pip install -r requirements.txt" # Ruby -git config --add gtr.hook.postCreate "bundle install" +gtr config add gtr.hook.postCreate "bundle install" # Rust -git config --add gtr.hook.postCreate "cargo build" +gtr config add gtr.hook.postCreate "cargo build" ``` ## Configuration Examples @@ -378,35 +378,35 @@ git config --add gtr.hook.postCreate "cargo build" ### Minimal Setup (Just Basics) ```bash -git config --local gtr.worktrees.prefix "wt-" -git config --local gtr.defaultBranch "main" +gtr config set gtr.worktrees.prefix "wt-" +gtr config set gtr.defaultBranch "main" ``` ### Full-Featured Setup (Node.js Project) ```bash # Worktree settings -git config --local gtr.worktrees.prefix "wt-" +gtr config set gtr.worktrees.prefix "wt-" # Editor -git config --local gtr.editor.default cursor +gtr config set gtr.editor.default cursor # Copy environment templates -git config --local --add gtr.copy.include "**/.env.example" -git config --local --add gtr.copy.include "**/.env.development" -git config --local --add gtr.copy.exclude "**/.env.local" +gtr config add gtr.copy.include "**/.env.example" +gtr config add gtr.copy.include "**/.env.development" +gtr config add gtr.copy.exclude "**/.env.local" # Build hooks -git config --local --add gtr.hook.postCreate "pnpm install" -git config --local --add gtr.hook.postCreate "pnpm run build" +gtr config add gtr.hook.postCreate "pnpm install" +gtr config add gtr.hook.postCreate "pnpm run build" ``` ### Global Defaults ```bash # Set global preferences -git config --global gtr.editor.default cursor -git config --global gtr.ai.default claude +gtr config set gtr.editor.default cursor --global +gtr config set gtr.ai.default claude --global ``` ## Advanced Usage @@ -477,17 +477,17 @@ Create a `.gtr-setup.sh` in your repo: #!/bin/sh # .gtr-setup.sh - Project-specific gtr configuration -git config --local gtr.worktrees.prefix "dev-" -git config --local gtr.editor.default cursor +gtr config set gtr.worktrees.prefix "dev-" +gtr config set gtr.editor.default cursor # Copy configs -git config --local --add gtr.copy.include ".env.example" -git config --local --add gtr.copy.include "docker-compose.yml" +gtr config add gtr.copy.include ".env.example" +gtr config add gtr.copy.include "docker-compose.yml" # Setup hooks -git config --local --add gtr.hook.postCreate "docker-compose up -d db" -git config --local --add gtr.hook.postCreate "npm install" -git config --local --add gtr.hook.postCreate "npm run db:migrate" +gtr config add gtr.hook.postCreate "docker-compose up -d db" +gtr config add gtr.hook.postCreate "npm install" +gtr config add gtr.hook.postCreate "npm run db:migrate" ``` Then run: `sh .gtr-setup.sh` @@ -592,7 +592,7 @@ gtr open 2 ```bash # Check your patterns -git config --get-all gtr.copy.include +gtr config get gtr.copy.include # Test patterns with find cd /path/to/repo diff --git a/bin/gtr b/bin/gtr index 26542ce..db0f144 100755 --- a/bin/gtr +++ b/bin/gtr @@ -737,7 +737,7 @@ cmd_config() { scope="global" shift ;; - get|set|unset) + get|set|unset|add) action="$1" shift ;; @@ -745,7 +745,7 @@ cmd_config() { if [ -z "$key" ]; then key="$1" shift - elif [ -z "$value" ] && [ "$action" = "set" ]; then + elif [ -z "$value" ] && { [ "$action" = "set" ] || [ "$action" = "add" ]; }; then value="$1" shift else @@ -775,6 +775,14 @@ cmd_config() { cfg_set "$key" "$value" "$scope" log_info "Config set: $key = $value ($scope)" ;; + add) + if [ -z "$key" ] || [ -z "$value" ]; then + log_error "Usage: gtr config add [--global]" + exit 1 + fi + cfg_add "$key" "$value" "$scope" + log_info "Config added: $key = $value ($scope)" + ;; unset) if [ -z "$key" ]; then log_error "Usage: gtr config unset [--global]" @@ -785,7 +793,7 @@ cmd_config() { ;; *) log_error "Unknown config action: $action" - log_error "Usage: gtr config {get|set|unset} [value] [--global]" + log_error "Usage: gtr config {get|set|add|unset} [value] [--global]" exit 1 ;; esac @@ -796,13 +804,23 @@ load_editor_adapter() { local editor="$1" local adapter_file="$GTR_DIR/adapters/editor/${editor}.sh" - if [ ! -f "$adapter_file" ]; then - log_error "Unknown editor: $editor" - log_info "Available editors: cursor, vscode, zed, idea, pycharm, webstorm, vim, nvim, emacs, sublime, nano, atom" + # Try loading explicit adapter first (allows special handling) + if [ -f "$adapter_file" ]; then + . "$adapter_file" + return 0 + fi + + # Generic fallback: check if command exists in PATH + if ! command -v "$editor" >/dev/null 2>&1; then + log_error "Editor '$editor' not found" + log_info "Built-in adapters: cursor, vscode, zed, idea, pycharm, webstorm, vim, nvim, emacs, sublime, nano, atom" + log_info "Or use any editor command available in your PATH (e.g., code-insiders, fleet)" exit 1 fi - . "$adapter_file" + # Define generic adapter functions dynamically + eval "editor_can_open() { command -v '$editor' >/dev/null 2>&1; }" + eval "editor_open() { '$editor' \"\$1\"; }" } # Load AI adapter @@ -810,13 +828,23 @@ load_ai_adapter() { local ai_tool="$1" local adapter_file="$GTR_DIR/adapters/ai/${ai_tool}.sh" - if [ ! -f "$adapter_file" ]; then - log_error "Unknown AI tool: $ai_tool" - log_info "Available AI tools: aider, claude, codex, cursor, continue" + # Try loading explicit adapter first (allows special handling) + if [ -f "$adapter_file" ]; then + . "$adapter_file" + return 0 + fi + + # Generic fallback: check if command exists in PATH + if ! command -v "$ai_tool" >/dev/null 2>&1; then + log_error "AI tool '$ai_tool' not found" + log_info "Built-in adapters: aider, claude, codex, cursor, continue" + log_info "Or use any AI tool command available in your PATH (e.g., bunx, gpt)" exit 1 fi - . "$adapter_file" + # Define generic adapter functions dynamically + eval "ai_can_start() { command -v '$ai_tool' >/dev/null 2>&1; }" + eval "ai_start() { local path=\"\$1\"; shift; (cd \"\$path\" && '$ai_tool' \"\$@\"); }" } # Help command @@ -885,14 +913,19 @@ CORE COMMANDS (daily workflow): SETUP & MAINTENANCE: - config {get|set|unset} [value] [--global] + config {get|set|add|unset} [value] [--global] Manage configuration + - get: read a config value + - set: set a single value (replaces existing) + - add: add a value (for multi-valued configs like hooks, copy patterns) + - unset: remove a config value doctor Health check (verify git, editors, AI tools) adapter List available editor & AI tool adapters + Note: Any command in your PATH can be used (e.g., code-insiders, bunx) clean Remove stale/prunable worktrees From a1c9ed957acee98de0ff70baa7a1eb5556436ab4 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 15:59:31 -0800 Subject: [PATCH 2/6] Enhance editor command handling in gtr script. Extract command name from potentially multi-word editor strings to ensure proper detection and execution. Update dynamic function definitions to accommodate editor arguments, improving compatibility with various editor commands. --- bin/gtr | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/gtr b/bin/gtr index db0f144..91ec20c 100755 --- a/bin/gtr +++ b/bin/gtr @@ -811,7 +811,10 @@ load_editor_adapter() { fi # Generic fallback: check if command exists in PATH - if ! command -v "$editor" >/dev/null 2>&1; then + # Extract first word (command name) from potentially multi-word string + local cmd_name="${editor%% *}" + + if ! command -v "$cmd_name" >/dev/null 2>&1; then log_error "Editor '$editor' not found" log_info "Built-in adapters: cursor, vscode, zed, idea, pycharm, webstorm, vim, nvim, emacs, sublime, nano, atom" log_info "Or use any editor command available in your PATH (e.g., code-insiders, fleet)" @@ -819,8 +822,9 @@ load_editor_adapter() { fi # Define generic adapter functions dynamically - eval "editor_can_open() { command -v '$editor' >/dev/null 2>&1; }" - eval "editor_open() { '$editor' \"\$1\"; }" + # Note: $editor may contain arguments (e.g., "code --wait") + eval "editor_can_open() { command -v '$cmd_name' >/dev/null 2>&1; }" + eval "editor_open() { $editor \"\$1\"; }" } # Load AI adapter From 33cf9a3381d312ab254734d0d67dd181ee2737a4 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 16:00:33 -0800 Subject: [PATCH 3/6] Refine AI tool command detection in gtr script. Extract command name from potentially multi-word AI tool strings to ensure accurate detection. Update dynamic function definitions to handle arguments correctly, enhancing compatibility with various AI tools. --- bin/gtr | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/gtr b/bin/gtr index 91ec20c..181f225 100755 --- a/bin/gtr +++ b/bin/gtr @@ -839,7 +839,10 @@ load_ai_adapter() { fi # Generic fallback: check if command exists in PATH - if ! command -v "$ai_tool" >/dev/null 2>&1; then + # Extract first word (command name) from potentially multi-word string + local cmd_name="${ai_tool%% *}" + + if ! command -v "$cmd_name" >/dev/null 2>&1; then log_error "AI tool '$ai_tool' not found" log_info "Built-in adapters: aider, claude, codex, cursor, continue" log_info "Or use any AI tool command available in your PATH (e.g., bunx, gpt)" @@ -847,8 +850,9 @@ load_ai_adapter() { fi # Define generic adapter functions dynamically - eval "ai_can_start() { command -v '$ai_tool' >/dev/null 2>&1; }" - eval "ai_start() { local path=\"\$1\"; shift; (cd \"\$path\" && '$ai_tool' \"\$@\"); }" + # Note: $ai_tool may contain arguments (e.g., "bunx @github/copilot@latest") + eval "ai_can_start() { command -v '$cmd_name' >/dev/null 2>&1; }" + eval "ai_start() { local path=\"\$1\"; shift; (cd \"\$path\" && $ai_tool \"\$@\"); }" } # Help command From 94f98310ba921c02661d1265991dfebbcb0f00f2 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 16:08:26 -0800 Subject: [PATCH 4/6] Refactor worktree creation logic in gtr script. Update create_worktree function to capture worktree path and redirect error output to stderr for better logging. Enhance log functions in ui.sh to ensure consistent error reporting. --- bin/gtr | 2 +- lib/core.sh | 14 +++++++------- lib/ui.sh | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bin/gtr b/bin/gtr index 181f225..580166b 100755 --- a/bin/gtr +++ b/bin/gtr @@ -184,7 +184,7 @@ cmd_create() { echo "Branch: $branch_name" # Create the worktree - if ! create_worktree "$base_dir" "$prefix" "$branch_name" "$from_ref" "$track_mode" "$skip_fetch" "$force" "$custom_name"; then + if ! worktree_path=$(create_worktree "$base_dir" "$prefix" "$branch_name" "$from_ref" "$track_mode" "$skip_fetch" "$force" "$custom_name"); then exit 1 fi diff --git a/lib/core.sh b/lib/core.sh index bf00309..d52391f 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -298,8 +298,8 @@ create_worktree() { # Force use of remote branch if [ "$remote_exists" -eq 1 ]; then log_step "Creating worktree from remote branch origin/$branch_name" - if git worktree add $force_flag "$worktree_path" -b "$branch_name" "origin/$branch_name" 2>/dev/null || \ - git worktree add $force_flag "$worktree_path" "$branch_name" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" -b "$branch_name" "origin/$branch_name" >&2 || \ + git worktree add $force_flag "$worktree_path" "$branch_name" >&2; then log_info "Worktree created tracking origin/$branch_name" printf "%s" "$worktree_path" return 0 @@ -314,7 +314,7 @@ create_worktree() { # Force use of local branch if [ "$local_exists" -eq 1 ]; then log_step "Creating worktree from local branch $branch_name" - if git worktree add $force_flag "$worktree_path" "$branch_name" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" "$branch_name" >&2; then log_info "Worktree created with local branch $branch_name" printf "%s" "$worktree_path" return 0 @@ -328,7 +328,7 @@ create_worktree() { none) # Create new branch from from_ref log_step "Creating new branch $branch_name from $from_ref" - if git worktree add $force_flag "$worktree_path" -b "$branch_name" "$from_ref" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" -b "$branch_name" "$from_ref" >&2; then log_info "Worktree created with new branch $branch_name" printf "%s" "$worktree_path" return 0 @@ -350,21 +350,21 @@ create_worktree() { fi # Now add worktree using the tracking branch - if git worktree add $force_flag "$worktree_path" "$branch_name" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" "$branch_name" >&2; then log_info "Worktree created tracking origin/$branch_name" printf "%s" "$worktree_path" return 0 fi elif [ "$local_exists" -eq 1 ]; then log_step "Using existing local branch $branch_name" - if git worktree add $force_flag "$worktree_path" "$branch_name" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" "$branch_name" >&2; then log_info "Worktree created with local branch $branch_name" printf "%s" "$worktree_path" return 0 fi else log_step "Creating new branch $branch_name from $from_ref" - if git worktree add $force_flag "$worktree_path" -b "$branch_name" "$from_ref" 2>/dev/null; then + if git worktree add $force_flag "$worktree_path" -b "$branch_name" "$from_ref" >&2; then log_info "Worktree created with new branch $branch_name" printf "%s" "$worktree_path" return 0 diff --git a/lib/ui.sh b/lib/ui.sh index b9820b5..7e2d700 100644 --- a/lib/ui.sh +++ b/lib/ui.sh @@ -2,7 +2,7 @@ # UI utilities for logging and prompting log_info() { - printf "[OK] %s\n" "$*" + printf "[OK] %s\n" "$*" >&2 } log_warn() { @@ -14,7 +14,7 @@ log_error() { } log_step() { - printf "==> %s\n" "$*" + printf "==> %s\n" "$*" >&2 } log_question() { From eff66f57d75559c4c107cbdca77d02fa9ba93d51 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 16:34:01 -0800 Subject: [PATCH 5/6] Update command references from 'gtr open' to 'gtr editor' across documentation and scripts for consistency. Modify completions and command handling in gtr script to reflect the new editor command. Enhance README and CLAUDE.md to guide users on the updated command usage. --- CLAUDE.md | 14 +++++++------- README.md | 24 ++++++++++++------------ bin/gtr | 26 +++++++++++++------------- completions/_gtr | 4 ++-- completions/gtr.bash | 4 ++-- completions/gtr.fish | 4 ++-- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5206a48..e34564b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -64,7 +64,7 @@ Test changes using this comprehensive checklist (from CONTRIBUTING.md): # Open in editor (if testing adapters) ./bin/gtr config set gtr.editor.default cursor -./bin/gtr open test-feature +./bin/gtr editor test-feature # Expected: Opens Cursor at worktree path # Run AI tool (if testing adapters) @@ -91,7 +91,7 @@ Test changes using this comprehensive checklist (from CONTRIBUTING.md): # Test shell completions with tab completion gtr new -gtr open +gtr editor # Expected: Shows available branches/worktrees # Test gtr go for main repo and worktrees @@ -171,7 +171,7 @@ git --version **Branch Name Mapping**: Branch names are sanitized to valid folder names (slashes and special chars → hyphens). For example, `feature/user-auth` becomes folder `feature-user-auth`. -**Special ID '1'**: The main repository is always accessible via ID `1` in commands (e.g., `gtr go 1`, `gtr open 1`). +**Special ID '1'**: The main repository is always accessible via ID `1` in commands (e.g., `gtr go 1`, `gtr editor 1`). **Configuration Storage**: All configuration is stored via `git config` (local, global, or system). No custom config files. This makes settings portable and follows git conventions. @@ -187,7 +187,7 @@ git --version Understanding how commands are dispatched through the system: 1. **Entry Point** (`bin/gtr:32-79`): Main dispatcher receives command and routes to appropriate handler -2. **Command Handlers** (`bin/gtr`): Each `cmd_*` function handles a specific command (e.g., `cmd_create`, `cmd_open`, `cmd_ai`) +2. **Command Handlers** (`bin/gtr`): Each `cmd_*` function handles a specific command (e.g., `cmd_create`, `cmd_editor`, `cmd_ai`) 3. **Library Functions** (`lib/*.sh`): Command handlers call reusable functions from library modules 4. **Adapters** (`adapters/*`): Dynamically loaded when needed via `load_editor_adapter` or `load_ai_adapter` @@ -202,11 +202,11 @@ bin/gtr main() → run_hooks_in() [lib/hooks.sh] ``` -**Example flow for `gtr open my-feature`:** +**Example flow for `gtr editor my-feature`:** ``` bin/gtr main() - → cmd_open() + → cmd_editor() → resolve_target() [lib/core.sh] → load_editor_adapter() → editor_open() [adapters/editor/*.sh] @@ -413,7 +413,7 @@ bash -c 'source adapters/editor/cursor.sh && editor_can_open && echo "Available" bash -c 'source adapters/ai/claude.sh && ai_can_start && echo "Available" || echo "Not found"' # Debug adapter loading with trace -bash -x ./bin/gtr open test-feature --editor cursor +bash -x ./bin/gtr editor test-feature --editor cursor # Shows full execution trace including adapter loading ``` diff --git a/README.md b/README.md index 3b8a470..1c2a725 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ gtr config set gtr.ai.default claude # One-time setup # Daily workflow gtr new my-feature # Create worktree -gtr open my-feature # Open in editor +gtr editor my-feature # Open in editor gtr ai my-feature # Start AI tool gtr rm my-feature # Remove when done ``` @@ -50,7 +50,7 @@ While `git worktree` is powerful, it's verbose and manual. `gtr` adds quality-of | Task | With `git worktree` | With `gtr` | | ----------------- | ------------------------------------------ | ------------------------------------ | | Create worktree | `git worktree add ../repo-feature feature` | `gtr new feature` | -| Open in editor | `cd ../repo-feature && cursor .` | `gtr open feature` | +| Open in editor | `cd ../repo-feature && cursor .` | `gtr editor feature` | | Start AI tool | `cd ../repo-feature && aider` | `gtr ai feature` | | Copy config files | Manual copy/paste | Auto-copy via `gtr.copy.include` | | Run build steps | Manual `npm install && npm run build` | Auto-run via `gtr.hook.postCreate` | @@ -83,7 +83,7 @@ gtr config set gtr.ai.default claude # Daily workflow gtr new my-feature # Create worktree folder: my-feature -gtr open my-feature # Open in cursor +gtr editor my-feature # Open in cursor gtr ai my-feature # Start claude # Navigate to worktree @@ -175,13 +175,13 @@ gtr new my-feature --name descriptive-variant # Optional: custom name without - `--name `: Custom folder name suffix (optional, required with --force) - `--yes`: Non-interactive mode -### `gtr open [--editor ]` +### `gtr editor [--editor ]` Open worktree in editor (uses `gtr.editor.default` or `--editor` flag). ```bash -gtr open my-feature # Uses configured editor -gtr open my-feature --editor vscode # Override with vscode +gtr editor my-feature # Uses configured editor +gtr editor my-feature --editor vscode # Override with vscode ``` ### `gtr ai [--ai ] [-- args...]` @@ -425,11 +425,11 @@ gtr config set gtr.ai.default claude --global ```bash # Terminal 1: Work on feature gtr new feature-a -gtr open feature-a +gtr editor feature-a # Terminal 2: Review PR gtr new pr/123 -gtr open pr/123 +gtr editor pr/123 # Terminal 3: Navigate to main branch (repo root) cd "$(gtr go 1)" # Special ID '1' = main repo @@ -448,7 +448,7 @@ gtr list # auth-feature ~/GitHub/frontend-worktrees/auth-feature # nav-redesign ~/GitHub/frontend-worktrees/nav-redesign -gtr open auth-feature # Open frontend auth work +gtr editor auth-feature # Open frontend auth work gtr ai nav-redesign # AI on frontend nav work # Backend repo (separate worktrees) @@ -459,12 +459,12 @@ gtr list # api-auth ~/GitHub/backend-worktrees/api-auth # websockets ~/GitHub/backend-worktrees/websockets -gtr open api-auth # Open backend auth work +gtr editor api-auth # Open backend auth work gtr ai websockets # AI on backend websockets # Switch back to frontend cd ~/GitHub/frontend -gtr open auth-feature # Opens frontend auth +gtr editor auth-feature # Opens frontend auth ``` **Key point:** Each repository has its own worktrees. Use branch names to identify worktrees. @@ -585,7 +585,7 @@ command -v cursor # or: code, zed gtr config get gtr.editor.default # Try opening again -gtr open 2 +gtr editor 2 ``` ### File Copying Issues diff --git a/bin/gtr b/bin/gtr index 580166b..9399f63 100755 --- a/bin/gtr +++ b/bin/gtr @@ -43,8 +43,8 @@ main() { go) cmd_go "$@" ;; - open) - cmd_open "$@" + editor) + cmd_editor "$@" ;; ai) cmd_ai "$@" @@ -210,7 +210,7 @@ cmd_create() { log_info "Worktree created: $worktree_path" echo "" echo "Next steps:" - echo " gtr open $branch_name # Open in editor" + echo " gtr editor $branch_name # Open in editor" echo " gtr ai $branch_name # Start AI tool" echo " cd \"\$(gtr go $branch_name)\" # Navigate to worktree" } @@ -332,8 +332,8 @@ cmd_go() { printf "%s\n" "$worktree_path" } -# Open command -cmd_open() { +# Editor command +cmd_editor() { local identifier="" local editor="" @@ -358,7 +358,7 @@ cmd_open() { done if [ -z "$identifier" ]; then - log_error "Usage: gtr open [--editor ]" + log_error "Usage: gtr editor [--editor ]" exit 1 fi @@ -869,7 +869,7 @@ QUICK START: gtr config set gtr.editor.default cursor # One-time setup gtr config set gtr.ai.default claude # One-time setup gtr new my-feature # Creates worktree in folder "my-feature" - gtr open my-feature # Opens in cursor + gtr editor my-feature # Opens in cursor gtr ai my-feature # Starts claude gtr rm my-feature # Remove when done @@ -877,9 +877,9 @@ QUICK START: KEY CONCEPTS: • Worktree folders are named after the branch name - • Main repo is accessible via special ID '1' (e.g., gtr go 1, gtr open 1) + • Main repo is accessible via special ID '1' (e.g., gtr go 1, gtr editor 1) • Commands accept branch names to identify worktrees - Example: gtr open my-feature, gtr go feature/user-auth + Example: gtr editor my-feature, gtr go feature/user-auth ──────────────────────────────────────────────────────────────────────────────── @@ -895,7 +895,7 @@ CORE COMMANDS (daily workflow): --name : custom folder name suffix (e.g., backend, frontend) --yes: non-interactive mode - open [--editor ] + editor [--editor ] Open worktree in editor (uses gtr.editor.default or --editor) Special: use '1' to open repo root @@ -952,18 +952,18 @@ WORKFLOW EXAMPLES: # Daily workflow gtr new feature/user-auth # Create worktree (folder: feature-user-auth) - gtr open feature/user-auth # Open in editor + gtr editor feature/user-auth # Open in editor gtr ai feature/user-auth # Start AI tool # Navigate to worktree directory cd "$(gtr go feature/user-auth)" # Override defaults with flags - gtr open feature/user-auth --editor vscode + gtr editor feature/user-auth --editor vscode gtr ai feature/user-auth --ai aider # Chain commands together - gtr new hotfix && gtr open hotfix && gtr ai hotfix + gtr new hotfix && gtr editor hotfix && gtr ai hotfix # When finished gtr rm feature/user-auth --delete-branch diff --git a/completions/_gtr b/completions/_gtr index 4fdb43d..29c8f9f 100644 --- a/completions/_gtr +++ b/completions/_gtr @@ -7,7 +7,7 @@ _gtr() { 'new:Create a new worktree' 'go:Navigate to worktree' 'rm:Remove worktree(s)' - 'open:Open worktree in editor' + 'editor:Open worktree in editor' 'ai:Start AI coding tool' 'ls:List all worktrees' 'list:List all worktrees' @@ -29,7 +29,7 @@ _gtr() { _describe 'commands' commands elif (( CURRENT == 3 )); then case "$words[2]" in - go|open|ai|rm) + go|editor|ai|rm) _describe 'branch names' all_options ;; new) diff --git a/completions/gtr.bash b/completions/gtr.bash index acb191b..5b844a1 100644 --- a/completions/gtr.bash +++ b/completions/gtr.bash @@ -9,13 +9,13 @@ _gtr_completion() { # Complete commands on first argument if [ "$cword" -eq 1 ]; then - COMPREPLY=($(compgen -W "new go open ai rm ls list clean doctor adapter config help version" -- "$cur")) + COMPREPLY=($(compgen -W "new go editor ai rm ls list clean doctor adapter config help version" -- "$cur")) return 0 fi # Commands that take branch names or '1' for main repo case "$cmd" in - go|open|ai|rm) + go|editor|ai|rm) if [ "$cword" -eq 2 ]; then # Complete with branch names and special ID '1' for main repo local branches all_options diff --git a/completions/gtr.fish b/completions/gtr.fish index 0b2b1c0..a7d1df0 100644 --- a/completions/gtr.fish +++ b/completions/gtr.fish @@ -4,7 +4,7 @@ complete -c gtr -f -n "__fish_use_subcommand" -a "new" -d "Create a new worktree" complete -c gtr -f -n "__fish_use_subcommand" -a "go" -d "Navigate to worktree" complete -c gtr -f -n "__fish_use_subcommand" -a "rm" -d "Remove worktree(s)" -complete -c gtr -f -n "__fish_use_subcommand" -a "open" -d "Open worktree in editor" +complete -c gtr -f -n "__fish_use_subcommand" -a "editor" -d "Open worktree in editor" complete -c gtr -f -n "__fish_use_subcommand" -a "ai" -d "Start AI coding tool" complete -c gtr -f -n "__fish_use_subcommand" -a "ls" -d "List all worktrees" complete -c gtr -f -n "__fish_use_subcommand" -a "list" -d "List all worktrees" @@ -52,4 +52,4 @@ function __gtr_worktree_branches end # Complete branch names for commands that need them -complete -c gtr -n "__fish_seen_subcommand_from go open ai rm" -f -a "(__gtr_worktree_branches)" +complete -c gtr -n "__fish_seen_subcommand_from go editor ai rm" -f -a "(__gtr_worktree_branches)" From e0da13faadfc93db639d43d5d85b3cdd66003cb2 Mon Sep 17 00:00:00 2001 From: Hans Elizaga Date: Thu, 13 Nov 2025 16:40:45 -0800 Subject: [PATCH 6/6] Enhance gtr script with generic adapter functions for editor and AI tool integration. Update README to reflect new configuration command options, including 'add'. Improve command handling for better compatibility with multi-word commands. --- README.md | 2 +- bin/gtr | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1c2a725..c6627ec 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ gtr rm my-feature --delete-branch --force # Delete branch and force List all worktrees. Use `--porcelain` for machine-readable output. -### `gtr config {get|set|unset} [value] [--global]` +### `gtr config {get|set|add|unset} [value] [--global]` Manage configuration via git config. diff --git a/bin/gtr b/bin/gtr index 9399f63..57a9ede 100755 --- a/bin/gtr +++ b/bin/gtr @@ -28,6 +28,32 @@ resolve_script_dir() { . "$GTR_DIR/lib/copy.sh" . "$GTR_DIR/lib/hooks.sh" +# Generic adapter functions (used when no explicit adapter file exists) +# These will be overridden if an adapter file is sourced +# Globals set by load_editor_adapter: GTR_EDITOR_CMD, GTR_EDITOR_CMD_NAME +editor_can_open() { + command -v "$GTR_EDITOR_CMD_NAME" >/dev/null 2>&1 +} + +editor_open() { + # $GTR_EDITOR_CMD may contain arguments (e.g., "code --wait") + # Using eval here is necessary to handle multi-word commands properly + eval "$GTR_EDITOR_CMD \"\$1\"" +} + +# Globals set by load_ai_adapter: GTR_AI_CMD, GTR_AI_CMD_NAME +ai_can_start() { + command -v "$GTR_AI_CMD_NAME" >/dev/null 2>&1 +} + +ai_start() { + local path="$1" + shift + # $GTR_AI_CMD may contain arguments (e.g., "bunx @github/copilot@latest") + # Using eval here is necessary to handle multi-word commands properly + (cd "$path" && eval "$GTR_AI_CMD \"\$@\"") +} + # Main dispatcher main() { local cmd="${1:-help}" @@ -821,10 +847,10 @@ load_editor_adapter() { exit 1 fi - # Define generic adapter functions dynamically + # Set globals for generic adapter functions # Note: $editor may contain arguments (e.g., "code --wait") - eval "editor_can_open() { command -v '$cmd_name' >/dev/null 2>&1; }" - eval "editor_open() { $editor \"\$1\"; }" + GTR_EDITOR_CMD="$editor" + GTR_EDITOR_CMD_NAME="$cmd_name" } # Load AI adapter @@ -849,10 +875,10 @@ load_ai_adapter() { exit 1 fi - # Define generic adapter functions dynamically + # Set globals for generic adapter functions # Note: $ai_tool may contain arguments (e.g., "bunx @github/copilot@latest") - eval "ai_can_start() { command -v '$cmd_name' >/dev/null 2>&1; }" - eval "ai_start() { local path=\"\$1\"; shift; (cd \"\$path\" && $ai_tool \"\$@\"); }" + GTR_AI_CMD="$ai_tool" + GTR_AI_CMD_NAME="$cmd_name" } # Help command