# @kody/linear — agent notes Human setup and intent live in [`README.md`](./README.md). This file is for agents: imports, smoke/dryRun execute snippets, and edge cases. Secrets and OAuth by **name** only — never paste tokens. Do not disable live webhooks or jobs. ## Auth | Call | Resolves to | | --- | --- | | omit | `linear` / `linearApiKey` | | `account: 'work'` | `linear-work` / `linearApiKey-work` | | `integrationName: 'linear-work'` | that exact OAuth name | | `secretName: 'linearApiKey-work'` | that exact API-key secret | | `auth: 'oauth' \| 'api-key'` | force lane when both exist | OAuth Bearer vs personal API key (no Bearer) is handled by the package. Host: `api.linear.app`. GraphQL: `https://api.linear.app/graphql`. Do not hard-code a personal workspace slug or alias. ## Import paths | Export | Import | | --- | --- | | overview / connect URLs / export map | `kody:@kody/linear` | | accounts | `kody:@kody/linear/accounts` | | smoke-test | `kody:@kody/linear/smoke-test` | | viewer | `kody:@kody/linear/viewer` | | list-teams | `kody:@kody/linear/list-teams` | | get-team | `kody:@kody/linear/get-team` | | list-projects | `kody:@kody/linear/list-projects` | | get-project | `kody:@kody/linear/get-project` | | create-project | `kody:@kody/linear/create-project` | | list-issues | `kody:@kody/linear/list-issues` | | get-issue | `kody:@kody/linear/get-issue` | | create-issue | `kody:@kody/linear/create-issue` | | update-issue | `kody:@kody/linear/update-issue` | | list-comments | `kody:@kody/linear/list-comments` | | create-comment | `kody:@kody/linear/create-comment` | | list-workflow-states | `kody:@kody/linear/list-workflow-states` | | request | `kody:@kody/linear/request` | | types | `kody:@kody/linear/types` | Prefer static `kody:@kody/linear/...` imports from `execute`. Do not lead with `packages.invoke`. Priority values: `0` none, `1` urgent, `2` high, `3` medium, `4` low. Workflow state types: `triage`, `backlog`, `unstarted`, `started`, `completed`, `canceled`. ## Smoke test (read-only) ```js import smokeTest from 'kody:@kody/linear/smoke-test' export default async function main() { return await smokeTest() // Without credentials: { ok: true, live: false } + connect / API-key URLs // With credentials: { live: true, hasViewerId, hasOrganizationId } (no email) } ``` ## dryRun / confirm Mutating helpers require `confirm: true`. Pass `dryRun: true` to inspect the GraphQL payload without calling Linear. `./request` treats query documents as read-only; mutation documents need confirmation. ```js import createIssue from 'kody:@kody/linear/create-issue' export default async function main() { const preview = await createIssue({ title: 'Investigate checkout timeout', teamId: 'team-uuid', priority: 2, dryRun: true, }) // After the user confirms the exact team and title: return await createIssue({ title: 'Investigate checkout timeout', teamId: 'team-uuid', priority: 2, confirm: true, }) } ``` Read helpers: ```js import listIssues from 'kody:@kody/linear/list-issues' import listWorkflowStates from 'kody:@kody/linear/list-workflow-states' export default async function main() { const states = await listWorkflowStates({ teamKey: 'ENG' }) return await listIssues({ teamKey: 'ENG', stateType: 'started', first: 20, }) } ``` Unwrapped GraphQL: ```js import request from 'kody:@kody/linear/request' export default async function main() { return await request({ query: `query ($key: String!) { team(id: $key) { id name key } }`, variables: { key: 'ENG' }, }) } ``` ## Edge cases - If Linear returns 401/403 or GraphQL `FORBIDDEN` / insufficient-scope, helpers throw a message that names the missing scope and the next setup URL. - `assigneeId: 'me'` on `./list-issues` filters to the authorizing user. - Helpers project slim objects. Use `./request` when you need extra fields. - Prefer `@kody/linear-mcp` only for a faster first win; this package is the preferred invoke path once BYO OAuth or an API key is set up.