> ## Documentation Index
> Fetch the complete documentation index at: https://meridiona-mintlify-bf718ac0.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Meridian to GitHub Issues or Linear Issues

> Pull open GitHub or Linear issues into Meridian so coding sessions are automatically classified against the right tickets, with no manual tracking needed.

Meridian supports two additional issue trackers alongside Jira: GitHub Issues and Linear. Both work the same way under the hood — Meridian fetches your open issues into the local `pm_tasks` table, uses them as classification targets when it processes each app session, and once classification matches a session to an issue it can also **draft a worklog** against that issue. You can enable one, the other, or both at the same time.

Neither GitHub nor Linear exposes a native time-tracking / worklog API, so on these trackers Meridian records a worklog as a **structured comment** on the matched issue: a single Markdown line of the form `**⏱ Worklog — 1h 30m** · 2026-06-02 09:00`, followed by the synthesised narrative of what you did, followed by an HTML-comment machine marker (`meridian-worklog v1 …`) carrying the exact UTC window and seconds so the entry can be parsed back out later. Worklogs are still gated by approval in the dashboard's **Worklogs** view — the same draft → approve → post pipeline as Jira, just with a different final hop. See [Review and approve worklogs](/guides/dashboard#worklogs-view).

<Tabs>
  <Tab title="GitHub Issues">
    ## What Meridian does with GitHub Issues

    Meridian fetches open issues from your GitHub organisation's repositories using the GitHub REST API. Each issue is stored in `pm_tasks` alongside any Jira or Linear issues you've configured. When Meridian classifies a coding session — say, an hour in VS Code on a feature branch — it matches that work against your open issues and writes a `ticket_links` row with the best-matching issue key.

    ## Prerequisites

    * A GitHub account with access to the organisation (or personal) issues you want to track
    * A personal access token (PAT) with **write** access to issue comments — Meridian needs this to post worklog comments after you approve them

    ## Create a GitHub personal access token

    <Steps>
      <Step title="Open GitHub Settings">
        Click your avatar in the top-right corner of GitHub, then choose **Settings**.
      </Step>

      <Step title="Navigate to Developer settings">
        Scroll to the bottom of the left sidebar and click **Developer settings**.
      </Step>

      <Step title="Generate a new token">
        Select **Personal access tokens → Tokens (classic)** or **Fine-grained tokens**. Click **Generate new token**.

        * **Classic token (simplest)** — enable the **`repo`** scope. This single scope covers both reading issues and posting worklog comments, on personal and org-owned repos.
        * **Fine-grained token** — grant **Issues: Read and write** on every repository Meridian should monitor (read-only is not enough; Meridian needs write access to add the worklog comment when you approve a draft).
      </Step>

      <Step title="Copy the token">
        Copy the token value before navigating away — GitHub only shows it once.
      </Step>
    </Steps>

    ## Set environment variables

    Open the Meridian env file:

    ```bash theme={null}
    meridian config edit
    ```

    Add the GitHub block to `~/.meridian/.env`:

    ```bash theme={null}
    # ~/.meridian/.env

    GITHUB_TOKEN=ghp_your_personal_access_token
    GITHUB_ORG=your-org-name   # org slug OR your own username

    # Optional: limit to specific repos (comma-separated owner/repo pairs)
    # GITHUB_REPOS=your-org/api,your-org/web
    ```

    `GITHUB_ORG` is the **issue owner** Meridian should sync — an organisation slug or your own GitHub username (for personal repos). Meridian fetches **open issues assigned to you** under that owner. If `GITHUB_REPOS` is omitted, every repository under the owner that your token can read is included.

    ## Apply and verify

    <Steps>
      <Step title="Restart the daemon">
        ```bash theme={null}
        meridian restart
        ```
      </Step>

      <Step title="Check the connection">
        ```bash theme={null}
        meridian doctor
        ```

        Look for `github: connected` in the output. Meridian reports the connection status for every configured integration.
      </Step>

      <Step title="Confirm issues were fetched">
        ```bash theme={null}
        sqlite3 ~/.meridian/meridian.db \
          "SELECT task_key, title FROM pm_tasks WHERE provider='github' LIMIT 10;"
        ```
      </Step>
    </Steps>

    ## Filter to specific repositories

    Set `GITHUB_REPOS` to a comma-separated list of `owner/repo` strings:

    ```bash theme={null}
    GITHUB_REPOS=myorg/api,myorg/web,myorg/infra
    ```

    Only open issues from those repositories will be pulled into `pm_tasks`. This is useful when your organisation has many repositories but you only actively work in a subset.

    ## What "posting a worklog" means on GitHub

    GitHub has no native time-tracking API, so when you approve a worklog draft Meridian posts it as a comment on the matched issue via `POST /repos/{owner}/{repo}/issues/{number}/comments`. The comment looks like:

    ```markdown theme={null}
    **⏱ Worklog — 1h 30m** · 2026-06-02 09:00

    Wired the new worklog provider router and migrated existing rows to default to `jira`. Wrote the comment formatter and idempotency check.

    <!-- meridian-worklog v1 window=2026-06-02T09:00:00Z/2026-06-02T10:00:00Z seconds=5400 -->
    ```

    In your tracker you will see:

    * A new comment on the issue authored by the token's user, with the time-spent line and the synthesised narrative.
    * The same comment surfaced on any **Project (v2)** board the issue belongs to — Project cards already show issue comments, so no extra setup is needed.
    * A hidden machine marker on the last line that Meridian (and any other tool) can grep for to reconstruct the exact window and seconds later. Worklogs are idempotent on `(task_key, window_start, window_end)` — re-running the pipeline never double-posts.

    The same `repo` (classic) or `Issues: Read and write` (fine-grained) scope you configured above is all that's needed — no separate Projects scope is required.

    ## Troubleshooting

    <AccordionGroup>
      <Accordion title="401 or 403 errors on startup, or when a worklog tries to post">
        Check that your token has not expired and has the correct scopes. Classic tokens need the `repo` scope; fine-grained tokens need **Issues: Read and write** (read-only will let issues sync but worklog comments will fail with 403). Regenerate the token in GitHub Settings if needed.
      </Accordion>

      <Accordion title="pm_tasks is empty for GitHub">
        Confirm that `GITHUB_ORG` matches your organisation's login name exactly (case-sensitive). If `GITHUB_REPOS` is set, verify each entry uses the full `owner/repo` format. Your token must have access to at least one repository in the org.
      </Accordion>

      <Accordion title="meridian doctor shows github: not configured">
        Both `GITHUB_TOKEN` and `GITHUB_ORG` are required. Run `meridian config edit` and confirm neither is commented out.
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Linear">
    ## What Meridian does with Linear

    Meridian fetches your open Linear issues via the Linear GraphQL API and stores them in `pm_tasks`. Session classification then uses these issues as candidates — when you spend time in a code editor or design tool, Meridian links that session to the most relevant Linear issue it can find.

    ## Prerequisites

    * A Linear account with access to one or more teams
    * A Linear API key

    ## Create a Linear API key

    <Steps>
      <Step title="Open Linear Settings">
        Click your avatar in the bottom-left corner of the Linear app, then choose **Settings**.
      </Step>

      <Step title="Navigate to API">
        In the Settings sidebar, click **API** under the **My account** section.
      </Step>

      <Step title="Create a personal API key">
        Under **Personal API keys**, click **Create key**. Give it a descriptive label such as `meridian-local` and click **Create key**.
      </Step>

      <Step title="Copy the key">
        Copy the key value immediately — Linear only shows it once. It starts with `lin_api_`.
      </Step>
    </Steps>

    ## Set environment variables

    Open the Meridian env file:

    ```bash theme={null}
    meridian config edit
    ```

    Add the Linear block to `~/.meridian/.env`:

    ```bash theme={null}
    # ~/.meridian/.env

    LINEAR_API_KEY=lin_api_your_key_here

    # Optional: restrict to specific teams (comma-separated team keys or ids)
    # LINEAR_TEAM_IDS=ENG,DESIGN
    ```

    Meridian sends the key **raw** in Linear's `Authorization` header — there is no `Bearer` prefix (that prefix is for OAuth tokens; personal API keys go in as-is). If `LINEAR_TEAM_IDS` is omitted, Meridian fetches the issues assigned to you across every team your account belongs to.

    ## Apply and verify

    <Steps>
      <Step title="Restart the daemon">
        ```bash theme={null}
        meridian restart
        ```
      </Step>

      <Step title="Check the connection">
        ```bash theme={null}
        meridian doctor
        ```

        Meridian reports connection status for each configured integration. Look for `linear: connected`.
      </Step>

      <Step title="Confirm issues were fetched">
        ```bash theme={null}
        sqlite3 ~/.meridian/meridian.db \
          "SELECT task_key, title FROM pm_tasks WHERE provider='linear' LIMIT 10;"
        ```
      </Step>
    </Steps>

    ## Filter to specific teams

    Set `LINEAR_TEAM_IDS` to a comma-separated list of team identifiers:

    ```bash theme={null}
    LINEAR_TEAM_IDS=ENG,DESIGN
    ```

    Only issues belonging to those teams will be pulled into `pm_tasks`. Find your team identifiers in Linear under **Settings → Teams** — each team has a short key (e.g. `ENG`) and an internal id; either works.

    ## What "posting a worklog" means on Linear

    Linear has no worklog, time-entry, or "time spent" field in its GraphQL schema. So when you approve a worklog draft, Meridian creates a structured comment on the matched issue via the `commentCreate` mutation:

    ```graphql theme={null}
    mutation {
      commentCreate(input: { issueId: "<issue-uuid>", body: "**⏱ Worklog — 1h 30m** · …" }) {
        success
        comment { id url }
      }
    }
    ```

    Meridian first resolves the issue UUID from its human identifier (e.g. `ENG-123`) and then posts the comment. In Linear you will see:

    * A new comment on the issue authored by the API key's user, with the **⏱ Worklog — 1h 30m** time-spent line followed by the synthesised narrative.
    * The comment counts toward Linear's issue activity feed and is visible in every view that surfaces comments (issue detail, Inbox, Slack mirror if you have it enabled).
    * A hidden machine marker on the last line carrying the exact UTC window and seconds, so the entry can be parsed back out programmatically. Worklogs are idempotent on `(task_key, window_start, window_end)` — re-running the pipeline never double-posts.

    The personal API key you configured above is the only credential required. Meridian uses the key's `viewer` (the user who created it) as the comment author, so worklog comments are attributed to you.

    ## Troubleshooting

    <AccordionGroup>
      <Accordion title="Authentication errors on startup">
        Confirm that `LINEAR_API_KEY` starts with `lin_api_` and has not been revoked. Regenerate the key in Linear Settings → API if needed.
      </Accordion>

      <Accordion title="pm_tasks is empty for Linear">
        Check that your account is a member of at least one team with open issues. If `LINEAR_TEAM_IDS` is set, verify the IDs match the identifiers shown in Linear Settings — they are case-sensitive.
      </Accordion>

      <Accordion title="meridian doctor shows linear: not configured">
        `LINEAR_API_KEY` is the only required variable for Linear. Run `meridian config edit` and confirm it is present and uncommented.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
