linear
Linear GraphQL patterns for Symphony agents. Use `linear_graphql` for all operations — comments, state transitions, PR attachments, file uploads, and issue creation. Never use schema introspection.
How do I install this agent skill?
npx skills add https://github.com/odysseus0/symphony --skill linearIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides patterns for interacting with the Linear GraphQL API and includes instructions for uploading files using curl. It possesses an indirect prompt injection surface as it retrieves and processes issue content from an external source.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 1 issue
- Runlayerwarn
7/7 files flagged
What does this agent skill do?
Linear GraphQL
All Linear operations go through the linear_graphql client tool exposed by
Symphony's app server. It handles auth automatically.
{
"query": "query or mutation document",
"variables": { "optional": "graphql variables" }
}
One operation per tool call. A top-level errors array means the operation
failed even if the tool call completed.
Workpad
Maintain a local workpad.md in your workspace. Edit freely (zero API cost),
then sync to Linear at milestones — plan finalized, implementation done,
validation complete. Do not sync after every small change.
First sync — create the comment, save the ID:
mutation CreateComment($issueId: String!, $body: String!) {
commentCreate(input: { issueId: $issueId, body: $body }) {
success
comment { id }
}
}
Write the returned comment.id to .workpad-id so subsequent syncs can update.
Subsequent syncs — read .workpad-id, update in place:
mutation UpdateComment($id: String!, $body: String!) {
commentUpdate(id: $id, input: { body: $body }) { success }
}
Query an issue
The orchestrator injects issue context (identifier, title, description, state, labels, URL) into your prompt at startup. You usually do not need to re-read.
When you do, use the narrowest lookup for what you have:
# By ticket key (e.g. MT-686)
query($key: String!) {
issue(id: $key) {
id identifier title url description
state { id name type }
project { id name }
}
}
For comments and attachments:
query($id: String!) {
issue(id: $id) {
comments(first: 50) { nodes { id body user { name } createdAt } }
attachments(first: 20) { nodes { url title sourceType } }
}
}
State transitions
Fetch team states first, then move with the exact stateId:
query($id: String!) {
issue(id: $id) {
team { states { nodes { id name } } }
}
}
mutation($id: String!, $stateId: String!) {
issueUpdate(id: $id, input: { stateId: $stateId }) {
success
issue { state { name } }
}
}
Attach a PR or URL
# GitHub PR (preferred for PRs)
mutation($issueId: String!, $url: String!, $title: String) {
attachmentLinkGitHubPR(issueId: $issueId, url: $url, title: $title, linkKind: links) {
success
}
}
# Plain URL
mutation($issueId: String!, $url: String!, $title: String) {
attachmentLinkURL(issueId: $issueId, url: $url, title: $title) {
success
}
}
File upload
Three steps:
- Get upload URL:
mutation($filename: String!, $contentType: String!, $size: Int!) {
fileUpload(filename: $filename, contentType: $contentType, size: $size, makePublic: true) {
success
uploadFile { uploadUrl assetUrl headers { key value } }
}
}
- PUT file bytes to
uploadUrlwith the returned headers (usecurl). - Embed
assetUrlin comments/workpad as.
Issue creation
Resolve project slug to IDs first:
query($slug: String!) {
projects(filter: { slugId: { eq: $slug } }) {
nodes { id teams { nodes { id key states { nodes { id name } } } } }
}
}
Then create:
mutation($input: IssueCreateInput!) {
issueCreate(input: $input) {
success
issue { identifier url }
}
}
$input fields: title, teamId, projectId, and optionally description,
priority (0–4), stateId. For relations, follow up with:
mutation($input: IssueRelationCreateInput!) {
issueRelationCreate(input: $input) { success }
}
Input: issueId, relatedIssueId, type (blocks or related).
Rules
- No introspection. Never use
__typeor__schemaqueries. They return the entire Linear schema (~200K chars) and waste the context window. Every pattern you need is documented above. - Keep queries narrowly scoped — ask only for fields you need.
- Sync the workpad at milestones, not after every change.
- For state transitions, always fetch team states first — never hardcode state IDs.
- Prefer
attachmentLinkGitHubPRover generic URL attachment for GitHub PRs.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/odysseus0/symphony/linear">View linear on skillZs</a>