Skip to content

Pull requests and issues

Open a pull request (or a GitLab merge request) or an issue as a block beside the terminal or agent working on it, with its checks, reviews, timeline and anything waiting on you. Arugula uses your existing command-line login for each forge: gh for GitHub, glab for GitLab and tea for Forgejo.

You can open a pull request from Open beside › Open pull request… in a pane’s menu, Open pull request… in the + button’s menu, + Pane › Pull request (Pull request in the phone’s sheet), by clicking a pull request link in a terminal (Shift-click opens it in your browser instead), or from the CLI:

Terminal window
arugula pr 84 # number 84 in this folder's repository
arugula pr OWNER/REPO#84 # GitHub, Forgejo
arugula pr GROUP/PROJECT!12 # GitLab
arugula pr https://… # a link

When a pull request needs you, a card appears on the rail, on your phone and as a notification, grouped by repository:

  • a review is asked of you (or of a team you’re in): Approve, on the block, the rail or the phone’s sheet, sends a review with your login;
  • checks failed on your pull request (Rerun where the forge allows it);
  • changes were requested on your pull request, or someone mentioned you since you last looked;
  • your pull request was merged, or is ready to merge (you’re notified once).

The code: Diff fetches the pull request’s head into your clone, without changing any of your branches, makes a worktree of it in .arugula/worktrees/pr-{N} (or .claude/worktrees/pr-{N}, where the repository keeps its worktrees), and opens a diff block from the merge base. Checkout opens a terminal there.

Writing: comment, review (approve, request changes, comment) and merge from the block, or from the CLI:

Terminal window
arugula pr comment %7 "LGTM"
arugula pr review %7 approve [TEXT] # or request_changes, comment
arugula pr merge %7 [--style squash] # or merge, rebase
arugula pr rerun %7 # rerun failed checks (also: arugula rerun %7)

An agent’s comment, review, merge or new issue never reaches the forge by itself. Whether it comes through MCP’s draft tool or from arugula pr … and arugula issue … run by an agent (under Claude Code, or with AI_AGENT set), it waits on the block as a card with the text to edit. Send posts it, as edited, with the login of the machine’s owner; Drop drops it. The owner and people who drive the session may send; people who watch can’t. The block and its history say who sent each one, and that an agent drafted it.

A person’s own write (the block’s buttons, or arugula pr comment in your shell) goes straight out.

On a linked repository, an agent’s draft waits on Arugula control instead of on one machine, so you can send it from your phone with every machine asleep.

Arugula uses your gh login (gh auth token --hostname {host}), keeps the token in memory only, and asks gh again when it expires. GitHub Enterprise works the same when gh has a login there.

  • Checks are both check runs and commit statuses. Branch protection that blocks a merge keeps the pull request from counting as ready.
  • Rerun on your pull request’s failed checks reruns the failed jobs of each failed workflow run.
  • Merge styles are merge, squash and rebase.
  • When the rate limit runs low, the block polls once a minute and says so.
  • Live updates: on a machine joined to Arugula control, control’s GitHub App tells the block when something changed, so it reads at once instead of polling. That needs you signed in to control with GitHub, and the App installed on the repository’s owner. For a repository nobody linked, control passes on only “something changed on OWNER/REPO#N”, never the event itself. A linked repository is different.
  • A machine with no gh login that’s joined to control can still read GitHub through control’s App, read-only. Writes from a block always go out as you, with your own gh login.

On Arugula control, you can link a GitHub repository to a project. Control then keeps the repository’s pull requests and issues itself, so your phone can see them and act on them while every one of your machines is asleep.

This changes what control holds. Control used to pass on only “something changed”, never the event itself, and every block read GitHub from its own machine. For a linked repository, control’s GitHub App reads the events and control keeps what lists and your inbox need. The privacy notice lists all of it.

  • What control keeps: each pull request’s and issue’s state, title, labels, people, the reviewers asked and its checks, and what happened to it, with no text. Bodies and comments are read from GitHub when you open one, and kept a few minutes in memory. A project can choose to keep them too, one repository at a time, so its search finds their text.
  • Who sees it: a private repository’s items show only to people GitHub says can see that repository. Being in the project isn’t enough.
  • Linking: a member of the project who is an admin or maintainer of the repository on GitHub links it, on the project’s settings page or with arugula project link OWNER/REPO. Control’s GitHub App has to be installed for the repository, and Arugula sends you to install it if it isn’t. Unlinking the repository, or uninstalling the App, removes everything control kept for it within 24 hours.
  • Blocks on a linked repository show control’s copy, without the description and comments’ text, and their machine stops reading GitHub for it.
  • Your inbox: control works out what wants you (a review asked of you, failed checks on your pull request, an issue assigned to you, a draft waiting) and notifies you, with every machine off. It’s on control’s platform page, and arugula forge inbox in a terminal.
  • Sending: when you send a comment, review or new issue from your phone or control’s page, control asks GitHub for a token that acts as you, makes that one call, and drops the token. It never stores your token, and what you send is yours on GitHub, not a bot’s. If that can’t happen, one of your machines sends it with its own gh login. Agents still only draft.

What works as before: repositories nobody linked, Forgejo, GitLab, and Arugula on a tailnet without control. Their blocks read from your own machine with your own command-line login, as the rest of this page says.

Arugula opens merge requests on gitlab.com or any host your glab knows: from a link, arugula pr URL, GROUP/PROJECT!N, or a number in a clone whose remote is on GitLab. It uses your glab login for that host and keeps the token in memory only.

  • With no login, a public project still reads anonymously, and the block says read-only: no glab login: it can’t show discussions or what’s waiting on you, or let you write.
  • Checks are the head pipeline’s jobs (allowed failures and manual jobs don’t count). A failed pipeline on your merge request offers Rerun.
  • Approve approves. Request changes posts your text as a comment, because GitLab’s API can’t set a reviewer’s state. Merge styles are merge and squash.
  • GitLab issues aren’t shown.

Arugula uses your tea login, run with your shell’s environment. The token stays in memory and is never written to the block’s config or log. The remote’s host picks the login; when more than one could fit, the block lists them so you can pick, and keeps your pick.

Forgejo has no API to rerun checks, so a failed check links to its run.

Live updates let a block read a change the moment it happens instead of polling. The machine’s owner turns them on with Live updates on a block: Arugula then creates a webhook on the repository with your login, pointed at this machine’s tailnet address, with a secret made on the machine. The forge must reach the machine over your tailnet; if the webhook goes quiet, the block goes back to polling. Stop live updates removes the webhook. The block’s footer says live or polling, and why.

Without live updates, a block polls every few seconds while you look at it or it wants you, and every few minutes otherwise.

Arugula shows GitHub and Forgejo issues with their labels, assignees, the pull requests that refer to them, and their timeline. Open one with Open beside › Open issue… in a pane’s menu, Open issue… in the + button’s menu, + Pane › Issue (Issue in the phone’s sheet), a link in a terminal, or arugula issue {N | OWNER/REPO#N | URL}.

When an issue needs you: an open issue was assigned to you, or someone mentioned you, since you last looked; or an issue assigned to you was closed (you’re notified once).

Agent on this (or arugula issue agent %N) starts an agent on the issue:

  • Arugula makes a branch i{N}-{slug} off the repository’s default branch, fetched fresh, in a worktree of its own. The branch has no upstream, so a bare git push can’t push to main by mistake.
  • The issue moves to a tab of its own, and Claude Code (or Codex) starts beside it in the worktree with the issue as its prompt, told to open a pull request that closes it.
  • The issue’s title and text are marked as written by the issue’s author, to read as a description and not to follow as instructions. The agent starts with nothing allowed ahead of time, so what it wants to do comes to you as a card first. With instructions… adds your own words to the prompt.
  • When a pull request from that branch appears, it opens beside the agent.

New issues and comments:

Terminal window
arugula issue new -t "Frobs leak" -b "…" # in a clone, or with --repo
arugula issue comment %8 "On it"

Run by an agent, both are drafts that a person sends.