Land a change
Landing publishes a change. Mend commits what the worktree holds, pushes it to a branch on the project’s origin, and opens or updates a GitHub pull request into the session’s base branch. Landing again after more work adds commits to the same branch and updates the same pull request. Merging stays on GitHub. Mend never merges, never force-pushes, and never says a change is ready to merge.
Landing is optional. You can review a change, send comments back, and pull it into your own clone without ever landing it.
What a landing does
Section titled “What a landing does”A landing runs four steps in order and stops at the first one that fails.
-
Mend takes a checkpoint of the worktree, so what lands is a recorded object and not a tree the agent may still be writing. This is the landed checkpoint.
-
Mend commits what the agent left uncommitted. The agent’s own commits are pushed as they are, and Mend squashes and rewrites nothing. Mend’s commit,
Mbelow, has the checkpoint’s tree:agent committed everything main ── A1 ── A2 Mend adds nothingagent committed some of it main ── A1 ── A2 ── M M holds only the leftoversagent committed nothing main ── M M holds the whole changeThe author of
Mis the change’s owner. Its message comes from the tour’s summary when a tour exists, or from the session’s label, and ends with aMend-Session:trailer that links to the session. On later landingsMis parented on the last landed commit, and on the agent’s head too when the agent committed since, so every push is a fast-forward. -
Mend pushes to origin with the project’s git access and the change owner’s key. The push only fast-forwards. If origin’s branch has commits Mend has not seen, or origin refuses the push for any other reason, nothing is pushed and Mend reports the remote’s own words.
-
When origin is on github.com, Mend opens a pull request into the session’s base branch, or updates the one it opened or adopted before. For any other origin the push happens and the pull request step says why it did not run, for example
pull request unavailable · origin is on gitlab.com, not GitHub.
Mend never moves the session’s branch. mend/<name> in the store, and the worktree’s files, index,
and HEAD, stay where the agent left them. Mend’s commit is kept under refs/mend/landed/<worktree>,
never under refs/heads.
When nothing is new since the last landing, Mend pushes nothing, records nothing, and says
landing not started · nothing new since the last landing. A landing whose pull request step
failed, or one given a new title or description, still goes ahead.
The branch on origin
Section titled “The branch on origin”Unless you name a branch, the landing pushes to the first of these that applies:
- the branch the change’s last landing pushed;
- the branch the agent last pushed itself;
- the head branch of a pull request opened outside Mend;
- the worktree’s own branch,
mend/<worktree>.
The branch is never the project’s default branch or the pull request’s base. Naming one of those is
refused with landing not started · <branch> is the project's default branch · name another branch.
The pull request
Section titled “The pull request”The pull request step needs the change owner’s GitHub account, connected with mend connect github
(see provider accounts). The token stays on the
platform and in workspaces, so Mend runs gh in a workspace:
- in the session’s own workspace when it is live and belongs to the change’s owner;
- otherwise in a short-lived workspace with the owner’s GitHub account and nothing else: no
worktree, no dotfiles, no secrets. Mend stops it when
ghreturns.
The short-lived workspace adds workspace start time to the landing. It mounts an empty directory from the Mend host, so a workspace runtime that accepts no host mounts refuses it. The push has already happened by then, and the landing records the platform’s refusal as the pull request step’s failure.
The title defaults to the session’s label. A title edited on GitHub is kept on later updates. The
description is Mend’s section between <!-- mend:landing:start --> and <!-- mend:landing:end -->:
the tour’s summary and approach, the changed files with their line counts, and links to the session,
the review, and the landed checkpoint. An update replaces only that section, so text people wrote
above or below it on GitHub survives. When no tour exists yet, the pull request opens with the file
list and the links, Mend queues the tour, and the description gains it when the tour completes.
Who lands
Section titled “Who lands”Only the change’s owner lands it. The change’s owner is the owner of the worktree’s first session,
the one that started the change. A teammate who starts a session in that worktree later, steers it
under shared control, or is an organization owner cannot land it. The push uses the owner’s key,
Mend’s commit is authored as the owner, and gh speaks on GitHub as the owner, so no one else can
publish as them.
Anyone who can see the project can see the landing record and the observed facts.
Land from the web
Section titled “Land from the web”The change’s review page has a Land panel. The session page links to it with Land → (or
Landing → for someone other than the owner) beside its latest landing fact.
The panel’s header says where the change goes, for example
push mend/fix-login to origin · pull request into main. Below it are the observed facts, or
not landed · nothing pushed from Mend yet.
For the change’s owner, the panel has Pull request title, Your description (written above Mend’s
section), Preview description, and one button:
Push and open pull requestfor the first landing on GitHub;Push and update pull requestonce there is an open pull request to update;Push to originwhen origin is not on GitHub, or when the change’s pull request is from a fork.
Everyone else sees only the change's owner lands it.
The panel also has:
Check origin, which fetches origin’s branch with your git access and compares it with the landed commit;Check GitHub, for the owner, which looks for a pull request opened outside Mend;Refresh pull request, for the owner, which asks GitHub for the pull request’s state now;Open #412 on GitHub ↗.
Mend does not poll GitHub. A pull request’s state is as fresh as the last landing, refresh, or check.
Land from the CLI
Section titled “Land from the CLI”mend land <session> [--branch <name>] [--no-pr] [--title <text>] [--project <p>]mend land <session> --check [--project <p>]<session> is a prefix of the session id or the worktree’s name. Settled sessions count.
# push mend/fix-login and open its pull requestmend land fix-login
# push only, to another branchmend land 3f2a --no-pr --branch wip/login
# set the pull request's titlemend land fix-login --title "Retry the login request once on a 502"The command prints the landing, what it wrote, and every fact Mend observed:
✓ pushed · mend/fix-login · 3f2a1c0 · pull request #412 · opened checkpoint 91bd2e4 commit 3f2a1c0 · Mend's, for the work left uncommitted pull request https://github.com/acme/web/pull/412 observed pushed · mend/fix-login · 3f2a1c0 · observed pull request #412 · open · observed 0 s agoIt exits 1 when the push was refused or a step failed.
What Mend reports
Section titled “What Mend reports”Landing facts are observations, with where Mend saw them. The web, the CLI, the desktop app, and Slack use the same lines:
pushed · mend/fix-login · 3f2a1c0 · observedpull request #412 · open · observed 2 min agopull request #412 · merged · observed 1 h agoorigin has moved · mend/fix-login has 2 commits Mend has not seenchanged since landing · 3 filespush refused · mend/fix-login · <the remote's words>landing failed · <what stopped it>pull request step failed · <gh's words>pushed by the agent · refs/heads/wip · 91bd2e4changes not landed · the request read as a questionintent not readA pull request’s state is open, closed, or merged, as gh last reported it. Pushes the agent
made itself, through the workspace’s git transport, are shown beside Mend’s landings and are not
landings. Failures do not retry. The next completed turn or a manual landing tries again.
Automatic landing
Section titled “Automatic landing”With automatic landing on, Mend lands the change after each completed turn whose request asked for a change. The first landing opens the pull request and later ones update it.
When it is on
Section titled “When it is on”-
A session started from the web, the CLI, or the desktop app follows its project’s
Land when a turn completessetting, which isinherit,on, oroff.inheritfollows the default in Settings, which is off unless an operator or organization owner turned it on. -
A session can override the project when it starts. The web composer’s menu has
Land when a turn completeswithAs the project,Land, andDo not land. The CLI has--landand--no-land:Terminal window mend claude "fix the flaky login test" --land -
A session started from Slack lands automatically when the Slack app’s
Land automaticallysetting is on, which it is by default.autopr=trueorautopr=falsein the request decides for that request. See Slack. -
A project set to
offwins over everything: the composer,--land, the Slack setting, andautopr=true.
Mend lands only after turns it runs itself. A terminal session, where mend codex or mend claude
attaches the agent to your terminal, has no turns Mend sees end, so it never lands by itself. It
does once the session is picked up as a conversation, on the phone for example. Until then, land it
with mend land or the Land panel.
When a completed turn lands
Section titled “When a completed turn lands”Mend checks these in order, and all must hold:
- The turn completed. A turn that failed, was interrupted, or was cancelled never lands.
- The agent is not waiting on a question or an approval, and no later turn follows.
- The change’s owner sent the turn, in a session they own. A follow-up someone else sent under shared control does not land, and neither does a turn in a session a teammate started in the owner’s worktree. Review comments sent back to a session count as sent by whoever sent them.
- The change is not empty, and it is not what the last landing already pushed.
- The request asked for a change.
Questions do not open pull requests
Section titled “Questions do not open pull requests”Mend guards the last check twice. First, the opening turn of every Slack request and of any session with automatic landing on carries these instructions after the request:
--- How this work is published ---Mend publishes the changes this session makes: it pushes the branch and opens or updates the pull request.- If the request is a question, answer it and change no files.- Change code only when the request asks for a change.- Never push and never open a pull request. Committing is fine.--- End of how this work is published ---Second, Mend uses inference to read each request as a change or a question. For Slack this is the
same call that picks the thread’s project. Web and CLI sessions with automatic landing on make one
small call per turn. autopr=true reads as a change and autopr=false as a question, without a
call. A later request that asks for a change lands, even if the first one was a question.
When a question still left files changed, Mend does not land it and says
changes not landed · the request read as a question. The Land panel then notes that a completed
turn left changes Mend did not land, and in Slack the reply carries a Push and open pull request
button that acts only for the change’s owner.
When the request could not be read, because inference is off or over its budget, Mend treats it as a
change and reports intent not read beside the landing.
Pull requests opened outside Mend
Section titled “Pull requests opened outside Mend”The agent may push a branch and open a pull request itself, despite the instructions, or a person may open one by hand. Mend adopts that pull request instead of opening a second one. It asks GitHub, as the change’s owner, about the worktree’s branch, every branch the agent pushed to origin, and any pull request that holds the agent’s head commit, including one from a fork.
Mend looks:
- 45 seconds after the agent pushes a branch through the workspace’s git transport;
- when an agent ends while its workspace is still up;
- when the owner presses
Check GitHubor runsmend land <session> --check.
The first two use only a live workspace of the owner’s. An adopted pull request reads
pull request #368 · open · observed 2 min ago · opened outside Mend, and the next landing pushes
to its branch and updates it.
A pull request from a fork is shown and never updated, because Mend pushes to origin only:
pull request #367 · open · observed 2 min ago · opened outside Mend · from anna's forkWhile it is open, the Land button reads Push to origin and the landing skips its pull request
step, saying pull request #367 is from anna's fork · Mend pushes to origin only.
Removing a landed worktree
Section titled “Removing a landed worktree”Removing a worktree refuses when its change is not on origin, and names what is unlanded:
This worktree holds a change that was never landed · 2 files · +32 −5 · src/login.ts +30 −5, test/login.test.ts +2 −0. Land it or discard it before removal, or pass force=true to remove it anyway.A worktree that changed after its last landing is refused the same way, naming the files changed since.
A worktree is removable without force when it holds nothing past its base, or when its latest landing’s checkpoint is what it holds and either the pull request was last reported merged or origin’s branch still has the landed commit. A merged pull request counts even after its branch was deleted, because a squash merge leaves no ancestry to fetch. Mend fetches origin’s branch with your git access to check.
Pull a change into your own clone
Section titled “Pull a change into your own clone”mend pull fetches a session’s change into a local clone of the same repository, as a branch named
after the session’s branch:
cd ~/src/webmend pull fix-logingit switch mend/fix-login✓ fetched mend/fix-login · 3f2a1c0 · 2 commits on 9e11c4a · created 3f2a1c0 Retry the login request once on a 502 b71d02e Add a failing test for the 502 case switch to it git switch mend/fix-loginThe CLI downloads a git bundle with the commits from the session’s base to the latest checkpoint. Uncommitted work is committed the way a landing commits it, without pushing. So pulling works before landing, without origin, and for projects nobody can push to.
- Pulling moves nothing on the server and writes no branch there. When the change’s owner pulls, Mend takes a checkpoint first. Anyone else gets the latest checkpoint that already exists.
- Your working tree, index, and current branch are not touched. An existing local branch of the same name only fast-forwards.
- The clone needs the session’s base commit, so fetch from origin first when it is missing.
- One of the clone’s remotes must be the project’s origin, compared by host and path so SSH and
HTTPS spellings match.
--forceskips that check. - A bundle over the server’s limit (
MEND_BUDGET_BUNDLE_BYTES, 64 MiB by default) is refused with its size, and nothing is fetched.
Where landing is not available
Section titled “Where landing is not available”The mobile app and the VS Code extension show no landing facts and cannot land. A project whose origin is not on GitHub gets the push and no pull request. GitLab and other hosts are not supported for the pull request step.