From lanes-desktop
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).
How this skill is triggered — by the user, by Claude, or both
Slash command
/lanes-desktop:github-lanes-bridgeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
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.
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.
Don't use for ad-hoc one-off tasks that didn't start in GitHub; for those, just use Lanes directly.
lanes_list_components. If missing, run /lanes:setup-mcp.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.
| 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
}
| 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.
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 step 6 if the issue is non-trivial — let them review the issue first.
1. lanes_github_list_issues { repo } (capped at 50)
or lanes_github_search_issues { repo, query: "label:p0" }
Show the user the result count BEFORE importing.
2. Confirm scope with the user.
3. lanes_list_components, lanes_list_labels (cache locally)
4. For each GitHub issue:
- dedup via lanes_list_issues { search: "<externalKey>" }
- lanes_create_issue (with marker, mapped labels → tags, external* metadata)
5. (Optional) batch lanes_start_session in plan mode with
flags: [{ flag: "dangerously-skip-permissions", value: "", kind: "flag" }]
For wider sweeps, prefer lanes_github_search_issues with explicit qualifiers (label:foo, assignee:@me, milestone:"v2") over list_issues with no filter — GitHub's search syntax composes naturally inside the query string.
1. lanes_github_get_issue { repo, number } // big ticket
2. Propose a breakdown to the user (numbered list).
3. After user approves:
a. lanes_create_issue for the parent (the umbrella, with GitHub marker).
b. lanes_create_issue for each sub-task with
dependencies: [parentLanesId].
4. lanes_start_session on the parent in plan mode (optional);
start sub-tasks once their dependencies are unblocked.
If the team needs sub-issues visible upstream too, call lanes_github_create_issue for each and add their #N to each Lanes description.
When a session is done and there's something concrete to report:
1. lanes_get_issue_changes { id } // confirm there is a diff
2. (User pushes the branch / opens a PR.)
3. lanes_github_comment_on_issue {
repo: "owner/name",
number: "42",
body: "Implemented locally via Lanes #<lanesId>. PR: <PR URL>\n\n<stat summary>"
}
4. (Optional) lanes_github_create_issue for follow-up work surfaced during the
session.
5. lanes_move_issue { id: lanesId, step: "done" }
PRs and issues share the comment endpoint on GitHub — you can use lanes_github_comment_on_issue to comment on a PR by passing its number.
Always include GitHub: owner/name#N in the Lanes description (and ideally in the title prefix). Before importing, run lanes_list_issues { search: "owner/name#N" } and skip if a match is found. For backlog imports, do the dedup check per-issue, not just up-front, so partially-imported batches can resume cleanly.
"42", not 42) so the same parameter shape works for arbitrary external-id forms.external* metadata on import. Without them, the Lanes UI can't show the "open in GitHub" badge or refresh the description.lanes_github_list_issues and expecting PRs. The endpoint mixes issues and PRs, but the tool filters PRs out (matching the renderer). Use the GitHub UI or gh pr list for PRs — there's no lanes_github_list_prs tool today.lanes_github_create_issue. Labels are by name (string), not ID — GitHub's REST API expects names.GitHub: owner/name#N in the description, a re-run double-imports the same ticket.lanes_github_* are read-only. lanes_github_create_issue and lanes_github_comment_on_issue write to upstream — always confirm with the user before invoking on production repos.Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Resolves in-progress git merge or rebase conflicts by analyzing history, understanding intent, and preserving both changes where possible. Runs automated checks after resolution.
npx claudepluginhub lanes-sh/app --plugin lanes-desktop