Connecting GitHub
Moʻolelo indexes issues and pull requests from the repositories you list. It uses GitHub's REST API for backfill and webhooks for steady-state.
Prerequisites
- A GitHub account with
reposcope on the repositories you want indexed. - The repositories' webhook secret (you'll generate this when you register the webhook).
- Network reachability: Moʻolelo's webhook endpoint must be reachable from GitHub's webhook IP ranges (or you set up a self-hosted GitHub Enterprise webhook delivery).
Step 1 — generate a Personal Access Token
A fine-grained PAT scoped to the repositories you want indexed is sufficient. The PAT needs Issues: read and Pull requests: read permissions.
For a deployment that watches many repositories, a GitHub App is more manageable; the configuration shape is the same in either case (you store the access token in the connector configuration).
Step 2 — register the connector
Insert a row into connector_configs:
INSERT INTO connector_configs
(tenant_id, source, instance, mode, resources, raw_config)
VALUES (
'default', -- your tenant id
'github', -- the source identifier
'acme', -- your GitHub org name (the "instance")
'backfill', -- start with backfill
'["acme/wiki", "acme/handbook"]'::jsonb, -- repositories to watch
'{
"api_base": "https://api.github.com",
"auth_token": "ghp_xxxxxxxxxxxx"
}'::jsonb
);Within milliseconds the connector starts walking the repositories' issues and pull requests. Progress is durable — if the backfill is interrupted, it resumes from the last record that landed in storage.
For GitHub Enterprise Server, set api_base to your enterprise URL (https://github.example.com/api/v3).
Step 3 — register the webhook on the GitHub side
Generate a strong random secret. On each repository's webhook settings page (or at the org level if you prefer one webhook per org), create a webhook with:
- Payload URL:
https://<your-moolelo-host>/webhooks/github/<instance> - Content type:
application/json - Secret: the random string you generated.
- Events: select "Issues", "Issue comments", and "Pull requests" — at minimum.
The same secret value goes into Moʻolelo's deployment as the WEBHOOK_INGRESS_GITHUB_SECRET environment variable on the webhook receiver. See Configuring webhooks for the details.
Step 4 — flip to webhook mode
Once the backfill completes (you'll see this in the operational logs as "backfill: done"), update the connector to webhook mode:
UPDATE connector_configs
SET mode = 'webhook'
WHERE tenant_id = 'default' AND source = 'github';The connector now waits for webhook deliveries instead of polling. If you ever need to recapture a missed period (for example after a network partition), insert a new tenant config row in backfill mode targeted at a specific repository — the connector will catch up without re-publishing already-indexed records.
What gets indexed
Per record, Moʻolelo indexes:
- Title — as a separate chunk, weighted higher in lexical scoring.
- Body — split into paragraph-sized chunks with their original heading path preserved as structural metadata.
- Author — for residency routing (if your tenant has subject-level residency configured).
- Source URL — for click-through from search results back to GitHub.
- Labels and assignees — surfaced as structured metadata.
What is not indexed today:
- Comments. (Coming in a later release; comments require a separate API walk during backfill.)
- Code in repository files. The walking-skeleton scope is structured records; full-codebase indexing arrives when your tenant turns it on.
- Wiki pages. GitHub wikis use a different API surface and aren't part of the issue/PR connector.
Permissions visible in search results
GitHub's permission model is simple: a record is visible to a user if and only if the user has read access to the repository. Moʻolelo extracts each indexed record's repository, checks the calling user's GitHub login against the repository's collaborators / team memberships, and filters accordingly.
When the calling user lacks GitHub read access on a repository, results from that repository do not appear in the response. There is no "preview" leakage of restricted record titles or snippets.
Troubleshooting
- No records appearing after the connector starts. Check that the PAT has
Issues: readandPull requests: readpermissions on at least one repository in theresourceslist. Hithttps://api.github.com/repos/<owner>/<name>/issuesdirectly with the same token to confirm. - Webhook deliveries 401-rejected. The secret on the GitHub webhook page does not match
WEBHOOK_INGRESS_GITHUB_SECRET. Re-paste the secret on the GitHub side and confirm. - Backfill loops without progress. Check Postgres for the connector cursor row in
connector_cursors. Ifupdated_atis stuck, the GitHub API is rate-limiting you — Moʻolelo automatically backs off and retries, but a heavily-rate-limited token may take hours to make progress.

