@bastani/atomic 0.5.4 → 0.5.5-0

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.
Files changed (173) hide show
  1. package/README.md +44 -1
  2. package/dist/lib/path-root-guard.d.ts +4 -0
  3. package/dist/lib/path-root-guard.d.ts.map +1 -0
  4. package/dist/sdk/components/color-utils.d.ts +1 -0
  5. package/dist/sdk/components/color-utils.d.ts.map +1 -0
  6. package/dist/sdk/components/connectors.d.ts +3 -2
  7. package/dist/sdk/components/connectors.d.ts.map +1 -0
  8. package/dist/sdk/components/connectors.test.d.ts +1 -0
  9. package/dist/sdk/components/connectors.test.d.ts.map +1 -0
  10. package/dist/sdk/components/edge.d.ts +2 -1
  11. package/dist/sdk/components/edge.d.ts.map +1 -0
  12. package/dist/sdk/components/error-boundary.d.ts +1 -0
  13. package/dist/sdk/components/error-boundary.d.ts.map +1 -0
  14. package/dist/sdk/components/graph-theme.d.ts +2 -1
  15. package/dist/sdk/components/graph-theme.d.ts.map +1 -0
  16. package/dist/sdk/components/header.d.ts +1 -0
  17. package/dist/sdk/components/header.d.ts.map +1 -0
  18. package/dist/sdk/components/hooks.d.ts +15 -0
  19. package/dist/sdk/components/hooks.d.ts.map +1 -0
  20. package/dist/sdk/components/layout.d.ts +2 -1
  21. package/dist/sdk/components/layout.d.ts.map +1 -0
  22. package/dist/sdk/components/layout.test.d.ts +1 -0
  23. package/dist/sdk/components/layout.test.d.ts.map +1 -0
  24. package/dist/sdk/components/node-card.d.ts +5 -3
  25. package/dist/sdk/components/node-card.d.ts.map +1 -0
  26. package/dist/sdk/components/orchestrator-panel-contexts.d.ts +3 -2
  27. package/dist/sdk/components/orchestrator-panel-contexts.d.ts.map +1 -0
  28. package/dist/sdk/components/orchestrator-panel-store.d.ts +2 -1
  29. package/dist/sdk/components/orchestrator-panel-store.d.ts.map +1 -0
  30. package/dist/sdk/components/orchestrator-panel-store.test.d.ts +1 -0
  31. package/dist/sdk/components/orchestrator-panel-store.test.d.ts.map +1 -0
  32. package/dist/sdk/components/orchestrator-panel-types.d.ts +1 -0
  33. package/dist/sdk/components/orchestrator-panel-types.d.ts.map +1 -0
  34. package/dist/sdk/components/orchestrator-panel.d.ts +2 -1
  35. package/dist/sdk/components/orchestrator-panel.d.ts.map +1 -0
  36. package/dist/sdk/components/session-graph-panel.d.ts +1 -0
  37. package/dist/sdk/components/session-graph-panel.d.ts.map +1 -0
  38. package/dist/sdk/components/status-helpers.d.ts +2 -1
  39. package/dist/sdk/components/status-helpers.d.ts.map +1 -0
  40. package/dist/sdk/components/statusline.d.ts +2 -1
  41. package/dist/sdk/components/statusline.d.ts.map +1 -0
  42. package/dist/sdk/components/workflow-picker-panel.d.ts +11 -8
  43. package/dist/sdk/components/workflow-picker-panel.d.ts.map +1 -0
  44. package/dist/sdk/define-workflow.d.ts +2 -1
  45. package/dist/sdk/define-workflow.d.ts.map +1 -0
  46. package/dist/sdk/define-workflow.test.d.ts +1 -0
  47. package/dist/sdk/define-workflow.test.d.ts.map +1 -0
  48. package/dist/sdk/errors.d.ts +3 -0
  49. package/dist/sdk/errors.d.ts.map +1 -0
  50. package/dist/sdk/errors.test.d.ts +2 -0
  51. package/dist/sdk/errors.test.d.ts.map +1 -0
  52. package/dist/sdk/index.d.ts +7 -6
  53. package/dist/sdk/index.d.ts.map +1 -0
  54. package/dist/sdk/providers/claude.d.ts +17 -6
  55. package/dist/sdk/providers/claude.d.ts.map +1 -0
  56. package/dist/sdk/providers/copilot.d.ts +2 -5
  57. package/dist/sdk/providers/copilot.d.ts.map +1 -0
  58. package/dist/sdk/providers/opencode.d.ts +2 -5
  59. package/dist/sdk/providers/opencode.d.ts.map +1 -0
  60. package/dist/sdk/runtime/discovery.d.ts +2 -1
  61. package/dist/sdk/runtime/discovery.d.ts.map +1 -0
  62. package/dist/sdk/runtime/executor-entry.d.ts +1 -0
  63. package/dist/sdk/runtime/executor-entry.d.ts.map +1 -0
  64. package/dist/sdk/runtime/executor.d.ts +3 -6
  65. package/dist/sdk/runtime/executor.d.ts.map +1 -0
  66. package/dist/sdk/runtime/executor.test.d.ts +1 -0
  67. package/dist/sdk/runtime/executor.test.d.ts.map +1 -0
  68. package/dist/sdk/runtime/graph-inference.d.ts +1 -0
  69. package/dist/sdk/runtime/graph-inference.d.ts.map +1 -0
  70. package/dist/sdk/runtime/loader.d.ts +5 -7
  71. package/dist/sdk/runtime/loader.d.ts.map +1 -0
  72. package/dist/sdk/runtime/panel.d.ts +3 -2
  73. package/dist/sdk/runtime/panel.d.ts.map +1 -0
  74. package/dist/sdk/runtime/theme.d.ts +1 -0
  75. package/dist/sdk/runtime/theme.d.ts.map +1 -0
  76. package/dist/sdk/runtime/tmux.d.ts +26 -8
  77. package/dist/sdk/runtime/tmux.d.ts.map +1 -0
  78. package/dist/sdk/types.d.ts +23 -1
  79. package/dist/sdk/types.d.ts.map +1 -0
  80. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +1 -0
  81. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -0
  82. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +1 -0
  83. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -0
  84. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts +1 -0
  85. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts.map +1 -0
  86. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +2 -1
  87. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +1 -0
  88. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts +1 -0
  89. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts.map +1 -0
  90. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +1 -0
  91. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -0
  92. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts +1 -0
  93. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -0
  94. package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts +1 -0
  95. package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -0
  96. package/dist/sdk/workflows/builtin/ralph/helpers/git.d.ts +1 -0
  97. package/dist/sdk/workflows/builtin/ralph/helpers/git.d.ts.map +1 -0
  98. package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts +1 -0
  99. package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts.map +1 -0
  100. package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts +2 -1
  101. package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts.map +1 -0
  102. package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts +1 -0
  103. package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -0
  104. package/dist/sdk/workflows/index.d.ts +14 -14
  105. package/dist/sdk/workflows/index.d.ts.map +1 -0
  106. package/dist/services/config/definitions.d.ts +85 -0
  107. package/dist/services/config/definitions.d.ts.map +1 -0
  108. package/dist/services/system/copy.d.ts +77 -0
  109. package/dist/services/system/copy.d.ts.map +1 -0
  110. package/dist/services/system/detect.d.ts +75 -0
  111. package/dist/services/system/detect.d.ts.map +1 -0
  112. package/package.json +13 -34
  113. package/src/cli.ts +11 -10
  114. package/src/commands/cli/chat/index.ts +11 -11
  115. package/src/commands/cli/chat.ts +1 -1
  116. package/src/commands/cli/config.ts +10 -9
  117. package/src/commands/cli/init/index.ts +11 -11
  118. package/src/commands/cli/init/onboarding.ts +4 -4
  119. package/src/commands/cli/init/scm.ts +5 -5
  120. package/src/commands/cli/init.ts +1 -1
  121. package/src/commands/cli/workflow-command.test.ts +19 -11
  122. package/src/commands/cli/workflow.test.ts +2 -2
  123. package/src/commands/cli/workflow.ts +6 -6
  124. package/src/lib/merge.ts +17 -31
  125. package/src/lib/path-root-guard.ts +2 -2
  126. package/src/lib/spawn.ts +13 -7
  127. package/src/scripts/bump-version.ts +1 -1
  128. package/src/scripts/constants.ts +2 -2
  129. package/src/sdk/components/header.tsx +21 -23
  130. package/src/sdk/components/hooks.ts +21 -0
  131. package/src/sdk/components/node-card.tsx +3 -2
  132. package/src/sdk/components/session-graph-panel.tsx +14 -18
  133. package/src/sdk/components/workflow-picker-panel.tsx +201 -216
  134. package/src/sdk/errors.test.ts +56 -0
  135. package/src/sdk/errors.ts +5 -0
  136. package/src/sdk/providers/claude.ts +279 -70
  137. package/src/sdk/providers/copilot.ts +17 -27
  138. package/src/sdk/providers/opencode.ts +17 -27
  139. package/src/sdk/runtime/discovery.ts +18 -18
  140. package/src/sdk/runtime/executor.test.ts +15 -48
  141. package/src/sdk/runtime/executor.ts +152 -121
  142. package/src/sdk/runtime/loader.ts +16 -21
  143. package/src/sdk/runtime/tmux.ts +95 -32
  144. package/src/sdk/types.ts +45 -0
  145. package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +27 -0
  146. package/src/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.ts +25 -16
  147. package/src/sdk/workflows/builtin/deep-research-codebase/helpers/scout.ts +25 -24
  148. package/src/sdk/workflows/builtin/ralph/claude/index.ts +5 -0
  149. package/src/sdk/workflows/index.ts +3 -3
  150. package/src/services/config/atomic-config.ts +7 -8
  151. package/src/services/config/atomic-global-config.ts +9 -9
  152. package/src/services/config/config-path.ts +1 -1
  153. package/src/services/config/definitions.ts +3 -4
  154. package/src/services/config/index.ts +1 -1
  155. package/src/services/config/settings.ts +30 -36
  156. package/src/services/system/agents.ts +3 -3
  157. package/src/services/system/auto-sync.ts +9 -9
  158. package/src/services/system/copy.ts +9 -9
  159. package/src/services/system/file-lock.ts +2 -2
  160. package/src/services/system/install-ui.ts +2 -2
  161. package/src/services/system/skills.ts +1 -1
  162. package/src/theme/colors.ts +1 -1
  163. package/src/theme/logo.ts +1 -1
  164. package/tsconfig.json +3 -4
  165. package/dist/chunk-1gb5qxz9.js +0 -1
  166. package/dist/chunk-fdk7tact.js +0 -417
  167. package/dist/chunk-xkxndz5g.js +0 -1041
  168. package/dist/sdk/index.js +0 -52
  169. package/dist/sdk/workflows/builtin/ralph/claude/index.js +0 -96
  170. package/dist/sdk/workflows/builtin/ralph/copilot/index.js +0 -119
  171. package/dist/sdk/workflows/builtin/ralph/opencode/index.js +0 -148
  172. package/dist/sdk/workflows/index.js +0 -100
  173. package/src/commands/cli/chat/client.ts +0 -18
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Utilities for command and platform detection
3
+ */
4
+ export declare const WSL_INSTALL_URL = "https://learn.microsoft.com/en-us/windows/wsl/install";
5
+ /**
6
+ * Check if a command is installed and available in PATH
7
+ */
8
+ export declare function isCommandInstalled(cmd: string): boolean;
9
+ /**
10
+ * Get the resolved absolute path to a command executable.
11
+ *
12
+ * On Windows, this properly resolves .cmd, .bat, .exe and other executable
13
+ * extensions through Bun.which(), which handles the PATHEXT environment
14
+ * variable. This is essential for spawning commands correctly on Windows
15
+ * where 'opencode' might actually be 'opencode.cmd'.
16
+ *
17
+ * @param cmd - The command name to resolve (e.g., 'opencode', 'claude')
18
+ * @returns The absolute path to the command, or null if not found
19
+ */
20
+ export declare function getCommandPath(cmd: string): string | null;
21
+ /**
22
+ * Get the version string of a command
23
+ * Returns null if command is not installed or version check fails
24
+ */
25
+ export declare function getCommandVersion(cmd: string): string | null;
26
+ /**
27
+ * Check if running on Windows
28
+ */
29
+ export declare function isWindows(): boolean;
30
+ /**
31
+ * Check if running on macOS
32
+ */
33
+ export declare function isMacOS(): boolean;
34
+ /**
35
+ * Check if running on Linux
36
+ */
37
+ export declare function isLinux(): boolean;
38
+ /**
39
+ * Get the appropriate script extension for the current platform
40
+ * Returns ".ps1" on Windows, ".sh" on Unix-like systems
41
+ */
42
+ export declare function getScriptExtension(): string;
43
+ /**
44
+ * Get the opposite script extension (for filtering)
45
+ * Returns ".sh" on Windows, ".ps1" on Unix-like systems
46
+ */
47
+ export declare function getOppositeScriptExtension(): string;
48
+ /**
49
+ * Check if WSL is installed on Windows
50
+ * Returns false on non-Windows platforms
51
+ */
52
+ export declare function isWslInstalled(): boolean;
53
+ /**
54
+ * Check if colors are enabled (respects NO_COLOR standard)
55
+ * See: https://no-color.org/
56
+ */
57
+ export declare function supportsColor(): boolean;
58
+ /**
59
+ * Check if the terminal supports true color (24-bit).
60
+ *
61
+ * Checks COLORTERM, TERM, and TERM_PROGRAM environment variables.
62
+ * macOS Terminal.app (Apple_Terminal) does NOT support truecolor and
63
+ * will degrade hex colors to washed-out 256-color approximations.
64
+ */
65
+ export declare function supportsTrueColor(): boolean;
66
+ /**
67
+ * Check if the terminal supports 256 colors
68
+ *
69
+ * Note: This returns true when supportsTrueColor() returns true.
70
+ * Since supportsTrueColor() defaults to true for modern terminals,
71
+ * this function will also return true in most cases. This is intentional -
72
+ * most modern terminals support at least 256 colors.
73
+ */
74
+ export declare function supports256Color(): boolean;
75
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/services/system/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,eAAe,0DAC6B,CAAC;AAE1D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc5D;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAIxC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAMvC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAgC3C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.5.4",
3
+ "version": "0.5.5-0",
4
4
  "description": "Configuration management CLI and SDK for coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,33 +28,11 @@
28
28
  "exports": {
29
29
  ".": {
30
30
  "bun": "./src/sdk/index.ts",
31
- "types": "./dist/sdk/index.d.ts",
32
- "import": "./dist/sdk/index.js",
33
- "default": "./dist/sdk/index.js"
31
+ "types": "./dist/sdk/index.d.ts"
34
32
  },
35
- "./workflows": {
36
- "bun": "./src/sdk/workflows/index.ts",
37
- "types": "./dist/sdk/workflows/index.d.ts",
38
- "import": "./dist/sdk/workflows/index.js",
39
- "default": "./dist/sdk/workflows/index.js"
40
- },
41
- "./workflows/builtin/ralph/claude": {
42
- "bun": "./src/sdk/workflows/builtin/ralph/claude/index.ts",
43
- "types": "./dist/sdk/workflows/builtin/ralph/claude/index.d.ts",
44
- "import": "./dist/sdk/workflows/builtin/ralph/claude/index.js",
45
- "default": "./dist/sdk/workflows/builtin/ralph/claude/index.js"
46
- },
47
- "./workflows/builtin/ralph/copilot": {
48
- "bun": "./src/sdk/workflows/builtin/ralph/copilot/index.ts",
49
- "types": "./dist/sdk/workflows/builtin/ralph/copilot/index.d.ts",
50
- "import": "./dist/sdk/workflows/builtin/ralph/copilot/index.js",
51
- "default": "./dist/sdk/workflows/builtin/ralph/copilot/index.js"
52
- },
53
- "./workflows/builtin/ralph/opencode": {
54
- "bun": "./src/sdk/workflows/builtin/ralph/opencode/index.ts",
55
- "types": "./dist/sdk/workflows/builtin/ralph/opencode/index.d.ts",
56
- "import": "./dist/sdk/workflows/builtin/ralph/opencode/index.js",
57
- "default": "./dist/sdk/workflows/builtin/ralph/opencode/index.js"
33
+ "./*": {
34
+ "bun": "./src/sdk/*",
35
+ "types": "./dist/sdk/*"
58
36
  }
59
37
  },
60
38
  "files": [
@@ -69,7 +47,7 @@
69
47
  ],
70
48
  "scripts": {
71
49
  "dev": "bun run src/cli.ts",
72
- "build": "bun run build.ts",
50
+ "build": "rm -rf dist && bunx tsc --project tsconfig.build.json",
73
51
  "prepack": "bun run build",
74
52
  "test": "bun test ./src ./tests",
75
53
  "test:coverage": "bun test --coverage ./src ./tests",
@@ -78,25 +56,26 @@
78
56
  "lint:fix": "oxlint --config=oxlint.json --fix src",
79
57
  "prepare": "lefthook install || true"
80
58
  },
59
+ "trustedDependencies": ["lefthook"],
81
60
  "devDependencies": {
82
- "@types/bun": "^1.3.11",
61
+ "@types/bun": "^1.3.12",
83
62
  "@types/react": "^19.2.14",
84
- "lefthook": "^2.1.4",
63
+ "lefthook": "^2.1.5",
85
64
  "oxlint": "^1.59.0",
86
65
  "typescript": "^6.0.2",
87
66
  "typescript-language-server": "^5.1.3"
88
67
  },
89
68
  "dependencies": {
90
- "@anthropic-ai/claude-agent-sdk": "^0.2.92",
69
+ "@anthropic-ai/claude-agent-sdk": "^0.2.104",
91
70
  "@clack/prompts": "^1.2.0",
92
71
  "@commander-js/extra-typings": "^14.0.0",
93
- "@github/copilot-sdk": "^0.2.1",
94
- "@opencode-ai/sdk": "^1.3.17",
72
+ "@github/copilot-sdk": "^0.2.2",
73
+ "@opencode-ai/sdk": "^1.4.3",
95
74
  "@opentui/core": "^0.1.97",
96
75
  "@opentui/react": "^0.1.97",
97
76
  "commander": "^14.0.3",
98
77
  "ignore": "^7.0.5",
99
- "react": "19",
78
+ "react": "^19.2.5",
100
79
  "yaml": "^2.8.3",
101
80
  "zod": "^4.3.6"
102
81
  }
package/src/cli.ts CHANGED
@@ -16,9 +16,9 @@
16
16
  */
17
17
 
18
18
  import { Command } from "@commander-js/extra-typings";
19
- import { VERSION } from "@/version.ts";
20
- import { COLORS } from "@/theme/colors.ts";
21
- import { AGENT_CONFIG, type AgentKey, SCM_CONFIG, type SourceControlType } from "@/services/config/index.ts";
19
+ import { VERSION } from "./version.ts";
20
+ import { COLORS } from "./theme/colors.ts";
21
+ import { AGENT_CONFIG, type AgentKey, SCM_CONFIG, type SourceControlType } from "./services/config/index.ts";
22
22
 
23
23
  /**
24
24
  * Create and configure the main CLI program
@@ -61,7 +61,7 @@ export function createProgram() {
61
61
  )
62
62
  .action(async (localOpts) => {
63
63
  const globalOpts = program.opts();
64
- const { initCommand } = await import("@/commands/cli/init.ts");
64
+ const { initCommand } = await import("./commands/cli/init.ts");
65
65
 
66
66
  await initCommand({
67
67
  showBanner: globalOpts.banner !== false,
@@ -117,9 +117,9 @@ Examples:
117
117
  // Collect extra args/options to forward to the native CLI
118
118
  const passthroughArgs = cmd.args;
119
119
 
120
- const { chatCommand } = await import("@/commands/cli/chat.ts");
120
+ const { chatCommand } = await import("./commands/cli/chat.ts");
121
121
  const exitCode = await chatCommand({
122
- agentType: agentType as "claude" | "opencode" | "copilot",
122
+ agentType: agentType as AgentKey,
123
123
  passthroughArgs,
124
124
  });
125
125
 
@@ -157,7 +157,7 @@ Examples:
157
157
  Run a structured-input workflow`,
158
158
  )
159
159
  .action(async (localOpts, cmd) => {
160
- const { workflowCommand } = await import("@/commands/cli/workflow.ts");
160
+ const { workflowCommand } = await import("./commands/cli/workflow.ts");
161
161
  const exitCode = await workflowCommand({
162
162
  name: localOpts.name,
163
163
  agent: localOpts.agent,
@@ -179,8 +179,9 @@ Examples:
179
179
  .argument("<key>", "Configuration key (e.g., telemetry)")
180
180
  .argument("<value>", "Value to set (e.g., true, false)")
181
181
  .action(async (key: string, value: string) => {
182
- const { configCommand } = await import("@/commands/cli/config.ts");
183
- await configCommand("set", key, value);
182
+ const { configCommand } = await import("./commands/cli/config.ts");
183
+ const exitCode = await configCommand("set", key, value);
184
+ process.exit(exitCode);
184
185
  });
185
186
 
186
187
  return program;
@@ -206,7 +207,7 @@ async function main(): Promise<void> {
206
207
  argv.includes("-h");
207
208
 
208
209
  if (!isInfoCommand) {
209
- const { autoSyncIfStale } = await import("@/services/system/auto-sync.ts");
210
+ const { autoSyncIfStale } = await import("./services/system/auto-sync.ts");
210
211
  await autoSyncIfStale();
211
212
  }
212
213
 
@@ -13,28 +13,28 @@
13
13
  * atomic chat -a <agent> [native-args...]
14
14
  */
15
15
 
16
- import { join } from "path";
17
- import { homedir } from "os";
18
- import { mkdir, writeFile, rm } from "fs/promises";
19
- import { AGENT_CONFIG, type AgentKey } from "@/services/config/index.ts";
20
- import { COLORS } from "@/theme/colors.ts";
21
- import { isCommandInstalled } from "@/services/system/detect.ts";
16
+ import { join } from "node:path";
17
+ import { homedir } from "node:os";
18
+ import { mkdir, writeFile, rm } from "node:fs/promises";
19
+ import { AGENT_CONFIG, type AgentKey } from "../../../services/config/index.ts";
20
+ import { COLORS } from "../../../theme/colors.ts";
21
+ import { isCommandInstalled } from "../../../services/system/detect.ts";
22
22
  import {
23
23
  ensureAtomicGlobalAgentConfigs,
24
- } from "@/services/config/atomic-global-config.ts";
25
- import { getConfigRoot } from "@/services/config/config-path.ts";
24
+ } from "../../../services/config/atomic-global-config.ts";
25
+ import { getConfigRoot } from "../../../services/config/config-path.ts";
26
26
  import {
27
27
  isInsideTmux,
28
28
  isTmuxInstalled,
29
29
  resetMuxBinaryCache,
30
- } from "@/sdk/workflows/index.ts";
30
+ } from "../../../sdk/workflows/index.ts";
31
31
  import {
32
32
  createSession,
33
33
  killSession,
34
34
  spawnMuxAttach,
35
35
  SOCKET_NAME,
36
- } from "@/sdk/workflows/index.ts";
37
- import { ensureTmuxInstalled } from "@/lib/spawn.ts";
36
+ } from "../../../sdk/workflows/index.ts";
37
+ import { ensureTmuxInstalled } from "../../../lib/spawn.ts";
38
38
 
39
39
  // ============================================================================
40
40
  // Types
@@ -5,4 +5,4 @@
5
5
  * The implementation lives under `commands/cli/chat/`.
6
6
  */
7
7
 
8
- export * from "@/commands/cli/chat/index.ts";
8
+ export * from "./chat/index.ts";
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { log } from "@clack/prompts";
11
- import { setTelemetryEnabled } from "@/services/config/settings.ts";
11
+ import { setTelemetryEnabled } from "../../services/config/settings.ts";
12
12
 
13
13
  /**
14
14
  * Execute the config command
@@ -17,39 +17,40 @@ export async function configCommand(
17
17
  subcommand: string | undefined,
18
18
  key: string | undefined,
19
19
  value: string | undefined
20
- ): Promise<void> {
20
+ ): Promise<number> {
21
21
  if (!subcommand) {
22
22
  log.error("Missing subcommand. Usage: atomic config set <key> <value>");
23
- process.exit(1);
23
+ return 1;
24
24
  }
25
25
 
26
26
  if (subcommand !== "set") {
27
27
  log.error(`Unknown subcommand: ${subcommand}. Only 'set' is supported.`);
28
- process.exit(1);
28
+ return 1;
29
29
  }
30
30
 
31
31
  if (!key) {
32
32
  log.error("Missing key. Usage: atomic config set <key> <value>");
33
- process.exit(1);
33
+ return 1;
34
34
  }
35
35
 
36
36
  if (key !== "telemetry") {
37
37
  log.error(`Unknown config key: ${key}. Only 'telemetry' is supported.`);
38
- process.exit(1);
38
+ return 1;
39
39
  }
40
40
 
41
41
  if (!value) {
42
42
  log.error("Missing value. Usage: atomic config set telemetry <true|false>");
43
- process.exit(1);
43
+ return 1;
44
44
  }
45
45
 
46
46
  if (value !== "true" && value !== "false") {
47
47
  log.error(`Invalid value: ${value}. Must be 'true' or 'false'.`);
48
- process.exit(1);
48
+ return 1;
49
49
  }
50
50
 
51
51
  const enabled = value === "true";
52
- setTelemetryEnabled(enabled);
52
+ await setTelemetryEnabled(enabled);
53
53
 
54
54
  log.success(`Telemetry has been ${enabled ? "enabled" : "disabled"}.`);
55
+ return 0;
55
56
  }
@@ -16,7 +16,7 @@ import {
16
16
  note,
17
17
  log,
18
18
  } from "@clack/prompts";
19
- import { join, resolve } from "path";
19
+ import { join, resolve } from "node:path";
20
20
 
21
21
  import {
22
22
  AGENT_CONFIG,
@@ -28,16 +28,16 @@ import {
28
28
  type SourceControlType,
29
29
  getScmKeys,
30
30
  isValidScm,
31
- } from "@/services/config/index.ts";
32
- import { pathExists } from "@/services/system/copy.ts";
33
- import { getConfigRoot } from "@/services/config/config-path.ts";
34
- import { isWindows, isWslInstalled, WSL_INSTALL_URL } from "@/services/system/detect.ts";
35
- import { saveAtomicConfig } from "@/services/config/atomic-config.ts";
36
- import { upsertTrustedWorkspacePath } from "@/services/config/settings.ts";
31
+ } from "../../../services/config/index.ts";
32
+ import { pathExists } from "../../../services/system/copy.ts";
33
+ import { getConfigRoot } from "../../../services/config/config-path.ts";
34
+ import { isWindows, isWslInstalled, WSL_INSTALL_URL } from "../../../services/system/detect.ts";
35
+ import { saveAtomicConfig } from "../../../services/config/atomic-config.ts";
36
+ import { upsertTrustedWorkspacePath } from "../../../services/config/settings.ts";
37
37
  import {
38
38
  ensureAtomicGlobalAgentConfigs,
39
39
  getTemplateAgentFolder,
40
- } from "@/services/config/atomic-global-config.ts";
40
+ } from "../../../services/config/atomic-global-config.ts";
41
41
  import {
42
42
  installLocalScmSkills,
43
43
  reconcileScmVariants,
@@ -47,8 +47,8 @@ import {
47
47
  applyManagedOnboardingFiles,
48
48
  hasProjectOnboardingFiles,
49
49
  } from "./onboarding.ts";
50
- import { displayBlockBanner } from "@/theme/logo.ts";
51
- import { createPainter } from "@/theme/colors.ts";
50
+ import { displayBlockBanner } from "../../../theme/logo.ts";
51
+ import { createPainter } from "../../../theme/colors.ts";
52
52
 
53
53
  /**
54
54
  * Thrown when the user cancels an interactive prompt during init.
@@ -268,7 +268,7 @@ export async function initCommand(options: InitOptions = {}): Promise<void> {
268
268
  await saveAtomicConfig(targetDir, {
269
269
  scm: scmType,
270
270
  });
271
- upsertTrustedWorkspacePath(resolve(targetDir), agentKey);
271
+ await upsertTrustedWorkspacePath(resolve(targetDir), agentKey);
272
272
 
273
273
  s.stop(paint("success", "✓", { bold: true }) + " Skills configured");
274
274
 
@@ -1,7 +1,7 @@
1
- import { dirname, join } from "path";
2
- import { AGENT_CONFIG, type AgentKey } from "@/services/config/index.ts";
3
- import { copyFile, pathExists, ensureDir } from "@/services/system/copy.ts";
4
- import { mergeJsonFile } from "@/lib/merge.ts";
1
+ import { dirname, join } from "node:path";
2
+ import { AGENT_CONFIG, type AgentKey } from "../../../services/config/index.ts";
3
+ import { copyFile, pathExists, ensureDir } from "../../../services/system/copy.ts";
4
+ import { mergeJsonFile } from "../../../lib/merge.ts";
5
5
 
6
6
  export async function applyManagedOnboardingFiles(
7
7
  agentKey: AgentKey,
@@ -1,12 +1,12 @@
1
- import { join } from "path";
2
- import { readdir } from "fs/promises";
3
- import { copyFile, pathExists, ensureDir } from "@/services/system/copy.ts";
4
- import { getOppositeScriptExtension } from "@/services/system/detect.ts";
1
+ import { join } from "node:path";
2
+ import { readdir } from "node:fs/promises";
3
+ import { copyFile, pathExists, ensureDir } from "../../../services/system/copy.ts";
4
+ import { getOppositeScriptExtension } from "../../../services/system/detect.ts";
5
5
  import {
6
6
  SCM_SKILLS_BY_TYPE,
7
7
  type AgentKey,
8
8
  type SourceControlType,
9
- } from "@/services/config/index.ts";
9
+ } from "../../../services/config/index.ts";
10
10
 
11
11
  export const SCM_PREFIX_BY_TYPE: Record<SourceControlType, "gh-" | "sl-"> = {
12
12
  github: "gh-",
@@ -5,4 +5,4 @@
5
5
  * historical `commands/cli/init.ts` path remains stable.
6
6
  */
7
7
 
8
- export * from "@/commands/cli/init/index.ts";
8
+ export * from "./init/index.ts";
@@ -29,17 +29,18 @@ import {
29
29
  afterEach,
30
30
  mock,
31
31
  } from "bun:test";
32
- import { mkdtemp, mkdir, rm, writeFile } from "fs/promises";
33
- import { join } from "path";
34
- import { tmpdir } from "os";
35
- import * as realWorkflows from "@/sdk/workflows/index.ts";
36
- import * as realDetect from "@/services/system/detect.ts";
32
+ import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
33
+ import { join } from "node:path";
34
+ import { tmpdir } from "node:os";
35
+ import * as realWorkflows from "../../sdk/workflows/index.ts";
36
+ import * as realDetect from "../../services/system/detect.ts";
37
37
  import * as realSpawn from "../../lib/spawn.ts";
38
+ import { AGENT_CONFIG } from "../../services/config/index.ts";
38
39
  import type {
39
40
  WorkflowDefinition,
40
41
  WorkflowRunOptions,
41
42
  DiscoveredWorkflow,
42
- } from "@/sdk/workflows/index.ts";
43
+ } from "../../sdk/workflows/index.ts";
43
44
 
44
45
  // Capture original function references BEFORE `mock.module` replaces the
45
46
  // module exports. `import * as realWorkflows` gives a LIVE namespace — after
@@ -77,9 +78,16 @@ const loadWorkflowsMetadataMock = mock<
77
78
  const isTmuxInstalledMock =
78
79
  mock<typeof realWorkflows.isTmuxInstalled>(() => true);
79
80
 
80
- // Default: real presence check. Tests override for the agent-missing branch.
81
+ // Default: delegate to the real check, but pretend agent CLIs are installed.
82
+ // CI runners won't have copilot/opencode/claude on PATH; without this
83
+ // override every test that passes through runPrereqChecks would bail early.
84
+ // Non-agent commands still hit the real check so mock.module doesn't break
85
+ // detect.test.ts (Bun shares one process across test files).
86
+ const AGENT_CMDS = new Set(Object.values(AGENT_CONFIG).map((c) => c.cmd));
87
+ const defaultIsCommandInstalled = (cmd: string) =>
88
+ AGENT_CMDS.has(cmd) || realIsCommandInstalled(cmd);
81
89
  const isCommandInstalledMock = mock<typeof realDetect.isCommandInstalled>(
82
- (cmd) => realIsCommandInstalled(cmd),
90
+ defaultIsCommandInstalled,
83
91
  );
84
92
 
85
93
  // Default: no-op so the best-effort installer branch in runPrereqChecks
@@ -91,14 +99,14 @@ const ensureBunInstalledMock = mock<typeof realSpawn.ensureBunInstalled>(
91
99
  async () => {},
92
100
  );
93
101
 
94
- mock.module("@/sdk/workflows/index.ts", () => ({
102
+ mock.module("../../sdk/workflows/index.ts", () => ({
95
103
  ...realWorkflows,
96
104
  executeWorkflow: executeWorkflowMock,
97
105
  discoverWorkflows: discoverWorkflowsMock,
98
106
  loadWorkflowsMetadata: loadWorkflowsMetadataMock,
99
107
  isTmuxInstalled: isTmuxInstalledMock,
100
108
  }));
101
- mock.module("@/services/system/detect.ts", () => ({
109
+ mock.module("../../services/system/detect.ts", () => ({
102
110
  ...realDetect,
103
111
  isCommandInstalled: isCommandInstalledMock,
104
112
  }));
@@ -201,7 +209,7 @@ beforeEach(async () => {
201
209
  isTmuxInstalledMock.mockClear();
202
210
  isTmuxInstalledMock.mockImplementation(() => true);
203
211
  isCommandInstalledMock.mockClear();
204
- isCommandInstalledMock.mockImplementation((cmd) => realIsCommandInstalled(cmd));
212
+ isCommandInstalledMock.mockImplementation(defaultIsCommandInstalled);
205
213
  ensureTmuxInstalledMock.mockClear();
206
214
  ensureTmuxInstalledMock.mockImplementation(async () => {});
207
215
  ensureBunInstalledMock.mockClear();
@@ -5,8 +5,8 @@ import {
5
5
  resolveInputs,
6
6
  renderWorkflowList,
7
7
  } from "./workflow.ts";
8
- import type { WorkflowInput } from "@/sdk/workflows/index.ts";
9
- import type { DiscoveredWorkflow } from "@/sdk/workflows/index.ts";
8
+ import type { WorkflowInput } from "../../sdk/workflows/index.ts";
9
+ import type { DiscoveredWorkflow } from "../../sdk/workflows/index.ts";
10
10
 
11
11
  // ─── Colour handling ────────────────────────────────────────────────────────
12
12
  // The renderer emits ANSI sequences when the host terminal claims truecolor
@@ -9,9 +9,9 @@
9
9
  * atomic workflow --list list discoverable workflows
10
10
  */
11
11
 
12
- import { AGENT_CONFIG, type AgentKey } from "@/services/config/index.ts";
13
- import { COLORS, createPainter, type PaletteKey } from "@/theme/colors.ts";
14
- import { isCommandInstalled } from "@/services/system/detect.ts";
12
+ import { AGENT_CONFIG, type AgentKey } from "../../services/config/index.ts";
13
+ import { COLORS, createPainter, type PaletteKey } from "../../theme/colors.ts";
14
+ import { isCommandInstalled } from "../../services/system/detect.ts";
15
15
  import { ensureTmuxInstalled, ensureBunInstalled } from "../../lib/spawn.ts";
16
16
  import {
17
17
  isTmuxInstalled,
@@ -21,14 +21,14 @@ import {
21
21
  executeWorkflow,
22
22
  WorkflowLoader,
23
23
  resetMuxBinaryCache,
24
- } from "@/sdk/workflows/index.ts";
24
+ } from "../../sdk/workflows/index.ts";
25
25
  import type {
26
26
  AgentType,
27
27
  DiscoveredWorkflow,
28
28
  WorkflowInput,
29
29
  WorkflowWithMetadata,
30
- } from "@/sdk/workflows/index.ts";
31
- import { WorkflowPickerPanel } from "@/sdk/components/workflow-picker-panel.tsx";
30
+ } from "../../sdk/workflows/index.ts";
31
+ import { WorkflowPickerPanel } from "../../sdk/components/workflow-picker-panel.tsx";
32
32
 
33
33
  // ─── Flag parser ────────────────────────────────────────────────────────────
34
34
 
package/src/lib/merge.ts CHANGED
@@ -2,29 +2,12 @@
2
2
  * Utilities for merging JSON configuration files
3
3
  */
4
4
 
5
- import { readFile, writeFile } from "fs/promises";
6
- import { resolve } from "path";
5
+ import { resolve } from "node:path";
7
6
 
8
- interface McpConfig {
9
- mcpServers?: Record<string, unknown>;
10
- servers?: Record<string, unknown>;
11
- lspServers?: Record<string, unknown>;
12
- [key: string]: unknown;
13
- }
7
+ type McpConfig = Record<string, unknown>;
14
8
 
15
- function mergeNamedObjectMap(
16
- destination: Record<string, unknown> | undefined,
17
- source: Record<string, unknown> | undefined,
18
- ): Record<string, unknown> | undefined {
19
- if (!destination && !source) {
20
- return undefined;
21
- }
22
-
23
- return {
24
- ...destination,
25
- ...source,
26
- };
27
- }
9
+ /** Keys that hold named-object maps (server registries). */
10
+ const SERVER_MAP_KEYS = ["mcpServers", "servers", "lspServers"] as const;
28
11
 
29
12
  /**
30
13
  * Merge source JSON file into destination JSON file
@@ -43,23 +26,26 @@ export async function mergeJsonFile(
43
26
  return;
44
27
  }
45
28
 
46
- const [srcContent, destContent] = await Promise.all([
47
- readFile(srcPath, "utf-8"),
48
- readFile(destPath, "utf-8"),
29
+ const [srcConfig, destConfig] = await Promise.all([
30
+ Bun.file(srcPath).json() as Promise<McpConfig>,
31
+ Bun.file(destPath).json() as Promise<McpConfig>,
49
32
  ]);
50
33
 
51
- const srcConfig: McpConfig = JSON.parse(srcContent);
52
- const destConfig: McpConfig = JSON.parse(destContent);
53
-
54
34
  // Merge top-level config - preserve destination's other keys
55
35
  const mergedConfig: McpConfig = {
56
36
  ...destConfig,
57
37
  ...srcConfig,
58
38
  };
59
39
 
60
- mergedConfig.mcpServers = mergeNamedObjectMap(destConfig.mcpServers, srcConfig.mcpServers);
61
- mergedConfig.servers = mergeNamedObjectMap(destConfig.servers, srcConfig.servers);
62
- mergedConfig.lspServers = mergeNamedObjectMap(destConfig.lspServers, srcConfig.lspServers);
40
+ // Server maps are merged individually so the destination's existing
41
+ // entries are preserved while source entries are added or updated.
42
+ for (const key of SERVER_MAP_KEYS) {
43
+ const dst = destConfig[key] as Record<string, unknown> | undefined;
44
+ const src = srcConfig[key] as Record<string, unknown> | undefined;
45
+ if (dst || src) {
46
+ mergedConfig[key] = { ...dst, ...src };
47
+ }
48
+ }
63
49
 
64
- await writeFile(destPath, JSON.stringify(mergedConfig, null, 2) + "\n");
50
+ await Bun.write(destPath, JSON.stringify(mergedConfig, null, 2) + "\n");
65
51
  }
@@ -1,5 +1,5 @@
1
- import { realpath } from "fs/promises";
2
- import { isAbsolute, relative, resolve } from "path";
1
+ import { realpath } from "node:fs/promises";
2
+ import { isAbsolute, relative, resolve } from "node:path";
3
3
 
4
4
  function isSubPath(rootPath: string, targetPath: string): boolean {
5
5
  const rel = relative(rootPath, targetPath);