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
2 changes: 1 addition & 1 deletion plugins-claude/git-tools/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "git-tools",
"version": "3.3.0",
"version": "3.4.0",
"description": "GitHub and Gitea tooling — platform detection plus blocking waiters for PR merges and CI runs, plus a ship orchestrator that drives the full branch/commit/push/PR/watch/cleanup lifecycle using gh/tea directly",
"author": {
"name": "Logan Gagne"
Expand Down
27 changes: 26 additions & 1 deletion plugins-claude/git-tools/scripts/git-wait
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
# job-level failures masked by a run-level success; `tea` has no watcher.
#
# Usage:
# git-wait [-C DIR] <command> ...
# Operate on the git repo at DIR instead of the current directory (like
# `git -C`). Must come before the command. gh/tea resolve the repo from the
# working directory, so this retargets every call without a caller-side cd.
#
# git-wait platform
# Echo "github" or "gitea" for the current repo's origin remote.
#
Expand Down Expand Up @@ -115,6 +120,26 @@ cli_json() {
echo "$raw" | jq "${jq_flags[@]+"${jq_flags[@]}"}" "$filter"
}

# ---------------------------------------------------------------------------
# Target repo (-C DIR)
#
# Handled before platform detection. The cd happens inside this script's own
# process, so the caller's working directory is never touched.
# ---------------------------------------------------------------------------

if [[ "${1:-}" == "-C" || "${1:-}" == "--repo-dir" ]]; then
[[ $# -gt 1 && -n "$2" ]] || die_usage "$1 requires a directory"
target_dir="$2"
[[ -d "$target_dir" ]] || die_usage "$1: not a directory: $target_dir"
git -C "$target_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|| die_usage "$1: not a git repository: $target_dir"
# Resolve the script path first: a relative $0 breaks once we cd (help reads it).
SELF="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
cd "$target_dir"
shift 2
fi
SELF="${SELF:-$0}"

# ---------------------------------------------------------------------------
# Platform detection
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1425,7 +1450,7 @@ case "$cmd:$sub" in
;;

--help:|-h:|:)
sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'
sed -n '2,/^$/p' "$SELF" | sed 's/^# \{0,1\}//'
exit 0
;;

Expand Down
12 changes: 12 additions & 0 deletions plugins-claude/git-tools/skills/git-wait/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ Exit codes: `0` terminal state reached (check `status:` for pass/fail),
`1` usage error, `2` timeout, `3` platform detection failure or no PR/workflow
found, `4` command failed.

## Targeting another repo

Put `-C DIR` before the command to run against a repo other than the current
directory — use it instead of `cd`:

```bash
bash ${CLAUDE_PLUGIN_ROOT}/scripts/git-wait -C /path/to/other-repo run watch --branch NAME
```

Only `git-wait` honors `-C`; direct `gh`/`tea` calls against another repo still
need their own `-R OWNER/REPO` / `--repo` flag.

## gh vs. tea command map

Verified against `gh` 2.100.0 and `tea` 0.15.1. Don't guess beyond this
Expand Down
2 changes: 1 addition & 1 deletion plugins-claude/session/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "session",
"version": "4.9.1",
"version": "4.9.2",
"dependencies": ["git-tools"],
"description": "Work session management — issue-driven and freeform doors sharing an explore-then-plan spine, with multi-agent orchestration and a wrap-up skill that reviews, sweeps issues, and ships",
"author": {
Expand Down
27 changes: 26 additions & 1 deletion plugins-claude/session/scripts/git-wait
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
# job-level failures masked by a run-level success; `tea` has no watcher.
#
# Usage:
# git-wait [-C DIR] <command> ...
# Operate on the git repo at DIR instead of the current directory (like
# `git -C`). Must come before the command. gh/tea resolve the repo from the
# working directory, so this retargets every call without a caller-side cd.
#
# git-wait platform
# Echo "github" or "gitea" for the current repo's origin remote.
#
Expand Down Expand Up @@ -115,6 +120,26 @@ cli_json() {
echo "$raw" | jq "${jq_flags[@]+"${jq_flags[@]}"}" "$filter"
}

# ---------------------------------------------------------------------------
# Target repo (-C DIR)
#
# Handled before platform detection. The cd happens inside this script's own
# process, so the caller's working directory is never touched.
# ---------------------------------------------------------------------------

if [[ "${1:-}" == "-C" || "${1:-}" == "--repo-dir" ]]; then
[[ $# -gt 1 && -n "$2" ]] || die_usage "$1 requires a directory"
target_dir="$2"
[[ -d "$target_dir" ]] || die_usage "$1: not a directory: $target_dir"
git -C "$target_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|| die_usage "$1: not a git repository: $target_dir"
# Resolve the script path first: a relative $0 breaks once we cd (help reads it).
SELF="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
cd "$target_dir"
shift 2
fi
SELF="${SELF:-$0}"

# ---------------------------------------------------------------------------
# Platform detection
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1425,7 +1450,7 @@ case "$cmd:$sub" in
;;

--help:|-h:|:)
sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'
sed -n '2,/^$/p' "$SELF" | sed 's/^# \{0,1\}//'
exit 0
;;

Expand Down
2 changes: 1 addition & 1 deletion plugins-copilot/git-tools/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "git-tools",
"version": "3.3.0",
"version": "3.4.0",
"description": "GitHub and Gitea tooling — platform detection plus blocking waiters for PR merges and CI runs, plus a ship orchestrator that drives the full branch/commit/push/PR/watch/cleanup lifecycle using gh/tea directly",
"author": {
"name": "Logan Gagne"
Expand Down
2 changes: 1 addition & 1 deletion plugins-copilot/session/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "session",
"version": "4.9.1",
"version": "4.9.2",
"description": "Work session management — issue-driven and freeform doors sharing an explore-then-plan spine, with multi-agent orchestration and a wrap-up skill that reviews, sweeps issues, and ships",
"author": {
"name": "Logan Gagne"
Expand Down
108 changes: 108 additions & 0 deletions tests/git-wait/test-target-repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
# test-target-repo.sh — git-wait -C DIR retargets every call at another repo.
#
# Two real throwaway repos (GitHub-hosted and Gitea-hosted origins) plus a tea
# login stub on PATH. git-wait is always launched from a third, unrelated
# directory so a pass proves -C — not the working directory — chose the repo.
#
# Usage: bash tests/git-wait/test-target-repo.sh [filter]

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
GIT_WAIT="$SCRIPT_DIR/../../utils/git-wait"

PASS=0
FAIL=0
FILTER="${1:-}"

WORK=""
cleanup() { [[ -n "$WORK" ]] && rm -rf "$WORK"; }
trap cleanup EXIT
WORK=$(mktemp -d)

pass() {
printf " \033[32m✓\033[0m %s\n" "$1"
((PASS++)) || true
}
fail() {
printf " \033[31m✗\033[0m %s (%s)\n" "$1" "$2"
((FAIL++)) || true
}
skip_filter() { [[ -n "$FILTER" ]] && ! echo "$1" | grep -qi "$FILTER"; }

mkdir -p "$WORK/bin" "$WORK/github-repo" "$WORK/gitea-repo" "$WORK/elsewhere" "$WORK/not-a-repo"
git init -q "$WORK/github-repo"
git -C "$WORK/github-repo" remote add origin "https://github.com/owner/repo.git"
git init -q "$WORK/gitea-repo"
git -C "$WORK/gitea-repo" remote add origin "https://git.example.test/owner/repo.git"

# Only the Gitea host is a configured tea login; anything else falls to gh.
cat >"$WORK/bin/tea" <<'EOS'
#!/usr/bin/env bash
case "$1 $2 $3" in
"login list --output") echo '[{"url":"https://git.example.test"}]' ;;
*) exit 1 ;;
esac
EOS
chmod +x "$WORK/bin/tea"
# Platform detection never calls gh, but the script requires it on PATH.
printf '#!/usr/bin/env bash\nexit 1\n' >"$WORK/bin/gh"
chmod +x "$WORK/bin/gh"

# Run git-wait from an unrelated cwd; sets OUT, ERR, CODE.
gw() {
CODE=0
OUT=$(cd "$WORK/elsewhere" && PATH="$WORK/bin:$PATH" bash "$GIT_WAIT" "$@" 2>"$WORK/stderr") || CODE=$?
ERR=$(cat "$WORK/stderr")
}

echo "── -C DIR ──"

label="-C picks the GitHub repo regardless of cwd"
if ! skip_filter "$label"; then
gw -C "$WORK/github-repo" platform
if [[ "$CODE" == "0" && "$OUT" == "github" ]]; then pass "$label"; else fail "$label" "exit=$CODE out=$OUT err=$ERR"; fi
fi

label="-C picks the Gitea repo regardless of cwd"
if ! skip_filter "$label"; then
gw -C "$WORK/gitea-repo" platform
if [[ "$CODE" == "0" && "$OUT" == "gitea" ]]; then pass "$label"; else fail "$label" "exit=$CODE out=$OUT err=$ERR"; fi
fi

label="--repo-dir is an alias for -C"
if ! skip_filter "$label"; then
gw --repo-dir "$WORK/gitea-repo" platform
if [[ "$CODE" == "0" && "$OUT" == "gitea" ]]; then pass "$label"; else fail "$label" "exit=$CODE out=$OUT err=$ERR"; fi
fi

label="-C composes with a subcommand (run watch usage error comes from the target)"
if ! skip_filter "$label"; then
gw -C "$WORK/github-repo" run watch --branch feat --settle 30
if [[ "$CODE" == "1" && "$ERR" == *"--settle requires --sha"* ]]; then pass "$label"; else fail "$label" "exit=$CODE err=$ERR"; fi
fi

echo "── -C validation ──"

label="nonexistent directory is a usage error (exit 1)"
if ! skip_filter "$label"; then
gw -C "$WORK/missing" platform
if [[ "$CODE" == "1" && "$ERR" == *"not a directory"* ]]; then pass "$label"; else fail "$label" "exit=$CODE err=$ERR"; fi
fi

label="non-git directory is a usage error (exit 1)"
if ! skip_filter "$label"; then
gw -C "$WORK/not-a-repo" platform
if [[ "$CODE" == "1" && "$ERR" == *"not a git repository"* ]]; then pass "$label"; else fail "$label" "exit=$CODE err=$ERR"; fi
fi

label="-C without a value is a usage error (exit 1)"
if ! skip_filter "$label"; then
gw -C
if [[ "$CODE" == "1" && "$ERR" == *"requires a directory"* ]]; then pass "$label"; else fail "$label" "exit=$CODE err=$ERR"; fi
fi

echo ""
echo "Total: $((PASS + FAIL)) PASS: $PASS FAIL: $FAIL"
[[ "$FAIL" -eq 0 ]]
27 changes: 26 additions & 1 deletion utils/git-wait
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
# job-level failures masked by a run-level success; `tea` has no watcher.
#
# Usage:
# git-wait [-C DIR] <command> ...
# Operate on the git repo at DIR instead of the current directory (like
# `git -C`). Must come before the command. gh/tea resolve the repo from the
# working directory, so this retargets every call without a caller-side cd.
#
# git-wait platform
# Echo "github" or "gitea" for the current repo's origin remote.
#
Expand Down Expand Up @@ -115,6 +120,26 @@ cli_json() {
echo "$raw" | jq "${jq_flags[@]+"${jq_flags[@]}"}" "$filter"
}

# ---------------------------------------------------------------------------
# Target repo (-C DIR)
#
# Handled before platform detection. The cd happens inside this script's own
# process, so the caller's working directory is never touched.
# ---------------------------------------------------------------------------

if [[ "${1:-}" == "-C" || "${1:-}" == "--repo-dir" ]]; then
[[ $# -gt 1 && -n "$2" ]] || die_usage "$1 requires a directory"
target_dir="$2"
[[ -d "$target_dir" ]] || die_usage "$1: not a directory: $target_dir"
git -C "$target_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|| die_usage "$1: not a git repository: $target_dir"
# Resolve the script path first: a relative $0 breaks once we cd (help reads it).
SELF="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
cd "$target_dir"
shift 2
fi
SELF="${SELF:-$0}"

# ---------------------------------------------------------------------------
# Platform detection
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1425,7 +1450,7 @@ case "$cmd:$sub" in
;;

--help:|-h:|:)
sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'
sed -n '2,/^$/p' "$SELF" | sed 's/^# \{0,1\}//'
exit 0
;;

Expand Down
Loading