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

# GitHub

> Sync issues and pull requests into tables, link PRs to the records they name, and show live PR status on a record.

## What it does

GitHub connects to Custral three ways. They are independent: set up one, two, or all three.

| Surface                       | What you get                                                                              | Setup                                             |
| ----------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------- |
| **Linked tables**             | Issues and pull requests as ordinary Custral objects you can filter, group, and report on | Pick a repository, tick what to sync              |
| **Pull requests on a record** | A Development section on a record, listing every PR that names it                         | None, once the record's object has an ID property |
| **Live PR status**            | One PR's state resolved onto a property you add                                           | Add an External property, point it at a PR link   |

## Connect

<Steps>
  <Step title="Authorize in Custral">
    Open **Settings → Integrations → GitHub** and start the OAuth flow.
  </Step>

  <Step title="Review the access requested">
    Custral requests the `repo` scope, which GitHub grants as read **and** write across the repositories you authorize, plus `read:user` for your profile. `repo` is the narrowest scope GitHub offers that can read private repositories. There is no read-only equivalent. Authorize only the repositories you want Custral to see.
  </Step>

  <Step title="Confirm">
    The connection appears in the integrations list. It is workspace-wide: once anyone connects GitHub, everyone in the workspace can use all three surfaces.
  </Step>
</Steps>

## Linked tables

Syncs a repository's issues or pull requests into a Custral object, kept current by webhook.

<Steps>
  <Step title="Open the sync tab">
    **Settings → Integrations → GitHub → Sync Data**. The tab appears once the connection exists.
  </Step>

  <Step title="Pick a repository">
    The **Repository** picker lists every repo the connection can see, private ones marked.
  </Step>

  <Step title="Choose what to sync">
    Tick **Issues**, **Pull Requests**, or both, then press **Connect & Sync**.
  </Step>
</Steps>

Each one becomes an object named after the repo, for example `GitHub Pull Requests — acme/widgets`. It is a normal object: add your own columns, build views on it, filter and group it. The sync only ever writes the provider columns, so anything you add is yours and stays untouched.

### Columns

<Tabs>
  <Tab title="Pull Requests">
    | Column                     | Type    | Notes                      |
    | -------------------------- | ------- | -------------------------- |
    | Title                      | Text    | The record's name          |
    | Number                     | Number  |                            |
    | State                      | Select  | `open`, `closed`, `merged` |
    | Author                     | Text    | GitHub login               |
    | Base / Head                | Text    | Branch refs                |
    | Draft                      | Text    | `Yes` or `No`              |
    | Created / Updated / Merged | Date    |                            |
    | URL                        | Website |                            |
    | Body                       | Text    | The description            |
  </Tab>

  <Tab title="Issues">
    | Column                     | Type    | Notes             |
    | -------------------------- | ------- | ----------------- |
    | Title                      | Text    | The record's name |
    | Number                     | Number  |                   |
    | State                      | Select  | `open`, `closed`  |
    | Author                     | Text    | GitHub login      |
    | Assignees / Labels         | Text    | Comma separated   |
    | Comments                   | Number  |                   |
    | Created / Updated / Closed | Date    |                   |
    | URL                        | Website |                   |
    | Body                       | Text    | The description   |
  </Tab>
</Tabs>

A merged pull request reports `closed` at GitHub. Custral surfaces it as **merged**, so the three states you filter on are the three you would expect.

<Note>
  **State is a Select, so it filters by option rather than by text.** The three options are created with the table. Filtering by a state that no record holds returns nothing, which is the correct answer and not an error: a repo where every PR has merged genuinely has no open ones.
</Note>

## Pull requests on a record

Put a record's ID in a branch name, a PR title, or a PR description, and the pull request appears in that record's **Development** section. Nothing to configure.

### What it needs

The record's object needs an [ID property](/data/properties/text/id) whose **prefix is at least two characters**. That prefix is what Custral matches on.

<Warning>
  An ID property with a one-character prefix, or none at all, does not participate. A blank prefix would make the pattern "any run of digits", so every pull request with a number in its title would attach itself to some record. Give the property a real prefix such as `ISSUE-` or `TICKET-`.
</Warning>

### How the match works

* **Case and padding do not matter.** `issue-42`, `ISSUE-42`, and `ISSUE-00042` all find the record stored as `ISSUE-00042`.
* **A prefix only matches on a word boundary.** `MYISSUE-42` does not match `ISSUE-`, and neither does `ISSUE-42x`.
* **Branch, then title, then description.** All three are scanned, and the row records which one matched: a branch name is the most deliberate, a description the least.
* **One pull request can name several records**, and each gets its own row.
* **Renaming moves the link.** Change a title from `ISSUE-42` to `ISSUE-51` and the PR leaves the first record and joins the second.
* **An ambiguous reference is skipped.** If two objects use the same ID prefix and both hold a record with that value, Custral links neither rather than guessing. Give the two objects different prefixes.

### What you see

Each row shows the pull request's state, its title as a link, and the `owner/repo#number` reference with the author beside it. Hover the branch icon at the end of the row to see which text matched and where, for example "Matched ISSUE-00042 in the branch name". The section is absent on records with no pull requests, so it costs nothing on the rest of your workspace.

<Note>
  This is read-only. Custral never comments on, updates, or closes a pull request from a record.
</Note>

## Live PR status

An [External property](/data/properties/complex/external) resolving one pull request onto the record it sits on. Use it when a record tracks a single PR and you want its state in a column beside your own fields.

<Steps>
  <Step title="Add a property to hold the link">
    A **Text**, **Website**, or **ID** property on the record's object, holding the PR URL or `owner/repo#number`.
  </Step>

  <Step title="Add the GitHub property">
    Add a property, open the **Type** picker, and choose **GitHub · Pull Request** from the **Connected Providers** group. You do not pick "External" yourself; choosing the resource sets the type for you.
  </Step>

  <Step title="Point it at the source">
    A **Source property** picker appears, listing only the properties that can hold a PR reference. Pick the one from step one.
  </Step>
</Steps>

The property resolves the pull request's title, its state (`open`, `closed` or `merged`), the `owner/repo` it lives in, its number, its author, and a link to it, refreshed on its own interval.

<Note>
  The **Connected Providers** group only appears once GitHub is connected, and it appears for everyone in the workspace, not just whoever ran the OAuth.
</Note>

## Choosing between them

* **A PR is one of many on a record** (a feature with several branches): use the Development section. It needs no property and no upkeep.
* **A record tracks exactly one PR** and you want it as a filterable column: use the External property.
* **You want to work the PRs themselves** in views, boards, and reports: use a linked table.

They compose. A linked table of pull requests and a Development section on your Issues object are answering different questions and can both be on at once.

## Limitations

* Reading private repositories requires granting access to them during authorization.
* Each External property has its own refresh interval. Custral will not refresh more often than that even if the data changed upstream.
* The Development section fills in as pull requests arrive. Opening it on a repository you just connected shows the PRs updated since, not the whole history.
* Custral does not modify pull requests or comment on them. The one thing it can write is a new issue, and only when you ask the assistant to file one. That write goes through the permission gate first.

## Troubleshooting

| Symptom                                           | Cause                                                                | Fix                                                                                                  |
| ------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| A pull request does not appear on its record      | The object has no ID property, or its prefix is under two characters | Add an ID property with a prefix such as `ISSUE-`                                                    |
| A pull request naming a record appears on neither | Two objects share that ID prefix and both hold a matching record     | Give the two objects different prefixes                                                              |
| A linked table stops updating                     | The repository webhook was removed at GitHub                         | Re-run **Connect & Sync** for that repository                                                        |
| External property shows a "not found" error       | The connection cannot see the repository                             | Re-authorize and grant access to that repository                                                     |
| External property is stale                        | The refresh interval is set high                                     | Lower it in the property settings. There is no manual refresh; the value updates on its own schedule |
| External property is empty                        | The source property is empty or malformed                            | Check that it holds a valid pull request URL                                                         |

## Disconnect

Disconnecting removes GitHub access from the workspace.

* **Linked tables stay**, with the records they already hold. They stop receiving updates.
* **Development sections stay** and stop gaining new pull requests.
* **External properties stop resolving.** The property stays on the object, and its next refresh replaces the value with an error, which the cell shows. Reconnecting GitHub fixes it without touching the property: an errored value is retried on the next read.

## See also

* [ID property](/data/properties/text/id)
* [External property type](/data/properties/complex/external)
* [Integrations overview](/integrations/overview)


## Related topics

- [Provider Tools](/ai/provider-tools.md)
- [External](/data/properties/complex/external.md)
- [ID](/data/properties/text/id.md)
- [Integrations](/integrations/overview.md)
- [Jobs](/automation/jobs/overview.md)
