Linear issue tracking workflow — manages commits, branches, PRs, issue creation, session kickoff, and setup in Linear-linked repos. Activate for any Linear context, issue references (e.g. ENG-123), repos with .claude/linear-sync.json, or when session-start hook injects [LINEAR-SETUP], [LINEAR-DIGEST], or Linear Sync directives.
From linear-syncnpx claudepluginhub b-open-io/claude-plugins --plugin linear-syncThis skill uses the workspace's default tool permissions.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Analyzes current state and user query to answer BMad questions or recommend the next skill(s) to use. Use when user asks for help, bmad help, what to do next, or what to start with in BMad.
This system keeps Linear and GitHub in sync automatically. Linear API queries go through the linear-sync:api subagent (foreground or background), while simple mutations use direct MCP tool calls from the main agent.
Subagent type: When using the Agent tool, always use
subagent_type: "linear-sync:api"(fully-qualified plugin:agent name). Do NOT use just"linear-sync"— that will fail.
At the start of every session, the linear-session-start hook fires and checks the repo:
workspace: "none"): The hook is silent. Do nothing related to Linear.[LINEAR-SETUP] directive. Follow the setup wizard rules below. If a .linear-sync-template.json is found, the hook also injects [LINEAR-TEMPLATE] with defaults to pre-fill.[LINEAR-SETUP] directive to reconfigure or opt out.[LINEAR-MCP-MISSING] is present, the Linear MCP server is not configured. Show the user the install instructions from the hook context. The plugin will fall back to linear-api.sh until the MCP server is installed, but MCP is the preferred path.When the hook injects config context for a linked repo:
Step 1: Digest and stale branches
[LINEAR-DIGEST] data is present in hook context): The session-start hook pre-fetches your active issues inline. Show the digest briefly (1 line) before asking what to work on.git push or gh pr create — no action needed at session start.[STALE-BRANCHES] is present): Show a brief warning. Example: "Heads up: branch dan/ENG-100-old-feature has had no commits in 7 days."Step 2: Resume or ask
If the hook context includes last_issue: <ISSUE_ID>, offer to resume that issue first:
Use AskUserQuestion: "What are you working on today in <repo>?"
linear-sync:api subagent (background) to fetch the issue summary. Include mcp_server and scripts_dir from hook context in the delegation prompt (see Execution Model). After fetching, save last_issue and last_issue_title for this repo (direct Read/Write). Check for blockers in the response and warn if any.linear-sync:api subagent (background) to fetch the dev's assigned in-progress issues ("Fetch My Issues" task). Include mcp_server and scripts_dir from hook context. Present the returned list as AskUserQuestion choices, plus an option to "Enter an issue ID manually". After selection, save last_issue and last_issue_title for this repo (direct Read/Write). Check for blockers in the response and warn if any.linear-sync:api subagent (foreground) to create a ticket in the correct project with the repo label. Include mcp_server and scripts_dir from hook context. After creation, offer to assign to current cycle (see Cycle Assignment below). Use the returned issue ID going forward.If no last_issue is present, skip option 1 and start with options 2-4 (renumber accordingly).
When the dev picks any issue (resume, existing, or new): If the issue is unassigned, auto-assign it via direct MCP call (mcp__<server>__update_issue) — see Execution Model, Tier 1. No need to ask — if they're working on it, they should own it.
Keep the kickoff brief and natural: "What are you working on today in <repo>?"
When a [LINEAR-SETUP] directive is injected:
workspace: "none", write back) and move on.linear-sync:api subagent in foreground mode to fetch real data from Linear MCP (workspaces, teams, projects, labels). Include mcp_server and scripts_dir from hook context (or from state file if setting up a new workspace).repo:<repo-name> as the default.github_org in the committed config..claude/linear-sync.json to the repo root with the shared config.workspace reference to the local state file for credential routing. Project, team, and label live in the repo-level config..claude/linear-sync.json as part of the Link Repo task.These conventions are mechanically enforced by hooks. They apply ONLY to repos with a valid workspace link.
| Action | Requirement | Enforcement |
|---|---|---|
git commit -m "..." | Issue ID in message (e.g., ENG-123: fix bug) | Hook blocks with exit 2 |
git checkout -b / git switch -c | Issue ID in branch name (e.g., ENG-123-fix-bug) | Hook blocks with exit 2 |
gh pr create --title "..." | Issue ID in PR title (e.g., ENG-123: Fix the bug) | Hook blocks with exit 2 |
git push | Cross-issue commit check | Hook allows with advisory context |
| Issue creation | Repo label auto-applied and auto-created if missing | Subagent handles |
| Issue creation | Check for duplicates first | Subagent search + AskUserQuestion |
| Issue creation | Infer priority from keywords | AskUserQuestion if detected |
| Issue creation | Offer cycle/sprint assignment | AskUserQuestion if active cycle |
| Issue picked / resumed | Auto-assign if unassigned | Direct MCP (update_issue) |
gh pr create (after success) | Offer a progress comment on the Linear issue | PostToolUse hook reminder + AskUserQuestion |
git push (final push) | Offer a progress comment on the Linear issue | PostToolUse hook reminder + AskUserQuestion |
| Session ending / major milestone | Offer a progress comment on the Linear issue | AskUserQuestion |
IMPORTANT: You MUST offer a comment at every natural stopping point. Never post automatically, but always ask.
The PostToolUse hook automatically injects a [Linear Comment Reminder] after git push and gh pr create in linked repos. When you see this reminder, follow the comment flow below.
Natural stopping points (offer every time):
Smart comment drafts: Before drafting a comment, run git log main..HEAD --oneline (or the appropriate base branch) to gather the commit history for this branch. Use the commit messages to auto-draft a concise progress summary.
Use AskUserQuestion with a draft comment:
I can add a quick update to ENG-423:
"Added sliding window rate limiter (3 commits):
- Redis-backed per-user rate limiting
- Configurable window size and limits
- 94% test coverage
PR: #142"
1. Post this comment
2. Let me edit it
3. Skip
If they pick "edit", ask them what they'd like it to say. Never post without showing them exactly what will be posted first. If they skip, don't ask again until the next stopping point.
Posting comments: Use direct MCP call (mcp__<server>__create_comment) — see Execution Model, Tier 1. No subagent needed for simple mutations.
If the dev explicitly asks to change a status, do it. No pushback, no warnings. Use direct MCP call (mcp__<server>__update_issue) and confirm.
For automatic status changes, only act at these moments:
Don't automatically change status beyond those two cases. The Linear <-> GitHub integration handles the rest.
Commits in linked repos must include an issue ID (e.g., ENG-123: description). Do NOT append Co-Authored-By lines to commit messages. Keep commit messages clean: just the issue ID prefix and a concise description.
Auto-generate branch names from the issue ID and title. Slugify and truncate the description portion to keep the total branch name under 50 characters.
Examples:
alice/ENG-456-add-sliding-window-ratealice/CP-89-fix-auth-timeout-mobileKeep the meaningful words, drop filler. The dev never manually names branches in a linked repo.
When a commit, branch, or PR is blocked by the hook for missing an issue ID:
linear-sync:api subagent (foreground) to create the ticket. Include mcp_server and scripts_dir from hook context.Before creating any new issue:
linear-sync:api subagent (background) with the "Search Issues" task. Include mcp_server and scripts_dir from hook context.When an issue is fetched, check for blocker warnings. If blockers are present:
When gh pr create is about to run and you have issue context:
## Summary
<1-2 sentence summary from issue context>
## Linear Issue
<ISSUE_ID>: <title>
## Changes
<bullet points from `git log main..HEAD --oneline`>
## Acceptance Criteria
<from issue description, or "See Linear issue" if none>
--title.When creating a new issue:
linear-sync:api subagent (foreground) to fetch the active cycle for the team. Include mcp_server and scripts_dir from hook context.mcp__<server>__update_issue with cycleId) — no subagent needed.Scan descriptions for urgency signals:
| Keywords | Suggested Priority |
|---|---|
urgent, asap, critical, emergency, p0, hotfix, production down, outage | 1 (Urgent) |
important, high priority, p1, blocker, blocking, regression | 2 (High) |
bug, fix, broken, error, p2 | 3 (Medium) |
nice to have, low priority, p3, p4, when possible, minor, cleanup, chore, refactor | 4 (Low) |
If keywords detected, use AskUserQuestion to confirm. If no keywords match, create without priority.
If the commit guard hook injects a [CROSS-ISSUE-COMMITS] advisory on push, show it: "Advisory: This branch has commits referencing different issues (ENG-123, ENG-456). This is usually fine for related work, but you may want to split into separate branches if the work is unrelated." This is a warning, not a block.
If the session-start digest mentions closed issues without linked PRs, surface it briefly: "Note: ENG-123 was marked Done but has no linked PR." This is informational only.
If a .linear-sync-template.json exists in the repo root and the hook injects [LINEAR-TEMPLATE], use its values as defaults during the setup wizard. Present them for confirmation: "Found a team config template. Use these defaults? Workspace: X, Project: Y, Team: Z, Label: W". The dev can override any value.
CRITICAL — Workspace isolation: Every subagent delegation and every direct MCP call MUST use the correct workspace's MCP server. The session-start hook injects
mcp_serverandscripts_dirin its context — these MUST be forwarded to the subagent in every delegation prompt. Using the wrong server routes operations to the wrong Linear workspace. Never omit, never default.
Operations use five tiers to minimize context consumption and maximize performance:
sync-github-issues.sh after git push / gh pr create in linked repos. Injects [Linear Comment Reminder] with the result.linear-api.sh. Result appears in [LINEAR-DIGEST] context.For fire-and-forget mutations the main agent handles directly using mcp__<server>__<tool>:
mcp__<server>__update_issue with assigneeIdmcp__<server>__update_issue with cycleIdmcp__<server>__create_commentmcp__<server>__update_issue with stateIdmcp__<server>__get_issue for compact inline resultsDetermine <server> from the mcp_server field in session-start context (e.g., mcp_server: linear-crystalpeak). NEVER default to linear — using the wrong server routes to the wrong workspace. If mcp_server is missing from hook context, read ~/.claude/linear-sync/state.json, find the workspace for the current repo, and use its mcp_server field. If still missing, delegate to the linear-sync:api subagent (foreground) to resolve it. These are auto-approved MCP tool calls — no permission prompts needed.
linear-sync:api)For multi-step operations where the main agent doesn't need the result immediately. Subagent uses MCP tools internally, returns concise 1-3 line summaries:
linear-sync:api)For operations where the main agent blocks on the result:
linear-api.sh (fallback only)For operations MCP tools can't handle, or for hook scripts running outside agent context. The linear-api-allow.sh PreToolUse hook auto-approves these calls. The script auto-detects the workspace MCP server from .claude/linear-sync.json + state file when no server name is passed — but always pass the server name explicitly when you have it.
Fallback notes: The Bash tool escapes ! to \! even inside single quotes, breaking GraphQL non-null types like CommentCreateInput!. If you must use linear-api.sh, use printf on a separate line to construct queries containing !:
SCRIPTS_DIR="/path/to/scripts"
QUERY=$(printf 'mutation($input: CommentCreateInput%s) { commentCreate(input: $input) { comment { id } } }' '!')
bash "$SCRIPTS_DIR/linear-api.sh" server-name "$QUERY" '{"input": {"issueId": "...", "body": "..."}}'
CRITICAL: Put each variable assignment and the bash call on separate lines — never chain with &&. The auto-approve hook validates each line independently and rejects &&/||/; chains. Using && will cause the user to see a manual approval prompt.
When delegating to the subagent, always include the mcp_server and scripts_dir from the session-start hook context in your prompt so the subagent knows which MCP server to use and where linear-api.sh is for fallback. Example: "Fetch issue summary for PEAK-123. mcp_server: linear-crystalpeak, scripts_dir: /path/to/scripts"
Always batch independent operations in the same message. Claude can make multiple tool calls simultaneously when they don't depend on each other. Key patterns:
update_issue MCP call in the same message when both are ready.Sequential only when dependent: A mutation that needs data from a query must wait for the query to complete first. But two independent operations should always run in parallel.
Use the Read and Write tools for state file updates — no permission prompts, no subagent overhead:
~/.claude/linear-sync/state.json, update repos.<repo>.last_issue and repos.<repo>.last_issue_title, Write backrepos.<repo>.workspace to "none", Write backThis skill orchestrates components at the plugin root (path injected by session-start hook as scripts_dir):
agents/api.md — handles Linear API queries (foreground and background modes)hooks/scripts/linear-session-start.sh (session init + inline digest), linear-commit-guard.sh (commit/branch/PR enforcement), linear-prompt-check.sh (issue reference injection), linear-post-push-sync.sh (GitHub sync + comment reminder)scripts/linear-api.sh (API wrapper), scripts/sync-github-issues.sh (GH sync)~/.claude/linear-sync/state.json (credential routing, session state)