Sarimarcus/claude-code-plugins/tree/main/plugins/linear-workflow
linear-workflow
Claude Code를 위한 Linear 워크플로: issue-next, issue-start, issue-review, issue-ship, issue-plan-cycle 스킬을 결정적 CLI, linear-manager 에이전트, 현재 issue와 다른 세션 및 충돌 경고를 프롬프트 위에 표시하는 mod로 지원합니다.
이 mod 소개
Linear 워크플로
Claude Code에서 Linear issue를 처리합니다. cycle에서 다음 issue를 고르는 것부터 PR을 병합하는 단계까지 이어집니다. 진행하는 동안 Linear는 최신 상태로 유지되고, 현재 issue는 항상 프롬프트 위에 표시됩니다.
개요
이 플러그인은 네 부분으로 이루어집니다.
- **스킬(슬래시 명령)**은 issue를 cycle에서 병합된 PR까지 진행합니다.
issue-next →issue-start → (work) →issue-review →issue-ship이며, cycle을 채우는 `issue-plan-cycle도 있습니다. - CLI(`bin/linear-workflow.mjs)는 판단이 필요 없는 Linear와 GitHub 단계를 실행합니다. issue 가져오기와 순위 지정, 상태 변경, cycle 변경, PR 검사입니다. LLM보다 빠르고 매번 같은 답을 제공합니다. 판단이 필요한 부분은 Claude가 맡습니다. issue 읽기, 코드 작성, commit message, PR 요약과 댓글을 처리합니다.
- 에이전트 `linear-manager는 issue를 만들고 편집하며, CLI가 Linear에 연결하지 못할 때 CLI를 대신합니다.
- mod: 현재 issue를 프롬프트 위에 실시간으로 표시하고, 다른 Claude Code 세션을 나열하며, 두 세션이 충돌하면 경고하는 라이브 코드입니다. CLI와 코드(`lib/)를 공유합니다.
Claude Code는 플러그인 스킬과 에이전트에 네임스페이스를 붙이므로 전체 이름은
/linear-workflow:issue-start와 linear-workflow:linear-manager입니다. `/issue를 입력하고 메뉴에서 고릅니다.
빠른 시작
/plugin marketplace add Sarimarcus/claude-code-plugins
/plugin install linear-workflow@sarimarcus
- Linear personal API key를 만듭니다(Settings →
Security & access; Linear's API docs도 참고). 셸 프로필에
export LINEAR_API_KEY=lin_api_…를 설정하거나 저장소의 git 무시.env에 `LINEAR_API_KEY= 한 줄을 추가합니다. CLI와 mod가 모두 사용합니다. - 선택 사항:
linear-manager 에이전트에 [Linear's MCP server](https://linear.app/docs/mcp)를 연결합니다(claude.ai의 Linear connector 또는claude mcp add --transport http linear https://mcp.linear.app/mcp). - `/linear-workflow:issue-next를 실행합니다.
스킬
`/linear-workflow:issue-next
다음에 작업할 항목을 고릅니다. 읽기 전용입니다. Haiku에서 실행되며 CLI가 순위를 매긴 목록만 보여 줍니다.
/linear-workflow:issue-next
Claude가 수행하는 일:
- active cycle에서 자신에게 할당되고 막히지 않은 Todo 및 In Progress issue를 가져옵니다
- 진행 중인 epic을 다음 막히지 않은 sub-issue로 바꿉니다
- 우선순위, milestone 날짜, 오래된 순서로 순위를 매겨 상위 5개와 각 이유를 보여 줍니다
- 첫 항목(
Y), 다른 항목(ABC-140) 또는 아무것도 선택하지 않을 수 있게 합니다
`/linear-workflow:issue-start <ABC-123>
issue 작업을 시작합니다.
/linear-workflow:issue-start ENG-123
Claude가 수행하는 일:
- issue를 In Progress로 옮깁니다
- reviewer를 위한 Acceptance Criteria는 보여 주지 않고 Context, Implementation, Scope를 보여 줍니다
- 실행 가능한 댓글을 원문 그대로 재현해 scope로 취급합니다(새 댓글이 description보다 우선합니다)
- issue에 열린 blocker가 있으면 계속하기 전에 묻습니다
- Linear 브랜치를 만들고 기다리지 않고 작업을 시작합니다
`/linear-workflow:issue-review [ABC-123]
작업을 review에 올립니다. 병합하거나 배포하지 않습니다.
/linear-workflow:issue-review
Claude가 수행하는 일:
- base 브랜치에 있거나 다른 issue를 가리키는 이름의 브랜치에 있으면 거부합니다
- 변경 사항을 각 acceptance criterion과 대조하고, 충족되지 않은 항목이 있으면 진행 전에 묻습니다
.claude/linear.json의 검사나npm test 같은 명백한 검사를 실행합니다- 이 issue의 파일만 commit합니다(관련 없는 파일이 있으면 묻습니다). 메시지에 ` (ENG-123)를 넣습니다
- 브랜치를 push하고 본문에 `Closes ENG-123이 있는 PR을 엽니다
- issue를 In Review로 옮기고 완료 댓글을 남깁니다
`/linear-workflow:issue-ship [ABC-123]
review된 PR을 병합하고 issue를 닫습니다.
/linear-workflow:issue-ship
Claude가 수행하는 일:
- 열린 PR이 없거나, draft이거나, 충돌이 있거나, 변경 요청을 받았거나, 검사에 실패했거나, 브랜치의 작업이 아직 PR에 들어가지 않았으면 거부합니다
- 병합합니다(
gh pr merge 또는 로컬에서git merge --no-ff를 실행해 `pre-push hook을 실행) - Linear를 건드리기 전에 PR이 실제로 병합됐는지 GitHub에서 확인합니다
- issue를 Done으로 옮기고 모든 sub-issue가 끝나면 parent issue로 합칩니다
`/linear-workflow:issue-plan-cycle
backlog에서 active cycle을 채웁니다. `issue-next와 마찬가지로 Haiku에서 실행됩니다. 다른 스킬은 현재 세션의 모델을 사용합니다. 코드 작성, acceptance criteria 판단 또는 병합을 수행하기 때문입니다.
Claude가 수행하는 일:
- active cycle에 아직 배정되지 않았고 막히지 않은 Backlog 및 Todo issue를 우선순위순으로 나열합니다. parent가 이미 cycle에 있으면 해당 sub-issue는 보류합니다
- 추가할 항목(
all,none 또는 id 목록)을 묻고 해당 issue에 cycle만 설정하며 다른 것은 바꾸지 않습니다
id가 없으면 issue-review와 issue-ship은 현재 세션의 issue, 브랜치 이름, Linear에서 자신이 시작한 issue 순서로 사용합니다. id를 추측했다면 먼저 보여 주고, `issue-ship은 병합 전에 확인을 요청합니다.
`linear-manager 에이전트
CLI가 하지 않는 작업에 사용합니다. issue 등록, 계획을 sub-issue로 나누기, label, relation, milestone, 검색(「linear-manager로 … 버그를 등록해」) 등을 처리합니다. CLI가 Linear에 연결하지 못할 때도 스킬은 이 에이전트로 대체합니다. CLI와 같은 규칙을 따릅니다.
- ID가 아니라 이름을 전달합니다(
state: "In Review",labels: ["Bug"], `assignee: "me") - 상태 변경은 멱등적으로 처리합니다. 이미 해당 상태면 아무것도 하지 않습니다
- parent의 sub-issue는 전부 나열하지 않고 완료되지 않은 항목이 있는지 물어 확인합니다
- 목록에 issue 설명을 절대 반환하지 않아 긴 backlog가 대화를 채우지 않게 합니다
- 파일을 편집하거나 git을 실행하지 않습니다
CLI
스킬은 node "\${CLAUDE_PLUGIN_ROOT}/bin/linear-workflow.mjs" <command>로 CLI를 호출합니다. 어느 저장소에서든 직접 실행할 수 있습니다. stdout에는 간결한 JSON을, stderr에는 검사한 내용을 한 줄 요약으로 출력합니다. 종료 코드: 0 성공, 1 오류 또는 잘못된 입력, 2 거부(사람의 판단 필요)입니다.
**작은 컨텍스트를 위해 만들어졌습니다.**각 스킬 단계는 한 번 호출하고 그 단계가 읽는 필드만 반환합니다. 모든 도구 호출은 대화를 다시 읽는 모델 턴이므로, 호출 횟수를 줄이고 반환 내용을 작게 하는 것이 가장 큰 절약입니다. start 뷰에는 acceptance criteria가 전혀 없으므로 구현자가 이를 보지 않게 하려고 Claude의 지시 준수에 의존할 필요도 없습니다.
| 스킬 단계당 한 번 호출 | 반환 내용 |
| --- | --- |
| start <ABC-123> | 작업할 issue(acceptance criteria 없는 설명, blocker, 브랜치 이름, 모든 댓글 원문)와 저장소 상태(브랜치, base, 브랜치 설정, 커밋되지 않은 파일) | | review [ABC-123] | issue(인수, 브랜치 이름 또는 시작한 유일한 issue), acceptance criteria, 저장소 상태: base 브랜치, 브랜치가 가리키는 issue, 이 브랜치의 열린 PR, 검사, 커밋되지 않은 파일 |
| ship [ABC-123] [--pr N] | issue, 병합 설정, PR 판정 결과(pr-check) |
| 단일 단계 | 하는 일 |
| --- | --- |
| config | 저장소 루트, 현재 브랜치와 그 브랜치가 가리키는 issue(branchIssue), 해석된 base 브랜치(그 외에는 origin의 기본 브랜치), 해당 브랜치인지 여부, 이 브랜치의 열린 PR, team key, key 발견 여부, .claude/linear.json | | resolve [ABC-123|123] | 작업할 issue: 인수, 브랜치 이름, 자신이 시작한 유일한 issue 순으로 확인합니다. 판단할 수 없으면 candidates와 종료 코드 2로 끝납니다 |
| issue <ABC-123> [--view start\|review] | 전체 issue(description, 파싱된 acceptanceCriteria, blocker, sub-issue, 링크, 브랜치 이름, 모든 댓글) 또는 스킬별 뷰 |
| queue [--limit N] | active cycle의 Todo 및 In Progress issue(In Review 및 차단된 항목 제외), epic은 다음 sub-issue로 바꾸고 각 항목에 rank 및 표시용 urgency(overdue 3d, ends in 5d…)를 붙입니다 | | plan-cycle [--limit N] | active cycle에 아직 배정되지 않았고 막히지 않은 backlog issue를 순위 매깁니다 |
| transition <ABC-123> <state> [--comment TEXT \| --comment-file F] | 멱등 상태 변경, 댓글, parent 집계(parent 자체의 team 상태에 반영) | | set-cycle <n> <ABC-123>… | issue를 cycle에 넣고 다른 것은 바꾸지 않습니다 |
| pr-check <ABC-123> [--pr N] | PR 병합 가능 여부: ready, wait(검사 진행 중) 또는 stop과 이유. 브랜치나 제목에 issue가 들어 있거나 본문이 issue를 닫는 PR만 포함되며 --pr로 여러 PR 중 하나를 고릅니다 | | pr-merged <ABC-123> --pr N | PR이 실제로 반영됐는지 확인합니다. GitHub가 병합됨을 표시하고 merge commit을 제공할 때만 종료 코드가 `0입니다 |
전역 플래그: --team KEY는 team key를 덮어쓰고, --pretty는 JSON을 들여 쓰며, `--out FILE은 전체 JSON을 파일에 쓰고 경로만 출력합니다. 커밋되지 않은 파일 목록은 앞의 20개와 총수로 제한합니다.
순위는 우선순위(Urgent 우선, 우선순위 없음은 마지막), milestone 목표 날짜, 오래된 순서입니다. parent는 완료되지 않은 sibling이 없을 때만 집계합니다. done 또는 canceled가 아닌 것은 모두 미완료로 계산합니다(목표가 Done이면 In Review도 포함).
mod
── Linear ─────────────────────────────────────────────────────────
◆ ENG-2919 In Progress · High
Core affiliate link builders
root branch · scope: web · parent ENG-2900 Details Hide
sessions ENG-2748 In Review (eng-2748) · ⚠ ENG-2912 In Progress (main)
- 프롬프트 위의 밴드: 현재 issue의 id, state, priority, title, scope, parent.
- Details pane(`/linear): description, sub-issue, 링크, 최신 댓글, Open in Linear.
- 자신의 issue만: 세션에는 자신이 맡은 issue가 표시됩니다. 직접 고정한 issue(
/linear ENG-123,/linear-workflow:issue-start ENG-123을 입력하거나 Claude가 말에서 시작한 issue), 또는 이 세션이 직접 전환한 브랜치 이름의 issue (alex/eng-2919-link-builders →ENG-2919)입니다. 같은 checkout에서 다른 라이브 세션이 그 issue를 맡았다면 그 세션에 남기고, 여기에는No Linear issue found와sessions 행을 표시합니다. feature branch에서 단독으로 연 세션도 issue를 가져옵니다. - 다른 세션(
sessions 행): 이 플러그인을 실행하는 컴퓨터의 모든 Claude Code 세션과 issue, checkout(main 또는 worktree 이름). - 충돌 경고: 같은 checkout에서 다른 issue를 작업하는 세션이 있거나(같은 브랜치와 작업 트리를 공유), 두 세션이 같은 issue를 작업하면 toast와 빨간색 ⚠를 표시합니다.
- 내 issue는 그대로입니다. 다른 세션이 공유 checkout을 다른 브랜치로 바꿔도 내 세션은 issue를 `held로 유지합니다. 해당 issue가 Done 또는 Canceled가 되거나 내 세션이 브랜치를 바꿀 때까지입니다.
- Scope drift(선택 사항): sub-project registry에서 issue에 표시된 sub-project 밖을 편집하면 toast가 뜹니다.
- 최신 상태 유지: Linear에 쓰는 턴(스킬의 transition,
linear-manager 에이전트, Linear MCP 쓰기)이 끝날 때 issue를 다시 가져오고, 그 외에는 매pollMinutes마다 가져옵니다. 상태가 바뀌면 toast로 알립니다.
| /linear | 기능 | | --- | --- | | /linear | Details pane 열기 |
| /linear ENG-123 | issue를 이 세션에 고정합니다. 이 세션이 다른 issue의 브랜치로 직접 바꿀 때까지 유지됩니다 | | /linear clear | 고정을 해제하고 브랜치를 다시 따릅니다 |
| /linear refresh | 지금 Linear에서 다시 가져옵니다 | | /linear hide / `show | 밴드를 숨기거나 표시합니다 |
요구 사항
- Claude Code 2.1.289 이상. Mods는 최근 기능이며 이 버전으로 플러그인을 빌드하고 테스트했습니다.
- CLI에는 Node.js 22.18 이상이 필요합니다(TypeScript를 직접 실행하며 build 단계가 없습니다).
- CLI와 mod에 사용할 Linear personal API key.
- 선택 사항: `linear-manager 에이전트용 Linear MCP 연결.
- 선택 사항: Linear's GitHub integration. PR을 issue에 연결하고 병합 시 이동시킵니다. 상태 변경이 멱등적이므로 이 연동 유무와 상관없이 스킬이 동작합니다.
- GitHub CLI `gh, lo
설치
먼저 작성자의 README에서 marketplace와 플러그인 이름을 확인하세요. 저장소 구조에 따라 명령어가 달라질 수 있습니다.
claude plugin marketplace add Sarimarcus/claude-code-plugins claude plugin install linear-workflow
원문 / README
Linear Workflow
Work Linear issues from Claude Code, from picking the next issue in the cycle to the merged PR. Linear stays up to date along the way, and the current issue is always shown above the prompt.
Overview
The plugin has four parts:
- Skills (slash commands) take an issue from the cycle to a merged PR:
issue-next→issue-start→ (work) →issue-review→issue-ship, plusissue-plan-cycleto fill the cycle. - A CLI (
bin/linear-workflow.mjs) runs the Linear and GitHub steps that need no judgment: fetching and ranking issues, status changes, cycle changes, PR checks. It's faster than an LLM and gives the same answer every time. Claude keeps the parts that need judgment: reading the issue, writing the code, the commit message, PR summary and comments. - An agent,
linear-manager, creates and edits issues, and stands in for the CLI when it can't reach Linear. - A mod: live code that shows the current issue above the prompt, lists your other Claude Code
sessions, and warns when two of them collide. It shares its code with the CLI (
lib/).
Claude Code namespaces plugin skills and agents, so the full names are
/linear-workflow:issue-start and linear-workflow:linear-manager. Type /issue and pick from
the menu.
Quick start
/plugin marketplace add Sarimarcus/claude-code-plugins
/plugin install linear-workflow@sarimarcus
- Create a Linear personal API key (Settings →
Security & access; see Linear's API docs) and set it:
export LINEAR_API_KEY=lin_api_…in your shell profile, or aLINEAR_API_KEY=line in your repo's git-ignored.env. The CLI and the mod both use it. - Optional: connect Linear's MCP server for the
linear-manageragent (the Linear connector on claude.ai, orclaude mcp add --transport http linear https://mcp.linear.app/mcp). - Run
/linear-workflow:issue-next.
Skills
/linear-workflow:issue-next
Picks what to work on next. Read-only. Runs on Haiku: it only presents the CLI's ranked list.
/linear-workflow:issue-next
Claude will:
- Fetch the active cycle's Todo and In Progress issues that are assigned to you and unblocked
- Replace an in-progress epic with its next unblocked sub-issue
- Rank them by priority, then milestone date, then age, and show the top 5 with a reason for each
- Offer to start the top one (
Y), another (ABC-140), or none
/linear-workflow:issue-start <ABC-123>
Starts work on an issue.
/linear-workflow:issue-start ENG-123
Claude will:
- Move the issue to In Progress
- Show its Context, Implementation and Scope, but not the Acceptance Criteria, which are for the reviewer
- Reproduce actionable comments verbatim and treat them as scope (a newer comment beats the description)
- Ask before continuing if the issue has open blockers
- Create Linear's branch for the issue, then start working without waiting
/linear-workflow:issue-review [ABC-123]
Puts the work up for review. Never merges or deploys.
/linear-workflow:issue-review
Claude will:
- Refuse if you're on the base branch, or on a branch that names another issue
- Check each acceptance criterion against the change, and ask before going on if one isn't met
- Run your checks (from
.claude/linear.json, or the obvious ones such asnpm test) - Commit only the files for this issue (asking about unrelated ones) with
(ENG-123)in the message - Push the branch and open a PR whose body says
Closes ENG-123 - Move the issue to In Review and post a completion comment
/linear-workflow:issue-ship [ABC-123]
Merges the reviewed PR and closes the issue.
/linear-workflow:issue-ship
Claude will:
- Refuse when there's no open PR, it's a draft, it has conflicts, changes were requested, checks failed, or work on the branch isn't in the PR yet
- Merge it (
gh pr merge, orgit merge --no-fflocally so yourpre-pushhooks run) - Check on GitHub that the PR really merged before touching Linear
- Move the issue to Done, and roll up the parent issue once all its sub-issues are finished
/linear-workflow:issue-plan-cycle
Fills the active cycle from the backlog. Runs on Haiku, like issue-next. The other skills use your
session's model, because they write code, judge acceptance criteria or merge.
Claude will:
- List unscheduled, unblocked Backlog and Todo issues by priority, holding back sub-issues whose parent is already in the cycle
- Ask which to add (
all,none, or a list of ids), then set the cycle on those issues and change nothing else
Without an id, issue-review and issue-ship use the session's issue, then the branch name, then
your issues in Linear. If the id was guessed, they show it first, and issue-ship asks you to
confirm it before merging.
The linear-manager agent
Use it for what the CLI doesn't do: filing issues, splitting a plan into sub-issues, labels, relations, milestones, searches ("use linear-manager to file a bug for…"). The skills also fall back to it when the CLI can't reach Linear. It follows the same rules as the CLI:
- passes names, not IDs (
state: "In Review",labels: ["Bug"],assignee: "me") - makes status changes idempotent: a no-op when the issue is already in that state
- checks a parent's sub-issues by asking whether an unfinished one exists, instead of listing them all
- never returns issue descriptions in lists, so long backlogs don't flood your conversation
- never edits files or runs git
The CLI
The skills call it as node "${CLAUDE_PLUGIN_ROOT}/bin/linear-workflow.mjs" <command>. You can run it
yourself from any repo. It prints compact JSON on stdout and one summary line on stderr, stating what
it examined. Exit codes: 0 ok, 1 error or bad input, 2 refused (needs a human).
Built for a small context. Each skill step makes one call, and each call returns only the fields that step reads. Every tool call is a model turn that re-reads the conversation, so fewer, smaller calls are the main saving. The start view doesn't contain the acceptance criteria at all, so keeping them out of the implementer's view doesn't depend on Claude following an instruction.
| One call per skill step | Returns |
| --- | --- |
| start <ABC-123> | The issue to work from (description without acceptance criteria, blockers, branch name, every comment verbatim) and the repo state (branch, base, branching setting, uncommitted files) |
| review [ABC-123] | Which issue (argument, branch name, or your only started issue), its acceptance criteria, and the repo state: base branch, the issue the branch names, this branch's open PR, checks, uncommitted files |
| ship [ABC-123] [--pr N] | Which issue, merge settings, and the PR verdict (as pr-check) |
| Single steps | What it does |
| --- | --- |
| config | Repo root, current branch and the issue its name points to (branchIssue), resolved base branch (baseBranch, else origin's default) and whether you're on it, this branch's open PR, team keys, whether a key was found, .claude/linear.json |
| resolve [ABC-123\|123] | Which issue to act on: the argument, then the branch name, then your only started issue. Exit 2 with candidates when it can't tell |
| issue <ABC-123> [--view start\|review] | The full issue (description, parsed acceptanceCriteria, blockers, sub-issues, links, branch name, every comment), or just one skill's view of it |
| queue [--limit N] | The active cycle's Todo and In Progress issues (not In Review, not blocked), epics replaced by their next sub-issue, ranked, each with its rank and display-ready urgency (overdue 3d, ends in 5d…) |
| plan-cycle [--limit N] | Unscheduled, unblocked backlog issues for the active cycle, ranked |
| transition <ABC-123> <state> [--comment TEXT \| --comment-file F] | Idempotent status change, comment, parent roll-up (into the parent's own team states) |
| set-cycle <n> <ABC-123>… | Put issues in a cycle and change nothing else |
| pr-check <ABC-123> [--pr N] | Whether the issue's PR can merge: ready, wait (checks running) or stop, with reasons. Only PRs whose branch or title names the issue, or whose body closes it, count; --pr picks one of several |
| pr-merged <ABC-123> --pr N | Whether that PR really landed: exit 0 only when GitHub says merged and names the merge commit |
Global flags: --team KEY overrides the team key; --pretty indents the JSON; --out FILE writes
the full JSON to a file and prints only its path. Uncommitted-file lists are capped at the first 20,
with the total count.
Ranking is priority (Urgent first, no priority last), then milestone target date, then age. A parent rolls up only when no sibling is unfinished, and anything not done or canceled counts as unfinished (In Review included when the target is Done).
The mod
── Linear ─────────────────────────────────────────────────────────
◆ ENG-2919 In Progress · High
Core affiliate link builders
root branch · scope: web · parent ENG-2900 Details Hide
sessions ENG-2748 In Review (eng-2748) · ⚠ ENG-2912 In Progress (main)
- Band above the prompt: the current issue's id, state, priority, title, scope and parent.
- Details pane (
/linear): description, sub-issues, links, latest comments, and Open in Linear. - Only your own issue: a session shows an issue it took on: one you pinned (
/linear ENG-123, typing/linear-workflow:issue-start ENG-123, or Claude starting it from your words), or the issue in a branch name (alex/eng-2919-link-builders→ENG-2919) that this session switched to itself. A branch issue that another live session in the same checkout has claimed is left to that session, and yours showsNo Linear issue foundand thesessionsrow. A lone session opened on a feature branch still picks its issue up. - Other sessions (
sessionsrow): every Claude Code session on your machine that runs the plugin, with its issue and checkout (mainor the worktree name). - Conflict warnings: a toast and a red ⚠ when another session in the same checkout is on a different issue (you share one branch and one working tree), or two sessions are on the same issue.
- Your issue stays put. If another session switches the shared checkout to another branch, your
session keeps its issue (
held) until that issue is Done or Canceled, or your own session switches branches. - Scope drift (optional): with a sub-project registry, an edit outside the issue's labelled sub-projects raises a toast.
- Stays current: the issue is fetched again at the end of any turn that wrote to Linear (a
skill's transition, the
linear-manageragent, a Linear MCP write), and everypollMinutesotherwise. A toast says when its state changed.
| /linear | What it does |
| --- | --- |
| /linear | Open the details pane |
| /linear ENG-123 | Pin an issue to this session. The pin lasts until this session itself switches to another issue's branch |
| /linear clear | Drop the pin and follow the branch again |
| /linear refresh | Re-fetch from Linear now |
| /linear hide / show | Hide or show the band |
Requirements
- Claude Code 2.1.289 or later. Mods are a recent feature, and this is the version the plugin was built and tested on.
- Node.js 22.18 or later for the CLI (it runs TypeScript directly, no build step).
- A Linear personal API key, for the CLI and the mod.
- Optional: a Linear MCP connection, for the
linear-manageragent. - Optional: Linear's GitHub integration, which links PRs to issues and moves them on merge. The skills work with or without it, because their transitions are idempotent.
- GitHub CLI
gh, logged in, forissue-reviewandissue-ship. - git 2.23 or later (
git switch).
Configuration
Nothing is required beyond the API key. Everything else is inferred, and each layer below overrides the one before it:
- Built-in defaults: GitHub flow, a branch per issue, standard Linear state names.
- Plugin settings (per user): the API key, team keys, polling, the session list.
- Project settings (
.claude/linear.json, per repo, committed): states, branching, checks, merge method, issue template. - Project conventions (
CLAUDE.md,CONTRIBUTING.md, the PR template): the skills follow them for commit messages, PR bodies and anything else they describe. - Your own skills: see Customizing.
Plugin settings
| Option | Default | Meaning |
| --- | --- | --- |
| linearApiKey | — | Linear API key, stored as a secret (secret options are not shown in /config). If unset: LINEAR_API_KEY in the environment, then in <repo>/.env |
| teamKeys | (auto) | Team keys to find in branch names, for repos whose .claude/linear.json sets no teamKey. Else the keys of the teams you belong to. The mod passes this to the CLI too |
| pinCommand | issue-start | Skill whose first argument pins an issue to the session. Empty disables it |
| pollMinutes | 5 | How often the mod refreshes the issue |
| showOtherSessions | true | Share this session's issue with your other sessions and list theirs |
| registryFile | — | Sub-project registry for scope and drift (monorepos). Empty: off |
Project settings (.claude/linear.json)
Optional, all fields optional. A missing value is inferred, or the skill asks once. See
linear.example.json.
{
"team": "Engineering",
"teamKey": "ENG",
"project": "Website",
"assignee": "me",
"baseBranch": "main",
"checks": ["npm run build", "npm test"],
"mergeMethod": "squash",
"deleteBranch": true,
"branching": "create",
"states": { "inProgress": "Doing", "inReview": "Ready for QA", "done": "Shipped" },
"issueTemplate": ".github/linear-issue.md"
}
| Field | Default | Meaning |
| --- | --- | --- |
| team, teamKey, project, assignee | inferred | Where the skills look and file issues. teamKey also lets you type bare numbers (123) |
| baseBranch | origin's default branch | Base for new branches and PRs |
| checks | inferred (npm test, make test…) | Commands issue-review runs before committing |
| mergeMethod | merge | merge, squash, rebase, or local (git merge --no-ff + push, so your own pre-push hooks run) |
| deleteBranch | false | Delete the branch after merging |
| branching | create | issue-start creates the issue's branch (create), asks (ask), or stays on the current one (none) |
| states | Linear's usual names | Your team's names for In Progress, In Review and Done, used by every transition and by the queue's review filter |
| issueTemplate | 4-section template | A markdown file the agent uses for new issue descriptions |
Sub-project registry (monorepos)
Set the registryFile plugin setting to a JSON file at the repo root:
{ "projects": [ { "key": "web", "path": "apps/web" }, { "key": "api", "path": "services/api" } ] }
An issue labelled web (or whose parent is) is scoped to apps/web, so editing
services/api/... raises a drift toast once per issue and sub-project. An issue with no matching
label is scoped to everything.
Customizing
- Settings first. Most differences between teams (state names, branching, checks, merge method,
templates) are settings above, and project conventions in
CLAUDE.mdtake precedence over the skills' defaults. - Replace a skill. Copy
skills/<name>/SKILL.mdinto your project's.claude/skills/<name>/and edit it. Yours runs as/<name>, and the plugin's stays available as/linear-workflow:<name>. Keep calling the CLI for the deterministic steps so the checks stay the same. If you renameissue-start, set thepinCommandplugin setting to your skill's name so the band follows it. - Use the CLI directly. It works without the skills, in your own scripts or CI:
node <plugin>/bin/linear-workflow.mjs queue. - Turn parts off.
/linear hidehides the band;showOtherSessions: falsestops the session list; leavingregistryFileempty keeps scope and drift checks off.
Safety
issue-plan-cyclecan't be started by Claude on its own. You have to type it.issue-reviewandissue-shipcan also be invoked by Claude. When Claude does that without you asking to ship,issue-shipconfirms the issue and PR with you before merging.- Typing
issue-revieworissue-shipyourself authorizes the push or merge for that issue only. - The skills never run
git push --force,git reset --hard,git clean,git checkout -- .,git restore ., a baregit stashorgit commit --amend: each can destroy work that isn't yours. Every eval checks this. The only push to the base branch is the merge itself, whenissue-shipusesmergeMethod: local. issue-reviewrefuses on a branch that names another issue, so work never lands under the wrong issue.issue-shipchecks GitHub before writing to Linear, so a merge that failed is never reported as done.
Best practices
- One issue per session. Several sessions work best in separate
git worktrees. In a shared checkout the band warns you, but the shared tree is still shared. - Put the steps of the work in the issue (Context, Implementation, Scope).
issue-startgives Claude those sections and leaves out the acceptance criteria. - Put decisions made after filing in comments, because
issue-starttreats them as scope. - Set
checksin.claude/linear.jsonsoissue-reviewruns exactly what your CI runs.
Privacy and data handling
- The CLI and the mod send GraphQL queries and updates to
api.linear.appwith your key. They never write it to disk. When you set the key as the secret plugin option, the mod exports it asLINEAR_API_KEYto the session's shell so the CLI can use it. - The CLI's
pr-checkand the review and ship skills use theghCLI. The agent uses your Linear MCP connection. What any of them return goes into the conversation like any tool output. - Session list: each session writes
~/.claude/linear-workflow/sessions/<session-id>.json(checkout path, issue id, title, state) every minute. These files stay on your machine and are deleted when the session ends, or after a day if it crashed. To turn this off, setshowOtherSessions: false.
Troubleshooting
No band. It only shows when the branch names an issue or one is pinned. Check teamKeys, or
pin one with /linear ENG-123. If the band says Linear API key not found, set the key (see
Configuration).
The details pane doesn't open by itself. A pane the session opens on its own needs a wide
terminal (about 144 columns). /linear opens it at any width.
A skill says LINEAR_API_KEY not set. Set the key (Quick start, step 1). Run
node "<plugin>/bin/linear-workflow.mjs" config to see what the CLI finds.
The agent says Linear tools are missing. Connect the Linear MCP server (Quick start, step 2), then restart the session.
gh errors in issue-review or issue-ship. Run gh auth status. If the repository doesn't
allow your mergeMethod, issue-ship asks which one to use.
The band shows held. Another session moved the shared branch, and yours kept its issue (until it is Done or Canceled).
/linear clear follows the branch again.
Limitations
- Single-repository workflow (one PR per issue). Multi-repo or submodule shipping isn't supported.
- The skills follow GitHub's PR model through
gh. GitLab and Bitbucket aren't supported. - The mod sees branch switches made through Claude Code, but not ones made in your own terminal.
Use
/linear clearafter those. - The shared logic (ranking, roll-up, state matching, PR verdicts, mod helpers) has unit tests, including transitions against a fake Linear API. The skills have evals that check they follow the CLI's verdicts, run against canned CLI answers. Nothing runs end to end against a real Linear workspace or GitHub repo.
Development
claude --plugin-dir . # from this folder: load from source, hot-reloads on save
claude plugin validate .
claude plugin test . # unit tests (lib/ and the mod)
Dev tooling lives at the repo root, outside the plugin, so installing the plugin pulls in none of it:
npm install # at the repo root: TypeScript and Node types
npm run typecheck # mod + lib, then CLI + lib
npm test # same as claude plugin test
npm run eval # skill evals, then writes evals/RESULTS.md
Evals (evals/) check the skills' guardrails: issue-ship stops on a missing, draft or failing PR
asks when several PRs or running checks are involved, and doesn't merge on its own when Claude reaches it
without being asked to ship; issue-review refuses on the base branch
or another issue's branch, flags unmet acceptance criteria and never stages unrelated files;
no skill ever runs a destructive git command; issue-start never stashes or discards a dirty tree, quotes
actionable comments verbatim and hides acceptance criteria; issue-next keeps the CLI's order and
urgency. Each case's scaffold.sh builds a git repo and canned CLI answers in .lw/; with
EVAL_LINEAR_WORKFLOW_FIXTURES set, the CLI answers from there (and logs each call to calls.log)
instead of calling Linear or GitHub. Granting Bash needs Claude Code's sandbox: on Linux,
apt install bubblewrap socat. Each case runs 3 times, so a full run costs real tokens (about $3). The latest results are in
evals/RESULTS.md: commit it with each release.
The engine generates .claude-plugin/types/ when the mod loads, and the type-check needs it.
Layout: lib/ is shared code with no Node or browser APIs; hooks/ is the mod; bin/ is the CLI.
Author
Olivier Depiesse (@Sarimarcus)
Version
See CHANGELOG.md for the current version and its history. The version lives only in
plugin.json (and the marketplace entry): don't write it here.
License
MIT

