# @kody/figma — 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 by **name** only — never paste token or OAuth client values. Do not hard-code a personal file key or team id. ## Auth | Lane | Credential | Notes | | --- | --- | --- | | A (recommended) | Integration `figma` or `figma-` | BYO OAuth; Bearer token | | B | User secret `figmaPat` (or `figmaPat-`) | `X-Figma-Token` | Resolution: `integrationName` / `integration` wins when set; `account: 'work'` → `figma-work` / `figmaPat-work`; omitted → `figma` / `figmaPat`. Pass `auth: 'oauth' | 'pat'` when both exist. Host: `api.figma.com`. ### Scopes (OAuth) | Scope | Needed for | | --- | --- | | `current_user:read` | `./viewer`, `./smoke-test` | | `file_content:read` | `./get-file`, `./get-file-nodes`, `./get-images`, `./get-image-fills` | | `file_metadata:read` | `./get-file-meta` | | `file_comments:read` | `./list-comments` | | `file_comments:write` | `./create-comment`, `./delete-comment` | | `file_versions:read` | Versioned reads via `./request` | | `library_content:read` | `./list-file-components`, `./list-file-styles` | | `library_assets:read` | Library image assets via `./request` | | `folders:read` | Folder and file listing via `./request` | Enable exactly these scopes on the Figma OAuth app. Figma returns HTTP 400 Invalid scopes when authorize asks for anything else: a scope the app does not offer, a deprecated scope, or an enterprise-only extra. ## Import paths | Export | Import | | --- | --- | | root overview | `kody:@kody/figma` | | accounts | `kody:@kody/figma/accounts` | | smoke-test | `kody:@kody/figma/smoke-test` | | viewer | `kody:@kody/figma/viewer` | | get-file | `kody:@kody/figma/get-file` | | get-file-nodes | `kody:@kody/figma/get-file-nodes` | | get-file-meta | `kody:@kody/figma/get-file-meta` | | list-comments | `kody:@kody/figma/list-comments` | | create-comment | `kody:@kody/figma/create-comment` | | delete-comment | `kody:@kody/figma/delete-comment` | | list-file-components | `kody:@kody/figma/list-file-components` | | list-file-styles | `kody:@kody/figma/list-file-styles` | | get-images | `kody:@kody/figma/get-images` | | get-image-fills | `kody:@kody/figma/get-image-fills` | | request | `kody:@kody/figma/request` | | types | `kody:@kody/figma/types` | Prefer static `kody:@kody/figma/...` imports from `execute`. Do not lead with `packages.invoke`. ## Smoke test (read-only) ```ts import smokeTest from 'kody:@kody/figma/smoke-test' export default async function main() { return await smokeTest() // without creds => { ok: true, live: false, setup: { ...URLs } } // with creds => { live: true, hasViewerId } (no email) } ``` ```ts import figma from 'kody:@kody/figma' export default async function main() { return await figma() } ``` Read-only samples: ```ts import getFile from 'kody:@kody/figma/get-file' import listComments from 'kody:@kody/figma/list-comments' export default async function main() { const file = await getFile({ fileKey: 'https://www.figma.com/design/abc123/Checkout', }) return { file, comments: await listComments({ fileKey: file.fileKey }), } } ``` Escape hatch: ```ts import request from 'kody:@kody/figma/request' export default async function main() { return await request({ path: '/v1/me' }) } ``` ## dryRun / confirm (writes) `create-comment`, `delete-comment`, and mutating `./request` methods: `dryRun: true` previews without calling Figma. Live writes also require `confirm: true`. GET on `./request` is read-only. ```ts import createComment from 'kody:@kody/figma/create-comment' export default async function main() { const preview = await createComment({ fileKey: 'abc123', message: 'Please bump the empty-state type to 16.', nodeId: '12:34', dryRun: true, }) // Only after explicit user confirmation of file + message: const created = await createComment({ fileKey: 'abc123', message: 'Please bump the empty-state type to 16.', nodeId: '12:34', confirm: true, }) return { preview, created } } ``` ## Edge cases / fork notes - REST base: `https://api.figma.com` - `fileKey` accepts a raw key or a `figma.com` file/design/board/proto URL - Node ids from Figma URLs (`1-2`) are normalized to API form (`1:2`) - `./get-file` defaults to slim document (`depth: 1`); use `./get-file-nodes` for specific layers - Insufficient-scope / 401/403 errors name the missing scope and next setup URL - Fork/adapt: connect the caller's Figma; do not treat `@kody/figma` storage as the caller's