/github-lanes-bridge
Use when bridging GitHub and Lanes — importing GitHub issues into Lanes for local Claude Code execution, batch-spawning sessions per ticket, decomposing one GitHub issue into multiple Lanes sub-issues with dependencies, or posting session results (PR links, comments, follow-up
$ npx -y skills add lanes-sh/app --skill github-lanes-bridge --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/github-lanes-bridge
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when bridging GitHub and Lanes — importing GitHub issues into Lanes for local Claude Code execution, batch-spawning sessions per ticket, decomposing one GitHub issue into multiple Lanes sub-issues with dependencies, or posting session results (PR links, comments, follow-up
SKILL.md
github-lanes-bridge.SKILL.mdname: github-lanes-bridge
description: Use when bridging GitHub and Lanes — importing GitHub issues into Lanes for local Claude Code execution, batch-spawning sessions per ticket, decomposing one GitHub issue into multiple Lanes sub-issues with dependencies, or posting session results (PR links, comments, follow-up issues) back to GitHub. Triggers on phrases like "import from GitHub", "bring this GitHub issue into Lanes", "comment back on the PR/issue", "spin off a GitHub issue from this Lanes ticket", or any mention of both GitHub and Lanes in the same request. Uses the Lanes MCP's built-in lanes_github_* tools — no separate GitHub MCP needed (the user must have connected GitHub in Lanes settings).
GitHub ↔ Lanes bridge
Use this skill to move work between GitHub (where issues and PRs live) and Lanes (the local agent execution board). Typical flows: pull an issue into Lanes, run a session on it, then push the outcome (a PR-linking comment, or a new follow-up issue) back to GitHub.
This skill assumes the **`lanes-sessions`** skill is also available — it covers the lanes_* issue/session tools in detail. This skill focuses on the **bridging** layer.
When a Lanes issue hosts more than one CLI session, follow the multi-session disambiguation rules in `lanes-sessions` (pass `session` on stop / resume / read_terminal). Bridge tools (`lanes_github_*`) never address sessions directly.
`lanes_start_session` always **adds** a session, and its launch is asynchronous. In the batch flows below, call it exactly once per issue and record the slot it returns. Never re-call it because a session looks missing — an empty status read inside the launch window is expected. See "Starting is asynchronous" in `lanes-sessions`.
When to use
- Work originates in GitHub and you want Claude Code to do the actual implementation locally.
- You want to fan out one GitHub issue into multiple Claude sessions on sub-tasks.
- You want PR links / progress updates to flow back to GitHub without leaving chat.
**Don't use** for ad-hoc one-off tasks that didn't start in GitHub; for those, just use Lanes directly.
Prerequisites
- **Lanes MCP must be connected** — verify with `lanes_list_components`. If missing, run `/lanes:setup-mcp`.
- **GitHub must be connected inside Lanes** — verify with `lanes_github_list_repos`. If it returns a "not connected" error, ask the user to connect GitHub from **Lanes → Settings → GitHub** (OAuth flow). The token is read from `integrations.json` on every call. GitHub tokens don't expire, so no refresh logic to worry about.
There is no standalone GitHub MCP required. The same Lanes MCP that exposes `lanes_list_issues` also exposes `lanes_github_list_repos`, `lanes_github_get_issue`, etc. — they're additional tools on the same server.
The GitHub tool surface
| Tool | Purpose | |---|---| | `lanes_github_list_repos` | List repos the user can access (owner, collaborator, or org member). Sorted by most-recently-pushed. Each is `{ id: "owner/name", name: "owner/name" }`. | | `lanes_github_list_issues` | First 50 open issues in a repo, most-recently-updated first. PRs are filtered out automatically. | | `lanes_github_search_issues` | Free-text search via the `/search/issues` endpoint. When the query is a pure number (`"#9"`, `"9"`), the exact-match issue is prepended. | | `lanes_github_get_issue` | Single issue by **number** (passed as a string, e.g. `"42"`). | | `lanes_github_create_issue` | Open a new issue. Labels are GitHub label **names** (not IDs). | | `lanes_github_comment_on_issue` | Post a comment on an issue or PR. (GitHub uses the same endpoint for both.) |
Returned `ExternalIssue` shape:
{
"provider": "github",
"externalId": "42", // issue number as a string
"externalKey": "#42",
"externalUrl": "https://github.com/owner/name/issues/42",
"title": "...",
"description": "...",
"state": "open",
"updatedAt": 1715600000000
}Field mapping (GitHub → Lanes)
| GitHub | Lanes | Notes | |---|---|---| | `externalKey` (e.g. `#42`) | Title prefix + description marker | Used as the dedup key. | | `title` | `title` | Pass through. | | `body` (markdown) | `description` | Prepend a marker line: `GitHub: owner/name#42 — <externalUrl>` so round-tripping is trivial. | | `state` (`open` / `closed`) | `step` | `open` → `backlog`/`todo` (your call); `closed` → `done` if explicitly importing closed issues. | | upstream `externalId` (issue number) | `externalId` on `lanes_create_issue` | Pass through. | | upstream `externalUrl` | `externalUrl` on `lanes_create_issue` | Pass through. | | upstream `externalKey` | `externalKey` on `lanes_create_issue` | Pass through. | | `labels` | `tags` | Different ID spaces. Look up Lanes label UUIDs via `lanes_list_labels` and map by name. Missing Lanes labels: ask user before creating. |
`lanes_create_issue` accepts `externalProvider`, `externalId`, `externalKey`, `externalUrl`, and `externalSyncedAt` — set all of them on import so the Lanes UI shows the badge and the refresh button works.
Workflow patterns
A. Single port (one GitHub issue → one Lanes session)
1. lanes_github_list_repos // (or user supplies "owner/name")
2. lanes_github_search_issues { repo: "owner/name", query: "#42" }
or lanes_github_get_issue { repo, number: "42" }
3. lanes_list_issues { search: "owner/name#42" } // dedup check
4. lanes_list_components // pick componentId
5. lanes_create_issue {
title: "owner/name#42 · <github title>",
description: "GitHub: owner/name#42 — <externalUrl>\n\n<github body>",
componentId,
cwd,
worktreeStrategy: "create",
worktreeName: "gh/owner-name-42",
externalProvider: "github",
externalId: "42",
externalKey: "#42",
externalUrl: "<github url>",
externalSyncedAt: <now epoch ms>
}
6. lanes_start_session { issueId, planMode: true }Confirm with the user before
Read more
name: github-lanes-bridge description: Use when bridging GitHub and Lanes — importing GitHub issues into Lanes for local Claude Code execution, batch-spawning sessions per ticket, decomposing one GitHub issue into multiple Lanes sub-issues with dependencies, or posting session results (PR links, comments, follow-up issues) back to GitHub. Triggers on phrases like "import from GitHub", "bring this GitHub issue into Lanes", "comment back on the PR/issue", "spin off a GitHub issue from this Lanes ticket", or any mention of both GitHub and Lanes in the same request. Uses the Lanes MCP's built-in lanes_github_* tools — no separate GitHub MCP needed (the user must have connected GitHub in Lanes settings).
GitHub ↔ Lanes bridge
Use this skill to move work between GitHub (where issues and PRs live) and Lanes (the local agent execution board). Typical flows: pull an issue into Lanes, run a session on it, then push the outcome (a PR-linking comment, or a new follow-up issue) back to GitHub.
This skill assumes the **`lanes-sessions`** skill is also available — it covers the lanes_* issue/session tools in detail. This skill focuses on the **bridging** layer.
When a Lanes issue hosts more than one CLI session, follow the multi-session disambiguation rules in `lanes-sessions` (pass `session` on stop / resume / read_terminal). Bridge tools (`lanes_github_*`) never address sessions directly.
`lanes_start_session` always **adds** a session, and its launch is asynchronous. In the batch flows below, call it exactly once per issue and record the slot it returns. Never re-call it because a session looks missing — an empty status read inside the launch window is expected. See "Starting is asynchronous" in `lanes-sessions`.
When to use
- Work originates in GitHub and you want Claude Code to do the actual implementation locally.
- You want to fan out one GitHub issue into multiple Claude sessions on sub-tasks.
- You want PR links / progress updates to flow back to GitHub without leaving chat.
**Don't use** for ad-hoc one-off tasks that didn't start in GitHub; for those, just use Lanes directly.
Prerequisites
- **Lanes MCP must be connected** — verify with `lanes_list_components`. If missing, run `/lanes:setup-mcp`.
- **GitHub must be connected inside Lanes** — verify with `lanes_github_list_repos`. If it returns a "not connected" error, ask the user to connect GitHub from **Lanes → Settings → GitHub** (OAuth flow). The token is read from `integrations.json` on every call. GitHub tokens don't expire, so no refresh logic to worry about.
There is no standalone GitHub MCP required. The same Lanes MCP that exposes `lanes_list_issues` also exposes `lanes_github_list_repos`, `lanes_github_get_issue`, etc. — they're additional tools on the same server.
The GitHub tool surface
| Tool | Purpose | |---|---| | `lanes_github_list_repos` | List repos the user can access (owner, collaborator, or org member). Sorted by most-recently-pushed. Each is `{ id: "owner/name", name: "owner/name" }`. | | `lanes_github_list_issues` | First 50 open issues in a repo, most-recently-updated first. PRs are filtered out automatically. | | `lanes_github_search_issues` | Free-text search via the `/search/issues` endpoint. When the query is a pure number (`"#9"`, `"9"`), the exact-match issue is prepended. | | `lanes_github_get_issue` | Single issue by **number** (passed as a string, e.g. `"42"`). | | `lanes_github_create_issue` | Open a new issue. Labels are GitHub label **names** (not IDs). | | `lanes_github_comment_on_issue` | Post a comment on an issue or PR. (GitHub uses the same endpoint for both.) |
Returned `ExternalIssue` shape:
{
"provider": "github",
"externalId": "42", // issue number as a string
"externalKey": "#42",
"externalUrl": "https://github.com/owner/name/issues/42",
"title": "...",
"description": "...",
"state": "open",
"updatedAt": 1715600000000
}Field mapping (GitHub → Lanes)
| GitHub | Lanes | Notes | |---|---|---| | `externalKey` (e.g. `#42`) | Title prefix + description marker | Used as the dedup key. | | `title` | `title` | Pass through. | | `body` (markdown) | `description` | Prepend a marker line: `GitHub: owner/name#42 — <externalUrl>` so round-tripping is trivial. | | `state` (`open` / `closed`) | `step` | `open` → `backlog`/`todo` (your call); `closed` → `done` if explicitly importing closed issues. | | upstream `externalId` (issue number) | `externalId` on `lanes_create_issue` | Pass through. | | upstream `externalUrl` | `externalUrl` on `lanes_create_issue` | Pass through. | | upstream `externalKey` | `externalKey` on `lanes_create_issue` | Pass through. | | `labels` | `tags` | Different ID spaces. Look up Lanes label UUIDs via `lanes_list_labels` and map by name. Missing Lanes labels: ask user before creating. |
`lanes_create_issue` accepts `externalProvider`, `externalId`, `externalKey`, `externalUrl`, and `externalSyncedAt` — set all of them on import so the Lanes UI shows the badge and the refresh button works.
Workflow patterns
A. Single port (one GitHub issue → one Lanes session)
1. lanes_github_list_repos // (or user supplies "owner/name")
2. lanes_github_search_issues { repo: "owner/name", query: "#42" }
or lanes_github_get_issue { repo, number: "42" }
3. lanes_list_issues { search: "owner/name#42" } // dedup check
4. lanes_list_components // pick componentId
5. lanes_create_issue {
title: "owner/name#42 · <github title>",
description: "GitHub: owner/name#42 — <externalUrl>\n\n<github body>",
componentId,
cwd,
worktreeStrategy: "create",
worktreeName: "gh/owner-name-42",
externalProvider: "github",
externalId: "42",
externalKey: "#42",
externalUrl: "<github url>",
externalSyncedAt: <now epoch ms>
}
6. lanes_start_session { issueId, planMode: true }Confirm with the user before
(RENAME desktop-app) Lanes makes parallel AI coding your unfair advantage
Other skills on app.
- /lanes-sessions
Use when managing Lanes issues or driving Claude Code sessions through the lanes_* MCP tools — creating issues, starting/stopping/inspecting sessions, batch-launching work across worktrees, reading terminal output, attaching labels and components by UUID, or moving issues across
Open skill - /linear-lanes-bridge
Use when bridging Linear and Lanes — importing Linear issues into Lanes for local Claude Code execution, batch-spawning sessions per Linear ticket, decomposing one Linear issue into multiple Lanes sub-issues with dependencies, or posting session results (PR links, comments,
Open skill - /lanes-forms
Use when the user wants a form backend or contact form set up (a live POST endpoint that captures submissions and emails them), OR wants an agent to fill in / submit to a form on their behalf. Lanes Forms creates and manages hosted form endpoints from Claude Code. Triggers on
Open skill

