Skip to content
Merged
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
83 changes: 83 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copilot Instructions

## Architecture & Flow

`bin/gtr` (961 lines) dispatches to `cmd_*` functions (case block lines 36‑77). Libraries sourced at startup:

- `lib/core.sh` - create/list/remove/resolve worktrees
- `lib/config.sh` - git config wrapper with precedence
- `lib/ui.sh` - log_error/log_info/prompts
- `lib/copy.sh` - glob pattern file copying
- `lib/hooks.sh` - postCreate/postRemove execution
- `lib/platform.sh` - OS detection + GUI helpers

Adapters in `adapters/{editor,ai}` each implement two functions with strict contracts (see below).

## Key Concepts

- Special ID `1` = main repo (usable in `open`, `go`, `ai`).
- Folder naming = sanitized branch (`feature/auth` → `feature-auth`).
- Base dir resolution (`resolve_base_dir`): config `gtr.worktrees.dir` → env → default `<repo>-worktrees`; relative paths resolved from repo root; tilde expanded; warns if inside repo unignored.
- Target resolution (`resolve_target`): ID `1` → current → sanitized path → scan directories; returns TSV: `is_main\tpath\tbranch`.
- Config precedence (`cfg_default`): git config (local→global→system) → env → fallback. Multi-value keys merged & deduped (`cfg_get_all`).

## Adapter Contract

Editor: `editor_can_open`, `editor_open <path>`; AI: `ai_can_start`, `ai_start <path> [args...]`. Must check tool availability (`command -v`), emit errors via `log_error`, never silently fail, and avoid side effects outside the target directory (AI uses subshell `(cd ...)`). Update README, help (`cmd_help`), completions.

## Manual Testing (Essential Subset)

```bash
./bin/gtr new feature/x # creates folder feature-x
./bin/gtr open feature/x # loads configured editor
./bin/gtr ai feature/x # starts configured AI tool
./bin/gtr list # lists main + worktrees
./bin/gtr rm feature/x # removes worktree
./bin/gtr go feature/x # prints path (use in cd)
```

Advanced: `--force --name backend` (same branch multi-worktree); `git config --add gtr.copy.include "**/.env.example"`; hooks: `git config --add gtr.hook.postCreate "npm install"`.
Full matrix: see `.github/instructions/testing.instructions.md`.

## Common Changes

**Add command**: new `cmd_<name>()` function in `bin/gtr` + case entry (lines 36‑77) + help text in `cmd_help` + all three completions (bash/zsh/fish) + README docs.

**Add adapter**: two functions (see contract below), `log_error` with install instructions, quote all paths, check `command -v`. Update: README, help text (`cmd_help`), completions (all three).

**Modify core (`lib/*.sh`)**: keep backwards compatibility, always quote variables `"$var"`, support Git <2.22 fallback (`branch --show-current` → `rev-parse --abbrev-ref HEAD`), test manually across macOS/Linux.

## Patterns & Gotchas

- Always quote paths (spaces). Avoid unguarded globbing.
- `set -e` active: ensure non-critical failures are guarded (`command || true`).
- Multi-value config keys require `git config --add` (do not overwrite entire list unintentionally).
- If placing worktrees inside repo (relative path), add directory to `.gitignore` to prevent accidental commits.

## Debugging

Trace: `bash -x ./bin/gtr new test`; scoped: `set -x` / `set +x`; list function: `declare -f resolve_target`; inspect var: `echo "DEBUG=$var" >&2`; adapter sourcing: `bash -c 'source adapters/ai/claude.sh && ai_can_start && echo OK'`.

## Troubleshooting Quick

Permission: `chmod +x bin/gtr`. Missing adapter: `gtr adapter`. Install check: `./bin/gtr doctor`. Config issues: `git config --list | grep gtr`. Worktree confusion: inspect `resolve_target` logic & naming. Symlink problems: ensure `/usr/local/bin` exists then `ln -s "$(pwd)/bin/gtr" /usr/local/bin/gtr`.

## Version

Update `GTR_VERSION` (line 8 `bin/gtr`) when releasing; affects `gtr version` / `--version`.

## Documentation Structure

- **`.github/copilot-instructions.md`** (this file) - High-level guide for AI agents
- **`.github/instructions/*.instructions.md`** - Specific guidance by file pattern:
- `testing.instructions.md` - Manual testing checklist (applies to: `bin/gtr`, `lib/**/*.sh`, `adapters/**/*.sh`)
- `sh.instructions.md` - Shell scripting conventions (applies to: `**/*.sh`, `**/*.bash`, `**/*.fish`)
- `lib.instructions.md` - Core library modification guidelines (applies to: `lib/**/*.sh`)
- `editor.instructions.md` - Editor adapter contract (applies to: `adapters/editor/**/*.sh`)
- `ai.instructions.md` - AI tool adapter contract (applies to: `adapters/ai/**/*.sh`)
- `completions.instructions.md` - Shell completion updates (applies to: `completions/*`)
- **`README.md`** - User-facing documentation
- **`CONTRIBUTING.md`** - Contribution guidelines
- **`CLAUDE.md`** - Extended development guide for Claude Code

Feedback: Ask if more detail needed on copy patterns, hooks, or multi-worktree `--force` safety.
42 changes: 42 additions & 0 deletions .github/instructions/ai.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
applyTo: adapters/ai/**/*.sh
---

# AI Instructions

## Adding Features

### New AI Tool Adapter (`adapters/ai/<name>.sh`)

```bash
#!/usr/bin/env bash
# ToolName adapter

ai_can_start() {
command -v tool-cli >/dev/null 2>&1
}

ai_start() {
local path="$1"
shift
if ! ai_can_start; then
log_error "ToolName not found. Install with: ..."
return 1
fi
(cd "$path" && tool-cli "$@") # Note: subshell for directory change
}
```

**Also update**: Same as editor adapters (README, completions, help text)

## Contract & Guidelines

- Must define: `ai_can_start` (0 = available), `ai_start <path> [args...]` (runs in subshell `(cd ...)`).
- Always quote: `"$path"` and arguments; never assume current working directory.
- Use `log_error` + helpful install hint; never silent fail.
- Keep side effects confined to worktree directory; do not modify repo root unintentionally.
- Accept extra args after `--`: preserve ordering (`ai_start` receives already-shifted args).
- Prefer fast startup; heavy initialization belongs in hooks (`postCreate`), not adapters.
- When adding adapter: update `cmd_help`, README tool list, and completions (bash/zsh/fish).
- Test manually: `bash -c 'source adapters/ai/<tool>.sh && ai_can_start && echo OK'`.
- Inspect function definition if needed: `declare -f ai_start`.
133 changes: 133 additions & 0 deletions .github/instructions/completions.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
applyTo: completions/gtr.bash, completions/_gtr, completions/gtr.fish
---

# Completions Instructions

## Overview

Shell completions provide tab-completion for `gtr` commands, flags, branches, and adapter names across Bash, Zsh, and Fish shells.

## When to Update Completions

**Always update all three completion files** when:

- Adding new commands (e.g., `gtr new-command`)
- Adding new flags to existing commands (e.g., `--new-flag`)
- Adding editor or AI adapters (completion must list available adapters)
- Changing command names or flag names

## File Responsibilities

- **`completions/gtr.bash`** - Bash completion (requires bash-completion v2+)
- **`completions/_gtr`** - Zsh completion (uses Zsh completion system)
- **`completions/gtr.fish`** - Fish shell completion

## Implementation Pattern

Each completion file implements:

1. **Command completion** - Top-level commands (`new`, `rm`, `open`, `ai`, `list`, etc.)
2. **Flag completion** - Command-specific flags (e.g., `--from`, `--force`, `--editor`)
3. **Branch completion** - Dynamic completion of existing worktree branches (via `gtr list --porcelain`)
4. **Adapter completion** - Editor names (`cursor`, `vscode`, `zed`) and AI tool names (`aider`, `claude`, `codex`)

## Testing Completions

**Manual testing** (no automated tests):

```bash
# Bash - source the completion file
source completions/gtr.bash
gtr <TAB> # Should show commands
gtr new <TAB> # Should show flags
gtr open <TAB> # Should show branches
gtr open --editor <TAB> # Should show editor names

# Zsh - fpath must include completions directory
fpath=(completions $fpath)
autoload -U compinit && compinit
gtr <TAB>

# Fish - symlink to ~/.config/fish/completions/
ln -s "$(pwd)/completions/gtr.fish" ~/.config/fish/completions/
gtr <TAB>
```

## Branch Completion Logic

All three completions dynamically fetch current worktree branches:

- Parse output of `gtr list --porcelain` (tab-separated: `path\tbranch\tstatus`)
- Extract branch column (second field)
- Exclude the special ID `1` (main repo) if needed

## Adapter Name Updates

When adding an editor or AI adapter:

**Bash** (`completions/gtr.bash`):

- Update `_gtr_editors` array or case statement
- Update flag completion for `--editor` in `open` command

**Zsh** (`completions/_gtr`):

- Update `_arguments` completion specs for `--editor` or `--ai`
- Use `_values` or `_alternative` for adapter names

**Fish** (`completions/gtr.fish`):

- Update `complete -c gtr` lines for editor/AI flags
- List adapter names explicitly or parse from `gtr adapter` output

## Keep in Sync

The three completion files must stay synchronized:

- Same commands supported
- Same flags for each command
- Same adapter names
- Same branch completion behavior

## Examples

**Adding a new command `gtr status`**:

1. Add `status` to main command list in all three files
2. Add flag completion if the command has flags
3. Test tab completion works

**Adding a new editor `sublime`**:

1. Create `adapters/editor/sublime.sh` with contract functions
2. Add `sublime` to editor list in all three completion files
3. Update help text in `bin/gtr` (`cmd_help` function)
4. Update README with installation instructions
5. Test `gtr open --editor s<TAB>` completes to `sublime`

## Common Pitfalls

- **Forgetting to update all three files** - Always update Bash, Zsh, AND Fish
- **Hardcoding adapter names** - Keep adapter lists in sync with actual files in `adapters/{editor,ai}/`
- **Not testing** - Source/reload completions and test with `<TAB>` key
- **Case sensitivity** - Command and flag names must match exactly (case-sensitive)

## Bash-Specific Notes

- Requires `bash-completion` v2+ package
- Use `COMPREPLY` array to return completions
- Use `compgen` to filter based on current word (`$cur`)
- Check `$COMP_CWORD` for argument position

## Zsh-Specific Notes

- Uses `_arguments` completion framework
- Supports more sophisticated completion logic (descriptions, grouping)
- Use `_describe` for simple lists, `_arguments` for complex commands

## Fish-Specific Notes

- Uses declarative `complete -c gtr` syntax
- Conditions can check previous arguments with `__fish_seen_subcommand_from`
- Can call external commands for dynamic completion
45 changes: 45 additions & 0 deletions .github/instructions/editor.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
applyTo: adapters/editor/**/*.sh
---

# Editor Instructions

## Adding Features

### New Editor Adapter (`adapters/editor/<name>.sh`)

```bash
#!/usr/bin/env bash
# EditorName adapter

editor_can_open() {
command -v editor-cli >/dev/null 2>&1
}

editor_open() {
local path="$1"
if ! editor_can_open; then
log_error "EditorName not found. Install from https://..."
return 1
fi
editor-cli "$path"
}
```

**Also update**:

- README.md (setup instructions)
- All three completion files: `completions/gtr.bash`, `completions/_gtr`, `completions/gtr.fish`
- Help text in `bin/gtr` (`cmd_help` function)

## Contract & Guidelines

- Required functions: `editor_can_open` (probe via `command -v`), `editor_open <path>`.
- Quote all paths; support spaces. Avoid changing PWD globally—no subshell needed (editor opens path).
- Use `log_error` with actionable install guidance if command missing.
- Keep adapter lean: no project scans, no blocking prompts.
- Naming: file name = tool name (`zed.sh` → `zed` flag). Avoid uppercase.
- Update: README editor list, completions (bash/zsh/fish), help (`Available editors:`), optional screenshots.
- Manual test: `bash -c 'source adapters/editor/<tool>.sh && editor_can_open && editor_open . || echo fail'`.
- Fallback behavior: if editor absent, fail clearly; do NOT silently defer to file browser.
- Inspect function definition if needed: `declare -f editor_open`.
28 changes: 28 additions & 0 deletions .github/instructions/lib.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
applyTo: lib/**/*.sh
---

# Lib Instructions

## Modifying Core (`lib/*.sh`)

- **Maintain backwards compatibility** with existing configs
- **Quote all paths**: Support spaces in directory names
- **Use `log_error` / `log_info`** from `lib/ui.sh` for user messages
- **Git version fallbacks**: Check `lib/core.sh:97-100` for example (Git 2.22+ `--show-current` vs older `rev-parse`)

## Key Functions & Responsibilities

- `resolve_base_dir`: config/env/default selection; warn if inside repo & not ignored.
- `resolve_target`: ID `1` + branch/current + sanitized path scan; returns TSV.
- `create_worktree`: decides remote/local/new; respects `--force` + `--name` safety.
- `cfg_default`: precedence local→global→system→env→fallback (do not reorder).
- `cfg_get_all`: merge multi-value keys; preserves order; deduplicates.

## Change Guidelines

- Preserve adapter contracts; do not rename exported functions used by `bin/gtr`.
- Add new config keys with `gtr.<name>` prefix; avoid collisions.
- For performance-sensitive loops (e.g. directory scans) prefer built-ins (`find`, `grep`) with minimal subshells.
- Any new Git command: add fallback for older versions or guard with detection.
- Manual test after changes (subset): `new`, `open`, `ai`, `rm`, `list --porcelain`, `config set/get/unset`, `go 1`, hooks run once.
47 changes: 47 additions & 0 deletions .github/instructions/sh.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
applyTo: **/*.bash, **/*.fish, **/*.sh
---

# Shell Instructions

## Architecture

**Key Pattern**: Everything is sourced at startup (`set -e` enabled). Functions call each other directly. No subshells except for hooks and AI tools.

## Code Conventions

### Shell Script Style

- **Bash 3.2+ compatible** (macOS default), but 4.0+ features allowed where appropriate
- **Always quote variables**: `"$var"` not `$var`
- **Function-scoped vars**: Use `local var="value"`
- **Error handling**: Check return codes; functions return 1 on failure
- **Naming**: `snake_case` for functions/vars, `UPPER_CASE` for constants

### Strict Mode & Safety

- Global `set -e` in `bin/gtr`: guard non-critical commands with `|| true`.
- Prefer `[ ]` over `[[ ]]` for POSIX portability (use `[[` only when needed).
- Always quote glob inputs; disable unintended globbing (`set -f` temporarily if required).

### Portability

- Target Bash 3.2+: avoid associative arrays; use simple string/loop constructs.
- Avoid `readarray` and process substitution unsupported in older Bash.

### Debugging

- Quick trace: `bash -x ./bin/gtr <cmd>`.
- Inline: wrap suspicious block with `set -x` / `set +x`.
- Function presence: `declare -f create_worktree` or `declare -f resolve_target`.
- Variable inspection: `echo "DEBUG var=$var" >&2` (stderr keeps stdout clean for command substitution).

### External Commands

- Keep dependencies minimal: only `git`, `sed`, `awk`, `find`, `grep` (avoid jq/curl unless justified).
- Check availability before use if adding new tools.

### Quoting & Paths

- Use `"${var}"`; for loop over lines: `while IFS= read -r line; do ... done` to preserve spaces.
- Sanitize branch names via `sanitize_branch_name` (do NOT duplicate logic elsewhere).
Loading