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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [v0.6.1] - 2026-05-21

### Fixes

- Add `-R, --repo OWNER/NAME` flag to `prs`, `issues`, and `checks` so agents can target any repo without first changing into a clone. Previously every PR / issue subcommand defaulted to `gh`'s cwd-based detection, which silently pointed at the wrong repo when the agent was running in a different working tree — leading to spurious 404s when looking up a PR in a different project.
- `checks -R OWNER/NAME` now falls back to that repo's default branch when `--branch` isn't given, instead of using the local current branch (which has no meaning cross-repo).

## [v0.6.0] - 2026-05-21

### Features
Expand Down
47 changes: 35 additions & 12 deletions bin/fledge-github-checks
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ set -euo pipefail

BRANCH=""
JSON=false
REPO_OVERRIDE=""

while [ $# -gt 0 ]; do
case "$1" in
-b|--branch)
BRANCH="${2:-}"
shift 2
;;
-R|--repo)
REPO_OVERRIDE="${2:-}"
shift 2
;;
--json)
JSON=true
shift
Expand All @@ -27,13 +32,15 @@ USAGE:
fledge github checks [OPTIONS]

OPTIONS:
-b, --branch <NAME> Branch to check (default: current branch)
--json Output raw GitHub API response as JSON
-h, --help Show this help
-b, --branch <NAME> Branch to check (default: current branch)
-R, --repo <OWNER/NAME> Target repo (default: current working repo)
--json Output raw GitHub API response as JSON
-h, --help Show this help

EXAMPLES:
fledge github checks
fledge github checks --branch main
fledge github checks -R CorvidLabs/merlin --branch main
fledge github checks --json | jq '.check_runs[].name'
EOF
exit 0
Expand All @@ -50,18 +57,34 @@ if ! command -v gh >/dev/null 2>&1; then
exit 127
fi

if [ -z "$BRANCH" ]; then
BRANCH="$(git branch --show-current 2>/dev/null || true)"
# Resolve repo. When -R is set, use that directly; otherwise let gh
# detect from cwd. Branch defaults to the current local branch — that
# only makes sense when REPO_OVERRIDE is empty, but the user can still
# pass --branch explicitly for the cross-repo case.
if [ -n "$REPO_OVERRIDE" ]; then
REPO="$REPO_OVERRIDE"
if [ -z "$BRANCH" ]; then
echo "fledge github checks: not on a branch (detached HEAD?). Use --branch <name>." >&2
exit 65
# Fall back to that repo's default branch when no --branch was passed.
BRANCH="$(gh repo view "$REPO" --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null || true)"
if [ -z "$BRANCH" ]; then
echo "fledge github checks: could not determine default branch for $REPO. Use --branch <name>." >&2
exit 65
fi
fi
else
if [ -z "$BRANCH" ]; then
BRANCH="$(git branch --show-current 2>/dev/null || true)"
if [ -z "$BRANCH" ]; then
echo "fledge github checks: not on a branch (detached HEAD?). Use --branch <name>." >&2
exit 65
fi
fi
fi

REPO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)"
if [ -z "$REPO" ]; then
echo "fledge github checks: could not detect GitHub repo. Run 'gh auth login' and ensure 'origin' points at a GitHub remote." >&2
exit 1
REPO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)"
if [ -z "$REPO" ]; then
echo "fledge github checks: could not detect GitHub repo. Run 'gh auth login' and ensure 'origin' points at a GitHub remote, or pass -R OWNER/NAME." >&2
exit 1
fi
fi

DATA="$(gh api "repos/${REPO}/commits/${BRANCH}/check-runs" 2>/dev/null || true)"
Expand Down
32 changes: 24 additions & 8 deletions bin/fledge-github-issues
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ BODY=""
ASSIGNEE=""
JSON=false
INCLUDE_COMMENTS=false
REPO=""

# Splice "${REPO_FLAGS[@]+...}" into each gh sub-call so it inherits
# the user's -R/--repo when set, or stays empty (gh falls back to its
# cwd detection) when not.
REPO_FLAGS=()

# First positional arg can be a subcommand.
if [ $# -gt 0 ] && [ "${1:0:1}" != "-" ]; then
Expand Down Expand Up @@ -48,6 +54,7 @@ while [ $# -gt 0 ]; do
-a|--assignee) ASSIGNEE="${2:-}"; shift 2;;
--json) JSON=true; shift;;
--comments) INCLUDE_COMMENTS=true; shift;;
-R|--repo) REPO="${2:-}"; shift 2;;
-h|--help)
cat <<'EOF'
fledge github issues — manage GitHub issues via the gh CLI
Expand Down Expand Up @@ -100,6 +107,12 @@ if ! command -v gh >/dev/null 2>&1; then
exit 127
fi

# Expand --repo into the gh flag form (see fledge-github-prs for the
# rationale on the +-form expansion below).
if [ -n "$REPO" ]; then
REPO_FLAGS=(--repo "$REPO")
fi

case "$ACTION" in
view|comment|close|reopen)
if [ -z "$NUMBER" ]; then
Expand All @@ -111,13 +124,13 @@ esac

if [ "$ACTION" = "view" ]; then
if [ "$JSON" = "true" ]; then
gh issue view "$NUMBER" --json number,title,state,author,body,labels,createdAt,updatedAt,url,assignees
gh issue view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --json number,title,state,author,body,labels,createdAt,updatedAt,url,assignees
else
gh issue view "$NUMBER"
gh issue view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
fi
if [ "$JSON" != "true" ] && [ "$INCLUDE_COMMENTS" = "true" ]; then
printf '\n--- Comments ---\n'
gh issue view "$NUMBER" --comments
gh issue view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --comments
fi
exit 0
fi
Expand All @@ -128,26 +141,27 @@ if [ "$ACTION" = "comment" ]; then
exit 64
fi
if [ "$JSON" = "true" ]; then
URL="$(gh issue comment "$NUMBER" -b "$BODY")"
URL="$(gh issue comment "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" -b "$BODY")"
printf '{"url":"%s"}\n' "$URL"
else
gh issue comment "$NUMBER" -b "$BODY"
gh issue comment "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" -b "$BODY"
fi
exit 0
fi

if [ "$ACTION" = "close" ]; then
gh issue close "$NUMBER"
gh issue close "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
exit 0
fi

if [ "$ACTION" = "reopen" ]; then
gh issue reopen "$NUMBER"
gh issue reopen "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
exit 0
fi

if [ "$ACTION" = "create" ]; then
ARGS=()
[ -n "$REPO" ] && ARGS+=(--repo "$REPO")
[ -n "$TITLE" ] && ARGS+=(--title "$TITLE")
[ -n "$BODY" ] && ARGS+=(--body "$BODY")
[ -n "$LABEL" ] && ARGS+=(--label "$LABEL")
Expand All @@ -161,7 +175,9 @@ if [ "$ACTION" = "create" ]; then
fi

# list
ARGS=(--state "$STATE" --limit "$LIMIT")
ARGS=()
[ -n "$REPO" ] && ARGS+=(--repo "$REPO")
ARGS+=(--state "$STATE" --limit "$LIMIT")
if [ -n "$LABEL" ]; then ARGS+=(--label "$LABEL"); fi

if [ "$JSON" = "true" ]; then
Expand Down
42 changes: 29 additions & 13 deletions bin/fledge-github-prs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ INCLUDE_DIFF=false
INCLUDE_COMMENTS=false
MERGE_METHOD="squash"
REVIEW_KIND=""
REPO=""

# When -R/--repo is set, every gh sub-call gets `--repo $REPO`
# appended via REPO_FLAGS. Empty when -R isn't set, so the gh CLI
# falls back to its normal cwd-based repo detection.
REPO_FLAGS=()

# ANSI color codes
BLUE=$'\033[0;34m'
Expand Down Expand Up @@ -69,6 +75,7 @@ while [ $# -gt 0 ]; do
--approve) REVIEW_KIND="approve"; shift;;
--request-changes) REVIEW_KIND="request-changes"; shift;;
--comment-review) REVIEW_KIND="comment"; shift;;
-R|--repo) REPO="${2:-}"; shift 2;;
-h|--help)
cat <<'EOF'
fledge github prs — manage GitHub pull requests via the gh CLI
Expand Down Expand Up @@ -141,6 +148,13 @@ if ! command -v gh >/dev/null 2>&1; then
exit 127
fi

# Expand --repo into the gh flag form. Done once here so every action
# branch can splice "${REPO_FLAGS[@]+...}" into its gh invocation
# without re-checking $REPO.
if [ -n "$REPO" ]; then
REPO_FLAGS=(--repo "$REPO")
fi

# All non-list actions except 'create' need a number.
case "$ACTION" in
view|comment|review|merge|close|reopen)
Expand All @@ -153,9 +167,9 @@ esac

if [ "$ACTION" = "view" ]; then
if [ "$JSON" = "true" ]; then
gh pr view "$NUMBER" --json number,title,state,author,body,labels,createdAt,updatedAt,url,baseRefName,headRefName,isDraft,mergeable,statusCheckRollup
gh pr view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --json number,title,state,author,body,labels,createdAt,updatedAt,url,baseRefName,headRefName,isDraft,mergeable,statusCheckRollup
else
gh pr view "$NUMBER"
gh pr view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
fi
# Optional appendices below the main view block. Each section is
# gated by its own flag and separated by a blank line so the output
Expand All @@ -164,11 +178,11 @@ if [ "$ACTION" = "view" ]; then
# parsing concatenated streams.
if [ "$JSON" != "true" ] && [ "$INCLUDE_COMMENTS" = "true" ]; then
printf '\n--- Comments + Reviews ---\n'
gh pr view "$NUMBER" --comments
gh pr view "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --comments
fi
if [ "$JSON" != "true" ] && [ "$INCLUDE_DIFF" = "true" ]; then
printf '\n--- Diff ---\n'
gh pr diff "$NUMBER"
gh pr diff "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
fi
exit 0
fi
Expand All @@ -181,10 +195,10 @@ if [ "$ACTION" = "comment" ]; then
if [ "$JSON" = "true" ]; then
# gh pr comment prints the comment URL to stdout when -b is used;
# wrap that in a tiny JSON shape so callers can parse it uniformly.
URL="$(gh pr comment "$NUMBER" -b "$BODY")"
URL="$(gh pr comment "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" -b "$BODY")"
printf '{"url":"%s"}\n' "$URL"
else
gh pr comment "$NUMBER" -b "$BODY"
gh pr comment "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" -b "$BODY"
fi
exit 0
fi
Expand All @@ -199,6 +213,7 @@ if [ "$ACTION" = "review" ]; then
exit 64
fi
ARGS=("$NUMBER")
[ -n "$REPO" ] && ARGS+=(--repo "$REPO")
case "$REVIEW_KIND" in
approve) ARGS+=(--approve);;
request-changes) ARGS+=(--request-changes);;
Expand All @@ -211,20 +226,20 @@ fi

if [ "$ACTION" = "merge" ]; then
case "$MERGE_METHOD" in
squash) gh pr merge "$NUMBER" --squash;;
merge) gh pr merge "$NUMBER" --merge;;
rebase) gh pr merge "$NUMBER" --rebase;;
squash) gh pr merge "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --squash;;
merge) gh pr merge "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --merge;;
rebase) gh pr merge "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --rebase;;
esac
exit 0
fi

if [ "$ACTION" = "close" ]; then
gh pr close "$NUMBER"
gh pr close "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
exit 0
fi

if [ "$ACTION" = "reopen" ]; then
gh pr reopen "$NUMBER"
gh pr reopen "$NUMBER" "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}"
exit 0
fi

Expand Down Expand Up @@ -372,6 +387,7 @@ Output only the title and body. No preamble, no meta-commentary."

# Build gh pr create argument list
ARGS=()
[ -n "$REPO" ] && ARGS+=(--repo "$REPO")
[ -n "$TITLE" ] && ARGS+=(--title "$TITLE")
[ -n "$BODY" ] && ARGS+=(--body "$BODY")
[ -n "$BASE" ] && ARGS+=(--base "$BASE")
Expand All @@ -387,8 +403,8 @@ fi

# list
if [ "$JSON" = "true" ]; then
gh pr list --state "$STATE" --limit "$LIMIT" \
gh pr list "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --state "$STATE" --limit "$LIMIT" \
--json number,title,state,author,createdAt,url,baseRefName,headRefName,isDraft,labels
else
gh pr list --state "$STATE" --limit "$LIMIT"
gh pr list "${REPO_FLAGS[@]+"${REPO_FLAGS[@]}"}" --state "$STATE" --limit "$LIMIT"
fi
6 changes: 3 additions & 3 deletions plugin.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[plugin]
name = "fledge-plugin-github"
version = "0.6.0"
version = "0.6.1"
description = "GitHub commands for fledge — list/view/create/comment/review/merge PRs, list/view/create/comment/close issues, read repo files, view CI checks, and poll for daemon events via the gh CLI"
author = "0xLeif"
license = "MIT"

[[commands]]
name = "github"
description = "GitHub commands via the gh CLI. Subcommands: prs (list/view <num> [--diff --comments]/create/comment <num> -b BODY/review <num> --approve|--request-changes|--comment-review -b BODY/merge <num>/close <num>/reopen <num>), issues (list/view <num> [--comments]/create/comment <num> -b BODY/close <num>/reopen <num>), repo (view / file <path> [--ref REF] [-R OWNER/NAME]), checks (CI status), poll (daemon event polling)."
description = "GitHub commands via the gh CLI. All subcommands accept -R OWNER/NAME to target any repo (the agent's working dir is otherwise used). Subcommands: prs (list/view <num> [--diff --comments]/create/comment <num> -b BODY/review <num> --approve|--request-changes|--comment-review -b BODY/merge <num>/close <num>/reopen <num>), issues (list/view <num> [--comments]/create/comment <num> -b BODY/close <num>/reopen <num>), repo (view / file <path> [--ref REF]), checks (CI status), poll (daemon event polling)."
binary = "bin/fledge-github"
args = [
{ name = "args", type = "string", required = true, description = "Subcommand and options, e.g. 'prs view 208 --diff', 'prs comment 208 -b \"LGTM\"', 'issues create -t \"Bug\" -b \"...\"', 'repo file CHANGELOG.md -R CorvidLabs/merlin'" },
{ name = "args", type = "string", required = true, description = "Subcommand and options. Pass -R OWNER/NAME to target any repo without changing directory. Examples: 'prs view 5 -R CorvidLabs/corvid-verify --diff', 'prs comment 208 -b \"LGTM\"', 'issues create -R CorvidLabs/merlin -t \"Bug\" -b \"...\"', 'repo file CHANGELOG.md -R CorvidLabs/merlin'" },
]
Loading