Ordinary search and the optional local index
| Ordinary (default) | Advanced: local index (optional) | |
|---|---|---|
| What it does | Reads the .fig on each call and answers search, find, inspect and export. |
Builds a search index of a chosen scope once, then answers search from it, ranked across sources. |
| What is written | No workspace or index database (export writes only the files you ask for). |
A local workspace (SQLite database) in the per-user state directory, or the --storage you chose. |
| When to use | One-off questions, scripts, CI. | Repeated searches of one file; several files of a project as one corpus (--workspace <dir>); exact usages of components, variables, styles and images. |
A normal design question never creates an index. You opt in once, explicitly ("create an index for this design"); figlens picks the storage and needs no SQLite or other setup.
# Ordinary: stateless, creates nothing
figlens search design.fig "checkout button"
# Advanced, once: pick a scope (a node id, or 0:0 for the whole file); the build runs in the foreground
figlens index prepare design.fig --scope 0:0
# Indexed search: pass the scope you prepared as --node
figlens search --file design.fig "checkout button" --node 0:0
# After you edit or re-export the .fig: rebuild only the scopes whose bytes changed
figlens index refresh --file design.fig
# After you move the .fig: keep the workspace, then refresh (use the workspaceId printed by prepare)
figlens index relocate <sourceId> new/design.fig --id <workspaceId>
figlens index refresh --id <workspaceId>
MCP: index prepare returns a job; poll jobs until succeeded, then search with the workspaceId from the reply and node set to the prepared scope (without node, search reads 0:0).
{"tool": "index", "arguments": {"action": "prepare", "file": "/abs/path/design.fig", "scope": "0:0"}}
{"tool": "jobs", "arguments": {"action": "status", "jobId": "<jobId from the reply>"}}
{"tool": "search", "arguments": {"workspaceId": "<workspaceId from the reply>", "node": "0:0", "query": "checkout button"}}
Lifecycle: refresh rebuilds only scopes whose .fig bytes changed; rebuild rebuilds even when unchanged; clear_cache deletes only data a build can recreate and keeps the registry and published indexes; reset deletes this workspace's database (never the .fig or exports) and runs only on your explicit request. New sources, a wider scope, reset and recreate each need their own explicit request.
Moved the .fig? index relocate keeps workspaceId, sourceId and storage; then refresh the affected scopes. There is no auto-discovery and no hash-based merge, and no reset is needed.
Several designs in one folder? index add <dir> --workspace DIR registers up to 10 .fig files under that directory in one step, skipping links that lead out of it; the reply lists added, existing, skipped and truncated, a repeat adds nothing, and each file still needs its own prepare --scope. A file moved inside the folder is a new source unless you relocate it. Pass the reply's nextCursor as --cursor C (MCP cursor) to add the next 10. Paged search and library cursors last one hour; after that they return cursor_expired, so search again.
Data: the SQLite database holds registered local paths, the selected scopes' layer names and effective text, instances' component property values, search postings, exact relations (containment, instances, variants, variable/style/image bindings, prototype targets) and the definitions they point at, hashes, generations and jobs. The original .fig stays unchanged where it is; its raw bytes are not stored in the database. Semantic and vision model layers add the vectors they embed, and visual indexing you enable adds PNG renders of the indexed layers, even without a model; query images are never stored.
Pi, OpenCode and OMP use the same index through their own opt-in entry, and the workspace is reused across restarts and hosts. Not implemented: file events (a watch polls the file, and only while a holder runs) and push events.
This page is built from docs/README.md in the repository.