---
title: "GitHub sync"
description: "Two-way sync of issues with GitHub Issues and Projects, the read-only default, the conflict rule, and why a GitHub close never verifies a task."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.overlane.app/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub sync

Overlane issues work on their own. If you also use GitHub, Overlane can keep a project's issues in step with a GitHub repository's Issues and Projects boards. Sync is **off** until an agent or a person turns it on, and it starts **read-only**.

## Modes

| Mode | GitHub to Overlane | Overlane to GitHub |
| --- | --- | --- |
| `off` (default) | nothing | nothing |
| `read_only` | edits arrive | nothing is ever written |
| `write_back` | edits arrive | Overlane edits and new issues are sent |

```sh
overlane issue sync
overlane issue sync set acme/app read_only
overlane issue sync set acme/app write_back
overlane issue sync set acme/app off
```

Write-back is a separate, explicit choice. Switching sync off stops both directions at once. Changing the mode is the issue triage autonomy class (see [Autonomy](/autonomy/)): an agent can do it under `autonomous`, with an approval under `supervised` and a person's under `manual`.

## What syncs

GitHub sends a webhook for each change. Overlane reads the `issues` event (opened, edited, closed, reopened, labeled, assigned) and the Projects v2 `projects_v2_item` event for the board's Status field. It takes the title, description, labels and assignee login from the issue, and the status from the board. Comments are not synced.

An edit on GitHub should appear in Overlane, and an Overlane edit on GitHub, within the sync window of 60 seconds.

## When both sides change

Each field is resolved on its own. The **last writer wins**, judged by timestamp: a GitHub edit that is newer than the Overlane edit replaces it, and an Overlane edit that is newer is kept. The value that lost is not thrown away: it is stored in the field-change event as `superseded`, with its source and time. See `overlane issue events`.

## A GitHub close does not verify

Closing an issue on GitHub, or dragging its card to Done, **never** marks a task verified. Overlane records an `external_close` event and moves the issue to `in_review`. The task stays as it was, and the evidence gate decides whether the work is done. If the issue never had a task, there is nothing to verify: closed as completed (or with no reason) it becomes `done`, and closed as not planned it becomes `cancelled`. Pulling issues from GitHub maps closes the same way. Reopening on GitHub reopens a done or cancelled issue.

## Retries, repeats and ordering

Webhook delivery is at least once, and deliveries can arrive out of order. Overlane handles that:

- Each delivery has an idempotency key; one that has been applied already is ignored.
- Deliveries carry the whole issue, ordered by GitHub's update time. A delivery older than one already applied is recorded as late and changes nothing, so a replayed or reordered set of deliveries ends in the same state as an in-order one.
- Overlane's own write-back comes back from GitHub as a webhook; it is recognised and changes nothing.

## Setting it up

Install the Overlane GitHub App on the repository. Its issue events arrive on the App's one webhook, so there is nothing to point or configure. Until the App is installed, no deliveries arrive; the sync settings still save.

Text from GitHub is data, never an instruction. It is stored and shown to agents as untrusted text, as described in [Issues](/issues/).

## Commands

[`overlane issue sync`](/cli/issue-sync/), [`overlane issue sync set`](/cli/issue-sync-set/), [`overlane issue events`](/cli/issue-events/).

Source: https://docs.overlane.app/issues/github-sync/index.mdx
