memtrace pr
Check and refresh the local watches that memtrace code-review --post --watch registers, and see the human response to a posted review.
Usage#
memtrace pr [status | sync [--no-execute] | help]memtrace pr manages the local PR review watches that memtrace code-review --post --watch registers on this machine. There's no separate add/remove subcommand — watches are created only by posting a review with --watch, and tracked in ~/.memtrace/pr-watches.json.
status is the default when no subcommand is given. Any value other than status, sync, or help errors out with unknown pr subcommand and a non-zero exit.
status#
Read-only and purely local. Prints one line per watched PR — owner/repo#number, current status, posted-comment count, and pending/completed/failed @memtrace-command counts — or No Memtrace PR watches registered. when the state file is missing, empty, or unreadable. status never fails and never touches the network.
A corrupt pr-watches.json is silently treated as empty (just a warn-level log). An empty status output doesn't prove watches were never registered — check the file directly if you suspect corruption.
sync#
memtrace pr sync [--no-execute]A one-shot poll. sync initializes Memtrace auth, drains any pending relay events from the Memtrace cloud, then for each watch (up to 50 per invocation) mints a short-lived GitHub App installation token, fetches the PR plus its issue comments, reviews, and review comments from api.github.com, refreshes that watch's status, parses any @memtrace commands newer than the watch's registration time, and — by default — executes them.
| Flag | Description |
|---|---|
--no-execute | Detect and record @memtrace commands found in PR comments as pending, but don't run them: no reactions, check runs, child processes, or GitHub writes. Watch statuses are still refreshed normally. |
Without --no-execute, sync runs any queued @memtrace review, rerun, explain, ignore, fix this, or merge command it finds in PR comments — which can post comments/reactions/check runs, push commits, or merge the PR. The top-level memtrace help text only says pr sync "polls GitHub once" and doesn't mention command execution; the full behavior is documented in memtrace pr help.
Command execution is permission-gated through GitHub's collaborator-permission API: ignore, fix this, and merge require write/maintain/admin access; review, rerun, and explain only require the PR author or any collaborator with read access. Unauthorized commands get an "I can't run that command" reply instead of running. Commands are matched case-insensitively with word-boundary checks, bot-authored comments are skipped, and each command is deduplicated so the same comment can't re-trigger a command twice.
Executing a recognized command follows the same shape for all of them: an eyes-emoji acknowledgment reaction, a "Memtrace / <label>" check run on the head SHA (updated to success/failure/action_required), a completion reaction, and a reply comment with the outcome. The commands themselves differ:
| Command | Effect |
|---|---|
@memtrace review / rerun | Re-execs the memtrace binary as memtrace code-review --pr <url> --post with the watch’s saved max-comments, min-severity, graph-mode, repo-root, and accumulated --ignore-finding flags. |
@memtrace explain | Replies with a description of the finding; enriched by MEMTRACE_PR_AGENT_COMMAND’s first non-empty stdout line when set, otherwise a static description. |
@memtrace ignore | Appends the referenced finding to the watch’s ignored_findings list. |
@memtrace fix this | Creates a git worktree on a memtrace-fix-pr-* branch tracking the PR head, pipes a JSON payload to MEMTRACE_PR_AGENT_COMMAND, and if files changed, commits as the bot identity and pushes to the PR’s head branch. Rejected outright on fork PRs. |
@memtrace merge | PUTs /pulls/{n}/merge pinned to the current head SHA. |
Any running memtrace start or memtrace mcp process already spawns a background poller (every MEMTRACE_PR_POLL_INTERVAL_SECS, default 5s) plus a cloud relay long-poll doing the same work continuously. Manual sync is for a one-off check right now, or a non-daemon/CI context.
sync takes an exclusive advisory lock on ~/.memtrace/pr-watches.lock (4 retries, 50–400ms exponential backoff with jitter). If a background poller already holds it, this invocation silently skips the cycle and just prints the unchanged status table — it does not error.
Watch states#
Each watch carries one status, refreshed by every sync:
| Status | Meaning |
|---|---|
| awaiting_response | No human review or newer comment since the watch was registered. |
| human_replied | A newer human comment exists, with no formal approve/changes-requested review yet. |
| approved | The most recent post-registration PR review event is APPROVED. |
| changes_requested | The most recent post-registration PR review event is CHANGES_REQUESTED. |
| merged | The PR was merged. |
| closed | The PR was closed without merging. |
| stale_after_push | The PR’s head SHA has changed since the review was posted — the posted findings no longer match the current diff. |
| poll_error | The last GitHub fetch for this watch failed; a classified error kind is recorded alongside it. |
Environment variables#
| Variable | Default | Description |
|---|---|---|
MEMTRACE_PR_POLL_INTERVAL_SECS | 5 | Interval for the background PR-watch poller running inside memtrace start/memtrace mcp processes — not the one-shot pr sync. Clamped to 2–300 seconds; grows geometrically up to 300s while every watch is stuck in poll_error. |
MEMTRACE_PR_AGENT_COMMAND | — | Shell command run via /bin/sh -lc with a JSON payload (PR URL, worktree, target finding, head SHA, ...) on stdin. Required for @memtrace fix this; optionally enriches @memtrace explain with its first non-empty stdout line. Without it, fix this fails and explain falls back to a static description. |
MEMTRACE_GITHUB_BOT_LOGIN | memtrace-code-reviewer[bot] | Git author/committer name used when @memtrace fix this commits to the PR branch. |
MEMTRACE_GITHUB_BOT_EMAIL | 286493472+memtrace-code-reviewer[bot]@users.noreply.github.com | Git author/committer email used when @memtrace fix this commits to the PR branch. |
MEMTRACE_AUTH_URL | https://www.memtrace.io | Base URL of the Memtrace cloud used by sync for the GitHub App installation-token broker and the PR relay long-poll. |
Gotchas#
sync requires a real Memtrace cloud session (memtrace auth login). With no session token it fails with "no Memtrace session token available for PR watch sync". An offline license does not provide that cloud session token. status has no such requirement.
There's no pr unwatch or pr remove. Watches are added only via memtrace code-review --post --watch; to drop one, edit ~/.memtrace/pr-watches.json directly.
A single sync invocation polls at most 50 watches. With more than that registered, extras wait for the next cycle (or the background poller, which runs continuously).
@memtrace fix this only works when MEMTRACE_PR_AGENT_COMMAND is set in the syncing process's environment, the watch has a saved repo root, and the PR is same-repo (not a fork) — fork PR fixes are rejected.
sync emits one aggregate pr_watch_synced telemetry event with counts only — never PR URLs, repo names, paths, or SHAs.
Examples#
$ memtrace pr # Same as `memtrace pr status`. $ memtrace pr status # Memtrace PR watches # owner/repo#123 approved comments=3 commands=pending:0 completed:2 failed:0 updated=2026-07-04T12:00:00+00:00 # owner/repo#456 awaiting_response comments=1 commands=pending:1 completed:0 failed:0 updated=2026-07-04T11:00:00+00:00 $ memtrace pr sync # Poll GitHub once, refresh every watch's status, and execute # any queued @memtrace commands found in PR comments. $ memtrace pr sync --no-execute # Refresh statuses and record newly seen @memtrace commands # as pending, without running them. $ MEMTRACE_PR_AGENT_COMMAND='claude -p "$(cat)"' memtrace pr sync # Provide the local agent command that @memtrace fix this # and @memtrace explain invoke (payload arrives as JSON on stdin).
See also memtrace code-review, memtrace start, memtrace mcp, and memtrace auth.