Copy your Figma comments, with the same text and position, from an old duplicate into the file you're working in.
- Open the Figma desktop app.
- Open the new duplicate file (the one that should receive the comments).
- Plugins → Development → Import plugin from manifest…, pick
manifest.jsonfrom this folder. - Run it: Plugins → Development → Comment Mirror.
The Plugin API can't read or write comments, so the plugin calls the Figma REST API with your personal access token.
- Figma → your avatar → Settings → Security → Personal access tokens → Generate new token.
- Choose an expiration and enable these scopes:
- Comments: Read (
file_comments:read) - Comments: Write (
file_comments:write)
- Comments: Read (
- Copy the token right away (Figma shows it once) and paste it in the plugin.
No other scope is needed. A 403 means a missing scope or no access to the file; a 404 means a wrong file key or no access for the token owner.
- Paste the token (Remember token stores it in
figma.clientStorage; Forget token deletes it). - Paste the source file URL (
figma.com/design/KEY/...or/file/KEY/...). The target is the open file; if its key can't be detected, a Target file URL field appears. - Click Mirror comments. The plugin reads both files' comments and shows the plan: number of POST requests and estimated time. Click Start to post. Stop finishes the current request and stops.
- Dry run fetches and previews everything without posting.
Starter plan: the plugin works on every plan, but Starter has the tightest API limits, so the plugin uses the same slow pace everywhere.
- It sends one request every 12 seconds (Starter allows about 5 per minute). 100 comments take about 20 minutes, so keep the plugin open.
- It only uses the comments endpoints, never the file, nodes or images endpoints.
- If Figma rate limits it (HTTP 429), it waits and retries. If the wait is over 5 minutes, it stops and lists the rest as not yet mirrored. Run it again later: comments already in the target are skipped, so it resumes where it stopped.
- Canvas comments (x, y) are posted as is.
- Comments attached to a node (
node_id) are posted as is if that node id exists in this file (duplicates normally keep node ids). Otherwise they are orphaned: not posted, listed with full text so you can re-add them by hand (Copy all orphans). - A comment counts as "already exists" when message and position (node id + offset, or x,y) match a comment in the target. Replies are matched by message under the already-mirrored parent.
- The token is only sent in the
X-Figma-Tokenheader, never in a URL, and never logged.
manifest.json– plugin config (network access limited toapi.figma.com)code.js– main thread: token storage, file key, node-existence checksui.html– UI, throttled REST calls and migration logic (no build step)
