Skip to content

neo pr

Manage pull requests

neo pr [OPTIONS] <COMMAND>

Open a pull request.

The source branch defaults to the current git branch.

neo pr create [OPTIONS] [TARGET]
Option Value Required Default Env Values Description
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--title <TITLE> no Pull request title. Defaults to the oldest commit subject in the local base..head range. Say what the change does and why — it is what a reviewer sees before opening anything; the detail belongs in --body
--body <BODY> no "" Markdown description
--base <BASE> no Target branch the PR merges into. Defaults to the repo’s default branch when omitted
--head <HEAD> no Source branch. Defaults to the current git branch
--draft no Open as a draft
--json no Print the raw response as JSON

List pull requests

neo pr list [OPTIONS] [TARGET]
Option Value Required Default Env Values Description
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--state <STATE> no open open, merged, closed, all Which pull requests to list
--json no Print the raw response as JSON

Show one PR with its diffstat, reviews and comments.

The diffstat is merge-base-aware (three-dot, the same range the merge would apply) and its totals cover the whole diff even when the file list is capped; the trailing line says which cap applied.

While the merge queue tests the PR on a candidate merge commit, the candidate’s checks (the ones that gate the merge) are listed above the head’s, whose runs the queue superseded.

neo pr view [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--json no Print {pull_request, checks, diffstat, reviews, comments} as JSON

Agent context pack for a pull request (always JSON).

The PR plus its checks roll-up, review comments and inline threads, a per-file change summary (paths and line counts, no patch text), and the issues it links to. Bounds are reported in truncated. --attachments <DIR> also downloads the images it references.

neo pr context [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--attachments <DIR> no Also download every attachment the pack references into DIR (created if missing), as <id>.<ext>. stdout is still exactly the JSON pack; each attachment gets one line on stderr, /a/<id> -> <path>, or a skip line for one you cannot read, which is not an error

Block until a PR reaches a terminal state, printing status transitions.

The first-class replacement for a shell loop around neo pr view: one process, and a distinct exit code per outcome instead of grepping prose. It wakes on the repo’s event stream, so a check going green is usually noticed in a second or two rather than at the next poll.

Exit codes: 0 the condition held · 3 a check failed, contexts listed (--for checks) · 4 closed without merging · 5 rejected from the queue or the merge gate still refuses after checks finish, with its reasons (--for merged) · 6 timed out · 7 every check was skipped, so nothing ran (--for checks) · 8 the PR is not being tested on a merge queue candidate (it left the queue, or the queue gates on its head), nothing on the head is red or running, and some head checks were superseded by an earlier candidate, so they will never finish: re-run them, or wait on the queue with --for merged (--for checks) · 1 the command itself failed.

The check set folds BOTH sources the merge gate judges — workflow runs and externally-posted commit statuses — so a red external status cannot read as green. While the merge queue tests the PR on a candidate merge commit, that candidate’s checks are the ones judged (they gate the merge), and each transition names the commit judged.

neo pr wait [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--for <WAIT_FOR> no checks checks, merged What to wait for. checks (the default) waits for the CI that gates the PR to finish — on its head, or on the merge queue’s candidate while the queue tests one — a question that always answers itself. merged waits for the PR to land, including queued candidate verification. It warns when no merge is requested and reports a queue rejection or a gate that still refuses after CI finishes outside the queue.
--timeout <TIMEOUT> no 3600 Maximum seconds to wait (at most 7 days)
--interval <INTERVAL> no 30 Poll interval in seconds. Values below the floor (30) are raised to it with a warning — replacing hot polling is the point of the command. This is the read cadence only when the forge’s event stream is unavailable (an older deploy, a proxy that will not pass text/event-stream, an exhausted stream budget). With the stream connected the command wakes on events and the timer is a backstop on a longer period, so a lost event costs latency and never a hang. A value above that backstop still wins.

Merge a PR when ready, or add it to the merge queue.

Merges immediately when requirements pass, the head is current, and the queue is empty. Otherwise the queue verifies its merge with the target in order. The freshly fetched head guards concurrent pushes. A refusal the queue reaches at once — a red required check, a moved head — exits non-zero with the reason; a PR that is merely waiting prints its queue position and exits 0.

neo pr merge [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--auto no Arm the merge without the fetched-head guard. Same merge-or-queue behaviour, but the request carries no expected_head: an armed intent is meant to outlive this command, and a guard taken from a momentarily stale view would have the queue eject it as “source branch moved” on its first look.
--merge no Land it as a two-parent merge commit. Omit both this and --squash to use the repository’s default method. The selected method is retained while queued.
--squash no Land it as ONE commit carrying the whole change, authored by the source head’s author, with Co-authored-by: trailers for everyone else on the branch. Refused for a PR with stacked children
--json no Print the resulting PR as JSON. Queued PRs stay open and carry merge_queue progress; only a completed merge has status: merged

Update a PR’s branch by merging the target into it.

The freshly fetched head commit is sent as a stale guard, so a concurrent push turns the update into an error.

neo pr update-branch [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--json no Print what the update DID as JSON — {outcome, new_head}, not a pull request. outcome is updated or already_up_to_date, and new_head carries the source branch’s new head commit exactly when the branch moved

Close a PR without merging

neo pr close [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--comment <BODY> no Markdown comment to post before closing
--json no Print the closed pull request as JSON

Edit a PR’s title or description.

Only supplied fields change; anything omitted keeps its current value. At least one of --title, --body, or --body-file is required. The new description is re-parsed for issue links, so a Closes #N line added or removed here links or unlinks that issue.

neo pr edit [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--title <TITLE> no Replace the title
--body <BODY> no Markdown description; --body "" clears it. Mutually exclusive with --body-file
--body-file <BODY_FILE> no Read the markdown description from a file instead of a shell argument — - reads stdin. Avoids shell-quoting long bodies. Mutually exclusive with --body
--json no Print the updated pull request as JSON

Mark a draft PR ready for review.

Clears the draft flag so the PR can merge and arm auto-merge. --undo converts it back to a draft. Idempotent either way.

neo pr ready [OPTIONS] <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--undo no Convert the pull request back to a draft instead
--json no Print the updated pull request as JSON

Comment on a PR

neo pr comment [OPTIONS] --body <BODY> <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--body <BODY> yes Markdown comment body
--json no Print the created comment as JSON

Submit a review decision on a PR

neo pr review [OPTIONS] <--approve|--request-changes|--comment> <NUMBER> [TARGET]
Option Value Required Default Env Values Description
<NUMBER> yes Pull request number (the 42 in acme/api#42)
<TARGET> no <owner>/<repo> or bare <repo>. Inferred from a checkout remote pointing at this host when omitted
--approve no Approve the PR
--request-changes no Request changes
--comment no Comment-only review (no approval state change)
--body <BODY> no "" Optional review summary (Markdown)
--json no Print the submitted review as JSON