Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/homebrew.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ on:
release:
types: [published]

permissions: read-all

jobs:
homebrew:
name: Bump Homebrew formula
runs-on: ubuntu-latest
if: ${{ !github.event.release.prerelease }}
steps:
- uses: mislav/bump-homebrew-formula-action@v3
- uses: mislav/bump-homebrew-formula-action@56a283fa15557e9abaa4bdb63b8212abc68e655c # v3
with:
formula-name: git-gtr
formula-path: Formula/git-gtr.rb
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ on:
pull_request:
branches: [main]

permissions: read-all

jobs:
shellcheck:
name: ShellCheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install ShellCheck
run: sudo apt-get update && sudo apt-get install -y shellcheck
Expand All @@ -24,7 +26,7 @@ jobs:
name: Completions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Verify completion files are up to date
run: ./scripts/generate-completions.sh --check
Expand All @@ -33,7 +35,7 @@ jobs:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install BATS
run: sudo apt-get update && sudo apt-get install -y bats
Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,16 @@ git gtr clean --merged --force --yes # Force-clean and auto-confirm

**Note:** The `--merged` mode auto-detects your hosting provider (GitHub or GitLab) from the `origin` remote URL and requires the corresponding CLI tool (`gh` or `glab`) to be installed and authenticated. For self-hosted instances, set the provider explicitly: `git gtr config set gtr.provider gitlab`.

### `git gtr trust`

Review and approve hook commands defined in the repository's `.gtrconfig` file. Hooks from `.gtrconfig` are **not executed** until explicitly trusted — this prevents malicious contributors from injecting arbitrary shell commands via shared config files.

```bash
git gtr trust # Review and approve .gtrconfig hooks
```

Trust is stored per repository path plus hook definitions and must be re-approved if hooks change. Hooks from your local git config (`.git/config`, `~/.gitconfig`) are always trusted.

### Other Commands

- `git gtr doctor` - Health check (verify git, editors, AI tools)
Expand All @@ -359,6 +369,14 @@ git gtr config set gtr.editor.default cursor
# Set your AI tool (aider, auggie, claude, codex, continue, copilot, cursor, gemini, opencode)
git gtr config set gtr.ai.default claude

# Override-backed adapters may include flags
git gtr config set gtr.editor.default "nano -w"
git gtr config set gtr.ai.default "claude --continue"

# Generic fallbacks may use other safe PATH commands
git gtr config set gtr.editor.default "code --wait"
git gtr config set gtr.ai.default "bunx @github/copilot@latest"

# Copy env files to new worktrees
git gtr config add gtr.copy.include "**/.env.example"

Expand Down Expand Up @@ -390,10 +408,14 @@ git gtr config set gtr.ui.color never
ai = claude
```

**Hook trust:** Hooks defined in `.gtrconfig` require explicit approval before they execute. Run `git gtr trust` after cloning a repository or when `.gtrconfig` hooks change. This protects against malicious hook injection in shared repositories.

**Adapter safety:** Generic `gtr.editor.default` and `gtr.ai.default` values must resolve to safe PATH commands. Filesystem paths such as `./tool` and shell wrapper forms such as `sh -c ...` are rejected. Override-backed adapters like `claude`, `cursor`, and `nano` may include additional flags, for example `claude --continue` or `nano -w`.

**Configuration precedence** (highest to lowest):

1. `git config --local` (`.git/config`) - personal overrides
2. `.gtrconfig` (repo root) - team defaults
2. `.gtrconfig` (repo root) - team defaults (hooks require `git gtr trust`)
3. `git config --global` (`~/.gitconfig`) - user defaults

> For complete configuration reference including all settings, hooks, file copying patterns, and environment variables, see [docs/configuration.md](docs/configuration.md)
Expand Down
3 changes: 2 additions & 1 deletion adapters/ai/claude.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ ai_can_start() {
ai_start() {
local path="$1"
shift
local configured_args=("${GTR_AI_CMD_ARGS[@]}")

local claude_cmd
claude_cmd="$(find_claude_executable)"
Expand All @@ -57,5 +58,5 @@ ai_start() {
return 1
fi

(cd "$path" && "$claude_cmd" "$@")
(cd "$path" && "$claude_cmd" "${configured_args[@]}" "$@")
}
5 changes: 3 additions & 2 deletions adapters/ai/cursor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ai_can_start() {
ai_start() {
local path="$1"
shift
local configured_args=("${GTR_AI_CMD_ARGS[@]}")

if ! ai_can_start; then
log_error "Cursor not found. Install from https://cursor.com"
Expand All @@ -25,9 +26,9 @@ ai_start() {

# Try cursor-agent first, then fallback to cursor CLI commands
if command -v cursor-agent >/dev/null 2>&1; then
(cd "$path" && cursor-agent "$@")
(cd "$path" && cursor-agent "${configured_args[@]}" "$@")
elif command -v cursor >/dev/null 2>&1; then
# Try various Cursor CLI patterns (implementation varies by version)
(cd "$path" && cursor cli "$@") 2>/dev/null || (cd "$path" && cursor "$@")
(cd "$path" && cursor cli "${configured_args[@]}" "$@") 2>/dev/null || (cd "$path" && cursor "${configured_args[@]}" "$@")
fi
}
6 changes: 6 additions & 0 deletions adapters/editor/nano.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ editor_can_open() {
# Usage: editor_open path
editor_open() {
local path="$1"
local configured_args=("${GTR_EDITOR_CMD_ARGS[@]}")

if ! editor_can_open; then
log_error "Nano not found. Usually pre-installed on Unix systems."
return 1
fi

if [ "${#configured_args[@]}" -gt 0 ]; then
(cd "$path" && nano "${configured_args[@]}")
return $?
fi

# Open nano in the directory (just cd there, nano doesn't open directories)
log_info "Opening shell in $path (nano doesn't support directory mode)"
(cd "$path" && exec "$SHELL")
Expand Down
3 changes: 3 additions & 0 deletions bin/git-gtr
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ main() {
init)
cmd_init "$@"
;;
trust)
cmd_trust "$@"
;;
version|--version|-v)
echo "git gtr version $GTR_VERSION"
;;
Expand Down
1 change: 1 addition & 0 deletions completions/_git-gtr
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ _git-gtr() {
'config:Manage configuration'
'completion:Generate shell completions'
'init:Generate shell integration for cd support'
'trust:Trust .gtrconfig hooks'
'version:Show version'
'help:Show help'
)
Expand Down
1 change: 1 addition & 0 deletions completions/git-gtr.fish
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ complete -f -c git -n '__fish_git_gtr_using_command completion' -a 'bash zsh fis
complete -f -c git -n '__fish_git_gtr_needs_command' -a init -d 'Generate shell integration for cd support'
complete -f -c git -n '__fish_git_gtr_using_command init' -a 'bash zsh fish' -d 'Shell type'
complete -c git -n '__fish_git_gtr_using_command init' -l as -d 'Custom function name' -r
complete -f -c git -n '__fish_git_gtr_needs_command' -a trust -d 'Trust .gtrconfig hooks'
complete -f -c git -n '__fish_git_gtr_needs_command' -a version -d 'Show version'
complete -f -c git -n '__fish_git_gtr_needs_command' -a help -d 'Show help'

Expand Down
2 changes: 1 addition & 1 deletion completions/gtr.bash
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ _git_gtr() {

# If we're completing the first argument after 'git gtr'
if [ "$cword" -eq 2 ]; then
COMPREPLY=($(compgen -W "new go run copy editor ai rm mv rename ls list clean doctor adapter config completion init help version" -- "$cur"))
COMPREPLY=($(compgen -W "new go run copy editor ai rm mv rename ls list clean doctor adapter config completion init trust help version" -- "$cur"))
return 0
fi

Expand Down
Loading
Loading