@kody/figma
Read Figma files, nodes, comments, components, styles, and images through OAuth or a token.
AGENTS.md
145 lines · 4.5 KB · Markdown@kody/figma — agent notes
Human setup and intent live in 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-<purpose> | BYO OAuth; Bearer token |
| B | User secret figmaPat (or figmaPat-<purpose>) | 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)
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)
}import figma from 'kody:@kody/figma'
export default async function main() {
return await figma()
}Read-only samples:
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:
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.
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 fileKeyaccepts a raw key or afigma.comfile/design/board/proto URL- Node ids from Figma URLs (
1-2) are normalized to API form (1:2) ./get-filedefaults to slim document (depth: 1); use./get-file-nodesfor 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/figmastorage as the caller's