Help us improve
Share bugs, ideas, or general feedback.
From lanes
Bridges Linear and Lanes by importing issues into Lanes for local execution, batch-spawning sessions per ticket, decomposing issues into sub-tasks, and posting results back to Linear.
npx claudepluginhub lanes-sh/app --plugin lanesHow this skill is triggered — by the user, by Claude, or both
Slash command
/lanes:linear-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 Linear (the team's source of truth) and Lanes (the local agent execution board). Typical flows: pull a ticket or a whole sprint into Lanes, run sessions on each, then push the outcome (PRs, comments, status) back to Linear.
Plans projects, features, or bug fixes by creating well-structured, agent-ready Linear issues via MCP tools. Handles research, decomposition, and Linear team/project setup.
Manages Lanes issues and drives Claude Code sessions via lanes_* MCP tools: create/update/move issues, start/stop/inspect sessions, read terminal output, and attach labels/components by UUID.
Manage Linear issues, projects, and teams using MCP tools, Linear CLI via Bash, or scripts with secure Varlock API key handling.
Share bugs, ideas, or general feedback.
Use this skill to move work between Linear (the team's source of truth) and Lanes (the local agent execution board). Typical flows: pull a ticket or a whole sprint into Lanes, run sessions on each, then push the outcome (PRs, comments, status) back to Linear.
This skill assumes the lanes-sessions skill is also available — it covers the lanes_* tools in detail. This skill focuses on the bridging layer.
Don't use for ad-hoc one-off tasks that didn't start in Linear; for those, just use Lanes directly.
Both MCPs must be connected in this Claude Code session:
lanes_list_components. If missing, run /lanes:setup-mcp (or follow the lanes-sessions skill's setup section).list_teams tool. The exact tool name depends on which Linear MCP the user has installed (e.g. mcp__claude_ai_Linear__list_teams from Claude.ai, or a different prefix from the official Linear MCP). Use whichever is available.If either is missing, stop and ask the user to install it before continuing.
| Linear | Lanes | Notes |
|---|---|---|
identifier (e.g. ENG-123) | Title prefix + description marker | Used as the dedup key. |
title | title | Pass through. |
description | description | Prepend a marker line: Linear: ENG-123 — https://linear.app/<workspace>/issue/ENG-123 so round-tripping is trivial. |
state type | step | triage / backlog → backlog; unstarted → todo; started → in-progress; completed / canceled → skip import (or done if explicitly requested). |
labels | tags | Different UUID spaces. Call lanes_list_labels, match by name, keep a Linear→Lanes UUID dict for the session. Missing Lanes labels: ask user before creating. |
team / project | componentId | Call lanes_list_components first; pick the closest match. |
parent | dependencies | Lanes dependency is a Lanes issue ID. Resolve the parent first, store its Lanes ID, then create children with dependencies: [parentLanesId]. |
assignee | — | Not stored on Lanes. Mention in the description if relevant. |
cycle, priority, estimate | — | Not currently mapped. Drop or surface in description. |
Status states are team-scoped in Linear. Use the state's type field (always one of triage/backlog/unstarted/started/completed/canceled) for the mapping above; never match on the human-readable name (it varies per team).
1. Linear list_issues → find the ticket (or the user supplies the identifier)
2. Linear get_issue → full description
3. lanes_list_issues { search: "ENG-123" } // dedup check
4. lanes_list_components → pick componentId
5. lanes_create_issue {
title: "ENG-123 · <linear title>",
description: "Linear: ENG-123 — <url>\n\n<linear description>",
componentId,
cwd,
worktreeStrategy: "create",
worktreeName: "linear/eng-123"
}
6. lanes_start_session { issueId, planMode: true }
Confirm with the user before step 6 if the ticket is non-trivial — let them review the issue first.
1. Linear list_issues with explicit filters:
team / project / cycle / state.type ∈ {backlog, unstarted}
Show the user the result count BEFORE importing.
2. Confirm scope with the user.
3. lanes_list_components, lanes_list_labels (cache)
4. For each Linear issue:
- dedup via lanes_list_issues { search: "<identifier>" }
- lanes_create_issue (with marker, mapped tags, componentId)
5. (Optional) batch lanes_start_session in plan mode with
flags: [{ flag: "dangerously-skip-permissions", value: "", kind: "flag" }]
Always require an explicit filter at step 1. Linear projects accumulate hundreds of stale issues — never list_issues with no filter.
1. Linear get_issue // big ticket
2. Propose a breakdown to the user (numbered list).
3. After user approves:
a. lanes_create_issue for the parent (the umbrella).
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.
The parent stays linked to Linear via the marker. Sub-tasks are Lanes-only; if the team needs them visible in Linear, create matching Linear sub-issues separately and add their identifiers 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, or you do via gh.)
3. Linear create_attachment {
issueId,
url: "<PR URL>",
title: "PR · <pr title>"
} // PR shows up in the Linear sidebar
4. Linear save_comment {
issueId,
body: "Implemented locally via Lanes #<lanesId>. Diff: <stat summary>."
}
5. (Optional) Linear save_status_update on the team if a stand-up post
makes sense, or move the Linear issue to In Review by saving a new
state on the issue.
6. lanes_move_issue { id: lanesId, step: "done" }
Prefer create_attachment over comments for URLs — Linear surfaces attachments in the sidebar; comments get buried.
Always include Linear: <IDENTIFIER> in the Lanes description (and ideally in the title prefix). Before importing, run lanes_list_issues { search: "ENG-123" } and skip if a match is found. For sprint imports, do the dedup check per-issue, not just up-front, so partially-imported sprints can resume cleanly.
name. Names vary per team ("Triage", "Backlog", "On deck"…). Use the type field.lanes_list_labels.save_comment or create_attachment. Don't save_issue to mutate the description — you'll clobber team context.Linear: ENG-XXX in the Lanes description, a re-run double-imports the same ticket.