refactor(#56): retire legacy runtime directory helpers into runtime-homes projection (#802)

* refactor(#56): retire legacy runtime directory helpers into runtime-homes projection

Consolidate per-runtime global config-dir resolution onto the single
canonical projection runtime-homes:getGlobalConfigDir. Extend it with the
explicitDir override (CLI --config-dir) and the opencode/kilo
OPENCODE_CONFIG/KILO_CONFIG file-path precedence the installer helpers had,
making it byte-for-behavior equivalent to the old getGlobalDir across all
15 install runtimes.

Delete bin/install.js's getGlobalDir/getOpencodeGlobalDir/getKiloGlobalDir
(and the orphaned local expandTilde), repoint all 9 call-sites, and remove
getGlobalDir from module.exports (net -242 lines in the installer). Migrate
the 5 test importers to the canonical projection; harden default/XDG
assertions against ambient *_CONFIG env vars. getAgentsDir now respects
OPENCODE_CONFIG/KILO_CONFIG consistently with the installer (intentional
convergence). Update CONTEXT.md Installer Module entry.

Completes the installer-refactor chain #58 -> #60 -> #56.

Closes #56

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#56): add changeset for runtime directory helper retirement

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-07 12:24:04 -04:00
committed by GitHub
parent f66c4a082c
commit 7e1112c28f
11 changed files with 207 additions and 297 deletions

View File

@@ -65,7 +65,8 @@ describe('bug #3126: runtime-homes getGlobalConfigDir — defaults', () => {
const envKeys = ['CLAUDE_CONFIG_DIR','CURSOR_CONFIG_DIR','GEMINI_CONFIG_DIR',
'CODEX_HOME','COPILOT_CONFIG_DIR','ANTIGRAVITY_CONFIG_DIR','WINDSURF_CONFIG_DIR',
'AUGMENT_CONFIG_DIR','TRAE_CONFIG_DIR','QWEN_CONFIG_DIR','HERMES_HOME',
'CODEBUDDY_CONFIG_DIR','CLINE_CONFIG_DIR','OPENCODE_CONFIG_DIR','KILO_CONFIG_DIR',
'CODEBUDDY_CONFIG_DIR','CLINE_CONFIG_DIR','OPENCODE_CONFIG_DIR','OPENCODE_CONFIG',
'KILO_CONFIG_DIR','KILO_CONFIG',
'XDG_CONFIG_HOME'];
const saved = {};
for (const k of envKeys) { saved[k] = process.env[k]; delete process.env[k]; }
@@ -105,15 +106,19 @@ describe('bug #3126: runtime-homes env-var overrides', () => {
});
test('opencode uses XDG_CONFIG_HOME when OPENCODE_CONFIG_DIR absent', () => {
withEnv('OPENCODE_CONFIG_DIR', undefined, () => {
withEnv('XDG_CONFIG_HOME', '/xdg', () => {
assert.strictEqual(getGlobalConfigDir('opencode'), path.join('/xdg', 'opencode'));
withEnv('OPENCODE_CONFIG', undefined, () => {
withEnv('XDG_CONFIG_HOME', '/xdg', () => {
assert.strictEqual(getGlobalConfigDir('opencode'), path.join('/xdg', 'opencode'));
});
});
});
});
test('kilo uses XDG_CONFIG_HOME when KILO_CONFIG_DIR absent', () => {
withEnv('KILO_CONFIG_DIR', undefined, () => {
withEnv('XDG_CONFIG_HOME', '/xdg', () => {
assert.strictEqual(getGlobalConfigDir('kilo'), path.join('/xdg', 'kilo'));
withEnv('KILO_CONFIG', undefined, () => {
withEnv('XDG_CONFIG_HOME', '/xdg', () => {
assert.strictEqual(getGlobalConfigDir('kilo'), path.join('/xdg', 'kilo'));
});
});
});
});
@@ -186,6 +191,110 @@ describe('bug #3126: runtime-homes getGlobalSkillDir', () => {
});
});
describe('getGlobalConfigDir — explicitDir override and opencode/kilo file-path precedence', () => {
// ── explicitDir override ──────────────────────────────────────────────────
test('explicitDir absolute path is returned as-is (claude)', () => {
assert.strictEqual(getGlobalConfigDir('claude', '/tmp/x'), '/tmp/x');
});
test('explicitDir with tilde is expanded (opencode)', () => {
assert.strictEqual(
getGlobalConfigDir('opencode', '~/foo'),
path.join(os.homedir(), 'foo'),
);
});
test('explicitDir wins even when OPENCODE_CONFIG_DIR is also set', () => {
withEnv('OPENCODE_CONFIG_DIR', '/should/not/win', () => {
assert.strictEqual(getGlobalConfigDir('opencode', '/explicit/wins'), '/explicit/wins');
});
});
// ── opencode: OPENCODE_CONFIG file-path step ──────────────────────────────
test('opencode: OPENCODE_CONFIG → path.dirname(expandTilde(value))', () => {
withEnv('OPENCODE_CONFIG_DIR', undefined, () => {
withEnv('XDG_CONFIG_HOME', undefined, () => {
withEnv('OPENCODE_CONFIG', '/home/u/cfg/opencode.json', () => {
assert.strictEqual(getGlobalConfigDir('opencode'), '/home/u/cfg');
});
});
});
});
test('opencode: OPENCODE_CONFIG_DIR takes precedence over OPENCODE_CONFIG', () => {
withEnv('OPENCODE_CONFIG_DIR', '/dir/wins', () => {
withEnv('OPENCODE_CONFIG', '/file/loses.json', () => {
assert.strictEqual(getGlobalConfigDir('opencode'), '/dir/wins');
});
});
});
test('opencode: OPENCODE_CONFIG takes precedence over XDG_CONFIG_HOME', () => {
withEnv('OPENCODE_CONFIG_DIR', undefined, () => {
withEnv('OPENCODE_CONFIG', '/cfg/opencode.json', () => {
withEnv('XDG_CONFIG_HOME', '/xdg/should/lose', () => {
assert.strictEqual(getGlobalConfigDir('opencode'), '/cfg');
});
});
});
});
test('opencode: default ~/.config/opencode when no env vars set', () => {
withEnv('OPENCODE_CONFIG_DIR', undefined, () => {
withEnv('OPENCODE_CONFIG', undefined, () => {
withEnv('XDG_CONFIG_HOME', undefined, () => {
assert.strictEqual(
getGlobalConfigDir('opencode'),
path.join(os.homedir(), '.config', 'opencode'),
);
});
});
});
});
// ── kilo: KILO_CONFIG file-path step ─────────────────────────────────────
test('kilo: KILO_CONFIG → path.dirname(expandTilde(value))', () => {
withEnv('KILO_CONFIG_DIR', undefined, () => {
withEnv('XDG_CONFIG_HOME', undefined, () => {
withEnv('KILO_CONFIG', '/home/u/cfg/kilo.json', () => {
assert.strictEqual(getGlobalConfigDir('kilo'), '/home/u/cfg');
});
});
});
});
test('kilo: KILO_CONFIG_DIR takes precedence over KILO_CONFIG', () => {
withEnv('KILO_CONFIG_DIR', '/dir/wins', () => {
withEnv('KILO_CONFIG', '/file/loses.json', () => {
assert.strictEqual(getGlobalConfigDir('kilo'), '/dir/wins');
});
});
});
test('kilo: KILO_CONFIG takes precedence over XDG_CONFIG_HOME', () => {
withEnv('KILO_CONFIG_DIR', undefined, () => {
withEnv('KILO_CONFIG', '/cfg/kilo.json', () => {
withEnv('XDG_CONFIG_HOME', '/xdg/should/lose', () => {
assert.strictEqual(getGlobalConfigDir('kilo'), '/cfg');
});
});
});
});
test('kilo: default ~/.config/kilo when no env vars set', () => {
withEnv('KILO_CONFIG_DIR', undefined, () => {
withEnv('KILO_CONFIG', undefined, () => {
withEnv('XDG_CONFIG_HOME', undefined, () => {
assert.strictEqual(
getGlobalConfigDir('kilo'),
path.join(os.homedir(), '.config', 'kilo'),
);
});
});
});
});
});
describe('bug #3126: init.cjs uses runtime-homes not hardcoded .claude', () => {
test('init.cjs has no hardcoded globalSkillsBase assignment to ~/.claude/skills', () => {
const fs = require('node:fs');

View File

@@ -30,20 +30,21 @@ const { createTempDir, cleanup } = require('./helpers.cjs');
const {
getDirName,
getGlobalDir,
getConfigDirFromHome,
convertClaudeToCliineMarkdown,
install,
finishInstall,
} = require('../bin/install.js');
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
describe('Cline runtime directory mapping', () => {
test('getDirName returns .cline for local installs', () => {
assert.strictEqual(getDirName('cline'), '.cline');
});
test('getGlobalDir returns ~/.cline for global installs', () => {
assert.strictEqual(getGlobalDir('cline'), path.join(os.homedir(), '.cline'));
test('getGlobalConfigDir returns ~/.cline for global installs', () => {
assert.strictEqual(getGlobalConfigDir('cline'), path.join(os.homedir(), '.cline'));
});
test('getConfigDirFromHome returns .cline fragment', () => {
@@ -52,7 +53,7 @@ describe('Cline runtime directory mapping', () => {
});
});
describe('getGlobalDir (Cline)', () => {
describe('getGlobalConfigDir (Cline)', () => {
let originalClineConfigDir;
beforeEach(() => {
@@ -69,30 +70,30 @@ describe('getGlobalDir (Cline)', () => {
test('returns ~/.cline with no env var or explicit dir', () => {
delete process.env.CLINE_CONFIG_DIR;
const result = getGlobalDir('cline');
const result = getGlobalConfigDir('cline');
assert.strictEqual(result, path.join(os.homedir(), '.cline'));
});
test('returns explicit dir when provided', () => {
const result = getGlobalDir('cline', '/custom/cline-path');
const result = getGlobalConfigDir('cline', '/custom/cline-path');
assert.strictEqual(result, '/custom/cline-path');
});
test('respects CLINE_CONFIG_DIR env var', () => {
process.env.CLINE_CONFIG_DIR = '~/custom-cline';
const result = getGlobalDir('cline');
const result = getGlobalConfigDir('cline');
assert.strictEqual(result, path.join(os.homedir(), 'custom-cline'));
});
test('explicit dir takes priority over CLINE_CONFIG_DIR', () => {
process.env.CLINE_CONFIG_DIR = '~/from-env';
const result = getGlobalDir('cline', '/explicit/path');
const result = getGlobalConfigDir('cline', '/explicit/path');
assert.strictEqual(result, '/explicit/path');
});
test('does not break other runtimes', () => {
assert.strictEqual(getGlobalDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalDir('codex'), path.join(os.homedir(), '.codex'));
assert.strictEqual(getGlobalConfigDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalConfigDir('codex'), path.join(os.homedir(), '.codex'));
});
});

View File

@@ -14,7 +14,6 @@ const { createTempDir, cleanup } = require('./helpers.cjs');
const {
getDirName,
getGlobalDir,
getConfigDirFromHome,
convertClaudeToCodebuddyMarkdown,
convertClaudeCommandToCodebuddySkill,
@@ -25,6 +24,8 @@ const {
installRuntimeArtifacts,
} = require('../bin/install.js');
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
// ─── Profile resolution for installRuntimeArtifacts tests ────────────────────
const _gsdLibDir = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib');
const { loadSkillsManifest, resolveProfile } = require(path.join(_gsdLibDir, 'install-profiles.cjs'));
@@ -37,7 +38,7 @@ describe('CodeBuddy runtime directory mapping', () => {
});
test('maps CodeBuddy to ~/.codebuddy for global installs', () => {
assert.strictEqual(getGlobalDir('codebuddy'), path.join(os.homedir(), '.codebuddy'));
assert.strictEqual(getGlobalConfigDir('codebuddy'), path.join(os.homedir(), '.codebuddy'));
});
test('returns .codebuddy config fragments for local and global installs', () => {
@@ -46,7 +47,7 @@ describe('CodeBuddy runtime directory mapping', () => {
});
});
describe('getGlobalDir (CodeBuddy)', () => {
describe('getGlobalConfigDir (CodeBuddy)', () => {
let originalCodebuddyConfigDir;
beforeEach(() => {
@@ -63,30 +64,30 @@ describe('getGlobalDir (CodeBuddy)', () => {
test('returns ~/.codebuddy with no env var or explicit dir', () => {
delete process.env.CODEBUDDY_CONFIG_DIR;
const result = getGlobalDir('codebuddy');
const result = getGlobalConfigDir('codebuddy');
assert.strictEqual(result, path.join(os.homedir(), '.codebuddy'));
});
test('returns explicit dir when provided', () => {
const result = getGlobalDir('codebuddy', '/custom/codebuddy-path');
const result = getGlobalConfigDir('codebuddy', '/custom/codebuddy-path');
assert.strictEqual(result, '/custom/codebuddy-path');
});
test('respects CODEBUDDY_CONFIG_DIR env var', () => {
process.env.CODEBUDDY_CONFIG_DIR = '~/custom-codebuddy';
const result = getGlobalDir('codebuddy');
const result = getGlobalConfigDir('codebuddy');
assert.strictEqual(result, path.join(os.homedir(), 'custom-codebuddy'));
});
test('explicit dir takes priority over CODEBUDDY_CONFIG_DIR', () => {
process.env.CODEBUDDY_CONFIG_DIR = '~/from-env';
const result = getGlobalDir('codebuddy', '/explicit/path');
const result = getGlobalConfigDir('codebuddy', '/explicit/path');
assert.strictEqual(result, '/explicit/path');
});
test('does not break other runtimes', () => {
assert.strictEqual(getGlobalDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalDir('codex'), path.join(os.homedir(), '.codex'));
assert.strictEqual(getGlobalConfigDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalConfigDir('codex'), path.join(os.homedir(), '.codex'));
});
});

View File

@@ -28,7 +28,6 @@ const { parseFrontmatter, createTempDir, cleanup } = require('./helpers.cjs');
const {
getDirName,
getGlobalDir,
getConfigDirFromHome,
claudeToCopilotTools,
convertCopilotToolName,
@@ -48,6 +47,8 @@ const {
buildRuntimePromptText,
} = require('../bin/install.js');
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
// ─── Profile resolution for installRuntimeArtifacts tests ────────────────────
const _gsdLibDir = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib');
const { loadSkillsManifest, resolveProfile } = require(path.join(_gsdLibDir, 'install-profiles.cjs'));
@@ -70,9 +71,9 @@ describe('getDirName (Copilot)', () => {
});
});
// ─── getGlobalDir ───────────────────────────────────────────────────────────────
// ─── getGlobalConfigDir ──────────────────────────────────────────────────────────
describe('getGlobalDir (Copilot)', () => {
describe('getGlobalConfigDir (Copilot)', () => {
let originalCopilotConfigDir;
beforeEach(() => {
@@ -89,30 +90,30 @@ describe('getGlobalDir (Copilot)', () => {
test('returns ~/.copilot with no env var or explicit dir', () => {
delete process.env.COPILOT_CONFIG_DIR;
const result = getGlobalDir('copilot');
const result = getGlobalConfigDir('copilot');
assert.strictEqual(result, path.join(os.homedir(), '.copilot'));
});
test('returns explicit dir when provided', () => {
const result = getGlobalDir('copilot', '/custom/path');
const result = getGlobalConfigDir('copilot', '/custom/path');
assert.strictEqual(result, '/custom/path');
});
test('respects COPILOT_CONFIG_DIR env var', () => {
process.env.COPILOT_CONFIG_DIR = '~/custom-copilot';
const result = getGlobalDir('copilot');
const result = getGlobalConfigDir('copilot');
assert.strictEqual(result, path.join(os.homedir(), 'custom-copilot'));
});
test('explicit dir takes priority over COPILOT_CONFIG_DIR', () => {
process.env.COPILOT_CONFIG_DIR = '~/env-path';
const result = getGlobalDir('copilot', '/explicit/path');
const result = getGlobalConfigDir('copilot', '/explicit/path');
assert.strictEqual(result, '/explicit/path');
});
test('does not break existing runtimes', () => {
assert.strictEqual(getGlobalDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalDir('codex'), path.join(os.homedir(), '.codex'));
assert.strictEqual(getGlobalConfigDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalConfigDir('codex'), path.join(os.homedir(), '.codex'));
});
});

View File

@@ -5,7 +5,7 @@
/**
* Installer Module — Sections 1–5.
*
* Covers: getDirName/getGlobalDir/getConfigDirFromHome, per-runtime
* Covers: getDirName/getGlobalConfigDir/getConfigDirFromHome, per-runtime
* install/uninstall spot-checks (hermes/qwen/trae), uninstall skills
* cleanup, Claude-reference leak tests, and Kilo-specific helpers.
*
@@ -34,7 +34,6 @@ const pkg = require('../package.json');
const {
getDirName,
getGlobalDir,
getConfigDirFromHome,
install,
uninstall,
@@ -46,13 +45,15 @@ const {
configureKiloPermissions,
} = require('../bin/install.js');
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
const {
RUNTIME_META,
stripAnsi,
walk,
} = require('./helpers/install-shared.cjs');
// ─── Section 1: getDirName / getGlobalDir / getConfigDirFromHome ──────────────
// ─── Section 1: getDirName / getGlobalConfigDir / getConfigDirFromHome ──────────
describe('getDirName — all runtimes', () => {
for (const runtime of allRuntimes) {
@@ -64,11 +65,14 @@ describe('getDirName — all runtimes', () => {
}
});
describe('getGlobalDir — all runtimes default paths', () => {
describe('getGlobalConfigDir — all runtimes default paths', () => {
// Test the default (no env var, no explicit dir) for each runtime
const ENV_KEYS = [
'HERMES_HOME', 'QWEN_CONFIG_DIR', 'TRAE_CONFIG_DIR', 'ANTIGRAVITY_CONFIG_DIR',
'KILO_CONFIG_DIR', 'KILO_CONFIG', 'XDG_CONFIG_HOME',
'CLAUDE_CONFIG_DIR', 'CURSOR_CONFIG_DIR', 'GEMINI_CONFIG_DIR', 'CODEX_HOME',
'GROK_AGENTS_HOME', 'COPILOT_CONFIG_DIR', 'WINDSURF_CONFIG_DIR', 'AUGMENT_CONFIG_DIR',
'TRAE_CONFIG_DIR', 'QWEN_CONFIG_DIR', 'HERMES_HOME', 'CODEBUDDY_CONFIG_DIR',
'CLINE_CONFIG_DIR', 'OPENCODE_CONFIG_DIR', 'OPENCODE_CONFIG', 'KILO_CONFIG_DIR',
'KILO_CONFIG', 'ANTIGRAVITY_CONFIG_DIR', 'XDG_CONFIG_HOME',
];
let savedEnv = {};
@@ -87,14 +91,14 @@ describe('getGlobalDir — all runtimes default paths', () => {
});
for (const runtime of allRuntimes) {
test(`getGlobalDir('${runtime}') returns expected home-relative path`, () => {
test(`getGlobalConfigDir('${runtime}') returns expected home-relative path`, () => {
const expected = path.join(os.homedir(), RUNTIME_META[runtime].globalSuffix);
assert.strictEqual(getGlobalDir(runtime), expected);
assert.strictEqual(getGlobalConfigDir(runtime), expected);
});
}
});
describe('getGlobalDir/getConfigDirFromHome — antigravity 2.x layout detection', () => {
describe('getGlobalConfigDir/getConfigDirFromHome — antigravity 2.x layout detection', () => {
const saved = {};
beforeEach(() => {
saved.HOME = process.env.HOME;
@@ -118,7 +122,7 @@ describe('getGlobalDir/getConfigDirFromHome — antigravity 2.x layout detection
process.env.HOME = home;
process.env.USERPROFILE = home;
assert.strictEqual(
getGlobalDir('antigravity'),
getGlobalConfigDir('antigravity'),
path.join(home, '.gemini', 'antigravity-ide'),
);
assert.strictEqual(
@@ -137,7 +141,7 @@ describe('getGlobalDir/getConfigDirFromHome — antigravity 2.x layout detection
process.env.HOME = home;
process.env.USERPROFILE = home;
assert.strictEqual(
getGlobalDir('antigravity'),
getGlobalConfigDir('antigravity'),
path.join(home, '.gemini', 'antigravity-cli'),
);
assert.strictEqual(
@@ -150,12 +154,12 @@ describe('getGlobalDir/getConfigDirFromHome — antigravity 2.x layout detection
});
});
describe('getGlobalDir — explicit configDir overrides env for all runtimes', () => {
describe('getGlobalConfigDir — explicit configDir overrides env for all runtimes', () => {
test('explicit dir overrides any env var for hermes', () => {
const savedHome = process.env.HERMES_HOME;
process.env.HERMES_HOME = '~/from-env';
try {
assert.strictEqual(getGlobalDir('hermes', '/explicit/hermes'), '/explicit/hermes');
assert.strictEqual(getGlobalConfigDir('hermes', '/explicit/hermes'), '/explicit/hermes');
} finally {
if (savedHome !== undefined) process.env.HERMES_HOME = savedHome;
else delete process.env.HERMES_HOME;
@@ -166,7 +170,7 @@ describe('getGlobalDir — explicit configDir overrides env for all runtimes', (
const saved = process.env.KILO_CONFIG_DIR;
process.env.KILO_CONFIG_DIR = '~/from-env';
try {
assert.strictEqual(getGlobalDir('kilo', '/explicit/kilo'), '/explicit/kilo');
assert.strictEqual(getGlobalConfigDir('kilo', '/explicit/kilo'), '/explicit/kilo');
} finally {
if (saved !== undefined) process.env.KILO_CONFIG_DIR = saved;
else delete process.env.KILO_CONFIG_DIR;
@@ -174,7 +178,7 @@ describe('getGlobalDir — explicit configDir overrides env for all runtimes', (
});
});
describe('getGlobalDir — HERMES_HOME env var', () => {
describe('getGlobalConfigDir — HERMES_HOME env var', () => {
let saved;
beforeEach(() => { saved = process.env.HERMES_HOME; });
afterEach(() => {
@@ -184,11 +188,11 @@ describe('getGlobalDir — HERMES_HOME env var', () => {
test('respects HERMES_HOME env var (tilde-expanded)', () => {
process.env.HERMES_HOME = '~/custom-hermes';
assert.strictEqual(getGlobalDir('hermes'), path.join(os.homedir(), 'custom-hermes'));
assert.strictEqual(getGlobalConfigDir('hermes'), path.join(os.homedir(), 'custom-hermes'));
});
});
describe('getGlobalDir — Kilo env var priority', () => {
describe('getGlobalConfigDir — Kilo env var priority', () => {
let savedEnv;
beforeEach(() => {
savedEnv = {
@@ -209,23 +213,23 @@ describe('getGlobalDir — Kilo env var priority', () => {
test('respects KILO_CONFIG_DIR', () => {
process.env.KILO_CONFIG_DIR = '~/custom-kilo';
assert.strictEqual(getGlobalDir('kilo'), path.join(os.homedir(), 'custom-kilo'));
assert.strictEqual(getGlobalConfigDir('kilo'), path.join(os.homedir(), 'custom-kilo'));
});
test('falls back to XDG_CONFIG_HOME/kilo', () => {
process.env.XDG_CONFIG_HOME = '~/xdg-config';
assert.strictEqual(getGlobalDir('kilo'), path.join(os.homedir(), 'xdg-config', 'kilo'));
assert.strictEqual(getGlobalConfigDir('kilo'), path.join(os.homedir(), 'xdg-config', 'kilo'));
});
test('uses dirname(KILO_CONFIG) when KILO_CONFIG_DIR unset', () => {
process.env.KILO_CONFIG = '~/profiles/work/kilo.jsonc';
assert.strictEqual(getGlobalDir('kilo'), path.join(os.homedir(), 'profiles', 'work'));
assert.strictEqual(getGlobalConfigDir('kilo'), path.join(os.homedir(), 'profiles', 'work'));
});
test('KILO_CONFIG_DIR takes precedence over KILO_CONFIG', () => {
process.env.KILO_CONFIG_DIR = '~/custom-kilo';
process.env.KILO_CONFIG = '~/profiles/work/kilo.jsonc';
assert.strictEqual(getGlobalDir('kilo'), path.join(os.homedir(), 'custom-kilo'));
assert.strictEqual(getGlobalConfigDir('kilo'), path.join(os.homedir(), 'custom-kilo'));
});
});

View File

@@ -5,9 +5,9 @@ const assert = require('node:assert/strict');
const os = require('os');
const path = require('path');
const { getGlobalDir } = require('../bin/install.js');
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
describe('getGlobalDir (Windsurf)', () => {
describe('getGlobalConfigDir (Windsurf)', () => {
let originalWindsurfConfigDir;
beforeEach(() => {
@@ -24,29 +24,29 @@ describe('getGlobalDir (Windsurf)', () => {
});
test('returns ~/.codeium/windsurf with no env var or explicit dir', () => {
const result = getGlobalDir('windsurf');
const result = getGlobalConfigDir('windsurf');
assert.strictEqual(result, path.join(os.homedir(), '.codeium', 'windsurf'));
});
test('returns explicit dir when provided', () => {
const result = getGlobalDir('windsurf', '/custom/windsurf-path');
const result = getGlobalConfigDir('windsurf', '/custom/windsurf-path');
assert.strictEqual(result, '/custom/windsurf-path');
});
test('respects WINDSURF_CONFIG_DIR env var', () => {
process.env.WINDSURF_CONFIG_DIR = '~/custom-windsurf';
const result = getGlobalDir('windsurf');
const result = getGlobalConfigDir('windsurf');
assert.strictEqual(result, path.join(os.homedir(), 'custom-windsurf'));
});
test('explicit dir takes priority over WINDSURF_CONFIG_DIR', () => {
process.env.WINDSURF_CONFIG_DIR = '~/from-env';
const result = getGlobalDir('windsurf', '/explicit/path');
const result = getGlobalConfigDir('windsurf', '/explicit/path');
assert.strictEqual(result, '/explicit/path');
});
test('does not break other runtimes', () => {
assert.strictEqual(getGlobalDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalDir('codex'), path.join(os.homedir(), '.codex'));
assert.strictEqual(getGlobalConfigDir('claude'), path.join(os.homedir(), '.claude'));
assert.strictEqual(getGlobalConfigDir('codex'), path.join(os.homedir(), '.codex'));
});
});