.agents/skills/linear-project-update/SKILL.md
You are helping the user draft a status update for a Linear project they lead. The end-state is either (a) a posted update plus an optional target-date change, applied only with the user's explicit go-ahead in this turn, or (b) a draft the user takes and posts themselves.
The user owns the words that go out under their name. Your job is to give them a strong starting point and clear options, then get out of the way. Never post or change anything without explicit confirmation in this turn.
If the user provided a project (URL, slug, or UUID), pass whatever they gave you straight to mcp__claude_ai_Linear__get_project as query and extract the id (UUID) from the response. Linear's MCP accepts all three forms — don't try to parse URLs yourself.
If they did not provide one, help them pick:
Get the current user's ID. Call mcp__claude_ai_Linear__get_user with query: "me" and extract the id field. You'll need it for filtering in step 3.
List the user's projects. Call mcp__claude_ai_Linear__list_projects with member: "me" and orderBy: "updatedAt". The member: "me" filter returns projects the user is a member of or leads — exactly the set you need, in a single call. In practice this returns a small list (usually <30 across all teams) and hasNextPage is false; paginate only if it isn't.
Do not list projects per team and filter client-side. list_projects has no direct lead filter, and big workspaces have hundreds of projects per team — paginating teams is slow, expensive, and unnecessary when member: "me" does the job in one call.
Filter to led + active projects. From the response, keep only projects where lead.id == <current-user-id>. Then drop any with status.type of completed or canceled — updating a Done or Canceled project almost never makes sense, and surfacing them clutters the picker. (If after this filter you have zero projects, stop and tell the user; don't fabricate. Offer the URL fallback: "paste a project URL if you want to update one you don't lead.")
Fetch the last-update timestamp per project, in parallel. The project payload doesn't carry it. For each surviving project, call mcp__claude_ai_Linear__get_status_updates with type: "project", project: <uuid>, limit: 1, orderBy: "createdAt" — all in the same turn, not sequentially.
Sort:
Present the list with AskUserQuestion. Format each option so the user can see at a glance which projects need attention:
<Project name> — status: <Status> · target: <YYYY-MM-DD or "—"> · last update: <X days ago or "never">
Once picked, continue with that project's UUID.
Invoke the linear-project-status skill on the resolved project UUID. That skill produces the health verdict, top concerns, dimension breakdown, recent activity, and blocker analysis you'll need to write a useful update.
Keep the audit output handy — you'll cite specifics in the proposal (e.g., "3 issues stale > 14 days", "target date in 12 days with 8 issues still open", "no movement on issues in the last 7 days"). Generic updates are useless; concrete ones build trust.
The audit tells you what Linear knows. The user knows what Linear doesn't. Ask once, broadly, rather than peppering them with separate questions:
"Anything I should know that isn't in Linear before I draft this? PTO or absences (yours or the team's), blockers, competing priorities, or general context you want stakeholders to hear. Or just say 'no' to skip."
Wait for their reply. Treat any short negation as a valid skip — "no", "nope", "skip", "nothing", or an empty reply all mean "proceed without extra context". Don't re-prompt.
Synthesize the audit + the user's context into two things: a target-date recommendation and an update body.
Recommend whatever the audit and the user's context actually support — but be cautious about small moves. A few-day push tends to signal indecision and erodes trust in the date.
warn/bad, or the date is already in the past): recommend a new date with real headroom given the open scope. Default to moving it out by at least a week — but if a shorter move genuinely fits the situation (e.g., a launch tied to a known external date a few days out, or the user's context makes a sub-week shift obviously right), recommend that and explain why.When recommending any new date, justify it in one line tied to audit specifics: "8 of 15 issues still open with 5 days to target — propose pushing to <date>."
A good status update is:
Cover, in roughly this order:
Match the user's voice. Read the last 2–3 status updates on this project before drafting. If the user writes in conversational paragraphs, don't return a bulleted formal report. If they use bullets and headers, match that. Mismatched tone is the fastest way to make the user feel the draft isn't theirs.
Show both proposals together in the chat:
**Proposed target date:** <new date or "no change"> — <one-line reason>
**Proposed update:**
<draft body>
Then use AskUserQuestion to offer three choices:
If they pick "Adjust first", treat it as collaborative editing, not a from-scratch rewrite. Preserve what they liked. Loop back through Step 5 after each revision.
Only if the user explicitly approved in Step 5:
mcp__claude_ai_Linear__save_project with the new targetDate.mcp__claude_ai_Linear__save_status_update with the project ID and final body. Set health from the audit verdict (Green → onTrack, Yellow → atRisk, Red → offTrack); if Linear's MCP rejects those enum values, check the schema and pick the closest valid one rather than guessing repeatedly.If any call fails, surface the exact error and stop. Do not retry silently or fudge the user's understanding of what's actually in Linear.