For the complete documentation index, see llms.txt. This page is also available as Markdown.

PR/MR Comments Reference

Reference for the /lunar commands Lunar accepts as comments on pull requests and merge requests, and what each one does to the merge gate.

Lunar watches the comments of GitHub pull requests and GitLab merge requests for commands addressed to it. They operate the merge gate's break-glass from the thread: one command overrides a block, the other takes the override back.

Two rules hold for every command:

  • The command must start the comment. A mention mid-sentence ("we could /lunar bypass this") is conversation, and Lunar ignores it.

  • Lunar answers a command it recognizes. An honored one is confirmed, and a refused one is answered with the reason rather than ignored. GitLab replies inside the command's discussion; GitHub posts a new comment on the Conversation tab, since a reply is audit evidence and is never edited afterwards.

A command on a request Lunar does not govern gets no reply at all: an untracked repository, or a request whose target branch matches no component. This is deliberate, because one repository can carry webhooks for several Hubs, but from the thread it looks the same as a dropped command. When a command fails covers the other reason a thread stays silent.

Availability

  • GitHub: any pull request where the Earthly Lunar check run reports. Whether that check blocks the merge is your branch-protection setting; the commands behave the same either way. Write the command as a plain comment in the Conversation tab, since comments inside a review, on a diff line or in the review summary, do not reach Lunar.

  • GitLab: merge requests on any project Lunar tracks, on every tier. The commands operate whichever merge gate the project has, the external status check on Ultimate and the Earthly Lunar commit status on Free and Premium. As on GitHub, whether that signal blocks the merge is your setting (Pipelines must succeed, in the commit-status case), and the commands behave the same either way.

The grammar is identical on both platforms, so the phrase an engineer types does not depend on where the repository lives. Only the authorizing role differs, and each command below spells it out.

/lunar bypass

  • Form:

    /lunar bypass: <reason>

Overrides the merge gate for the request's current head commit. Lunar flips its signal to passing (the check run on GitHub, and on GitLab the external status check or, where the tier has none, the commit status), records the override on the audit ledger, and replies confirming who bypassed, which commit it covers, and why. To customize that reply, set customization.bypass_template.

Lunar also refreshes the results comment, so it stops listing the bypassed checks as failing and credits the override instead. The refresh re-posts the results already stored for the commit rather than re-running the policies, so it needs neither a push nor a fresh evaluation. A commit Lunar has never evaluated has nothing stored to re-post and gets a full evaluation, which is slower.

<reason>

  • Required

Why the gate is being overridden, recorded verbatim on the ledger. It may span multiple lines. A comment without one (/lunar bypass alone, or /lunar bypass: with nothing after it) is refused with usage guidance.

Authorization

The comment is held to the same permission as the CLI commands, bypasses.manage, checked against the commenter's role on the request's repository.

Platform
Required role by default

GitHub

maintain or admin on the repository

GitLab

Maintainer or above on the project

Setting bypasses.manage under authorization in lunar-config.yml moves this bar for comments and CLI alike: raise it to admin / Owner so only administrators can override a gate, or lower it to write / Developer so any committer can. The refusal reply names the role the Hub applied.

These are the platforms' own roles. Lunar checks them with the platform when the comment arrives and has no role system of its own, so you grant them as usual: collaborator and team settings on a GitHub repository, project or inherited group membership on GitLab. GitHub computes the role across repository, team, organization, and enterprise grants; a custom role qualifies when its base permissions reach the required role, and is recorded under its own name. On older GitHub Enterprise Server versions that do not report a role name, maintain and plain write arrive as the same value and are read as write, so at the default bar only admin qualifies there.

The configuration repository administrator rule does not reach the thread: a comment is authorized on the request's own repository only.

The role that authorized the bypass is recorded with it, provider-qualified: github:admin, gitlab:maintainer, and so on.

The request's own author may bypass: a self-bypass is allowed, and recorded as such.

Scope

A bypass covers one commit: pushing again re-blocks the request and needs a fresh bypass. Unlike a CLI bypass it carries no expiry; for a time-bound override, use lunar policy bypass-pr from the CLI, which clears the same gate. The state of the check does not matter: a check stuck pending, one that reads an error, and one that never appeared are all concluded passing the same way a failing one is.

A bypass is for one commit or one window. If a policy should not apply to a component at all, narrow the policy's on expression in lunar-config.yml instead, for example on: "domain:engineering AND NOT component:github.com/foo/bar".

Audit trail

Every bypass lands on the same ledger the CLI bypass commands write: who, their verified role, the reason, the commit, and whether it was a self-bypass. A comment-driven override therefore shows up in lunar policy bypass-ls, can be ended early with /lunar bypass rm or lunar policy bypass-rm, records what it actually masked when the pull or merge request merges, and is queryable over the SQL API alongside every other override.

/lunar bypass rm

  • Form:

Withdraws the overrides granted by /lunar bypass comments on the same request, without leaving the thread. Lunar re-arms the gate for the current commit, confirms with a reply, and refreshes the results the same way a grant does. If the request has no comment-driven bypass to withdraw, Lunar says so instead. To customize the reply, set customization.bypass_revocation_template.

<reason>

  • Optional

Why the override is being taken back. It appears in the confirmation reply; the ledger keeps the reason the bypass was granted with either way.

Authorization

Revoking is held to the same bar as granting (bypasses.manage: maintain or admin on GitHub and Maintainer or above on GitLab by default), so nobody below that bar can re-block a merge someone else authorized.

What it withdraws

Only the overrides made by /lunar bypass comments on this pull or merge request. Anything else is left alone:

  • A lunar policy bypass-pr made from the CLI records an intent formed outside the thread, usually with an expiry. Withdraw it with lunar policy bypass-rm where it was made.

  • Comment bypasses on other requests, and component-wide bypasses, are untouched.

The gate afterwards

The check reports pending, not failed. Lunar cannot recompute the verdict at the moment you revoke, so it reports that it has no current verdict, which blocks the merge: the check run goes back to in progress on GitHub, the external status check goes to pending on GitLab Ultimate, and the commit status returns to running on the tiers below it. Revoking also refreshes the results, and that post settles the check, without a push.

Soft revoke

Revocation is the same soft revoke the CLI performs: the ledger row survives with the revoker and timestamp attached, and still appears in lunar policy bypass-ls without --active. A second rm on the same request finds nothing left to withdraw, and Lunar replies saying so.

When a command fails

Either command can fail before Lunar acts on it, most often because the Git platform is rate limiting Lunar and will not serve the pull or merge request. Lunar answers in the thread saying what went wrong: a GitHub rate limit names how long its window has left to run, and a GitLab one asks you to try again in a few minutes. Nothing was recorded and the gate is untouched, so comment the command again to retry.

The comment's webhook delivery can also be redelivered from the platform, which re-runs the command: Settings → Webhooks → Recent Deliveries on GitHub, where it shows as failed, or Settings → Webhooks → Recent events on GitLab.

An exhausted rate limit is the one failure that cannot announce itself, since posting a reply spends the same budget the command just failed on. If a command gets no reply at all, check lunar policy bypass-ls to see whether the override was recorded before commenting it again.

Last updated