launch-linear-sync
Skill0 starsChanged 35 days agoMITView on GitHub
Sync a launch from the GrowthCast release checklist studio to Linear through Composio. Creates or updates a Linear project with a milestone per phase and one issue per open task, assigned to the person staffed on it with its due date and launch context, links each task to what it waits on with "blocked by" relations, and pulls issue state back into the checklist. Use for "Sync to Linear" requests, or when someone asks to push a launch plan to Linear, create launch tickets, or assign launch tasks to the team.
In this repository9 other files it gives its agents.
- changelog-automationSkill
- launch-assetsSkill
- launch-kickoffSkill
- launch-measureSkill
- launch-messagingSkill
- launch-readinessSkill
- launch-retroSkill
- launch-videoSkill
- product-release-checklistSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
Team: If team.id is empty, call LINEAR_LIST_LINEAR_TEAMS and ask the user which team owns the launch (AskUserQuestion).
- Very specific: line 29
If project.existingId is empty, this is the first sync.
- Very specific: line 38
If project.existingId is empty, call LINEAR_CREATE_LINEAR_PROJECT with these fields:
- Very specific: line 55
Existing and still open in the studio: call LINEAR_UPDATE_ISSUE with issueId, title, dueDate, description, plus assigneeId only if the …
- Very specific: line 60
After the issues exist, map each blocker and blocked key to its issue id (from existing.id or what you just created).
- Very specific: line 69
Read every linked issue's state with one LINEAR_RUN_QUERY_OR_MUTATION: query($id: String!) { project(id: $id) { issues(first: 250) { nodes …
- Distinctive: line 97
If any calls failed, list them and say that re-running the sync retries only what's missing, because linked issues are never duplicated.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Launch → Linear (via Composio)
The studio never talks to Linear itself. You do, with Composio's Linear tools, then write the result back so the studio
shows issue links and stays in step. Run every Composio call through COMPOSIO_MULTI_EXECUTE_TOOL, after a
COMPOSIO_SEARCH_TOOLS call for Linear that gives you a session id. Check each tool's successful flag, because a failure
can arrive with an HTTP 200.
1. Get the payload
node <tools>/studio.mjs sync-plan <id> prints:
team:{ id, name }. The id is empty before the first sync.project:{ existingId, name, description (≤250 chars), start_date, target_date, lead_email }milestones[]:{ phase, name, target_date, existingId }people[]:{ email, name, linearUserId }issues[]:{ key, existing, open, title, description, due_date, priority, milestone, role, assignee_email, assignee_name }. The description already holds the task's context and what it waits on; send it as is.relations[]:{ key, blocker, blocked, existing }, one per dependency where both tasks have an issue.existingis the relation id from an earlier sync.remove[]:{ key, id }, relations an earlier sync made for dependencies that no longer exist.
2. Resolve the team and people
- Team. If
team.idis empty, callLINEAR_LIST_LINEAR_TEAMSand ask the user which team owns the launch (AskUserQuestion). Read bothdata.teamsanddata.items. Use the UUID, never the key or name. - People. Call
LINEAR_LIST_LINEAR_USERSand paginate untilpage_info.hasNextPageis false. Match each payload person by email, case-insensitive,active: trueonly. An assignee must be a member of the team (the members come from the teams listing). List anyone unmatched or outside the team: their issues go in unassigned. Never guess by name.
3. Confirm before the first write
If project.existingId is empty, this is the first sync. Show the user a short preview and wait for a yes:
- the team
- the project name
- the number of issues to create, per person
- the unassigned count
Mention that Linear notifies assignees. On a re-sync, go ahead without asking unless more than 20 new issues would be created.
4. Project and milestones
If
project.existingIdis empty, callLINEAR_CREATE_LINEAR_PROJECTwith these fields:name,team_ids: [teamId](a list)description,start_date,target_date(YYYY-MM-DD)lead_id(the lead's Linear id, if matched)
Omit
icon. RecordprojectIdand the projecturl. If the response has no url, read it back withLINEAR_GET_LINEAR_PROJECT.- For each milestone with no
existingId, callLINEAR_CREATE_PROJECT_MILESTONEwith{ project_id, name, target_date, sort_order: index }. Recordphase → milestone id.
5. Issues
Batch up to 50 independent calls per COMPOSIO_MULTI_EXECUTE_TOOL.
New (
existingis null andopen): callLINEAR_CREATE_LINEAR_ISSUEwith these fields:team_id,project_idtitle,descriptiondue_date,priorityassignee_id, only when matched
Record
key → { id, identifier, url }fromdata.- Existing and still open in the studio: call
LINEAR_UPDATE_ISSUEwithissueId,title,dueDate,description, plusassigneeIdonly if the studio has a matched owner. Every field you send is overwritten, so omit the rest. - Existing but closed in the studio (
open: false): leave the issue alone and list it in the summary, so the owner can close it in Linear. - Milestones. Attach issues to their phase milestone with one
LINEAR_RUN_QUERY_OR_MUTATION, using aliased mutations:m1: issueUpdate(id: "<issue id>", input: { projectMilestoneId: "<milestone id>" }) { success }, chunked about 25 per call. This is optional: if it errors, skip it and say so.
6. Dependencies
After the issues exist, map each blocker and blocked key to its issue id (from existing.id or what you just created).
- Read what's there. One
LINEAR_RUN_QUERY_OR_MUTATIONper 20 blocker issues, aliased:i0: issue(id: "<id>") { id relations(first: 50) { nodes { id type relatedIssue { id } } } }. Ablocksrelation from the blocker to the blocked issue already exists if one is listed; use its id. - Create the missing ones with aliased mutations, about 20 per call:
r0: issueRelationCreate(input: { issueId: "<blocker issue id>", relatedIssueId: "<blocked issue id>", type: blocks }) { success issueRelation { id } }. - Delete each
remove[]relation that still exists:d0: issueRelationDelete(id: "<id>") { success }. - Skip any pair where either issue is gone from the project. Record
key → relation idfor every relation that exists after this, andkey → nullfor each one you deleted.
7. Pull state back
Read every linked issue's state with one LINEAR_RUN_QUERY_OR_MUTATION:
query($id: String!) { project(id: $id) { issues(first: 250) { nodes { id identifier url state { type } } } } }.
Map each issue id back to its key. The studio maps state.type like this:
completed→ done, with the issue URL as evidencecanceled→ N/Astarted→ in progress
8. Write back
Save this JSON to a file in the scratchpad, then run node <tools>/studio.mjs link <id> <file>:
{ "teamId": "", "teamName": "", "projectId": "", "projectUrl": "",
"milestones": { "decide": "<id>", "...": "..." },
"issues": { "<key>": { "id": "", "identifier": "GRO-12", "url": "", "state": "unstarted" } },
"people": { "<email>": "<linear user id>" },
"relations": { "<blocker key>><blocked key>": "<relation id or null>" },
"pulled": { "<key>": { "state": "completed" } } }The output lists the checklist items whose status changed. The open studio reloads by itself.
9. Report
In chat, give:
- the project link
- issues created, updated and left alone
- dependency links created and removed
- who got how many issues
- who couldn't be assigned, and why
- the items the pull ticked off
If any calls failed, list them and say that re-running the sync retries only what's missing, because linked issues are never duplicated.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

