$ lanes link connect github --profile personal --workspace localYou are asked for one fine-grained personal access token. There is no browser consent, no OAuth client, and nothing to register.
What your agent can do
GitHub runs its own MCP server, and serves a different tool list per toolset. This connection asks
for context, repos, issues, pull_requests, actions, and labels, which is what an agent
working in a repository actually uses. The full set is considerably larger and is more than most
agents reason over well.
lanes link status lists what your connection actually discovered.
The token
-
Open github.com/settings/personal-access-tokens and choose Generate new token.
-
Name it
Lanes Link. The name is how you revoke this one later without touching your other tokens. Set an expiry you are willing to renew. -
Resource owner: yourself, or the organisation whose repositories you want reachable. An organisation may require an owner to approve the token first, and until they do it authenticates and returns nothing.
-
Repository access: only the repositories you want an agent to see. All repositories is the setting people regret.
-
Permissions, matching the toolsets above:
Permission Level Contents Read Metadata Read (added for you) Issues Read and write Pull requests Read and write Actions Read Add Administration or Workflows only if you know you need them.
-
Generate, then copy the token. GitHub shows it once, and it starts with
github_pat_.
A classic token works too, with the repo scope, but it is all or nothing across every repository
you can reach. Prefer the fine-grained one.
The token goes into the encrypted credential store at github/<login>, never into config.
Renewing it
A fine-grained token expires. When it does, generate another and run:
$ lanes link connect github --replace --profile personal --workspace localWithout --replace, connect finds the expired token already stored and reuses it. Same shape as
iCloud's app-specific password, and for the same reason: the stored credential is the one that was
just refused.
A read-only connection
GitHub also serves a read-only variant. It is a manifest of your own rather than a flag:
# ~/.lanes-link/data/<profile>/providers.d/github-readonly.yaml
id: github_readonly
name: GitHub (read-only)
connector:
kind: mcp
endpoint: https://api.githubcopilot.com/mcp/readonly
auth:
kind: bearer
identity:
kind: http
url: https://api.github.com/user
field: login
setup:
prompts:
- key: token
label: GitHub personal access token
secret: true
scope: connectionThat is a separate provider with its own token and its own policy line, which is the point: you can grant one profile the read-only connection and never the other.
Connecting without a terminal to answer
GitHub is the straightforward case for an agent with a shell, because nothing here needs a browser:
$ printf %s "$GITHUB_TOKEN" | lanes link secrets set github/octocat --profile personal
$ lanes link connect github --id octocat --non-interactive --json --profile personalThe credential goes in on stdin, never as a flag. An argument lands in shell history, in ps
output, and in any transcript.
Why a token rather than a browser sign-in
Notion and Linear support Dynamic Client Registration, so Lanes Link registers itself and you do
nothing. GitHub does not offer that yet, and the documented alternative fails on a detail: an OAuth
App matches its callback URL exactly, port included, and connect listens on a port the kernel
picks per run, so there is no port to register. GitHub's remote MCP server accepts a personal access
token as Authorization: Bearer, which is the credential GitHub issues for exactly this case.
Troubleshooting
| What you see | What it is |
|---|---|
GitHub refused the token | The token expired, the repository was not in the set you granted, or an organisation token is still waiting on an owner's approval |
| The connection is labelled with something you typed rather than your login | The identity probe could not reach api.github.com/user, which nearly always means the token is wrong |
| A tool you expected is missing | Check the toolsets above, then lanes link status |
What is recorded
Repository, issue, and pull request identifiers are kept, along with the method. Bodies and comment text are withheld, and reads reduce every argument to a type marker.
One caveat worth stating rather than leaving to be discovered: GitHub's MCP server is GitHub's, so
capabilities are discovered at connect time and nothing here can check the argument names against
theirs. If GitHub renames an argument, the value is withheld and the log reads exactly as it does
when redaction is working. lanes link doctor reporting capability drift is the signal that the
list wants re-reading. See the audit log.
Next: every provider, or Add it to your agent.