@nemus-cli/nemus 0.2.1

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 (320) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -0
  4. package/assets/README.md +53 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/banner.svg +66 -0
  7. package/assets/favicon-32.png +0 -0
  8. package/assets/favicon-64.png +0 -0
  9. package/assets/icon-256.png +0 -0
  10. package/assets/icon.svg +23 -0
  11. package/assets/logo-256.png +0 -0
  12. package/assets/logo-512.png +0 -0
  13. package/assets/logo-wordmark.svg +35 -0
  14. package/assets/logo.svg +32 -0
  15. package/bin/workspace.js +130 -0
  16. package/dist/cli/ai-prompt.js +421 -0
  17. package/dist/cli/dashboard/AgentList.js +61 -0
  18. package/dist/cli/dashboard/DashboardSidebar.js +280 -0
  19. package/dist/cli/dashboard/HelpFooter.js +73 -0
  20. package/dist/cli/dashboard/StatusBadge.js +50 -0
  21. package/dist/cli/dashboard/index.js +11 -0
  22. package/dist/cli/dashboard/types.js +2 -0
  23. package/dist/cli/tui.js +48 -0
  24. package/dist/commands/ai-prompt.js +22 -0
  25. package/dist/commands/analyze-deps.js +138 -0
  26. package/dist/commands/archive.js +113 -0
  27. package/dist/commands/branch/create.js +119 -0
  28. package/dist/commands/branch/index.js +104 -0
  29. package/dist/commands/branch/merge.js +90 -0
  30. package/dist/commands/branch/rebase.js +84 -0
  31. package/dist/commands/branch/switch.js +165 -0
  32. package/dist/commands/cache/index.js +80 -0
  33. package/dist/commands/cache/manager.js +198 -0
  34. package/dist/commands/cleanup.js +153 -0
  35. package/dist/commands/configure-claude.js +55 -0
  36. package/dist/commands/configure.js +231 -0
  37. package/dist/commands/create.js +204 -0
  38. package/dist/commands/dashboard/hook-handler.js +162 -0
  39. package/dist/commands/dashboard/index.js +258 -0
  40. package/dist/commands/dashboard/launcher.js +40 -0
  41. package/dist/commands/dashboard/session-picker.js +106 -0
  42. package/dist/commands/dashboard/sidebar.js +39 -0
  43. package/dist/commands/dashboard/workspace-picker.js +95 -0
  44. package/dist/commands/delete.js +194 -0
  45. package/dist/commands/deprecated-aliases.js +44 -0
  46. package/dist/commands/diff.js +129 -0
  47. package/dist/commands/doctor.js +141 -0
  48. package/dist/commands/generate-docs.js +77 -0
  49. package/dist/commands/ghq-status.js +72 -0
  50. package/dist/commands/go.js +154 -0
  51. package/dist/commands/history.js +124 -0
  52. package/dist/commands/list.js +191 -0
  53. package/dist/commands/mcp/index.js +69 -0
  54. package/dist/commands/migrate.js +296 -0
  55. package/dist/commands/remove-repo.js +217 -0
  56. package/dist/commands/report-bug.js +112 -0
  57. package/dist/commands/run.js +147 -0
  58. package/dist/commands/save-context.js +171 -0
  59. package/dist/commands/sessions.js +129 -0
  60. package/dist/commands/status.js +138 -0
  61. package/dist/commands/suite/create.js +212 -0
  62. package/dist/commands/suite/delete.js +64 -0
  63. package/dist/commands/suite/export.js +126 -0
  64. package/dist/commands/suite/import.js +128 -0
  65. package/dist/commands/suite/index.js +94 -0
  66. package/dist/commands/suite/list.js +49 -0
  67. package/dist/commands/suite/use.js +227 -0
  68. package/dist/commands/sync.js +117 -0
  69. package/dist/commands/update.js +203 -0
  70. package/dist/mcp/install.js +550 -0
  71. package/dist/mcp/server.js +398 -0
  72. package/dist/mcp/tools.js +922 -0
  73. package/dist/pi-extensions/permission-sync.ts.template +41 -0
  74. package/dist/pi-extensions/permissions-gate.ts.template +69 -0
  75. package/dist/pi-extensions/pr-fix-trigger.ts.template +124 -0
  76. package/dist/pi-extensions/review-reminder.ts.template +58 -0
  77. package/dist/pi-extensions/workspace-input-status.ts.template +919 -0
  78. package/dist/program.js +136 -0
  79. package/dist/scripts/workspace-table.py +394 -0
  80. package/dist/types/dashboard.js +11 -0
  81. package/dist/types/index.js +2 -0
  82. package/dist/utils/agent-config.js +263 -0
  83. package/dist/utils/agent-state.js +178 -0
  84. package/dist/utils/banner.js +24 -0
  85. package/dist/utils/branch-operations.js +232 -0
  86. package/dist/utils/bug-report.js +355 -0
  87. package/dist/utils/cache.js +168 -0
  88. package/dist/utils/claude-integration.js +617 -0
  89. package/dist/utils/claude-sessions.js +260 -0
  90. package/dist/utils/cleanup-operations.js +120 -0
  91. package/dist/utils/colors.js +26 -0
  92. package/dist/utils/command-helpers.js +44 -0
  93. package/dist/utils/config.js +150 -0
  94. package/dist/utils/context-file.js +33 -0
  95. package/dist/utils/dashboard-hooks.js +172 -0
  96. package/dist/utils/dependency-analyzer.js +234 -0
  97. package/dist/utils/diff-operations.js +80 -0
  98. package/dist/utils/doc-generator.js +184 -0
  99. package/dist/utils/ghq-integration.js +332 -0
  100. package/dist/utils/git-operations.js +237 -0
  101. package/dist/utils/git-status.js +187 -0
  102. package/dist/utils/github.js +68 -0
  103. package/dist/utils/health-checks.js +345 -0
  104. package/dist/utils/history.js +150 -0
  105. package/dist/utils/hooks.js +100 -0
  106. package/dist/utils/logger.js +40 -0
  107. package/dist/utils/permission-sync.js +681 -0
  108. package/dist/utils/pi-extensions.js +224 -0
  109. package/dist/utils/progress.js +92 -0
  110. package/dist/utils/prompts.js +279 -0
  111. package/dist/utils/repo-resolver.js +260 -0
  112. package/dist/utils/retry.js +65 -0
  113. package/dist/utils/run-operations.js +30 -0
  114. package/dist/utils/suite.js +159 -0
  115. package/dist/utils/sync-operations.js +107 -0
  116. package/dist/utils/tmux-dashboard.js +184 -0
  117. package/dist/utils/validation.js +153 -0
  118. package/dist/utils/version-check.js +121 -0
  119. package/dist/utils/workspace-meta.js +185 -0
  120. package/install-shell-integration.sh +532 -0
  121. package/install.sh +401 -0
  122. package/package.json +90 -0
  123. package/remove-shell-block.awk +44 -0
  124. package/scripts/postinstall.js +85 -0
  125. package/skills/analyze-deps.md +23 -0
  126. package/skills/archive-workspace.md +26 -0
  127. package/skills/branch-create.md +18 -0
  128. package/skills/create-workspace.md +39 -0
  129. package/skills/delete-workspace.md +37 -0
  130. package/skills/list-org-repos.md +26 -0
  131. package/skills/list-suites.md +24 -0
  132. package/skills/list-workspaces.md +27 -0
  133. package/skills/refresh-workspace-docs.md +89 -0
  134. package/skills/remove-repo.md +25 -0
  135. package/skills/run-command.md +23 -0
  136. package/skills/save-context.md +68 -0
  137. package/skills/search-repos.md +31 -0
  138. package/skills/snapshot-list.md +18 -0
  139. package/skills/snapshot-save.md +12 -0
  140. package/skills/switch-branch.md +18 -0
  141. package/skills/update-cache.md +21 -0
  142. package/skills/update-workspace.md +66 -0
  143. package/skills/workspace-cleanup.md +18 -0
  144. package/skills/workspace-diff.md +23 -0
  145. package/skills/workspace-doctor.md +23 -0
  146. package/skills/workspace-info.md +45 -0
  147. package/skills/workspace-manager/SKILL.md +201 -0
  148. package/skills/workspace-manager/references/ai-prompt.md +44 -0
  149. package/skills/workspace-manager/references/analyze-deps.md +45 -0
  150. package/skills/workspace-manager/references/archive-workspace.md +38 -0
  151. package/skills/workspace-manager/references/branch-create.md +31 -0
  152. package/skills/workspace-manager/references/branch-merge.md +22 -0
  153. package/skills/workspace-manager/references/branch-rebase.md +22 -0
  154. package/skills/workspace-manager/references/cache-clear.md +18 -0
  155. package/skills/workspace-manager/references/cache-info.md +22 -0
  156. package/skills/workspace-manager/references/configure-claude.md +31 -0
  157. package/skills/workspace-manager/references/configure.md +35 -0
  158. package/skills/workspace-manager/references/create-workspace.md +45 -0
  159. package/skills/workspace-manager/references/dashboard.md +61 -0
  160. package/skills/workspace-manager/references/delete-workspace.md +33 -0
  161. package/skills/workspace-manager/references/generate-docs.md +36 -0
  162. package/skills/workspace-manager/references/ghq-status.md +28 -0
  163. package/skills/workspace-manager/references/go.md +33 -0
  164. package/skills/workspace-manager/references/history.md +41 -0
  165. package/skills/workspace-manager/references/list-org-repos.md +26 -0
  166. package/skills/workspace-manager/references/list-suites.md +21 -0
  167. package/skills/workspace-manager/references/list-workspaces.md +27 -0
  168. package/skills/workspace-manager/references/mcp.md +49 -0
  169. package/skills/workspace-manager/references/remove-repo.md +26 -0
  170. package/skills/workspace-manager/references/run-command.md +44 -0
  171. package/skills/workspace-manager/references/search-repos.md +24 -0
  172. package/skills/workspace-manager/references/sessions.md +27 -0
  173. package/skills/workspace-manager/references/suite-create.md +22 -0
  174. package/skills/workspace-manager/references/suite-delete.md +21 -0
  175. package/skills/workspace-manager/references/suite-export.md +19 -0
  176. package/skills/workspace-manager/references/suite-import.md +19 -0
  177. package/skills/workspace-manager/references/suite-use.md +27 -0
  178. package/skills/workspace-manager/references/switch-branch.md +25 -0
  179. package/skills/workspace-manager/references/update-cache.md +22 -0
  180. package/skills/workspace-manager/references/update-workspace.md +50 -0
  181. package/skills/workspace-manager/references/workspace-cleanup.md +33 -0
  182. package/skills/workspace-manager/references/workspace-diff.md +27 -0
  183. package/skills/workspace-manager/references/workspace-doctor.md +27 -0
  184. package/skills/workspace-manager/references/workspace-info.md +33 -0
  185. package/skills/workspace-manager/references/workspace-status.md +43 -0
  186. package/skills/workspace-manager/references/workspace-sync.md +26 -0
  187. package/skills/workspace-status.md +26 -0
  188. package/skills/workspace-sync.md +23 -0
  189. package/src/cli/ai-prompt.test.ts +667 -0
  190. package/src/cli/ai-prompt.ts +421 -0
  191. package/src/cli/dashboard/AgentList.tsx +44 -0
  192. package/src/cli/dashboard/DashboardSidebar.tsx +291 -0
  193. package/src/cli/dashboard/HelpFooter.tsx +22 -0
  194. package/src/cli/dashboard/StatusBadge.tsx +23 -0
  195. package/src/cli/dashboard/index.ts +5 -0
  196. package/src/cli/dashboard/types.ts +16 -0
  197. package/src/cli/tui.tsx +51 -0
  198. package/src/cli/workspace-cli.test.ts +30 -0
  199. package/src/commands/ai-prompt.ts +21 -0
  200. package/src/commands/analyze-deps.ts +119 -0
  201. package/src/commands/archive.ts +114 -0
  202. package/src/commands/branch/create.ts +94 -0
  203. package/src/commands/branch/index.ts +74 -0
  204. package/src/commands/branch/merge.ts +61 -0
  205. package/src/commands/branch/rebase.ts +54 -0
  206. package/src/commands/branch/switch.ts +150 -0
  207. package/src/commands/cache/index.ts +51 -0
  208. package/src/commands/cache/manager.ts +168 -0
  209. package/src/commands/cleanup.ts +132 -0
  210. package/src/commands/configure-claude.ts +55 -0
  211. package/src/commands/configure.ts +204 -0
  212. package/src/commands/create.ts +196 -0
  213. package/src/commands/dashboard/hook-handler.ts +138 -0
  214. package/src/commands/dashboard/index.ts +248 -0
  215. package/src/commands/dashboard/launcher.ts +42 -0
  216. package/src/commands/dashboard/session-picker.ts +73 -0
  217. package/src/commands/dashboard/sidebar.js +39 -0
  218. package/src/commands/dashboard/workspace-picker.ts +62 -0
  219. package/src/commands/delete.test.ts +250 -0
  220. package/src/commands/delete.ts +171 -0
  221. package/src/commands/deprecated-aliases.ts +55 -0
  222. package/src/commands/diff.ts +106 -0
  223. package/src/commands/doctor.ts +110 -0
  224. package/src/commands/generate-docs.ts +45 -0
  225. package/src/commands/ghq-status.ts +70 -0
  226. package/src/commands/go.ts +125 -0
  227. package/src/commands/history.ts +136 -0
  228. package/src/commands/list.test.ts +219 -0
  229. package/src/commands/list.ts +176 -0
  230. package/src/commands/mcp/index.ts +39 -0
  231. package/src/commands/migrate.ts +277 -0
  232. package/src/commands/remove-repo.ts +194 -0
  233. package/src/commands/report-bug.ts +88 -0
  234. package/src/commands/run.ts +125 -0
  235. package/src/commands/save-context.test.ts +113 -0
  236. package/src/commands/save-context.ts +141 -0
  237. package/src/commands/sessions.ts +99 -0
  238. package/src/commands/status.ts +111 -0
  239. package/src/commands/suite/create.ts +240 -0
  240. package/src/commands/suite/delete.ts +65 -0
  241. package/src/commands/suite/export.ts +97 -0
  242. package/src/commands/suite/import.ts +100 -0
  243. package/src/commands/suite/index.ts +66 -0
  244. package/src/commands/suite/list.ts +54 -0
  245. package/src/commands/suite/use.ts +232 -0
  246. package/src/commands/sync.ts +97 -0
  247. package/src/commands/update.ts +197 -0
  248. package/src/mcp/install.ts +529 -0
  249. package/src/mcp/server.ts +579 -0
  250. package/src/mcp/tools.test.ts +545 -0
  251. package/src/mcp/tools.ts +1019 -0
  252. package/src/mcp/update-workspace.test.ts +220 -0
  253. package/src/pi-extensions/permission-sync.ts.template +41 -0
  254. package/src/pi-extensions/permissions-gate.ts.template +69 -0
  255. package/src/pi-extensions/pr-fix-trigger.ts.template +124 -0
  256. package/src/pi-extensions/review-reminder.ts.template +58 -0
  257. package/src/pi-extensions/workspace-input-status.ts.template +919 -0
  258. package/src/program.ts +112 -0
  259. package/src/scripts/workspace-table.py +394 -0
  260. package/src/types/dashboard.ts +29 -0
  261. package/src/types/index.ts +109 -0
  262. package/src/types/ink.d.ts +171 -0
  263. package/src/utils/agent-config.test.ts +303 -0
  264. package/src/utils/agent-config.ts +264 -0
  265. package/src/utils/agent-state.test.ts +166 -0
  266. package/src/utils/agent-state.ts +135 -0
  267. package/src/utils/banner.ts +24 -0
  268. package/src/utils/branch-operations.ts +237 -0
  269. package/src/utils/bug-report.test.ts +174 -0
  270. package/src/utils/bug-report.ts +355 -0
  271. package/src/utils/cache.ts +150 -0
  272. package/src/utils/claude-integration.test.ts +381 -0
  273. package/src/utils/claude-integration.ts +649 -0
  274. package/src/utils/claude-sessions.test.ts +262 -0
  275. package/src/utils/claude-sessions.ts +251 -0
  276. package/src/utils/cleanup-operations.ts +94 -0
  277. package/src/utils/colors.ts +25 -0
  278. package/src/utils/command-helpers.ts +46 -0
  279. package/src/utils/config.test.ts +203 -0
  280. package/src/utils/config.ts +133 -0
  281. package/src/utils/context-file.ts +36 -0
  282. package/src/utils/dashboard-hooks.test.ts +168 -0
  283. package/src/utils/dashboard-hooks.ts +163 -0
  284. package/src/utils/dependency-analyzer.ts +243 -0
  285. package/src/utils/diff-operations.ts +59 -0
  286. package/src/utils/doc-generator.ts +187 -0
  287. package/src/utils/ghq-integration.test.ts +195 -0
  288. package/src/utils/ghq-integration.ts +317 -0
  289. package/src/utils/git-operations.test.ts +265 -0
  290. package/src/utils/git-operations.ts +233 -0
  291. package/src/utils/git-status.ts +171 -0
  292. package/src/utils/github.ts +74 -0
  293. package/src/utils/health-checks.ts +359 -0
  294. package/src/utils/history.ts +140 -0
  295. package/src/utils/hooks.ts +92 -0
  296. package/src/utils/logger.ts +37 -0
  297. package/src/utils/permission-sync.test.ts +593 -0
  298. package/src/utils/permission-sync.ts +720 -0
  299. package/src/utils/pi-extensions.test.ts +182 -0
  300. package/src/utils/pi-extensions.ts +226 -0
  301. package/src/utils/progress.ts +73 -0
  302. package/src/utils/prompts.test.ts +169 -0
  303. package/src/utils/prompts.ts +296 -0
  304. package/src/utils/repo-resolver.test.ts +313 -0
  305. package/src/utils/repo-resolver.ts +294 -0
  306. package/src/utils/retry.test.ts +124 -0
  307. package/src/utils/retry.ts +85 -0
  308. package/src/utils/run-operations.ts +38 -0
  309. package/src/utils/suite.test.ts +256 -0
  310. package/src/utils/suite.ts +144 -0
  311. package/src/utils/sync-operations.ts +87 -0
  312. package/src/utils/tmux-dashboard.ts +193 -0
  313. package/src/utils/validation.test.ts +139 -0
  314. package/src/utils/validation.ts +128 -0
  315. package/src/utils/version-check.test.ts +108 -0
  316. package/src/utils/version-check.ts +96 -0
  317. package/src/utils/workspace-meta.ts +173 -0
  318. package/sync-permissions.sh +137 -0
  319. package/tsconfig.json +20 -0
  320. package/uninstall.sh +162 -0
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.registerConfigureCommand = registerConfigureCommand;
40
+ const child_process_1 = require("child_process");
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const inquirer_1 = __importDefault(require("inquirer"));
44
+ const config_1 = require("../utils/config");
45
+ const cache_1 = require("../utils/cache");
46
+ const logger_1 = require("../utils/logger");
47
+ const colors_1 = require("../utils/colors");
48
+ function registerConfigureCommand(parent) {
49
+ parent
50
+ .command('configure')
51
+ .alias('cfg')
52
+ .description('Configure workspace manager settings')
53
+ .action(async () => {
54
+ await handleConfigure();
55
+ });
56
+ }
57
+ async function handleConfigure() {
58
+ console.log('\n' + '='.repeat(60));
59
+ console.log((0, colors_1.colorize)('Workspace Manager Configuration', 'bright'));
60
+ console.log('='.repeat(60) + '\n');
61
+ const current = (0, config_1.getUserConfig)();
62
+ console.log('Current settings:');
63
+ console.log(` Workspaces directory: ${(0, colors_1.colorize)(current.workspacesDir, 'cyan')}`);
64
+ console.log(` GitHub organization: ${(0, colors_1.colorize)(current.githubOrg, 'cyan')}`);
65
+ console.log(` Clone protocol: ${(0, colors_1.colorize)(current.cloneProtocol, 'cyan')}`);
66
+ console.log(` Auto-launch agent: ${current.autoLaunchClaude ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
67
+ console.log(` Generate context file: ${current.generateClaudeContext ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
68
+ console.log(` MCP server: ${current.installMcp ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
69
+ console.log(` AI Agent: ${(0, colors_1.colorize)(current.aiAgent, 'cyan')}`);
70
+ console.log(` Primary agent: ${(0, colors_1.colorize)(current.primaryAgent, 'cyan')}`);
71
+ console.log(` Pi workspace widget: ${current.piWorkspaceInputStatus !== false ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
72
+ console.log(` Claude workspace table: ${current.claudeWorkspaceStatusLine !== false ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
73
+ console.log('');
74
+ try {
75
+ const answers = await inquirer_1.default.prompt([
76
+ { type: 'input', name: 'workspacesDir', message: 'Workspaces directory:', default: current.workspacesDir, validate: (val) => val.trim().length > 0 || 'Directory path is required' },
77
+ { type: 'input', name: 'githubOrg', message: 'GitHub organization:', default: current.githubOrg, validate: (val) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' },
78
+ { type: 'list', name: 'cloneProtocol', message: 'Clone protocol:', choices: [{ name: 'SSH (git@github.com:...)', value: 'ssh' }, { name: 'HTTPS (https://github.com/...)', value: 'https' }], default: current.cloneProtocol },
79
+ { type: 'confirm', name: 'autoLaunchClaude', message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude },
80
+ { type: 'confirm', name: 'generateClaudeContext', message: 'Generate context file in workspaces?', default: current.generateClaudeContext },
81
+ { type: 'confirm', name: 'installMcp', message: 'Install MCP server (Claude Code only)?', default: current.installMcp },
82
+ { type: 'list', name: 'aiAgent', message: 'AI Agent(s) to integrate with:', choices: [
83
+ { name: 'Auto-detect (recommended)', value: 'auto' },
84
+ { name: 'Claude Code only', value: 'claude' },
85
+ { name: 'Pi only', value: 'pi' },
86
+ { name: 'OpenCode only', value: 'opencode' },
87
+ { name: 'All available', value: 'both' },
88
+ ], default: current.aiAgent },
89
+ // Only ask about primary agent when aiAgent is 'both' or 'auto'
90
+ // (when specific agent chosen, primary is implicitly that agent)
91
+ { type: 'list', name: 'primaryAgent', message: 'Primary agent (used for launching):', choices: [
92
+ { name: 'Auto-detect (first available)', value: 'auto' },
93
+ { name: 'Claude Code', value: 'claude' },
94
+ { name: 'Pi', value: 'pi' },
95
+ { name: 'OpenCode', value: 'opencode' },
96
+ ], default: current.primaryAgent, when: (ans) => ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
97
+ { type: 'confirm', name: 'piWorkspaceInputStatus',
98
+ message: 'Show workspace status widget in Pi input area (branch, PRs, CI)?',
99
+ default: current.piWorkspaceInputStatus !== false,
100
+ when: (ans) => ans.aiAgent === 'pi' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
101
+ { type: 'confirm', name: 'claudeWorkspaceStatusLine',
102
+ message: 'Add workspace repo table to Claude Code status line?',
103
+ default: current.claudeWorkspaceStatusLine !== false,
104
+ when: (ans) => ans.aiAgent === 'claude' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
105
+ { type: 'confirm', name: 'autoReportBugs',
106
+ message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
107
+ default: current.autoReportBugs === true },
108
+ ]);
109
+ // Validate and normalize config
110
+ let primaryAgent = answers.primaryAgent || 'auto';
111
+ // If aiAgent is specific, primaryAgent must match
112
+ if (answers.aiAgent === 'claude')
113
+ primaryAgent = 'claude';
114
+ if (answers.aiAgent === 'pi')
115
+ primaryAgent = 'pi';
116
+ if (answers.aiAgent === 'opencode')
117
+ primaryAgent = 'opencode';
118
+ const newConfig = {
119
+ workspacesDir: answers.workspacesDir.trim(),
120
+ githubOrg: answers.githubOrg.trim(),
121
+ cloneProtocol: answers.cloneProtocol,
122
+ autoLaunchClaude: answers.autoLaunchClaude,
123
+ generateClaudeContext: answers.generateClaudeContext,
124
+ installMcp: answers.installMcp,
125
+ aiAgent: answers.aiAgent,
126
+ primaryAgent,
127
+ piWorkspaceInputStatus: answers.piWorkspaceInputStatus ?? current.piWorkspaceInputStatus ?? true,
128
+ claudeWorkspaceStatusLine: answers.claudeWorkspaceStatusLine ?? current.claudeWorkspaceStatusLine ?? true,
129
+ autoReportBugs: answers.autoReportBugs ?? current.autoReportBugs ?? false,
130
+ };
131
+ (0, config_1.saveUserConfig)(newConfig);
132
+ console.log('');
133
+ (0, logger_1.logSuccess)('Configuration saved!');
134
+ console.log('');
135
+ console.log(` ${(0, colors_1.colorize)('Workspaces directory:', 'gray')} ${newConfig.workspacesDir}`);
136
+ console.log(` ${(0, colors_1.colorize)('GitHub organization:', 'gray')} ${newConfig.githubOrg}`);
137
+ console.log(` ${(0, colors_1.colorize)('Clone protocol:', 'gray')} ${newConfig.cloneProtocol}`);
138
+ console.log(` ${(0, colors_1.colorize)('Auto-launch agent:', 'gray')} ${newConfig.autoLaunchClaude ? 'Yes' : 'No'}`);
139
+ console.log(` ${(0, colors_1.colorize)('Generate context:', 'gray')} ${newConfig.generateClaudeContext ? 'Yes' : 'No'}`);
140
+ console.log(` ${(0, colors_1.colorize)('MCP server:', 'gray')} ${newConfig.installMcp ? 'Yes' : 'No'}`);
141
+ console.log(` ${(0, colors_1.colorize)('AI Agent:', 'gray')} ${newConfig.aiAgent}`);
142
+ console.log(` ${(0, colors_1.colorize)('Primary agent:', 'gray')} ${newConfig.primaryAgent}`);
143
+ console.log('');
144
+ // Install / upgrade shell integration.
145
+ // Skip if MCP install just ran it (mcp/install always installs shell integration).
146
+ let mcpInstalled = false;
147
+ if (newConfig.installMcp && !current.installMcp) {
148
+ (0, logger_1.logInfo)('Installing MCP server...');
149
+ try {
150
+ const mcpInstallScript = path.join(__dirname, '..', '..', 'dist', 'mcp', 'install.js');
151
+ (0, child_process_1.execSync)(`node "${mcpInstallScript}" install`, { stdio: 'inherit' });
152
+ mcpInstalled = true;
153
+ }
154
+ catch {
155
+ (0, logger_1.logError)('MCP install failed. You can retry later with: w mcp install');
156
+ }
157
+ }
158
+ if (newConfig.githubOrg !== current.githubOrg) {
159
+ await (0, cache_1.clearCache)();
160
+ (0, logger_1.logInfo)(`GitHub org changed from "${current.githubOrg}" to "${newConfig.githubOrg}". Repo cache has been cleared.`);
161
+ }
162
+ // Always install / upgrade the shell integration so the 'w' function
163
+ // is available. This is especially important on first-time setup where
164
+ // postinstall may not have run or the user hasn't sourced their RC file.
165
+ // Skip if mcp install already did it to avoid printing the reminder twice.
166
+ if (!mcpInstalled) {
167
+ installShellIntegration();
168
+ }
169
+ }
170
+ catch (error) {
171
+ (0, logger_1.logError)('Failed to save configuration');
172
+ if (error instanceof Error) {
173
+ (0, logger_1.logError)(error.message);
174
+ }
175
+ process.exit(1);
176
+ }
177
+ }
178
+ /**
179
+ * Install or upgrade the shell integration (w/workspace shell functions).
180
+ * Uses an absolute path derived from this file so it works regardless of CWD.
181
+ * Always prints a prominent "source your RC file" reminder afterwards.
182
+ */
183
+ function installShellIntegration() {
184
+ // __dirname is dist/commands/ at runtime — script is two levels up at package root
185
+ const scriptPath = path.join(__dirname, '..', '..', 'install-shell-integration.sh');
186
+ if (!fs.existsSync(scriptPath)) {
187
+ (0, logger_1.logWarning)('Shell integration script not found — skipping auto-install');
188
+ printSourceReminder();
189
+ return;
190
+ }
191
+ const shell = process.env.SHELL || '';
192
+ const shellType = shell.endsWith('/zsh') ? 'zsh'
193
+ : shell.endsWith('/bash') ? 'bash'
194
+ : '';
195
+ if (!shellType) {
196
+ (0, logger_1.logWarning)('Unknown shell — skipping shell integration (run install-shell-integration.sh manually)');
197
+ printSourceReminder();
198
+ return;
199
+ }
200
+ try {
201
+ (0, child_process_1.execSync)(`bash "${scriptPath}" ${shellType}`, { stdio: 'inherit' });
202
+ }
203
+ catch {
204
+ (0, logger_1.logWarning)('Shell integration install failed — you can run it manually:');
205
+ (0, logger_1.logInfo)(` bash "${scriptPath}" ${shellType}`);
206
+ }
207
+ printSourceReminder();
208
+ }
209
+ /**
210
+ * Print a loud, impossible-to-miss reminder to source the RC file.
211
+ * Without this step the 'w' shell function is not available in the
212
+ * current terminal session even after a successful install.
213
+ */
214
+ function printSourceReminder() {
215
+ const shell = process.env.SHELL || '';
216
+ const rcFile = shell.endsWith('/zsh') ? '~/.zshrc'
217
+ : shell.endsWith('/bash') ? '~/.bashrc'
218
+ : '~/.profile';
219
+ console.log('');
220
+ console.log((0, colors_1.colorize)(' ⚠️ IMPORTANT — activate the shell function in this session:', 'yellow'));
221
+ console.log('');
222
+ console.log(` ${(0, colors_1.colorize)(`source ${rcFile}`, 'cyan')}`);
223
+ console.log('');
224
+ console.log(` Or open a new terminal tab. Until then the ${(0, colors_1.colorize)('nemus', 'cyan')}/${(0, colors_1.colorize)('nem', 'cyan')} shell`);
225
+ console.log(` functions (which auto-cd into new workspaces) aren't active yet.`);
226
+ console.log('');
227
+ console.log(` Tip: ${(0, colors_1.colorize)('nemus', 'cyan')} works immediately without sourcing:`);
228
+ console.log(` ${(0, colors_1.colorize)('nemus configure', 'cyan')} ${(0, colors_1.colorize)('# first-time setup', 'gray')}`);
229
+ console.log(` ${(0, colors_1.colorize)('nemus list', 'cyan')} ${(0, colors_1.colorize)('# list workspaces', 'gray')}`);
230
+ console.log('');
231
+ }
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerCreateCommand = registerCreateCommand;
37
+ const config_1 = require("../utils/config");
38
+ const path = __importStar(require("path"));
39
+ const github_1 = require("../utils/github");
40
+ const prompts_1 = require("../utils/prompts");
41
+ const git_operations_1 = require("../utils/git-operations");
42
+ const ghq_integration_1 = require("../utils/ghq-integration");
43
+ const workspace_meta_1 = require("../utils/workspace-meta");
44
+ const claude_integration_1 = require("../utils/claude-integration");
45
+ const logger_1 = require("../utils/logger");
46
+ const colors_1 = require("../utils/colors");
47
+ const banner_1 = require("../utils/banner");
48
+ const validation_1 = require("../utils/validation");
49
+ const command_helpers_1 = require("../utils/command-helpers");
50
+ const repo_resolver_1 = require("../utils/repo-resolver");
51
+ function registerCreateCommand(parent) {
52
+ parent
53
+ .command('create')
54
+ .alias('c')
55
+ .description('Create a new workspace')
56
+ .option('-w, --workspace <name>', 'Workspace name')
57
+ .option('-r, --repos <repos>', 'Comma-separated repository names. Use repo:suffix to add the same repo more than once under a separate folder, e.g. casper:cas-101 -> casper-cas-101')
58
+ .option('--prompt <prompt>', 'Original prompt that triggered workspace creation (saved to metadata)')
59
+ .option('--allow-empty', 'Create the workspace with no repositories (e.g. investigate-first: the agent adds repos later)')
60
+ .action(async (opts, cmd) => {
61
+ const globalOpts = (0, command_helpers_1.getGlobalOpts)(cmd);
62
+ await handleCreate({ ...opts, ...globalOpts });
63
+ });
64
+ }
65
+ async function handleCreate(opts) {
66
+ (0, banner_1.printBanner)();
67
+ try {
68
+ // Step 1: Verify gh CLI authentication
69
+ (0, logger_1.logStep)(1, 6, 'Verifying GitHub CLI authentication...');
70
+ const isAuthenticated = await (0, github_1.verifyGhAuth)();
71
+ if (!isAuthenticated) {
72
+ (0, logger_1.logError)('GitHub CLI is not authenticated');
73
+ (0, github_1.displayAuthInstructions)();
74
+ process.exit(1);
75
+ }
76
+ (0, logger_1.logSuccess)('GitHub CLI authenticated');
77
+ // Investigate-first empty workspace: no repos to resolve, so skip the org
78
+ // catalog fetch entirely — otherwise an empty/failed catalog would abort
79
+ // creation on the guard below even though we need no repos.
80
+ const investigateEmpty = !!opts.allowEmpty && !opts.repos;
81
+ // Step 2: Fetch repositories (only when we actually need to resolve repos)
82
+ let repos = [];
83
+ if (!investigateEmpty) {
84
+ (0, logger_1.logStep)(2, 6, 'Fetching repositories...');
85
+ repos = await (0, github_1.fetchOrgRepos)({ forceRefresh: opts.forceRefresh });
86
+ if (repos.length === 0) {
87
+ (0, logger_1.logError)('No repositories found');
88
+ process.exit(1);
89
+ }
90
+ }
91
+ // Step 3: Select repositories
92
+ (0, logger_1.logStep)(3, 6, 'Select repositories to clone...');
93
+ let selectedEntries;
94
+ if (investigateEmpty) {
95
+ // Investigate-first: start with no repos; the in-session agent discovers
96
+ // and adds the relevant repos itself.
97
+ (0, logger_1.logInfo)('Creating an empty workspace (no repositories) — repos can be added later.');
98
+ selectedEntries = [];
99
+ }
100
+ else if (opts.repos) {
101
+ const repoSpecs = (0, command_helpers_1.parseList)(opts.repos);
102
+ const { resolved, notFound, invalidSuffix } = (0, repo_resolver_1.resolveRepoSpecs)(repoSpecs, repos);
103
+ if (invalidSuffix.length > 0) {
104
+ (0, logger_1.logError)(`Invalid instance suffix in: ${invalidSuffix.join(', ')}`);
105
+ (0, logger_1.logInfo)('Use repo:suffix (e.g. casper:cas-101). Suffix may contain letters, numbers, hyphens, underscores.');
106
+ process.exit(1);
107
+ }
108
+ // Warn about fuzzy-resolved names so the user knows what was used
109
+ for (const r of resolved) {
110
+ if (!r.exact) {
111
+ (0, logger_1.logInfo)(`Repo "${r.input}" not found exactly — using "${(0, colors_1.colorize)(r.repo.name, 'cyan')}" (best match)`);
112
+ }
113
+ }
114
+ if (notFound.length > 0) {
115
+ (0, logger_1.logError)(`Repositories not found: ${notFound.join(', ')}`);
116
+ process.exit(1);
117
+ }
118
+ selectedEntries = resolved.map(r => ({ repo: r.repo, directoryName: r.directoryName }));
119
+ }
120
+ else {
121
+ selectedEntries = await (0, prompts_1.promptRepositorySelection)(repos);
122
+ }
123
+ if (selectedEntries.length === 0 && !opts.allowEmpty) {
124
+ (0, logger_1.logInfo)('No repositories selected');
125
+ return;
126
+ }
127
+ // Step 4: Get workspace name
128
+ (0, logger_1.logStep)(4, 6, 'Configure workspace...');
129
+ let workspaceName;
130
+ if (opts.workspace) {
131
+ workspaceName = (0, validation_1.sanitizeWorkspaceName)(opts.workspace);
132
+ const nameError = (0, validation_1.validateWorkspaceName)(workspaceName);
133
+ if (nameError !== true) {
134
+ (0, logger_1.logError)(typeof nameError === 'string' ? nameError : 'Invalid workspace name');
135
+ process.exit(1);
136
+ }
137
+ const exists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
138
+ if (exists) {
139
+ const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, selectedEntries.map(e => e.directoryName));
140
+ (0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
141
+ workspaceName = resolved;
142
+ }
143
+ }
144
+ else {
145
+ workspaceName = await (0, prompts_1.promptWorkspaceName)();
146
+ // Auto-resolve conflict in case the interactively chosen name already exists
147
+ // (the prompt validates format but not uniqueness at this point)
148
+ const interactiveExists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
149
+ if (interactiveExists) {
150
+ const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, selectedEntries.map(e => e.directoryName));
151
+ (0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
152
+ workspaceName = resolved;
153
+ }
154
+ }
155
+ // Step 5: Confirm
156
+ const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
157
+ if (!opts.yes) {
158
+ const confirmed = await (0, prompts_1.confirmWorkspaceCreation)(workspaceName, selectedEntries.length, workspacePath);
159
+ if (!confirmed) {
160
+ (0, logger_1.logInfo)('Operation cancelled');
161
+ return;
162
+ }
163
+ }
164
+ // Step 6: Clone repositories
165
+ (0, logger_1.logStep)(5, 6, 'Creating workspace...');
166
+ const { mkdir } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
167
+ await mkdir(workspacePath, { recursive: true });
168
+ if (selectedEntries.length > 0)
169
+ await (0, ghq_integration_1.warnIfGhqMissing)();
170
+ const results = await (0, git_operations_1.cloneRepositories)(selectedEntries, workspacePath);
171
+ (0, git_operations_1.reportCloneResults)(results);
172
+ // Step 7: Save metadata & generate context
173
+ (0, logger_1.logStep)(6, 6, 'Saving workspace metadata...');
174
+ const metadata = (0, workspace_meta_1.createMetadata)(workspaceName, results, { prompt: opts.prompt });
175
+ await (0, workspace_meta_1.saveMetadata)(workspacePath, metadata);
176
+ const successfulRepos = results
177
+ .filter(r => r.status === 'success')
178
+ .map(r => r.repo);
179
+ // Generate context + .mcp.json even for an empty (investigate-first)
180
+ // workspace, so the in-session agent lands with the MCP tools (search-repos
181
+ // / update-workspace) needed to discover and add repos.
182
+ if (successfulRepos.length > 0 || opts.allowEmpty) {
183
+ await (0, claude_integration_1.generateClaudeContext)(workspacePath, workspaceName, successfulRepos, metadata);
184
+ }
185
+ (0, logger_1.logSuccess)(`Workspace "${(0, colors_1.colorize)(workspaceName, 'cyan')}" created successfully!`);
186
+ // Write workspace path to temp file for shell integration auto-CD
187
+ const { writeFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
188
+ const os = await Promise.resolve().then(() => __importStar(require('os')));
189
+ const tempFile = path.join(os.homedir(), '.workspace-last-created');
190
+ try {
191
+ await writeFile(tempFile, workspacePath, 'utf-8');
192
+ }
193
+ catch {
194
+ // Non-critical — shell integration CD won't work but workspace was created
195
+ }
196
+ }
197
+ catch (error) {
198
+ (0, logger_1.logError)('Failed to create workspace');
199
+ if (error instanceof Error) {
200
+ (0, logger_1.logError)(error.message);
201
+ }
202
+ process.exit(1);
203
+ }
204
+ }
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Hook handler for Claude Code hooks.
5
+ * Invoked via ~/.claude/settings.json hooks — reads JSON from stdin,
6
+ * maps the event to an agent status, and writes to state file.
7
+ *
8
+ * Status model:
9
+ * idle — agent is not working (new, finished, waiting for input)
10
+ * working — agent is actively processing (thinking, calling tools)
11
+ * waiting — agent needs user action (permission approval)
12
+ * stopped — session ended
13
+ *
14
+ * Event mapping:
15
+ * SessionStart → idle (session opened, not working yet)
16
+ * UserPromptSubmit → working (user sent prompt, agent starts)
17
+ * PreToolUse → working (agent calling a tool)
18
+ * PostToolUse → working (tool done, agent still processing)
19
+ * Notification:
20
+ * permission_prompt → waiting (needs user to approve tool use)
21
+ * idle_prompt → idle (agent finished, waiting for input)
22
+ * Stop → idle (agent finished its turn)
23
+ * SessionEnd → stopped (session ended)
24
+ *
25
+ * IMPORTANT: Must never write to stderr or throw — always exit 0.
26
+ */
27
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ var desc = Object.getOwnPropertyDescriptor(m, k);
30
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
31
+ desc = { enumerable: true, get: function() { return m[k]; } };
32
+ }
33
+ Object.defineProperty(o, k2, desc);
34
+ }) : (function(o, m, k, k2) {
35
+ if (k2 === undefined) k2 = k;
36
+ o[k2] = m[k];
37
+ }));
38
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
39
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
40
+ }) : function(o, v) {
41
+ o["default"] = v;
42
+ });
43
+ var __importStar = (this && this.__importStar) || (function () {
44
+ var ownKeys = function(o) {
45
+ ownKeys = Object.getOwnPropertyNames || function (o) {
46
+ var ar = [];
47
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
48
+ return ar;
49
+ };
50
+ return ownKeys(o);
51
+ };
52
+ return function (mod) {
53
+ if (mod && mod.__esModule) return mod;
54
+ var result = {};
55
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
56
+ __setModuleDefault(result, mod);
57
+ return result;
58
+ };
59
+ })();
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const agent_state_1 = require("../../utils/agent-state");
64
+ const config_1 = require("../../utils/config");
65
+ function main() {
66
+ try {
67
+ const args = process.argv.slice(2);
68
+ const eventIdx = args.indexOf('--event');
69
+ const event = eventIdx >= 0 ? args[eventIdx + 1] : null;
70
+ if (!event) {
71
+ process.exit(0);
72
+ }
73
+ let input;
74
+ try {
75
+ const raw = fs.readFileSync('/dev/stdin', 'utf-8');
76
+ input = JSON.parse(raw);
77
+ }
78
+ catch {
79
+ process.exit(0);
80
+ }
81
+ const sessionId = input.session_id;
82
+ if (!sessionId || !/^[a-zA-Z0-9\-]{1,100}$/.test(sessionId)) {
83
+ process.exit(0); // reject missing or invalid session IDs
84
+ }
85
+ (0, agent_state_1.ensureStateDir)();
86
+ let newStatus;
87
+ switch (event) {
88
+ case 'SessionStart':
89
+ newStatus = 'idle';
90
+ break;
91
+ case 'UserPromptSubmit':
92
+ newStatus = 'working';
93
+ break;
94
+ case 'PreToolUse':
95
+ newStatus = 'working';
96
+ break;
97
+ case 'PostToolUse':
98
+ newStatus = 'working';
99
+ break;
100
+ case 'Notification': {
101
+ const notifType = input.notification_type || '';
102
+ if (notifType === 'permission_prompt') {
103
+ newStatus = 'waiting'; // needs user to approve
104
+ }
105
+ else if (notifType === 'idle_prompt') {
106
+ newStatus = 'idle'; // just idle, not a special state
107
+ }
108
+ else {
109
+ process.exit(0);
110
+ }
111
+ break;
112
+ }
113
+ case 'Stop':
114
+ newStatus = 'idle';
115
+ break;
116
+ case 'SessionEnd':
117
+ newStatus = 'stopped';
118
+ break;
119
+ default:
120
+ process.exit(0);
121
+ }
122
+ const now = new Date().toISOString();
123
+ const existing = (0, agent_state_1.readAgentState)(sessionId);
124
+ if (existing) {
125
+ existing.status = newStatus;
126
+ existing.lastUpdatedAt = now;
127
+ // Always update PID — handles resumed sessions where the old
128
+ // process is dead but session ID is reused with a new process
129
+ existing.pid = process.ppid || existing.pid;
130
+ (0, agent_state_1.writeAgentState)(existing);
131
+ process.exit(0);
132
+ }
133
+ // New session — infer workspace from cwd
134
+ const cwd = input.cwd || process.cwd();
135
+ let workspace = 'unknown';
136
+ let workspacePath = cwd;
137
+ const workspacesDir = config_1.WORKSPACES_DIR;
138
+ if (cwd.startsWith(workspacesDir + path.sep) || cwd === workspacesDir) {
139
+ const relative = cwd.slice(workspacesDir.length + 1);
140
+ const parts = relative.split(path.sep);
141
+ if (parts[0]) {
142
+ workspace = parts[0];
143
+ workspacePath = path.join(workspacesDir, workspace);
144
+ }
145
+ }
146
+ const state = {
147
+ sessionId,
148
+ workspace,
149
+ workspacePath,
150
+ pid: process.ppid || 0,
151
+ status: newStatus,
152
+ startedAt: now,
153
+ lastUpdatedAt: now,
154
+ };
155
+ (0, agent_state_1.writeAgentState)(state);
156
+ process.exit(0);
157
+ }
158
+ catch {
159
+ process.exit(0);
160
+ }
161
+ }
162
+ main();