plugins/linear-orchestrator/skills/planner-bridge/SKILL.md
This skill should be used when implementing or debugging two-way sync between Linear issues and Microsoft Planner via Microsoft Graph delta queries. Activates on "planner sync", "planner bridge", "microsoft planner", "graph delta", "tasks.readwrite".
npx skillsauth add markus41/claude Microsoft Planner ↔ Linear BridgeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference: https://learn.microsoft.com/en-us/graph/api/resources/planner-overview
App-only (client credentials) flow:
GRAPH_CLIENT_ID, GRAPH_CLIENT_SECRET, GRAPH_TENANT_IDhttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/tokenTasks.ReadWrite.All, Group.Read.All, User.Read.All, Files.ReadWrite.All (for attachment mirror)const tokenRes = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
method: "POST",
body: new URLSearchParams({
client_id, client_secret,
grant_type: "client_credentials",
scope: "https://graph.microsoft.com/.default"
})
});
Tokens expire at 60 min; refresh proactively at 50 min.
Initial bootstrap:
GET /planner/plans/{planId}/tasks/delta
Returns first batch + @odata.nextLink (for paging) and eventually @odata.deltaLink (the cursor).
Subsequent polls:
GET <deltaLink>
Returns only changed tasks since the last call.
The bridge stores deltaLink per plan in lib/state.ts. TTL is 30 days; on expiry, full re-bootstrap.
| Planner field | Linear field |
|---------------|--------------|
| title | title |
| details.description | description (markdown) |
| bucketId | state (via bucket → state map) |
| assignments (AAD user IDs) | assignee (via email) |
| dueDateTime | dueDate |
| percentComplete | state (0=Triage, 50=In Progress, 100=Done) |
| appliedCategories | priority + first label |
| details.checklist | sub-issues (mapped 1:1) |
| details.references | attachments (link-only) |
| Linear → Planner | Planner → Linear |
|------------------|------------------|
| Webhook on Issue create/update → POST/PATCH /planner/tasks/{id} | Delta poll → GraphQL mutations |
| Webhook on Comment create → no direct equivalent; appended to task description with timestamp | Task description change → re-fetch issue, reconcile |
| Webhook on Reaction → ignored | Task appliedCategories change → label add/remove |
By email (case-insensitive). If Linear user's email isn't in AAD, the bridge:
GET /users?$filter=mail eq '[email protected]' returns the AAD user. Cache in SQLite for 24h.
Planner has no real sub-tasks. Linear sub-issues map to entries in details.checklist (max 20 per task). The bridge:
customAttributes on the Planner sideisChecked: true), transitions the corresponding Linear sub-issue to "Done"Planner has 4 priority slots (1-10 mapped to "Urgent", "Important", "Medium", "Low"). Linear's 5 levels (None, Urgent, High, Medium, Low) collapse to:
Plus an appliedCategory for color coding (red/orange/yellow/green/blue).
Planner has no cycle concept. The bridge encodes cycle membership in the task title prefix:
[Cycle: Sprint 23] Fix login bugA bridge utility re-titles tasks on cycle transitions (updateCycle webhook).
Linear projects map to Planner plans: one Linear project ↔ one Planner plan. The mapping is stored in plugin state; users configure via /linear:planner-sync map.
When a Linear issue's attachment is uploaded:
Authorization: Bearer <linear_key>)PUT /drives/{driveId}/items/{path}:contentPATCH /planner/tasks/{id}/details setting references["<onedrive-url>"]For Planner → Linear, references are link-only attachments (no byte copy).
Microsoft Graph: 600 reqs / 30s per app per tenant. Bridge implements:
Retry-After header| Failure | Behaviour |
|---------|-----------|
| Graph 401 | Refresh token; on second 401, pause bridge + alert |
| Graph 403 | Likely missing admin consent on scope; alert with required scope name |
| Graph 429 | Honor Retry-After, backoff |
| Delta token expired | Re-bootstrap (full scan) |
| AAD user not found | Skip assignment, log warning |
| Planner plan deleted | Disable mapping; preserve historic links |
@emaildevelopment
Enhanced plan-authoring skill with Pre-Writing context gathering, task metadata, non-TDD templates, Red Flags, telemetry, and an automated plan linter. Use when you have a spec or requirements for a multi-step task, before touching code.
tools
Documentation intelligence engine with graph-based API docs, algorithm library, and drift detection
tools
Ultraplan cloud planning — kick off a plan in the cloud from your terminal, review and revise in the browser, then execute remotely or send back to CLI
tools
--- name: mcp description: Configure MCP servers for Claude Code — stdio vs HTTP, authentication, Tools/Resources/Prompts distinction, channels (CI webhook, mobile relay, Discord bridge, fakechat), and cost of always-loaded tools. Use this skill whenever adding an MCP server, debugging connection issues, choosing between MCP Tools vs Prompts vs Resources, installing channel servers, or managing .mcp.json. Triggers on: "MCP server", "mcp config", "add Obsidian MCP", "install context7", "channels"