Skip to main content

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.

Lettuce can pull repos directly from GitHub through a GitHub App that your operator (the team running the Lettuce backend) installs once on their GitHub organisation. Users in your account then install that App on their own GitHub account/org, pick repos from a list, and Lettuce indexes them plus wires up auto-refresh webhooks — no copy-pasting URLs or webhook secrets. The manual “paste a git URL” flow keeps working alongside this — use it for public repos hosted anywhere git speaks.
There are two audiences here. Operators (you self-host Lettuce) do the one-time GitHub App setup. Users (you sign in to Lettuce on the web) just click Add via GitHub and pick repos.

For operators — one-time setup

You only do this once per Lettuce deployment.
1

Create a new GitHub App

Open https://github.com/settings/apps/new (or, for an org-owned App, https://github.com/organizations/<your-org>/settings/apps/new).Fill in:
  • GitHub App name: Lettuce (must be globally unique — try Lettuce - acme if Lettuce is taken). Whatever you choose, the slug in the URL of the App’s settings page is what you’ll paste into GITHUB_APP_NAME below.
  • Homepage URL: your Lettuce public URL, e.g. https://diet.uselettuce.dev.
  • Callback URL: https://<your-lettuce-host>/v1/integrations/github/callback — Lettuce verifies an HMAC-signed state param here, so the URL must be exact. Tick Redirect on update.
  • Setup URL (optional): same as Callback URL. Tick Redirect on update.
  • Webhook:
    • Set Webhook URL to anything (e.g. https://example.com/unused) and untick Active. Lettuce wires webhooks per-repo at add-time using a per-account secret; the App-level webhook is intentionally unused.
    • You can also enable Active and point it at the same URL — Lettuce only reads repo-scoped deliveries so the App-level hook is harmless.
2

Permissions and events

Under Repository permissions:
  • Contents: Read-only (needed to clone)
  • Metadata: Read-only (mandatory baseline)
  • Webhooks: Read and write (so Lettuce can install a hook per repo)
Leave all Organization permissions unset.Under Subscribe to events: nothing. The per-repo webhooks Lettuce creates subscribe to push directly.
3

Where can this GitHub App be installed?

Choose Any account so your users can install it on their personal accounts or their orgs. Leave it as Only on this account if you only want internal users.
4

Create the App

Click Create GitHub App. GitHub redirects you to the App’s settings.
5

Generate a private key

Scroll to Private keysGenerate a private key. A .pem file downloads. Keep this file safe — Lettuce signs short-lived installation tokens with it on every clone.
6

Note the App ID and Client ID, generate a Client secret

On the App settings page:
  • Copy the App ID (numeric, near the top).
  • Copy the Client ID.
  • Click Generate a new client secret and copy the value — you can only see it once.
7

Set env vars on the Lettuce backend

# Required
GITHUB_APP_ID=123456
GITHUB_APP_NAME=lettuce            # the slug in https://github.com/apps/<slug>
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIE...
-----END RSA PRIVATE KEY-----"

# Optional, only needed if you later add OAuth-style user auth
GITHUB_APP_CLIENT_ID=Iv1.abcdef...
GITHUB_APP_CLIENT_SECRET=...
Notes:
  • GITHUB_APP_PRIVATE_KEY is the full PEM contents, newlines and all. Most platforms accept multiline env vars; on Render set it as a secret file or use \n escapes in a single-line value.
  • GITHUB_APP_NAME is the App’s slug, not its display name. If your App’s URL is https://github.com/apps/lettuce-prod, the slug is lettuce-prod.
  • CODEWAZE_PUBLIC_URL must already be set on the backend to a URL that GitHub can reach — the Callback URL above is built from it.
8

Restart the backend

Lettuce reads the env vars at request time, so a rolling restart is enough. On the next request, GET /v1/integrations reports available.github: true and the “Add via GitHub” button appears in every user’s Add-repo dialog.

How the security model works

  • The App’s private key lives only in GITHUB_APP_PRIVATE_KEY on the backend. It is never written to the database.
  • When Lettuce needs to clone or call the GitHub API for an account, it mints a fresh installation access token (≈1 hour TTL) from the App JWT. The token is held in memory for the duration of the request and discarded.
  • The OAuth-style state param on the install callback is an HMAC of (account_id, provider, timestamp, nonce) signed with the backend’s admin token. This binds the install to the account that started it — even though GitHub’s redirect carries no session cookie.
  • The webhook secret is per-account, stored in accounts.webhook_secret, and reused across every repo the account adds. Rotating it via POST /v1/account/webhook/rotate invalidates every existing GitHub webhook for that account.

For users — connect GitHub and add repos

This is what users see in the Lettuce UI once the operator has set up the App above.
1

Open the Repos page

Sign in to Lettuce, go to Repos, click + Add repo.
2

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 organisation you have admin rights on.
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.
3

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.
4

(Optional) Add more 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 → SettingsIntegrationsApplications → find Lettuce → ConfigureRepository access.

Disconnecting

Owners can disconnect the GitHub install from the Lettuce side at DELETE /v1/integrations/github (a UI button is on the roadmap). Disconnecting:
  • Removes the provider_installations row.
  • 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, uninstall the App on the GitHub side too: GitHub Settings → Integrations → Applications → Lettuce → Uninstall.

Troubleshooting

The operator hasn’t set the four GITHUB_APP_* env vars (or the backend hasn’t been restarted since). GET /v1/integrations returns available.github: false in that state.
The signed state param is older than 15 minutes, or the backend’s admin token has rotated since you started the install. Restart the install from the Add-repo dialog.
Check the Recent ingestion jobs section on the Repos page — failed clones surface the underlying git error there. Common cases: the user who installed the App didn’t grant access to that repo (re-configure the install on GitHub), or the operator’s backend can’t reach github.com.
The auto-webhook step may have failed if the installer didn’t have Webhooks: read-and-write on the repo. Use Automatic refresh on the Repos page — it shows the per-account webhook URL + secret you can paste into the repo’s Settings → Webhooks manually.

What’s next

GitLab and Bitbucket integrations land in the next two Lettuce releases — same shape: operator-side OAuth app, user-side one-click install, auto- webhooks. Until then, paste your GitLab/Bitbucket git URL on the Other (paste URL) tab.