> ## Documentation Index
> Fetch the complete documentation index at: https://recipe.uselettuce.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub

> Connect your organization's GitHub repos to Lettuce — install the Lettuce GitHub App, pick repos, push webhooks wired automatically.

Lettuce pulls repos directly from GitHub through the **Lettuce GitHub App**.
As the org admin connecting your team to Lettuce, you install the App on
your GitHub organization (or personal account), authorize the repos you
want indexed, and Lettuce takes care of cloning them plus wiring up
push-event webhooks so future commits trigger a re-index.

The manual "paste a git URL" flow keeps working alongside this — use it for
public repos hosted anywhere git speaks.

<Note>
  **This page is for the admin connecting your org to Lettuce Cloud.** If
  you're standing up a self-hosted Lettuce install for your team, the
  one-time GitHub App registration that backs this flow is documented in
  [Self-hosted install §5](/self-hosted/install#5-register-your-github-app).
</Note>

## Connect GitHub and add repos

<Steps>
  <Step title="Open the Repos page">
    Sign in to Lettuce, go to **Repos**, click **+ Add repo**.
  </Step>

  <Step title="Install the Lettuce GitHub App">
    On the **GitHub** tab, click **Install GitHub App →**. You're redirected
    to GitHub.

    Choose where to install the App:

    * Your personal account, or
    * An organization you have admin rights on. (If your GitHub org
      requires owner approval for third-party Apps, you'll need to
      request access from a GitHub org owner first — see the GitHub
      docs on [Approving an application](https://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/approving-oauth-apps-for-your-organization).)

    Then choose either **All repositories** (lets you add any of them
    later without coming back to GitHub) or **Only select repositories**
    (pick a short list now).

    Click **Install**. GitHub redirects you back to Lettuce.
  </Step>

  <Step title="Pick a repo">
    You land back on **Repos** with a green toast — "GitHub connected".
    The Add-repo dialog now lists every repo the install can see; filter by
    `owner/repo` substring, then click one.

    Lettuce:

    1. Registers the repo against your account.
    2. Auto-creates a webhook on it (push events) so future commits trigger
       a re-index.
    3. Queues a clone + index job. Status moves from *pending* to *indexing*
       to *ready* — usually in a few seconds for small repos.

    No copy-pasting URLs, no fiddling with webhook secrets.
  </Step>

  <Step title="(Optional) Grant access to more repos later">
    The dialog remembers your install — re-open it any time to add another
    repo. If you later need to grant access to additional repos, go to
    your GitHub account/org → **Settings** → **Integrations** →
    **Applications** → find Lettuce → **Configure** → **Repository access**.
  </Step>
</Steps>

## What Lettuce asks for, and why

The Lettuce GitHub App requests the minimum scopes to clone your repos
and keep them current:

| Permission            | Access       | Why                                                    |
| --------------------- | ------------ | ------------------------------------------------------ |
| Repository — Contents | Read         | Clone the repo to build its index.                     |
| Repository — Metadata | Read         | List the repos visible to the install.                 |
| Repository — Webhooks | Read & write | Register a per-account push hook on each repo you add. |

Lettuce never asks for write access to your code. We do not push
commits.

## How the security model works

* Lettuce mints a fresh, short-lived **installation access token**
  (≈1 hour TTL) for each clone, then discards it. There is no long-lived
  user token stored against your account.
* The OAuth-style **`state`** param on the install callback is signed
  with HMAC and bound to the Lettuce account that started the install,
  so a redirect can't be replayed against a different account.
* The **webhook secret** is per-account, generated automatically the
  first time you add a repo, and reused across every repo you add. You
  can rotate it from **Settings → Webhook** in the Lettuce dashboard;
  rotation invalidates every existing GitHub webhook for your account
  and re-registers them with the new secret.

## Disconnecting

Owners can disconnect the GitHub install from the Lettuce side under
**Settings → Connected integrations** (or via the `DELETE
/v1/integrations/github` API). Disconnecting:

* Removes the GitHub install from your Lettuce account.
* Leaves all your existing repos in place — they keep working as long as
  they're public. Private repos will fail their next re-clone until you
  reconnect or switch them to a paste-URL with credentials.

To fully revoke access, also uninstall the App on the GitHub side:
**GitHub Settings → Integrations → Applications → Lettuce → Uninstall**.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The 'Add via GitHub' button is greyed out / missing">
    On Lettuce Cloud the GitHub App is always available — if you see
    this state, refresh the page and re-open the Add-repo dialog. On a
    self-hosted Lettuce install, this means your admin hasn't
    finished the App registration; see the self-hosted admin note
    below.
  </Accordion>

  <Accordion title="GitHub redirects me back with 'invalid or expired install state'">
    The signed `state` param is older than 15 minutes. Restart the
    install from the Add-repo dialog.
  </Accordion>

  <Accordion title="A repo I just added is stuck on 'pending'">
    Check the **Recent ingestion jobs** section on the Repos page — failed
    clones surface the underlying git error there. Most common cause: the
    repo wasn't included when you authorized the App. Go to your GitHub
    org → **Settings → Integrations → Applications → Lettuce →
    Configure → Repository access** and grant access to that repo.
  </Accordion>

  <Accordion title="My private repo clones but later pushes don't trigger a refresh">
    The auto-webhook step may have failed if the user who installed the
    Lettuce App didn't have admin rights on that specific repo. On the
    Lettuce repo page, the **Manual webhook setup** card shows the
    per-account webhook URL and secret you can paste into the repo's
    **Settings → Webhooks** manually.
  </Accordion>

  <Accordion title="My GitHub org owner has to approve the Lettuce App">
    Some GitHub orgs require an owner to pre-approve third-party Apps.
    If you don't have owner rights, click **Install** anyway — GitHub
    shows a *Request approval* link that emails the owner. Once they
    approve, come back to Lettuce and re-open the Add-repo dialog.
  </Accordion>
</AccordionGroup>

<Note>
  **Self-hosted admin note.** The end-user flow above only works once
  the Lettuce GitHub App has been registered against the GitHub instance
  you're indexing. On Lettuce Cloud, the Lettuce team has done this for
  you. On a self-hosted install, your admin registers the App once
  and points the worker / api pods at it via the `GITHUB_APP_*` env
  vars — full runbook in
  [Self-hosted install §5](/self-hosted/install#5-register-your-github-app).
  GitHub Enterprise Server is supported there with a `GITHUB_HOST`
  override.
</Note>
