Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 2.2.5 (2026-09-26)

### Fixed

- The daemon is only restarted when it runs an older version than the CLI. With two installs of different versions (global and project-local) they no longer restart each other on every command; the newer daemon stays

## 2.2.4 (2026-09-26)

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "figma-ds-cli",
"version": "2.2.4",
"version": "2.2.5",
"description": "CLI for managing Figma design systems. Create variables, components, and more. No API key required.",
"author": {
"name": "Sil Bormüller",
Expand Down
21 changes: 16 additions & 5 deletions src/lib/cli-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,16 +246,26 @@ const DAEMON_HEALTH_TTL_MS = 2000;
function invalidateDaemonHealthCache() { _daemonHealthCache = { time: 0, value: null }; }
let _daemonHealthBody = null;

// true when version a is older than b (plain x.y.z)
function versionOlder(a, b) {
const p = v => String(v || '0').split('-')[0].split('.').map(n => parseInt(n, 10) || 0);
const x = p(a), y = p(b);
for (let i = 0; i < 3; i++) { if ((x[i] || 0) !== (y[i] || 0)) return (x[i] || 0) < (y[i] || 0); }
return false;
}

/**
* True when the running daemon was started from different figma-cli code:
* another version (after npm update) or another install path. render-batch and
* eval run INSIDE the daemon, so a stale one silently serves old behaviour.
* A daemon too old to report its version counts as stale.
* True when the running daemon runs OLDER figma-cli code than this CLI (after
* npm update). render-batch and eval run INSIDE the daemon, so a stale one
* silently serves old behaviour. A daemon too old to report its version counts
* as older. Only older, never merely different: with two installs of different
* versions (global and project-local) "restart on any mismatch" made them
* restart each other on every command; this way the newer one wins and stays.
*/
function daemonCodeMismatch() {
const h = _daemonHealthBody;
if (!h || h.status === undefined) return false;
return h.version !== pkg.version || (h.root && h.root !== join(__dirname));
return !h.version || versionOlder(h.version, pkg.version);
}

// Check if daemon is running (returns object with details, or false)
Expand Down Expand Up @@ -991,6 +1001,7 @@ async function isInSafeMode() {
}

export {
versionOlder,
CONFIG_DIR,
CONFIG_FILE,
DAEMON_PID_FILE,
Expand Down
11 changes: 11 additions & 0 deletions tests/daemon-version.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { versionOlder } from '../src/lib/cli-core.js';

test('only an older daemon counts as stale, so two installs never restart each other', () => {
assert.equal(versionOlder('2.2.3', '2.2.4'), true);
assert.equal(versionOlder('2.2.4', '2.2.4'), false);
assert.equal(versionOlder('2.3.0', '2.2.9'), false);
assert.equal(versionOlder('2.10.0', '2.9.0'), false);
assert.equal(versionOlder(undefined, '2.2.4'), true);
});
Loading