poppa · Rust + Playwright · CLI · interactive console · MCP

Poppa

Poppa gets pull requests through a Proof of Presence check. Some enterprise GitHub organisations require one before a pull request can merge: a person signs in through the organisation's identity provider for that exact commit. Poppa finds the pull requests waiting on it across several accounts, opens their sign-in pages in a batch or completes them one at a time, and merges them only if asked.

poppa list                        # ready PRs needing PoP, every configured account
poppa open --dry-run              # preview the sign-in tabs
poppa auto                        # complete them one at a time
poppa auto --merge --squash       # then request squash merges
poppa i                           # the interactive console

Finding pull requests

Accounts are GitHub logins on their hosts, each authenticated with gh. For every call, Poppa asks gh for that login's token and hands it only to that account's own API children: it never switches gh's active account, never stores a token, and strips ambient token variables first, so a personal token can't silently stand in for a work login.

Drafts are excluded unless you include them, and "ready" means only "not a draft": not approved, not green, not mergeable. open launches one sign-in tab per PR, in a stable order, and stops there: a dispatched tab is not a completed check, so you rerun list to see what actually passed.

Serial mode

poppa auto works through the queue serially in one dedicated, persistent browser, waiting for GitHub to confirm the check on the PR's exact head commit, and for the sign-in to settle, before it touches the next.

Proving presence, one PR at a time What poppa auto does for each pull request in its queue. It opens the PR's Proof of Presence link, built for the PR's current head commit, in one dedicated, persistent browser. It advances the sign-in steps and, if configured, types the password read from a local secret file, or one asked for once with echo hidden; the password is never taken from arguments, configuration, the environment or MCP, and never handed to the browser automation. It then waits for GitHub to report success for that exact head and for the sign-in callback to settle before starting the next PR. An uncertain submission waits for real verification instead of retrying, and an unresolved request stops the queue. Merging happens only when explicitly asked, through GitHub's normal rules with the head commit pinned. open the PoP link for head abc1231 sign-in steps2 password from a local secret, or typed once, echo hidden verified3 PoP check: success on head abc1234 callback settled5 next PR (never two at once)6 optional: gh pr merge --match-head-commit7 poppa autoserial corepoppa autoserial core one browserpersistent profileone browserpersistent profile identity providersign-inidentity providersign-in GitHubPR checksGitHubPR checks
Never two at once, never a blind retry. An uncertain submission waits for real verification; an unresolved one stops the queue.