Manage a Linear project board: fetch issues, assess state, plan waves by dependency, and update issue status. Use for "/pm", "/pm status", "/pm plan", "/pm wave".
From architectnpx claudepluginhub jabberlockie/the-human-stack-plugins-public --plugin architectThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides implementation of event-driven hooks in Claude Code plugins using prompt-based validation and bash commands for PreToolUse, Stop, and session events.
Fetch the Linear board, assess what is done/in-progress/blocked, build a dependency graph, plan parallel work waves, and update issue states.
Preferred: Use Linear MCP tools when available (mcp__plugin_linear_linear_*).
Fallback: GraphQL via curl:
LINEAR_TOKEN=$(op-connect gc364u5r25bfme5mrvd3jj5yke credential)
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: $LINEAR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "<graphql>"}'
| Invocation | Action |
|---|---|
/pm | Full board overview: fetch, assess, and summarize |
/pm plan | Dependency graph + wave plan |
/pm wave | Show the current executable wave (no blockers) |
Determine the Linear team key from context:
docs/architect/master_intent.md for the active team key (e.g. HOARD)Fetch team details:
{
team(id: "<team-key-or-id>") {
id
name
key
projects { nodes { id name } }
states { nodes { id name type position } }
}
}
Alternative: query by key filter:
{
teams(filter: { key: { eq: "HOARD" } }) {
nodes { id name key states { nodes { id name type } } }
}
}
Query all issues for the team, including their state and blocker relations:
{
issues(
filter: { team: { key: { eq: "HOARD" } } }
orderBy: priority
) {
nodes {
identifier
title
priority
state { id name type }
blockedBy { nodes { identifier title state { name type } } }
blocks { nodes { identifier title } }
assignee { name }
estimate
labels { nodes { name } }
updatedAt
}
}
}
Build a local board map keyed by identifier.
Categorize issues by state type:
| State Type | State Names | Meaning |
|---|---|---|
unstarted | Backlog, Todo | Not yet started |
started | In Progress, In Review | Active work |
completed | Done | Finished |
cancelled | Cancelled | Dropped |
For each unstarted issue, check if it is blocked:
blockedBy issue that is NOT in completed stateReport:
Board: <team> (<N> issues)
Done: X
In Progress: X
In Review: X
Todo: X (Y unblocked, Z blocked)
Backlog: X
For each unstarted issue, resolve its full blocker chain:
Output the graph as a text tree:
Wave 1 (executable now):
HOARD-20 essence schema (P1)
HOARD-22 ledger table (P2)
Wave 2 (unblocked after Wave 1):
HOARD-26 RLS policies -- blocked by HOARD-20, HOARD-22
Wave 3:
HOARD-30 bootstrap -- blocked by HOARD-26
For the current wave, identify which items can run in parallel:
Output a parallel execution plan:
Current wave (can run in parallel):
Thread A: HOARD-20 -> HOARD-22
Thread B: HOARD-21 (independent)
Start here: HOARD-20, HOARD-21 (no blockers)
To move an issue to a new state:
{
team(id: "<team-id>") {
states { nodes { id name type } }
}
}
mutation {
issueUpdate(id: "<issue-id>", input: { stateId: "<state-id>" }) {
success
issue { identifier state { name } }
}
}
Or using MCP: mcp__plugin_linear_linear_update_issue
Confirm the update succeeded before reporting to the user.
BOARD: <team-name> (<N> total)
Done: X
In Progress: X
Todo: X (Y ready)
Blocked: Z
WAVE 1 (start now):
[HOARD-XX] Title (P1)
[HOARD-YY] Title (P2)
WAVE 2 (after wave 1):
[HOARD-ZZ] Title -- blocked by HOARD-XX