repoq
v1.0.3
Published
Query Git and GitHub repository state with structured, machine-readable output.
Maintainers
Readme
repoq
Query Git repository state without parsing command output.
Each repoq command replaces multiple git/gh commands, handling edge cases
(detached HEAD, unborn branches, missing remotes) and returning validated JSON.
Works offline, degrades gracefully when GitHub CLI is unavailable.
Why repoq?
Getting reliable repository state from git and gh is harder than it looks:
- Parsing is fragile.
git status --porcelainuses two-character codes.git logoutput varies by format string. Worktree listings are multi-line records. - Edge cases break scripts. Detached HEAD, unborn branches, missing upstream tracking, and offline mode all need special handling.
- GitHub data requires multiple calls. PR checks/reviews come from
gh pr view. Unresolved review threads require GraphQL. Combining them takes orchestration. - Fallbacks are tedious. Finding the default branch might need
gh repo view, orgit symbolic-ref, or probing formain/master—depending on what's available.
repoq handles all of this internally and returns typed, validated JSON.
What it does
repoq can query:
status: one-shot repository snapshot- Runs multiple git commands plus optional gh queries
- Returns branch state, working tree breakdown, worktree summary, and last commit
- Handles detached HEAD, unborn branches, and missing GitHub auth gracefully
branch: branch lifecycle and tracking- Runs multiple git commands plus optional gh queries
- Reports local/remote existence, upstream tracking, worktree location, PR status
- Detects detached HEAD and unborn state without cryptic errors
diff-range: merge-base diff summary- Runs multiple git commands, with optional gh default-branch lookup
- Returns commit count, conventional commit metadata, file changes, line stats
- Tries remote branch first, falls back to local; handles unborn HEAD
worktrees: worktree inventory with status- Runs 1 + N git commands (status per worktree)
- Returns cleanliness, uncommitted counts, issue IDs from branch names
- Filters by
--issue-idor--uncommitted-only
pr: pull request with derived summaries- Uses
gh pr viewplus GraphQL for unresolved thread summaries - Returns checks (passing/failing/pending), reviews, unresolved thread counts
- Works without error if PR doesn't exist
- Uses
default-branch: resilient resolution- Fallback order: GitHub API → symref →
remote set-head --autoretry → probemain/master→ fallbackmain - Works offline, without gh, and on fresh clones
- Fallback order: GitHub API → symref →
Requirements
- Node.js >= 22.19.0
- Git
Optional: GitHub CLI (gh) enables PR queries and GitHub-backed default branch
detection. Without it, commands degrade gracefully—git-only data still works.
Install / run
# one-off
npx -y repoq status --json
# global
pnpm add -g repoq
repoq status --jsonRun it from inside a Git repository.
Usage
repoq <command> [options]Common examples:
# Get current branch name
repoq status --json | jq -r '.branch.current'
# Check if working tree is clean
repoq status --json | jq '.workingTree.isClean'
# Check upstream tracking
repoq status --json | jq '.branch.tracking | {ahead, behind}'
# Check if PR exists for current branch
repoq status --json | jq '.branch.pr.exists'
# Count commits since main
repoq diff-range --json | jq '.commits.count'
# List worktrees with uncommitted changes
repoq worktrees --uncommitted-only --json | jq '.[].path'
# Check if PR is approved
repoq pr --json | jq '.reviews.approved > 0'
# Check CI status
repoq pr --json | jq '.checks.failing == 0'
# Verify all commits are conventional
repoq diff-range --json | jq '[.commits.messages[].isConventional] | all'
# List changed files
repoq diff-range --json | jq '.files.added + .files.modified | .[]'
# Inspect a specific branch
repoq branch feature/login --json | jq '.tracking'Before and after
Getting PR approval status without repoq:
# Check if PR is approved (fragile, verbose)
pr_json=$(gh pr view --json reviews)
approved=$(echo "$pr_json" | jq '[.reviews[] | select(.state == "APPROVED")] | length')
if [ "$approved" -gt 0 ]; then echo "Approved"; fiWith repoq:
repoq pr --json | jq '.reviews.approved > 0'The difference grows with complexity. Checking if a branch is ready for merge
(clean working tree + CI passing + approved + no unresolved threads) takes
50+ lines of shell. With repoq:
repoq status --json | jq '.workingTree.isClean' && \
repoq pr --json | jq '.checks.failing == 0 and .reviews.approved > 0 and .unresolved.threads == 0'Command reference
| Command | Purpose |
| ----------------------------------------------------------- | ------------------------------------------------------------------------- |
| status [--json] | One-shot repo snapshot with full branch info, working tree, last commit |
| branch <branch> [--json] [--issue-id <id>] | Branch lifecycle/tracking/worktree/PR status with unborn detection |
| diff-range [base] [--json] [--head <branch>] | Merge-base diff summary, commit metadata, file/stats, fast-forwardability |
| worktrees [--json] [--issue-id <id>] [--uncommitted-only] | Enumerate worktrees with cleanliness/unborn state and filters |
| pr [branch] [--json] | PR metadata plus checks/reviews/unresolved summaries |
| default-branch [--json] | Resolve default branch with GitHub + git fallbacks |
For detailed command help:
repoq --help
repoq <command> --helpEnvironment variables
| Variable | Description |
| ---------------- | ----------------------------------------------- |
| REPOQ_GIT_PATH | Path to git binary (default: git from PATH) |
| REPOQ_GH_PATH | Path to gh binary (default: gh from PATH) |
Agent rule
Add to your CLAUDE.md or AGENTS.md:
# Rule: Use `repoq` for Repository Queries
Run `npx -y repoq --help` to learn available options.
Use `repoq` instead of piping `git`/`gh` commands through `awk`/`jq`/`grep`.
Each command handles edge cases (detached HEAD, unborn branches, missing auth)
and returns validated JSON. Prefer `repoq` for reading state; use raw `git`/`gh`
for mutations (commit, push, merge).License
MIT
