@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,258 @@
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.registerDashboardCommand = registerDashboardCommand;
37
+ const child_process_1 = require("child_process");
38
+ const path = __importStar(require("path"));
39
+ const logger_1 = require("../../utils/logger");
40
+ const colors_1 = require("../../utils/colors");
41
+ const dashboard_hooks_1 = require("../../utils/dashboard-hooks");
42
+ const dashboard_1 = require("../../types/dashboard");
43
+ const agent_state_1 = require("../../utils/agent-state");
44
+ const tmux_dashboard_1 = require("../../utils/tmux-dashboard");
45
+ const agent_config_1 = require("../../utils/agent-config");
46
+ const { sessionName, sidebarWidthPercent } = dashboard_1.DASHBOARD_DEFAULTS;
47
+ function isTmuxAvailable() {
48
+ try {
49
+ (0, child_process_1.execFileSync)('which', ['tmux'], { stdio: 'pipe' });
50
+ return true;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ function isInsideTmux() {
57
+ return !!process.env.TMUX;
58
+ }
59
+ function registerDashboardCommand(parent) {
60
+ parent
61
+ .command('dashboard')
62
+ .alias('dash')
63
+ .description('Launch multi-agent management dashboard')
64
+ .option('--install-hooks', 'Install Claude status hooks without launching dashboard')
65
+ .option('--uninstall-hooks', 'Remove dashboard hooks from Claude settings')
66
+ .option('--list', 'List running agents as JSON (non-interactive)')
67
+ .option('--status', 'Show agent status summary (non-interactive)')
68
+ .option('--kill <sessionId>', 'Kill agent by session ID (non-interactive)')
69
+ .option('--launch <workspace>', 'Launch a new agent in a workspace (non-interactive)')
70
+ .action(async (opts) => {
71
+ await handleDashboard(opts);
72
+ });
73
+ }
74
+ async function handleDashboard(opts) {
75
+ // Handle hook-only commands
76
+ if (opts.installHooks) {
77
+ (0, dashboard_hooks_1.installDashboardHooks)();
78
+ (0, logger_1.logSuccess)('Dashboard hooks installed in ~/.claude/settings.json');
79
+ return;
80
+ }
81
+ if (opts.uninstallHooks) {
82
+ (0, dashboard_hooks_1.uninstallDashboardHooks)();
83
+ (0, logger_1.logSuccess)('Dashboard hooks removed from ~/.claude/settings.json');
84
+ return;
85
+ }
86
+ // --list: print running agents as JSON
87
+ if (opts.list) {
88
+ const agents = (0, agent_state_1.readAllAgentStates)().filter(a => a.status !== 'stopped');
89
+ console.log(JSON.stringify(agents, null, 2));
90
+ return;
91
+ }
92
+ // --status: human-readable status summary
93
+ if (opts.status) {
94
+ const agents = (0, agent_state_1.readAllAgentStates)().filter(a => a.status !== 'stopped');
95
+ if (agents.length === 0) {
96
+ console.log('No agents running.');
97
+ return;
98
+ }
99
+ for (const a of agents) {
100
+ console.log(`${(0, colors_1.colorize)(a.workspace, 'cyan')} ${(0, colors_1.colorize)(a.status, 'yellow')} ${a.sessionId.slice(0, 8)}`);
101
+ }
102
+ return;
103
+ }
104
+ // --kill: kill agent by session ID
105
+ if (opts.kill) {
106
+ const sessionId = opts.kill;
107
+ const agents = (0, agent_state_1.readAllAgentStates)();
108
+ const agent = agents.find(a => a.sessionId === sessionId || a.sessionId.startsWith(sessionId));
109
+ if (!agent) {
110
+ (0, logger_1.logError)(`No agent found with session ID: ${sessionId}`);
111
+ process.exit(1);
112
+ }
113
+ // Try to kill the tmux pane if dashboard is running
114
+ const panes = (0, tmux_dashboard_1.getAgentPanes)();
115
+ const pane = (0, tmux_dashboard_1.findPaneForAgent)(agent, panes);
116
+ if (pane) {
117
+ (0, child_process_1.spawnSync)('tmux', ['kill-pane', '-t', `${sessionName}:0.${pane.index}`], { stdio: 'pipe' });
118
+ setTimeout(() => (0, tmux_dashboard_1.resetLayout)(), 100);
119
+ }
120
+ else {
121
+ // Kill the process directly (guard: pid 0 would kill entire process group)
122
+ if (agent.pid > 0) {
123
+ try {
124
+ process.kill(agent.pid);
125
+ }
126
+ catch { /* already dead */ }
127
+ }
128
+ }
129
+ (0, agent_state_1.removeAgentState)(agent.sessionId);
130
+ (0, logger_1.logSuccess)(`Killed agent: ${agent.workspace} (${agent.sessionId.slice(0, 8)})`);
131
+ return;
132
+ }
133
+ // --launch: launch a new agent in a workspace
134
+ if (opts.launch) {
135
+ const workspaceName = opts.launch;
136
+ const { listWorkspaces } = await Promise.resolve().then(() => __importStar(require('../../utils/workspace-meta')));
137
+ const workspaces = await listWorkspaces();
138
+ const ws = workspaces.find(w => w.name === workspaceName);
139
+ if (!ws) {
140
+ (0, logger_1.logError)(`Workspace not found: ${workspaceName}`);
141
+ (0, logger_1.logInfo)(`Available: ${workspaces.map(w => w.name).join(', ')}`);
142
+ process.exit(1);
143
+ }
144
+ // Check if dashboard is running by verifying the session exists
145
+ const sessionCheck = (0, child_process_1.spawnSync)('tmux', ['has-session', '-t', sessionName], { stdio: 'pipe' });
146
+ if (sessionCheck.status === 0) {
147
+ // Dashboard running — split a pane
148
+ (0, child_process_1.spawnSync)('tmux', [
149
+ 'split-window', '-t', `${sessionName}:0`, '-h',
150
+ '-c', ws.path,
151
+ (0, agent_config_1.getPrimaryAgent)().launchCommand,
152
+ ], { stdio: 'pipe' });
153
+ (0, child_process_1.spawnSync)('tmux', ['select-layout', '-t', sessionName, 'main-vertical'], { stdio: 'pipe' });
154
+ (0, child_process_1.spawnSync)('tmux', ['resize-pane', '-t', `${sessionName}:0.0`, '-x', '32'], { stdio: 'pipe' });
155
+ (0, logger_1.logSuccess)(`Launched agent in workspace: ${workspaceName}`);
156
+ }
157
+ else {
158
+ (0, logger_1.logInfo)(`Dashboard not running. Start it with: w dash`);
159
+ }
160
+ return;
161
+ }
162
+ // Check tmux for interactive dashboard
163
+ if (!isTmuxAvailable()) {
164
+ (0, logger_1.logError)('tmux is required for the agent dashboard');
165
+ console.log((0, colors_1.colorize)('Install tmux: brew install tmux', 'gray'));
166
+ process.exit(1);
167
+ }
168
+ // Auto-install hooks if not present
169
+ if (!(0, dashboard_hooks_1.areDashboardHooksInstalled)()) {
170
+ (0, dashboard_hooks_1.installDashboardHooks)();
171
+ (0, logger_1.logInfo)('Installed dashboard hooks in ~/.claude/settings.json');
172
+ }
173
+ // Check if dashboard session already exists — reconnect if so
174
+ const sessionExists = (0, child_process_1.spawnSync)('tmux', [
175
+ 'has-session', '-t', sessionName,
176
+ ], { stdio: 'pipe' }).status === 0;
177
+ if (sessionExists) {
178
+ (0, logger_1.logInfo)('Reconnecting to existing dashboard session...');
179
+ if (isInsideTmux()) {
180
+ (0, child_process_1.spawnSync)('tmux', ['switch-client', '-t', sessionName], { stdio: 'inherit' });
181
+ }
182
+ else {
183
+ (0, child_process_1.spawnSync)('tmux', ['attach-session', '-t', sessionName], { stdio: 'inherit' });
184
+ }
185
+ (0, logger_1.logSuccess)('Dashboard session ended');
186
+ return;
187
+ }
188
+ // Resolve paths to compiled scripts
189
+ const sidebarScript = path.join(__dirname, 'sidebar.js');
190
+ // Create tmux session with sidebar in the left pane
191
+ const newSessionResult = (0, child_process_1.spawnSync)('tmux', [
192
+ 'new-session', '-d', '-s', sessionName,
193
+ '-x', '200', '-y', '50',
194
+ `node "${sidebarScript}"`,
195
+ ], { stdio: 'pipe' });
196
+ if (newSessionResult.status !== 0) {
197
+ (0, logger_1.logError)('Failed to create tmux session');
198
+ const stderr = newSessionResult.stderr?.toString();
199
+ if (stderr)
200
+ (0, logger_1.logError)(stderr);
201
+ process.exit(1);
202
+ }
203
+ // Split right pane (80%) with placeholder message
204
+ (0, child_process_1.spawnSync)('tmux', [
205
+ 'split-window', '-h', '-t', sessionName,
206
+ '-p', String(100 - sidebarWidthPercent),
207
+ 'bash', '-c',
208
+ 'echo ""; echo " No agents running."; echo " Press n in the sidebar to launch an agent."; echo ""; sleep infinity',
209
+ ], { stdio: 'pipe' });
210
+ // Focus the sidebar pane (left)
211
+ (0, child_process_1.spawnSync)('tmux', ['select-pane', '-t', `${sessionName}:0.0`], { stdio: 'pipe' });
212
+ // ── Session-scoped key bindings ──
213
+ // Use set-hook to add bindings only while this session is active and
214
+ // restore them on detach — avoids polluting global tmux key tables.
215
+ // prefix + M → focus sidebar + reset layout (M chosen to avoid overriding standard keys)
216
+ (0, child_process_1.spawnSync)('tmux', [
217
+ 'set-hook', '-t', sessionName, 'session-created',
218
+ `bind-key -T prefix M run-shell "tmux select-layout -t ${sessionName} main-vertical \\\\; resize-pane -t ${sessionName}:0.0 -x 32 \\\\; select-pane -t ${sessionName}:0.0"`,
219
+ ], { stdio: 'pipe' });
220
+ // Bind immediately for the current session
221
+ (0, child_process_1.spawnSync)('tmux', [
222
+ 'bind-key', '-T', 'prefix', 'M',
223
+ 'run-shell',
224
+ `tmux select-layout -t ${sessionName} main-vertical \\; resize-pane -t ${sessionName}:0.0 -x 32 \\; select-pane -t ${sessionName}:0.0`,
225
+ ], { stdio: 'pipe' });
226
+ // Unbind prefix+M when the dashboard session ends (cleanup)
227
+ (0, child_process_1.spawnSync)('tmux', [
228
+ 'set-hook', '-t', sessionName, 'session-closed',
229
+ 'unbind-key -T prefix M',
230
+ ], { stdio: 'pipe' });
231
+ // ── Status bar ──
232
+ (0, child_process_1.spawnSync)('tmux', [
233
+ 'set-option', '-t', sessionName,
234
+ 'status-left', ' 🤖 Agent Dashboard ',
235
+ ], { stdio: 'pipe' });
236
+ (0, child_process_1.spawnSync)('tmux', [
237
+ 'set-option', '-t', sessionName,
238
+ 'status-right', ' prefix+M:sidebar/reset q:detach Q:quit ',
239
+ ], { stdio: 'pipe' });
240
+ (0, child_process_1.spawnSync)('tmux', [
241
+ 'set-option', '-t', sessionName,
242
+ 'status-style', 'bg=colour235,fg=colour255',
243
+ ], { stdio: 'pipe' });
244
+ // Enable mouse support for pane selection
245
+ (0, child_process_1.spawnSync)('tmux', [
246
+ 'set-option', '-t', sessionName,
247
+ 'mouse', 'on',
248
+ ], { stdio: 'pipe' });
249
+ (0, logger_1.logInfo)('Launching agent dashboard...');
250
+ // Attach to the session
251
+ if (isInsideTmux()) {
252
+ (0, child_process_1.spawnSync)('tmux', ['switch-client', '-t', sessionName], { stdio: 'inherit' });
253
+ }
254
+ else {
255
+ (0, child_process_1.spawnSync)('tmux', ['attach-session', '-t', sessionName], { stdio: 'inherit' });
256
+ }
257
+ (0, logger_1.logSuccess)('Agent dashboard session ended');
258
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.launchAgentPane = launchAgentPane;
4
+ const child_process_1 = require("child_process");
5
+ const dashboard_1 = require("../../types/dashboard");
6
+ const { sessionName } = dashboard_1.DASHBOARD_DEFAULTS;
7
+ /**
8
+ * Launch an agent in the dashboard by spawning a new tmux pane.
9
+ * Kills any placeholder pane (sleep infinity), splits a new pane,
10
+ * and rebalances the layout.
11
+ *
12
+ * @param workspacePath - absolute path to the workspace directory
13
+ * @param command - shell command to run in the new pane (e.g. 'claude' or 'claude --resume <id> --fork-session')
14
+ */
15
+ function launchAgentPane(workspacePath, command) {
16
+ // Kill placeholder pane (sleep infinity) if present
17
+ const paneResult = (0, child_process_1.spawnSync)('tmux', [
18
+ 'list-panes', '-t', sessionName, '-F',
19
+ '#{pane_index} #{pane_current_command}',
20
+ ], { stdio: 'pipe' });
21
+ if (paneResult.stdout) {
22
+ const lines = paneResult.stdout.toString().trim().split('\n');
23
+ for (const line of lines) {
24
+ const parts = line.split(' ');
25
+ if (parts[0] !== '0' && parts.slice(1).join(' ').includes('sleep')) {
26
+ (0, child_process_1.spawnSync)('tmux', ['kill-pane', '-t', `${sessionName}:0.${parts[0]}`], { stdio: 'pipe' });
27
+ break;
28
+ }
29
+ }
30
+ }
31
+ // Create a new pane for the agent
32
+ (0, child_process_1.spawnSync)('tmux', [
33
+ 'split-window', '-t', `${sessionName}:0`, '-h',
34
+ '-c', workspacePath,
35
+ command,
36
+ ], { stdio: 'pipe' });
37
+ // Rebalance layout: sidebar left, agents stacked right
38
+ (0, child_process_1.spawnSync)('tmux', ['select-layout', '-t', sessionName, 'main-vertical'], { stdio: 'pipe' });
39
+ (0, child_process_1.spawnSync)('tmux', ['resize-pane', '-t', `${sessionName}:0.0`, '-x', '32'], { stdio: 'pipe' });
40
+ }
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Session resume picker for the agent dashboard.
5
+ * Shows recent sessions sorted by last active, launches
6
+ * the appropriate agent CLI with --resume <id> --fork in a new dashboard pane.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const claude_sessions_1 = require("../../utils/claude-sessions");
46
+ const launcher_1 = require("./launcher");
47
+ const agent_config_1 = require("../../utils/agent-config");
48
+ const colors_1 = require("../../utils/colors");
49
+ const inquirer_1 = __importDefault(require("inquirer"));
50
+ const inquirer_autocomplete_prompt_1 = __importDefault(require("inquirer-autocomplete-prompt"));
51
+ const fuzzy = __importStar(require("fuzzy"));
52
+ inquirer_1.default.registerPrompt('autocomplete', inquirer_autocomplete_prompt_1.default);
53
+ async function main() {
54
+ try {
55
+ const sessions = await (0, claude_sessions_1.getWorkspaceSessions)();
56
+ if (sessions.length === 0) {
57
+ console.log('No sessions found. Launch a new agent with n.');
58
+ process.exit(1);
59
+ }
60
+ const items = sessions.map(session => ({
61
+ session,
62
+ displayName: session.workspaceName,
63
+ timeLabel: session.lastActiveLabel,
64
+ }));
65
+ const { selected } = await inquirer_1.default.prompt([{
66
+ type: 'autocomplete',
67
+ name: 'selected',
68
+ message: 'Select session to resume:',
69
+ source: async (_answersSoFar, input) => {
70
+ const searchInput = input || '';
71
+ const source = items.map(item => ({
72
+ name: `${item.displayName} ${(0, colors_1.colorize)(item.timeLabel, 'dim')}`,
73
+ value: item,
74
+ }));
75
+ if (!searchInput)
76
+ return source;
77
+ const results = fuzzy.filter(searchInput, items, { extract: (item) => item.displayName });
78
+ return results.map(result => ({
79
+ name: `${result.original.displayName} ${(0, colors_1.colorize)(result.original.timeLabel, 'dim')}`,
80
+ value: result.original,
81
+ }));
82
+ },
83
+ pageSize: 15,
84
+ }]);
85
+ const item = selected;
86
+ const session = item.session;
87
+ const rawSessionId = session.sessionId;
88
+ // Sanitize session ID before interpolating into shell command
89
+ if (!/^[a-zA-Z0-9\-]{1,100}$/.test(rawSessionId)) {
90
+ console.error('Invalid session ID format — skipping');
91
+ process.exit(1);
92
+ }
93
+ // Use the session's agent type for resume, fall back to primary if missing
94
+ // (sessions from before the multi-agent upgrade won't have agentType)
95
+ const agentType = session.agentType || (0, agent_config_1.getPrimaryAgent)().type;
96
+ const agent = (0, agent_config_1.getAgentPaths)(agentType);
97
+ (0, launcher_1.launchAgentPane)(session.workspacePath, agent.resumeCommand(rawSessionId));
98
+ console.log(`\nResuming ${agentType} session in ${session.workspaceName}`);
99
+ }
100
+ catch (error) {
101
+ if (error?.name === 'ExitPromptError')
102
+ process.exit(0);
103
+ process.exit(1);
104
+ }
105
+ }
106
+ main();
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Dashboard sidebar entry point.
4
+ *
5
+ * This is a plain .js file (not .ts) to preserve the real dynamic import().
6
+ * TypeScript compiles `await import('ink')` into `require('ink')` in CJS mode,
7
+ * which fails because ink v5 is ESM-only with top-level await.
8
+ *
9
+ * By keeping this as .js, tsc copies it as-is to dist/ and the real
10
+ * import() call is preserved at runtime.
11
+ */
12
+
13
+ async function main() {
14
+ try {
15
+ const React = require('react');
16
+ const path = require('path');
17
+
18
+ // Real dynamic ESM import — NOT compiled by tsc
19
+ const { render, Box, Text, useInput, useApp } = await import('ink');
20
+
21
+ // CJS require for our compiled TSX components
22
+ const { DashboardSidebar } = require(path.join(__dirname, '..', '..', 'cli', 'dashboard'));
23
+
24
+ const App = () => React.createElement(DashboardSidebar, {
25
+ Box,
26
+ Text,
27
+ useInput,
28
+ useApp,
29
+ });
30
+
31
+ render(React.createElement(App), { exitOnCtrlC: false });
32
+ } catch (error) {
33
+ console.error('Dashboard sidebar failed to start:', error.message);
34
+ // Keep the pane alive so user can see the error
35
+ await new Promise(() => {});
36
+ }
37
+ }
38
+
39
+ main();
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Workspace picker for the agent dashboard.
5
+ * Runs inside a tmux popup — lets the user select a workspace,
6
+ * then spawns a fresh claude agent pane in the dashboard session.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const workspace_meta_1 = require("../../utils/workspace-meta");
46
+ const launcher_1 = require("./launcher");
47
+ const agent_config_1 = require("../../utils/agent-config");
48
+ const inquirer_1 = __importDefault(require("inquirer"));
49
+ const inquirer_autocomplete_prompt_1 = __importDefault(require("inquirer-autocomplete-prompt"));
50
+ const fuzzy = __importStar(require("fuzzy"));
51
+ inquirer_1.default.registerPrompt('autocomplete', inquirer_autocomplete_prompt_1.default);
52
+ async function main() {
53
+ try {
54
+ const workspaces = await (0, workspace_meta_1.listWorkspaces)();
55
+ if (workspaces.length === 0) {
56
+ console.log('No workspaces found. Create one with: workspace create');
57
+ process.exit(1);
58
+ }
59
+ const items = workspaces.map(ws => ({
60
+ name: ws.name,
61
+ path: ws.path,
62
+ repoCount: ws.metadata?.repositories?.length ?? 0,
63
+ }));
64
+ const { selected } = await inquirer_1.default.prompt([{
65
+ type: 'autocomplete',
66
+ name: 'selected',
67
+ message: 'Select workspace to launch agent in:',
68
+ source: async (_answersSoFar, input) => {
69
+ const searchInput = input || '';
70
+ const source = items.map(item => ({
71
+ name: `${item.name} (${item.repoCount} repos)`,
72
+ value: item,
73
+ }));
74
+ if (!searchInput)
75
+ return source;
76
+ const results = fuzzy.filter(searchInput, items, { extract: (item) => item.name });
77
+ return results.map(result => ({
78
+ name: `${result.original.name} (${result.original.repoCount} repos)`,
79
+ value: result.original,
80
+ }));
81
+ },
82
+ pageSize: 15,
83
+ }]);
84
+ const workspace = selected;
85
+ const agent = (0, agent_config_1.getPrimaryAgent)();
86
+ (0, launcher_1.launchAgentPane)(workspace.path, agent.launchCommand);
87
+ console.log(`\nLaunched agent in ${workspace.name}`);
88
+ }
89
+ catch (error) {
90
+ if (error?.name === 'ExitPromptError')
91
+ process.exit(0);
92
+ process.exit(1);
93
+ }
94
+ }
95
+ main();