coder-config 0.47.1-beta → 0.47.2-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/config-loader.js CHANGED
@@ -137,7 +137,7 @@ class ClaudeConfigManager {
137
137
  applyForGemini(projectDir) { return applyForGemini(this.registryPath, projectDir); }
138
138
  detectInstalledTools() { return detectInstalledTools(); }
139
139
  getToolPaths() { return TOOL_PATHS; }
140
- applyForTools(projectDir, tools) { return applyForTools(this.registryPath, projectDir, tools); }
140
+ applyForTools(projectDir, tools) { return applyForTools(this.registryPath, projectDir, tools, this.installDir); }
141
141
 
142
142
  // MCPs (project)
143
143
  list() { return list(this.registryPath); }
@@ -197,7 +197,7 @@ class ClaudeConfigManager {
197
197
  workstreamInstallHook() { return workstreamInstallHook(); }
198
198
  workstreamInstallHookGemini() { return workstreamInstallHookGemini(); }
199
199
  workstreamInstallHookCodex() { return workstreamInstallHookCodex(); }
200
- workstreamDeactivate() { return workstreamDeactivate(); }
200
+ workstreamDeactivate() { return workstreamDeactivate(this.installDir); }
201
201
  workstreamCheckPath(targetPath, silent) { return workstreamCheckPath(this.installDir, targetPath, silent); }
202
202
  // Workstream folder auto-activation
203
203
  getSettingsPath() { return getSettingsPath(this.installDir); }
package/lib/apply.js CHANGED
@@ -8,7 +8,7 @@ const { execSync } = require('child_process');
8
8
  const { TOOL_PATHS } = require('./constants');
9
9
  const { loadJson, saveJson, loadEnvFile, interpolate, resolveEnvVars } = require('./utils');
10
10
  const { findProjectRoot, findAllConfigs, mergeConfigs, findAllConfigsForTool } = require('./config');
11
- const { getActiveWorkstream, writeWorkstreamSandboxSettings } = require('./workstreams');
11
+ const { getActiveWorkstream, applySandboxIfEnabled } = require('./workstreams');
12
12
 
13
13
  /**
14
14
  * Generate .mcp.json for a project (with hierarchical config merging)
@@ -104,17 +104,13 @@ function apply(registryPath, projectDir = null, installDir = null) {
104
104
  // Generate settings.local.json with additionalDirectories for workstream sandbox scope
105
105
  if (installDir) {
106
106
  const active = getActiveWorkstream(installDir);
107
- if (active && active.projects && active.projects.length > 0 && active.sandbox === true) {
108
- const otherProjects = active.projects.filter(p => {
109
- const resolved = path.resolve(p);
110
- return resolved !== path.resolve(dir) && !dir.startsWith(resolved + path.sep);
111
- });
112
-
113
- if (otherProjects.length > 0) {
114
- writeWorkstreamSandboxSettings(dir, otherProjects);
115
- console.log(`✓ Generated .claude/settings.local.json (sandbox scope)`);
116
- console.log(` └─ ${otherProjects.length} additional director${otherProjects.length === 1 ? 'y' : 'ies'}`);
117
- }
107
+ if (applySandboxIfEnabled(active, dir)) {
108
+ const resolvedDir = path.resolve(dir);
109
+ const count = active.projects.filter(p =>
110
+ path.resolve(p) !== resolvedDir && !resolvedDir.startsWith(path.resolve(p) + path.sep)
111
+ ).length;
112
+ console.log(`✓ Generated .claude/settings.local.json (sandbox scope)`);
113
+ console.log(` └─ ${count} additional director${count === 1 ? 'y' : 'ies'}`);
118
114
  }
119
115
  }
120
116
 
@@ -442,12 +438,12 @@ function detectInstalledTools() {
442
438
  /**
443
439
  * Apply config for multiple tools based on preferences
444
440
  */
445
- function applyForTools(registryPath, projectDir = null, tools = ['claude']) {
441
+ function applyForTools(registryPath, projectDir = null, tools = ['claude'], installDir = null) {
446
442
  const results = {};
447
443
 
448
444
  for (const tool of tools) {
449
445
  if (tool === 'claude') {
450
- results.claude = apply(registryPath, projectDir);
446
+ results.claude = apply(registryPath, projectDir, installDir);
451
447
  } else if (tool === 'gemini') {
452
448
  results.gemini = applyForGemini(registryPath, projectDir);
453
449
  } else if (tool === 'antigravity') {
package/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.47.1-beta';
5
+ const VERSION = '0.47.2-beta';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
@@ -396,18 +396,7 @@ function workstreamInject(installDir, silent = false) {
396
396
  console.log(output);
397
397
 
398
398
  // Generate settings.local.json with additionalDirectories for sandbox scope
399
- // Only when sandbox mode is explicitly enabled (default: off)
400
- if (active.sandbox === true && active.projects && active.projects.length > 0) {
401
- const cwd = process.cwd();
402
- const otherProjects = active.projects.filter(p => {
403
- const resolved = path.resolve(p);
404
- return resolved !== path.resolve(cwd) && !cwd.startsWith(resolved + path.sep);
405
- });
406
-
407
- if (otherProjects.length > 0) {
408
- writeWorkstreamSandboxSettings(cwd, otherProjects);
409
- }
410
- }
399
+ applySandboxIfEnabled(active, process.cwd());
411
400
 
412
401
  return output;
413
402
  }
@@ -651,6 +640,31 @@ fi
651
640
  return true;
652
641
  }
653
642
 
643
+ /**
644
+ * Apply sandbox settings if the workstream has sandbox enabled.
645
+ * Shared logic used by both workstreamInject() and apply().
646
+ * @param {object} active - Active workstream object
647
+ * @param {string} dir - Target project directory (absolute)
648
+ * @returns {boolean} Whether sandbox settings were written
649
+ */
650
+ function applySandboxIfEnabled(active, dir) {
651
+ if (!active || active.sandbox !== true || !active.projects || active.projects.length === 0) {
652
+ return false;
653
+ }
654
+
655
+ const resolvedDir = path.resolve(dir);
656
+ const otherProjects = active.projects.filter(p => {
657
+ const resolved = path.resolve(p);
658
+ return resolved !== resolvedDir && !resolvedDir.startsWith(resolved + path.sep);
659
+ });
660
+
661
+ if (otherProjects.length > 0) {
662
+ writeWorkstreamSandboxSettings(resolvedDir, otherProjects);
663
+ return true;
664
+ }
665
+ return false;
666
+ }
667
+
654
668
  /**
655
669
  * Write additionalDirectories to .claude/settings.local.json for sandbox scope
656
670
  */
@@ -700,8 +714,17 @@ function removeWorkstreamSandboxSettings(dir) {
700
714
  /**
701
715
  * Deactivate workstream (output shell command to unset env var)
702
716
  */
703
- function workstreamDeactivate() {
704
- // Clean up sandbox settings from CWD
717
+ function workstreamDeactivate(installDir) {
718
+ // Clean up sandbox settings from all workstream project directories
719
+ if (installDir) {
720
+ const active = getActiveWorkstream(installDir);
721
+ if (active && active.projects) {
722
+ for (const p of active.projects) {
723
+ removeWorkstreamSandboxSettings(path.resolve(p));
724
+ }
725
+ }
726
+ }
727
+ // Also clean CWD in case it's not a listed project
705
728
  removeWorkstreamSandboxSettings(process.cwd());
706
729
 
707
730
  console.log('To deactivate the workstream for this session, run:');
@@ -1377,8 +1400,8 @@ function workstreamRemoveTrigger(installDir, idOrName, folderPath) {
1377
1400
 
1378
1401
  /**
1379
1402
  * Set sandbox mode for a workstream
1380
- * When true (default): generates additionalDirectories in settings.local.json for OS-level enforcement
1381
- * When false: only injects advisory LLM rules (softer, LLM can override if important)
1403
+ * When true: generates additionalDirectories in settings.local.json for OS-level enforcement
1404
+ * When false (default): only injects advisory LLM rules (softer, LLM can override if important)
1382
1405
  */
1383
1406
  function workstreamSetSandbox(installDir, idOrName, value) {
1384
1407
  const data = loadWorkstreams(installDir);
@@ -1397,6 +1420,9 @@ function workstreamSetSandbox(installDir, idOrName, value) {
1397
1420
  } else if (value === 'off' || value === false || value === 'false') {
1398
1421
  ws.sandbox = false;
1399
1422
  console.log(`✓ Sandbox disabled for ${ws.name} (advisory LLM rules only)`);
1423
+ } else {
1424
+ console.error(`Invalid value: ${value}. Use "on" or "off".`);
1425
+ return null;
1400
1426
  }
1401
1427
 
1402
1428
  ws.updatedAt = new Date().toISOString();
@@ -1737,7 +1763,6 @@ module.exports = {
1737
1763
  workstreamInstallCdHook,
1738
1764
  workstreamUninstallCdHook,
1739
1765
  workstreamCdHookStatus,
1740
- writeWorkstreamSandboxSettings,
1741
- removeWorkstreamSandboxSettings,
1766
+ applySandboxIfEnabled,
1742
1767
  workstreamSetSandbox,
1743
1768
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.47.1-beta",
3
+ "version": "0.47.2-beta",
4
4
  "description": "Configuration manager for AI coding tools - Claude Code, Gemini CLI, Codex CLI, Antigravity. Manage MCPs, rules, permissions, memory, and workstreams.",
5
5
  "author": "regression.io",
6
6
  "main": "config-loader.js",