figma-agent
Local font helper for Figma, Linux and macOS.
A small Rust daemon that exposes the two endpoints the Figma web client calls to enumerate and load locally-installed fonts.
| Endpoint | Purpose |
|---|---|
GET /font-files |
List installed fonts + metadata (mirrors macOS Figma Agent's schema) |
GET /font-file?file=<path> |
Stream a font file by path |
OPTIONS preflight is handled for CORS, including
Access-Control-Allow-Private-Network: true, required by Chrome 94+ when
figma.com (public origin) reaches 127.0.0.1 (private network).
Responses are gzip/deflate/zstd-compressed when the client sends
Accept-Encoding. Server: FigmaAgent/<version> is set on every response.
Trailing slashes are normalised (so /font-files/ and /font-files route
to the same handler). Matches the orig macOS Figma Agent's middleware stack.
The non-browser endpoints from the official macOS Figma Agent (spell-check,
desktop/open-url, clear-data, assets/*, font-preview) are
intentionally not implemented; they exist for the Figma desktop app's
IPC with macOS system APIs and are not exercised by figma.com itself.
Build
--release --no-default-features to drop TLS (smaller binary, HTTP-only).
Run
Default ports: HTTP 127.0.0.1:44950, HTTPS 127.0.0.1:44951 (same as the
macOS Figma Agent).
Config
Optional JSON file at $XDG_CONFIG_HOME/figma-agent/config.json,
falling back to ~/.config/figma-agent/config.json on both Linux and macOS.
font_dirsentries can be plain strings (treated asuser_installed=false) or detailed objects to override the classification.tls_port: nulldisables HTTPS entirely.- If
tls_cert/tls_keyare absent, a self-signed cert is generated forlocalhost/127.0.0.1at startup; trust it once on your machine (macOS:security add-trusted-cert; Linux: NSS DB).
Font discovery
Two sources, deduped by absolute path:
- OS registry:
CTFontManagerCopyAvailableFontURLson macOS,fc-liston Linux. Captures Font Book registrations, Adobe Fonts, fontconfig user dirs, and anything else the system already knows about. font_dirsconfig: explicit directories you want walked. Entries here override the auto-classification (e.g., mark a system path asuser_installed: trueif you want).
The parsed catalogue is cached to
$XDG_CACHE_HOME/figma-agent/font_cache.json (default
~/.cache/figma-agent/font_cache.json) on Linux and macOS alike. Cache is
keyed by daemon version; delete the file or upgrade to force a refresh
(e.g., after adding fonts).
Response schema
{
"version": "0.1.0",
"modified_at": 1716000000,
"modified_fonts": [],
"fonts": [
{
"family": "Inter",
"style": "Regular",
"postscript": "Inter-Regular",
"weight": 400.0,
"stretch": 100.0,
"italic": false,
"variationAxes": [
{
"tag": "wght",
"name": "Weight",
"value": 400.0,
"min": 100.0,
"max": 900.0,
"default": 400.0,
"hidden": false
}
],
"user_installed": false,
"name": "Inter Regular",
"path": "/usr/share/fonts/Inter-Regular.ttf"
}
],
"request_id": 1,
"elapsed_ms": 42
}
This matches the macOS Figma Agent's FontInfo schema 1:1, except for the
trailing path field, which we add so the follow-up GET /font-file call
has a usable identifier (the orig daemon's client knows the path through
other means).
Variable fonts with fvar named-instances expand to one entry per instance
(Inter VF becomes Thin, Light, Regular, etc.), matching CoreText's behaviour
on the orig macOS agent. The instance's weight / stretch reflect the
runtime wght / wdth axis coordinates, and each variationAxes[i].value
is the per-instance coordinate rather than the file-level default.
/font-file errors return JSON: { error, detail, version, request_id }.
Validation: non-empty, ≤ 4 KB path, absolute, no .. segments, regular
file, ≤ 256 MB, and inside one of font_dirs. The 256 MB ceiling is higher
than orig's 32 MB so large macOS CJK collections (AppleSDGothicNeo.ttc,
PingFang.ttc) remain reachable.
License
MIT, see LICENSE.