# @kody/jira — 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 or emails. Do not disable live webhooks or jobs. ## Auth | Call | Resolves to | | --- | --- | | omit | `jira` / `jiraEmail` + `jiraApiToken` | | `account: 'jira-work'` | `jira-work` / `jiraEmail-work` + `jiraApiToken-work` | | `auth: 'oauth' \| 'token'` | force lane when both exist | | `site: 'acme'` | `*.atlassian.net` subdomain (API-token lane; also when multi-site OAuth) | | `cloudId` | OAuth cloud id from `./list-sites` | OAuth: `https://api.atlassian.com/ex/jira/{cloudId}/rest/api/3`. API token: `https://{site}.atlassian.net/rest/api/3`. Do not hard-code personal workspace aliases or project keys. ## Import paths | Export | Import | | --- | --- | | root dispatcher (defaults to smoke-test) | `kody:@kody/jira` | | setup | `kody:@kody/jira/setup` | | smoke-test | `kody:@kody/jira/smoke-test` | | list-sites | `kody:@kody/jira/list-sites` | | list-projects | `kody:@kody/jira/list-projects` | | get-issue | `kody:@kody/jira/get-issue` | | search | `kody:@kody/jira/search` | | create-issue | `kody:@kody/jira/create-issue` | | list-comments | `kody:@kody/jira/list-comments` | | add-comment | `kody:@kody/jira/add-comment` | | list-transitions | `kody:@kody/jira/list-transitions` | | transition-issue | `kody:@kody/jira/transition-issue` | | request | `kody:@kody/jira/request` | Prefer static `kody:@kody/jira/...` imports from `execute`. Do not lead with `packages.invoke`. ## Smoke test (read-only) ```js import smokeTest from 'kody:@kody/jira/smoke-test' export default async function main() { return await smokeTest({ // account: 'jira-work', // site: 'acme', }) // Without credentials: { ok: true, live: false } + setup URLs // With credentials: live `/myself` (no email) } ``` Root dispatcher dry preview: ```js import jira from 'kody:@kody/jira' export default async function main() { return await jira({ dryRun: true }) } ``` ## dryRun / confirm `create-issue`, `add-comment`, `transition-issue`, and mutating `request` calls never write when `dryRun: true`. A live write also requires `confirm: true` after the user approved the exact issue or fields. ```js import createIssue from 'kody:@kody/jira/create-issue' import addComment from 'kody:@kody/jira/add-comment' export default async function main() { const previewIssue = await createIssue({ projectKey: 'PROJ', summary: 'Follow up with the customer', issueType: 'Task', dryRun: true, }) const previewComment = await addComment({ issueIdOrKey: 'PROJ-123', body: 'Posted from Kody after review.', dryRun: true, }) return { previewIssue, previewComment } } ``` Read helpers: ```js import searchIssues from 'kody:@kody/jira/search' import listProjects from 'kody:@kody/jira/list-projects' export default async function main() { const projects = await listProjects({ query: 'platform', maxResults: 20 }) const issues = await searchIssues({ jql: 'assignee = currentUser() AND statusCategory != Done ORDER BY updated DESC', maxResults: 10, // site: 'acme', }) return { projects, issues } } ``` Multi-account: ```js import listProjects from 'kody:@kody/jira/list-projects' export default async function main() { return listProjects({ account: 'jira-work', site: 'acme' }) } ``` ## Edge cases / troubleshooting - OAuth authorize fails: confirm redirect URI is exactly `https://kody.codes/connect/oauth` and the Jira API permissions are added on the Atlassian app. - `audience` errors: reconnect with the prefilled URL so `extraAuthorizeParams` includes `audience=api.atlassian.com` and `prompt=consent`. - Host approval: OAuth needs `api.atlassian.com` (and `auth.atlassian.com` for token refresh). API token needs `{site}.atlassian.net` on both secrets. - Several OAuth sites: pass `site` or `cloudId` from `./list-sites`. This package will not pick a default project or site. - CAPTCHA / `AUTHENTICATION_DENIED`: unlock the Atlassian account in the browser, then retry. - Prefer `@kody/atlassian-mcp` only for a faster first win; this package is the preferred invoke path once BYO OAuth or an API token is set up.