Deskhand

io.github.duncanbottrillPublished by GitHub account duncanbottrillv1.0.1Updated Nov 1, 2026

Claude in your Figma file. Builds with your components, checks what it wrote. Runs on your computer.

VerifiedSTDIODesktop onlyDeveloper ToolsMedia & Design

Overview

AI-generated overview

Deskhand connects Claude to a Figma file through a local plugin, letting it read, build, edit, export and review designs on your machine.

What you can do
  • Inspect the open Figma document: file info, pages, selection, selection history, node details, brand styles, components and variables
  • Create and edit design content: frames, rectangles, text, fills, strokes, corner radius, opacity, visibility, grouping, cloning, moving, resizing, size limits, image fills
  • Run custom JavaScript in the Figma plugin, with job status and cancellation for long runs
  • Export and render: single or batch export to PNG, SVG, JPG or PDF, inline screenshots, and pixel-diff against a reference node
  • Quality checks and assets: screen lint with findings and fixes, Lucide icon lookup and placement, iOS chrome templates
  • FigJam support: sticky notes, shapes with text…
When to use it
Use it when you want an assistant to work directly inside a Figma file: building screens from existing components and styles, reproducing a reference design, auditing a frame before handoff, or exporting assets. It suits design and design-engineering workflows rather than general coding.
Requirements
Runs as a local npm package over stdio, on desktop only. A Figma plugin must be running and connected on port 3055; every tool returns NOT_CONNECTED otherwise. A Deskhand licence key is needed beyond the trial. The optional DESKHAND_PROFILE environment variable selects which tools are registered (design, figjam or all).
Before you install
The server can change the open Figma document: it creates, moves, resizes, restyles and deletes nodes, so take a snapshot before risky edits. figma_execute runs arbitrary JavaScript inside the plugin. figma_licence_activate submits a licence key. Image fills can fetch from http(s) URLs, and exports write files to disk under ~/.deskhand.

Installation

In SourceWeft

  1. Open Deskhand in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Tools

113

figma_server_info

Server version, WebSocket port, connection state and connected document info.

Takes no parameters.

figma_get_context

File info, current page and selection. Call once per conversation; every tool reports NOT_CONNECTED if the plugin is down.

Takes no parameters.

figma_get_selection_history

Recent selection changes, newest first, with timestamps. Default: the user's own selections; source: 'all' adds those made by bridge commands. Served from a server buffer, so it works after the plugin disconnects. If the default returns nothing, retry with source: 'all'.

Parameterslimitsource

figma_bridge_diagnostics

Check the bridge end to end: versions, plugin handshake, buffered events, reverse round-trip timing. Call when a tool fails or after an upgrade.

Takes no parameters.

figma_licence_status

Deskhand licence state: trial days left, masked key, last check.

Takes no parameters.

figma_licence_activate

Activate a Deskhand licence key.

Parameterskeyrequired

figma_execute

Run JavaScript in the Figma plugin: an async function body with figma (Plugin API) and bridge (log, sleep, icon, text, instance, image, snapshot; progress/cancelled in jobs). Return plain data, never nodes (EXECUTE_BAD_RETURN). Errors: EXECUTE_SYNC_API, EXECUTE_SYNTAX, EXECUTE_FAILED. job: true past 30 s, then figma_job_status (waits). screenshot renders it. Recipes: figma_get_design_rules.

ParametersjobcoderequiredlintlabeltimeoutMsscreenshot

figma_job_status

Waits for a figma_execute job to end (up to waitMs), then returns state (running | done | error | cancelled | timeout), progress and the result or error. Jobs live for the server session.

ParametersjobIdrequiredwaitMs

figma_job_cancel

Ask a running figma_execute job to stop (sets the flag bridge.cancelled() returns; scripts that never check it run to completion). Poll figma_job_status.

ParametersjobIdrequired

figma_list_pages

List pages (ids and names). The active page is in figma_get_context.

Takes no parameters.

figma_get_nodes

Full node details by id: geometry, fills, strokes, effects, auto-layout, text, constraints, boundVariables, explicitVariableModes, childIds. Default-valued props are omitted unless verbose. Composite instance ids (I<inst>;<child>) resolve; unknown ids land in notFound. Find ids with figma_search_nodes/figma_get_children first.

ParametersdepthnodeIdsrequiredverbose

figma_set_fills

Set fill color. Accepts hex shorthand or fills array.

ParametersfillsrequirednodeIdrequired

figma_set_strokes

Set stroke color and/or weight. Per-side weights (strokeTopWeight etc., for border-top-only dividers) work on RECTANGLE and frame-like nodes only. Omit `strokes` to change weights only.

ParametersnodeIdrequiredstrokesstrokeWeightstrokeTopWeightstrokeLeftWeightstrokeRightWeightstrokeBottomWeight

figma_create_rectangle

Create a rectangle.

ParametersxynamefillswidthheightparentId

figma_set_text

Set text content. Auto-loads fonts.

ParameterstextrequirednodeIdrequired

figma_clone_nodes

Duplicate nodes.

ParametersoffsetnodeIdsrequiredparentId

figma_delete_nodes

Delete nodes.

ParametersnodeIdsrequired

figma_move_nodes

Move nodes. Use relative=true for offset.

ParametersxynodeIdsrequiredrelative

figma_resize_nodes

Resize nodes to explicit pixels. To fit a child to its parent prefer figma_set_layout_align STRETCH (keeps size binds). Instance sublayers are rejected (INSTANCE_SUBLAYER_RESTRICTED): resize the master. Size binds are re-applied; the result is read back: RESIZE_NO_OP for a no-op, a clamp is a warning.

ParameterswidthheightnodeIdsrequired

figma_set_size_limits

Set or clear minWidth/maxWidth/minHeight/maxHeight: a number sets, null clears, omit leaves it. Applies to auto-layout frames and their direct children (others get a warning). Verified by readback (LIMIT_NOT_APPLIED / LIMIT_NOT_CLEARED). A variable-bound field keeps its bound value; unbind with figma_unbind_variable.

ParametersnodeIdsrequiredmaxWidthminWidthmaxHeightminHeight

figma_set_opacity

Set opacity (0-1).

ParametersnodeIdrequiredopacityrequired

figma_set_visible

Show or hide nodes via node.visible; don't bind a BOOLEAN variable or set opacity to 0 for this.

ParametersnodeIdsrequiredvisiblerequired

figma_set_clips_content

Set whether frame-like nodes (FRAME, COMPONENT, COMPONENT_SET, INSTANCE, SLOT, SLIDE) clip children to their bounds; others error.

ParametersnodeIdsrequiredclipsContentrequired

figma_set_corner_radius

Set corner radius. Use individual values for asymmetric.

ParametersnodeIdrequiredradiustopLefttopRightbottomLeftbottomRight

figma_group_nodes

Group nodes.

ParametersnamenodeIdsrequired

figma_ungroup_nodes

Ungroup nodes.

ParametersnodeIdsrequired

figma_create_frame

Create a frame.

ParametersxynamefillswidthheightparentId

figma_create_text

Create a text node.

ParametersxynametextfillsfontSizeparentIdfontStylefontFamily

figma_set_selection

Set selection. Empty array clears.

ParametersnodeIdsrequired

figma_set_current_page

Switch to a different page in the Figma document.

ParameterspageIdrequired

figma_export_node

Export a node as PNG, SVG, JPG or PDF to disk and return { path, format, scale, bytes }; read the file to view it. outputPath sets the destination; returnBase64: true inlines raw data instead. To see the render in context use figma_screenshot.

ParametersscaleformatnodeIdrequiredoutputPathreturnBase64

figma_screenshot

Render a node (or the selection) as PNG and return it inline, with path, pixel size and scale. Scale is reduced to fit maxPixels (default 1,000,000); the inline image stays under 200 KB (one retry at half scale), larger renders stay on disk. Use after layout changes: readback cannot see overlap, clipping or mid-word breaks.

ParametersscaleinlinenodeIdmaxPixels

figma_compare_to_reference

Pixel-diff a built frame against a reference node. Both render at the reference's effective scale; returns mismatchPercent, a per-quadrant breakdown (tl/tr/bl/br), the size delta and paths to the diff/ref/built PNGs. A mismatch in one quadrant usually means one misplaced element.

ParametersscalemaxPixelsrefNodeIdrequiredthresholdinlineDiffbuiltNodeIdrequired

figma_export_batch

Export many nodes in one call, each at a scale or targetWidth (scale = targetWidth / node width, clamped 0.01–4). Files go to outputDir (default: a fresh folder under ~/.deskhand/exports/) named by namePattern with tokens {name} {id} {scale} {ext} {index}. One row per item (path and size, or an error); nothing is inlined.

ParametersitemsrequiredoutputDirnamePattern

figma_resolve_icon

Check icon concepts against the bundled Lucide set before drawing anything; never hand-draw glyphs. Aliases resolve (close → x), then exact names; otherwise you get real-name suggestions: pick one, do not invent. Insert with figma_place_icon or bridge.icon.

Parametersconceptsrequired

figma_place_icon

Insert a Lucide icon as a vector frame named icon/<concept>. Resolves like figma_resolve_icon. Appended to parentId (or the current page) at x/y, scaled and stroked.

ParametersxysizecolorconceptrequiredparentId

figma_place_chrome

Insert an iOS chrome template (status-bar 393×54, home-indicator 393×34, keyboard 393×291), named chrome/<kind>. With parentId it scales to the parent width, top or bottom unless y is given.

ParametersykindrequiredthemeparentId

figma_review_screen

Per-screen quality gate: lint one frame → { pass, findings, counts, fixes }; a finding carries its own fix only when it differs from fixes[code]. Errors: invisible text, overflow, zero-size, collapsed auto-layout, low contrast. Warnings: misaligned rows, hand-drawn icons, placeholder avatars, raw fills/text, detached instances. Capped at 200, errors first.

ParameterschecksnodeIdrequired

figma_brand_styles

Read the brand the open file already defines: local paint/text/effect styles, every component and set (keys, variant properties, all pages) and common frame sizes; samples fills and fonts when there are no styles. Use its colours, type and components in everything you build. Cached under ~/.deskhand/brands/ so bridge.instance(name) can import components later.

Takes no parameters.

figma_set_image_fill

Fill a node with an image from an absolute path (~/ allowed) or http(s) URL: PNG, JPEG, GIF or WebP, up to 4096 px per side and 20 MB. Replaces the fills with one IMAGE fill. Use for photos, avatars and reference art instead of placeholder shapes; bridge.image does the same in scripts.

ParametersnodeIdrequiredsourcerequiredscaleMode

figma_snapshot

Save a restorable copy of a node before a risky edit: cloned onto a "🗄 Bridge Snapshots" page with parent/index/position recorded. Keeps the newest 10 per file. Restore with figma_restore_snapshot or bridge.snapshot() in scripts.

ParameterslabelnodeIdrequired

figma_restore_snapshot

Undo to a snapshot: removes the current node (if present) and moves the saved clone back to its recorded parent/index/position/name. New id: restoredId — update ids you held. Snapshot is consumed. SNAPSHOT_NOT_FOUND if unknown or the clone was deleted.

ParameterssnapshotIdrequired

figma_list_snapshots

List saved snapshots in this file, newest first, with whether each clone still exists. Returns { count, page, snapshots }.

Takes no parameters.

figma_get_design_rules

One cookbook section as markdown: rules plus a runnable figma_execute recipe. Sections: helpers, auto-layout, components, variants, text, lint, jobs, reference-match. Read it before building that kind of thing. Whole cookbook: skill://deskhand/COOKBOOK.md. Needs no plugin.

Parameterssectionrequired

figma_create_ellipse

Create ellipse. Use arcData for arcs/rings.

ParametersxynamefillswidthheightarcDataparentId

figma_set_effects

Set effects. Replaces existing.

ParametersnodeIdrequiredeffectsrequired

figma_set_auto_layout

Configure auto-layout on a frame: direction, sizing modes, alignment, padding, spacing, wrap. Size variable binds are captured and re-applied (rebound/warnings). See skill://deskhand/SKILL.md.

ParametersnodeIdrequiredlayoutModelayoutWrappaddingTopitemSpacingpaddingLeftpaddingRightpaddingBottomcounterAxisSpacingcounterAxisAlignItemscounterAxisSizingModeprimaryAxisAlignItems+1 more

figma_get_local_styles

List all local styles (colors, text, effects, grids). To find specific styles by name use figma_search_styles: fewer tokens.

Parameterstypelimitoffsetverbose

figma_apply_style

Apply a local style (paint, text, stroke, effect, grid) to a node using Figma's async setters. The applied id is read back: appliedStyleId with verified: true, or STYLE_NOT_APPLIED.

ParametersnodeIdrequiredstyleIdrequiredpropertyrequired

figma_create_component

Create a component.

ParametersxynamefillswidthheightparentIdfromNodeIddescription

figma_create_instance

Create a component instance.

ParametersxynameparentIdcomponentIdrequired

figma_get_local_variables

All local variables and collections: types (COLOR, FLOAT, STRING, BOOLEAN), modes, values. Paged: limit (default 100) and offset; next gives the following page.

Parameterstypelimitoffset

figma_search_variables

Search variables by name pattern (e.g. "tailwind/orange/*"). Compact results, far fewer tokens than figma_get_local_variables.

ParameterstypelimitoffsetcompactnamePatternnameContainscollectionName

figma_search_nodes

Search nodes by name within a scope (parentId required). Preferred for finding frames, sections or elements; compact results (~50 tokens/node).

ParameterslimittypesoffsetcompactmaxDepthparentIdrequirednamePatternnameContains

figma_search_components

Search local components by name. Returns compact metadata.

ParameterslimitoffsetcompactnamePatternnameContainsincludeVariants

figma_search_styles

Search local styles by name; cheaper than figma_get_local_styles.

ParameterstypelimitoffsetcompactnameContains

figma_get_children

Immediate children of a node — more efficient than figma_get_nodes for browsing hierarchy. Default limit 100, with truncated/next for paging. Compact results include x/y for layout. Composite instance-sublayer parent IDs resolve too.

ParameterslimitoffsetcompactparentIdrequired

figma_set_variable

Set a variable's value for a mode, or bind it to a node property or local style (styleId + field). Text styles bind font/spacing fields; paint styles bind 'paints'. Verified by readback (BIND_NOT_APPLIED otherwise). width/height on an instance sublayer: INSTANCE_SUBLAYER_RESTRICTED, bind the master.

ParametersfieldvaluemodeIdnodeIdstyleIdpaintIndexvariableIdrequired

figma_create_line

Create a line.

ParametersxynamelengthstrokesparentIdrotationstrokeCapstrokeWeight

figma_set_constraints

Set resize constraints on a node: how it resizes when its parent frame resizes. Only for nodes inside frames (not auto-layout frames).

ParametersnodeIdrequiredverticalhorizontal

figma_detach_instance

Detach an instance into a regular frame: keeps overrides, severs the link to the main component.

ParametersnodeIdrequired

figma_set_layout_align

Set how a child behaves in an auto-layout frame: alignment (STRETCH), growth (fill container) and absolute positioning.

ParametersnodeIdrequiredlayoutGrowlayoutAlignlayoutPositioning

figma_rename_node

Rename one or more nodes (a batch shares one name).

ParametersnamerequirednodeIdnodeIds

figma_reorder_node

Change a node's z-order among its siblings. position is the FINAL index (0 = back/bottom, childCount-1 = front/top); 'back' and 'front' also work. Out-of-range values are clamped. Verified by readback (REORDER_FAILED otherwise). Children of instances cannot be reordered (INSTANCE_SUBLAYER_RESTRICTED): reorder on the master.

ParametersnodeIdrequiredpositionrequired

figma_set_text_style

Set text font properties.

ParametersnodeIdrequiredfontSizetextCasefontStylefontFamilylineHeightletterSpacingtextDecorationtextAlignVerticaltextAlignHorizontal

figma_create_paint_style

Create a paint style.

Parametersnamerequiredfillsrequireddescription

figma_create_text_style

Create a text style.

ParametersnamerequiredfontSizetextCasefontStylefontFamilylineHeightdescriptionletterSpacingtextDecoration

figma_delete_style

Delete a local style (paint, text, effect or grid). Library styles return REMOTE_STYLE. Nodes keep their resolved values but lose the link.

ParametersstyleIdrequired

figma_create_variable_collection

Create a variable collection.

Parametersnamerequiredmodes

figma_create_variable

Create a variable in a collection.

ParametersnamerequiredtyperequiredvaluescopesaliasOfdescriptioncollectionIdrequired

figma_rename_variable

Rename a variable; "/" makes groups.

ParametersnamerequiredvariableIdrequired

figma_delete_variables

Delete variables. Cannot be undone.

ParametersvariableIdsrequired

figma_delete_variable_collection

Delete a variable collection and all its variables. Cannot be undone.

ParameterscollectionIdrequired

figma_rename_variable_collection

Rename a variable collection.

ParametersnamerequiredcollectionIdrequired

figma_rename_mode

Rename a mode in a variable collection.

ParametersnamerequiredmodeIdrequiredcollectionIdrequired

figma_add_mode

Add a new mode to a variable collection.

ParametersnamerequiredcollectionIdrequired

figma_delete_mode

Delete a mode from a variable collection. Cannot delete the last mode.

ParametersmodeIdrequiredcollectionIdrequired

figma_set_variable_mode

Pin an explicit variable mode on nodes or pages (e.g. a mobile frame pinned to the Spacing collection's mobile mode), or clear: true to unpin. Works on scene nodes and page ids. Echoes explicitVariableModes ({} = nothing pinned).

ParametersclearmodeIdnodeIdsrequiredcollectionIdrequired

figma_unbind_variable

Remove a variable binding from a node property, verified by readback (UNBIND_FAILED otherwise). For minWidth/maxWidth/minHeight/maxHeight the leftover literal clamp is cleared too (previousLiteral, clearedLiteral).

ParametersfieldrequirednodeIdrequiredpaintIndex

figma_create_page

Create a page. Figma Design only: FigJam returns FIGMA_DESIGN_ONLY (create FigJam pages in its UI).

Parametersnamerequiredindex

figma_rename_page

Rename a page.

ParametersnamerequiredpageIdrequired

figma_delete_page

Delete a page. The last page cannot be deleted.

ParameterspageIdrequired

figma_reparent_nodes

Move nodes to a different parent.

ParametersindexnodeIdsrequirednewParentIdrequired

figma_move_to_page

Move nodes from their current page to a different page.

ParametersxynodeIdsrequiredtargetPageIdrequired

figma_swap_instance

Swap an instance to a different component, keeping position and size.

ParametersinstanceIdrequirednewComponentIdrequired

figma_duplicate_page

Clone a page and its contents, inserted after the original. Figma Design only (FIGMA_DESIGN_ONLY in FigJam).

ParametersnamepageIdrequired

figma_set_rotation

Rotate nodes by degrees. pivot 'center' (default) keeps the visual centre in place; 'top-left' is Figma's raw rotation, which moves the centre. Children of auto-layout parents (unless ABSOLUTE) cannot use a centre pivot: they get top-left plus a warning. Echoes appliedPivot, rotation and absoluteBoundingBox.

ParameterspivotnodeIdsrequiredrotationrequired

figma_combine_as_variants

Combine components into a variant set; names must use variant naming (e.g. "Size=Large").

ParameterscomponentIdsrequired

figma_create_sticky

FigJam only: create a sticky note (fixed 240×240). Author name/visibility are set by Figma and cannot be changed.

ParametersxytextfillsparentIdisWideWidth

figma_set_sticky

FigJam only: toggle a sticky between square and wide. Use figma_set_text for body text.

ParametersnodeIdrequiredisWideWidth

figma_create_shape_with_text

FigJam only: flowchart shape with embedded text (30 shape types; cornerRadius is fixed).

ParametersxytextfillswidthheightstrokesparentIdshapeTyperequiredstrokeWeight

figma_set_shape_type

FigJam only: change the shape type of a shape-with-text node.

ParametersnodeIdrequiredshapeTyperequired

figma_create_connector

FigJam only: connector (arrow) between two nodes. Endpoints attach via magnets (AUTO recommended), fixed positions, or float free. Default end cap ARROW_EQUILATERAL. STRAIGHT only supports CENTER/NONE magnets.

ParametersendtextstartendCapstrokeslineTypeparentIdstartCapstrokeWeight

figma_set_connector

FigJam only: modify an existing connector's endpoints, line type, end caps, or label.

ParametersendtextstartendCapnodeIdrequiredlineTypestartCap

figma_create_section

Create a labeled section (works in both Figma Design and FigJam) to group content. Supports dev status (READY_FOR_DEV/COMPLETED).

ParametersxynamefillswidthheightparentIddevStatusdevStatusDescriptionsectionContentsHidden

figma_set_section

Update a section's name, dev status, or content visibility. Pass devStatus: null to clear.

ParametersnamenodeIdrequireddevStatusdevStatusDescriptionsectionContentsHidden

figma_create_table

FigJam only: create a table (default 2×2), optionally seeded via cells.

ParametersxycellsfillsnumRowsparentIdnumColumns

figma_set_table_cell

FigJam only: set the text and/or fill color of a single table cell.

ParametersrowrequiredtextfillscolumnrequirednodeIdrequired

figma_insert_table_row

FigJam only: insert a row at the given index (existing rows at and after the index shift down).

ParametersnodeIdrequiredrowIndexrequired

figma_insert_table_column

FigJam only: insert a column at the given index (existing columns at and after the index shift right).

ParametersnodeIdrequiredcolumnIndexrequired

figma_remove_table_row

FigJam only: remove the row at the given index.

ParametersnodeIdrequiredrowIndexrequired

figma_remove_table_column

FigJam only: remove the column at the given index.

ParametersnodeIdrequiredcolumnIndexrequired

figma_resize_table_row

FigJam only: set the height of a table row.

ParametersheightrequirednodeIdrequiredrowIndexrequired

figma_resize_table_column

FigJam only: set the width of a table column.

ParameterswidthrequirednodeIdrequiredcolumnIndexrequired

figma_move_table_row

FigJam only: move a row from one index to another.

ParametersnodeIdrequiredtoIndexrequiredfromIndexrequired

figma_move_table_column

FigJam only: move a column from one index to another.

ParametersnodeIdrequiredtoIndexrequiredfromIndexrequired

figma_create_code_block

FigJam only: create a syntax-highlighted code block.

ParametersxycoderequiredparentIdcodeLanguage

figma_set_code_block

FigJam only: update an existing code block's code text or language.

ParameterscodenodeIdrequiredcodeLanguage

figma_get_reactions

Prototype (Figma Design only): get a node's reactions (trigger and action details).

ParametersnodeIdrequired

figma_add_reaction

Prototype (Figma Design only): add an interaction to a node; existing reactions are kept.

ParametersactionrequirednodeIdrequiredtriggerrequired

figma_remove_reaction

Prototype (Figma Design only): remove a reaction by its zero-based index; find it with figma_get_reactions first.

ParametersindexrequirednodeIdrequired

figma_set_flow_starting_point

Prototype (Figma Design only): set a top-level frame as a flow starting point on the page, or clear it. Stored page-level as { nodeId, name } entries.

ParametersclearnodeIdrequiredflowName

Version history

1
  1. v1.0.1LatestNov 1, 2026

Score

65% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts

    Declare a GitHub repository with a README, or serve resource_documentation in the OAuth protected-resource metadata.

  • License10 pts

    Declare a license in the repository or the registry entry.