Run a team's Linear workspace like an operator: triage inbox sweeps with real accept/decline/route decisions, cycle planning against velocity, workflow-state discipline, and scripted GraphQL API workflows for issues, labels, and comments. Triggers on "Linear triage", "cycle planning", "Linear API", "manage issues in Linear", or any request to operate a Linear workspace from the terminal.
./install.sh linear-tracker-opsname: linear_tracker_ops description: Run a team's Linear workspace like an operator: triage inbox sweeps with real accept/decline/route decisions, cycle planning against velocity, workflow-state discipline, and scripted GraphQL API workflows for issues, labels, and comments. Triggers on "Linear triage", "cycle planning", "Linear API", "manage issues in Linear", or any request to operate a Linear workspace from the terminal.
Make Linear actually do its job: nothing sits in triage unexamined, cycles hold their scope, and issue states reflect reality. This skill is the operator's handbook plus a working CLI for the routine moves.
bin/linear-ops.py (stdlib only, no deps) covers the common operations:
bash
export LINEAR_API_KEY='lin_api_...' # personal key, never commit it
linear-ops.py auth # verify the key
linear-ops.py triage --team ENG # everything sitting in triage
linear-ops.py my # my open assigned issues, priority-ordered
linear-ops.py states --team ENG # workflow states for the team
linear-ops.py cycle --team ENG # recent cycles with scope/finished counts
linear-ops.py create --team ENG --title "..." --priority 2 --label bug
linear-ops.py update --issue ENG-123 --state "In Progress"
linear-ops.py comment --issue ENG-123 --body "Verified on staging."
linear-ops.py list --filter '{"priority": {"gte": 2}}' # raw IssueFilter escape hatch
For one-off calls without the CLI, see references/graphql-queries.md.
Personal API keys are the right credential for operator scripts. Create one in Linear under Settings > Security & access > API keys. Every request goes to POST https://api.linear.app/graphql with the key raw in the header:
Authorization: lin_api_...
Content-Type: application/json
No Bearer prefix on personal keys (that prefix is for OAuth access tokens, a different credential). Keep the key in an env var or a secrets manager, never in the repo, never in chat. The key acts with the permissions of the person who created it, so a service account with the narrowest team access beats a personal key when automation runs unattended.
linear-ops.py triage --team ENG gives you the inbox. Every item gets a decision, not a glance. The full decision tree lives in references/triage-runbook.md. The short version:
linear-ops.py cycle --team ENG shows recent cycles with scope vs finished. Checklist in references/cycle-planning.md. The short version: pull issues from Backlog into Todo, confirm scope against the team's recent velocity (Linear shows median velocity in Insights), set scope early and hold it. Incomplete issues roll forward by default, so scope creep is a commitment problem, not a tooling problem. Auto-archive keeps old cycles tidy (default keeps 6).
Run linear-ops.py states --team ENG once and keep the list short. The default flow is enough for most teams: Backlog -> Todo -> In Progress -> In Review -> Done, plus Canceled. Signs of rot: more than one issue In Progress per person, issues sitting In Progress with no activity, Done meaning "merged" instead of "shipped". Fix the behavior, not the board.
update or comment echoes the resulting issue identifier and state so the caller can verify it landed.list --filter or references/graphql-queries.md only when the CLI genuinely lacks the operation.references/webhooks.md) are for reactive automation, polling is for audits. Do not build a poll loop when Linear can push.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.