dmux 3.5.4 → 4.1.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 (137) hide show
  1. package/dist/DmuxApp.d.ts.map +1 -1
  2. package/dist/DmuxApp.js +69 -4
  3. package/dist/DmuxApp.js.map +1 -1
  4. package/dist/actions/implementations/closeAction.js +81 -31
  5. package/dist/actions/implementations/closeAction.js.map +1 -1
  6. package/dist/actions/merge/conflictResolution.d.ts.map +1 -1
  7. package/dist/actions/merge/conflictResolution.js +6 -4
  8. package/dist/actions/merge/conflictResolution.js.map +1 -1
  9. package/dist/actions/merge/multiMergeOrchestrator.js +6 -4
  10. package/dist/actions/merge/multiMergeOrchestrator.js.map +1 -1
  11. package/dist/components/dialogs/AgentChoiceDialog.d.ts +1 -1
  12. package/dist/components/dialogs/AgentChoiceDialog.d.ts.map +1 -1
  13. package/dist/components/dialogs/AgentChoiceDialog.js +3 -2
  14. package/dist/components/dialogs/AgentChoiceDialog.js.map +1 -1
  15. package/dist/components/dialogs/TmuxHooksPromptDialog.d.ts +13 -0
  16. package/dist/components/dialogs/TmuxHooksPromptDialog.d.ts.map +1 -0
  17. package/dist/components/dialogs/TmuxHooksPromptDialog.js +36 -0
  18. package/dist/components/dialogs/TmuxHooksPromptDialog.js.map +1 -0
  19. package/dist/components/panes/MergePane.js +1 -1
  20. package/dist/components/panes/MergePane.js.map +1 -1
  21. package/dist/components/panes/PaneCard.d.ts.map +1 -1
  22. package/dist/components/panes/PaneCard.js +18 -3
  23. package/dist/components/panes/PaneCard.js.map +1 -1
  24. package/dist/components/panes/PanesGrid.d.ts.map +1 -1
  25. package/dist/components/panes/PanesGrid.js +3 -3
  26. package/dist/components/panes/PanesGrid.js.map +1 -1
  27. package/dist/components/popups/agentChoicePopup.js +7 -1
  28. package/dist/components/popups/agentChoicePopup.js.map +1 -1
  29. package/dist/components/ui/FooterHelp.d.ts.map +1 -1
  30. package/dist/components/ui/FooterHelp.js +3 -3
  31. package/dist/components/ui/FooterHelp.js.map +1 -1
  32. package/dist/hooks/useAgentDetection.d.ts +1 -1
  33. package/dist/hooks/useAgentDetection.d.ts.map +1 -1
  34. package/dist/hooks/useAgentDetection.js +27 -0
  35. package/dist/hooks/useAgentDetection.js.map +1 -1
  36. package/dist/hooks/usePaneCreation.d.ts +2 -2
  37. package/dist/hooks/usePaneCreation.d.ts.map +1 -1
  38. package/dist/hooks/usePaneCreation.js.map +1 -1
  39. package/dist/hooks/usePaneLoading.d.ts +4 -0
  40. package/dist/hooks/usePaneLoading.d.ts.map +1 -1
  41. package/dist/hooks/usePaneLoading.js +33 -9
  42. package/dist/hooks/usePaneLoading.js.map +1 -1
  43. package/dist/hooks/usePaneSync.d.ts +4 -0
  44. package/dist/hooks/usePaneSync.d.ts.map +1 -1
  45. package/dist/hooks/usePaneSync.js +13 -3
  46. package/dist/hooks/usePaneSync.js.map +1 -1
  47. package/dist/hooks/usePanes.d.ts +10 -1
  48. package/dist/hooks/usePanes.d.ts.map +1 -1
  49. package/dist/hooks/usePanes.js +65 -13
  50. package/dist/hooks/usePanes.js.map +1 -1
  51. package/dist/hooks/useServices.d.ts +2 -2
  52. package/dist/hooks/useServices.d.ts.map +1 -1
  53. package/dist/index.js +22 -19
  54. package/dist/index.js.map +1 -1
  55. package/dist/layout/SpacerManager.d.ts +3 -0
  56. package/dist/layout/SpacerManager.d.ts.map +1 -1
  57. package/dist/layout/SpacerManager.js +27 -3
  58. package/dist/layout/SpacerManager.js.map +1 -1
  59. package/dist/server/embedded-assets.d.ts.map +1 -1
  60. package/dist/server/embedded-assets.js +93 -25
  61. package/dist/server/embedded-assets.js.map +1 -1
  62. package/dist/server/routes/panesRoutes.d.ts.map +1 -1
  63. package/dist/server/routes/panesRoutes.js +32 -5
  64. package/dist/server/routes/panesRoutes.js.map +1 -1
  65. package/dist/services/LogService.d.ts +7 -2
  66. package/dist/services/LogService.d.ts.map +1 -1
  67. package/dist/services/LogService.js +96 -17
  68. package/dist/services/LogService.js.map +1 -1
  69. package/dist/services/PaneAnalyzer.d.ts +35 -1
  70. package/dist/services/PaneAnalyzer.d.ts.map +1 -1
  71. package/dist/services/PaneAnalyzer.js +167 -65
  72. package/dist/services/PaneAnalyzer.js.map +1 -1
  73. package/dist/services/PaneEventService.d.ts +101 -0
  74. package/dist/services/PaneEventService.d.ts.map +1 -0
  75. package/dist/services/PaneEventService.js +246 -0
  76. package/dist/services/PaneEventService.js.map +1 -0
  77. package/dist/services/PopupManager.d.ts +3 -3
  78. package/dist/services/PopupManager.d.ts.map +1 -1
  79. package/dist/services/PopupManager.js +8 -6
  80. package/dist/services/PopupManager.js.map +1 -1
  81. package/dist/services/TmuxHookManager.d.ts +76 -0
  82. package/dist/services/TmuxHookManager.d.ts.map +1 -0
  83. package/dist/services/TmuxHookManager.js +229 -0
  84. package/dist/services/TmuxHookManager.js.map +1 -0
  85. package/dist/services/TmuxService.d.ts +34 -1
  86. package/dist/services/TmuxService.d.ts.map +1 -1
  87. package/dist/services/TmuxService.js +69 -1
  88. package/dist/services/TmuxService.js.map +1 -1
  89. package/dist/types.d.ts +3 -2
  90. package/dist/types.d.ts.map +1 -1
  91. package/dist/utils/agentDetection.d.ts +5 -1
  92. package/dist/utils/agentDetection.d.ts.map +1 -1
  93. package/dist/utils/agentDetection.js +29 -0
  94. package/dist/utils/agentDetection.js.map +1 -1
  95. package/dist/utils/conflictResolutionPane.d.ts +1 -1
  96. package/dist/utils/conflictResolutionPane.d.ts.map +1 -1
  97. package/dist/utils/conflictResolutionPane.js +12 -2
  98. package/dist/utils/conflictResolutionPane.js.map +1 -1
  99. package/dist/utils/execAsync.d.ts +78 -0
  100. package/dist/utils/execAsync.d.ts.map +1 -0
  101. package/dist/utils/execAsync.js +141 -0
  102. package/dist/utils/execAsync.js.map +1 -0
  103. package/dist/utils/generated-agents-doc.d.ts +1 -1
  104. package/dist/utils/generated-agents-doc.js +1 -1
  105. package/dist/utils/git.d.ts +27 -0
  106. package/dist/utils/git.d.ts.map +1 -1
  107. package/dist/utils/git.js +150 -0
  108. package/dist/utils/git.js.map +1 -1
  109. package/dist/utils/hooksDocs.d.ts +1 -1
  110. package/dist/utils/layoutManager.d.ts.map +1 -1
  111. package/dist/utils/layoutManager.js +51 -3
  112. package/dist/utils/layoutManager.js.map +1 -1
  113. package/dist/utils/paneCapture.d.ts +11 -0
  114. package/dist/utils/paneCapture.d.ts.map +1 -1
  115. package/dist/utils/paneCapture.js +69 -0
  116. package/dist/utils/paneCapture.js.map +1 -1
  117. package/dist/utils/paneCreation.d.ts +2 -2
  118. package/dist/utils/paneCreation.d.ts.map +1 -1
  119. package/dist/utils/paneCreation.js +18 -3
  120. package/dist/utils/paneCreation.js.map +1 -1
  121. package/dist/utils/reopenWorktree.d.ts.map +1 -1
  122. package/dist/utils/reopenWorktree.js +28 -5
  123. package/dist/utils/reopenWorktree.js.map +1 -1
  124. package/dist/utils/settingsManager.d.ts.map +1 -1
  125. package/dist/utils/settingsManager.js +7 -0
  126. package/dist/utils/settingsManager.js.map +1 -1
  127. package/dist/utils/systemCheck.d.ts.map +1 -1
  128. package/dist/utils/systemCheck.js +7 -5
  129. package/dist/utils/systemCheck.js.map +1 -1
  130. package/dist/workers/PaneWorker.js.map +1 -1
  131. package/dist/workers/WorkerMessages.d.ts +1 -1
  132. package/dist/workers/WorkerMessages.d.ts.map +1 -1
  133. package/dist/workers/panePollingWorker.d.ts +13 -0
  134. package/dist/workers/panePollingWorker.d.ts.map +1 -0
  135. package/dist/workers/panePollingWorker.js +129 -0
  136. package/dist/workers/panePollingWorker.js.map +1 -0
  137. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conflictResolutionPane.d.ts","sourceRoot":"","sources":["../../src/utils/conflictResolutionPane.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAO5C,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,QAAQ,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,QAAQ,CAAC,CAgInB"}
1
+ {"version":3,"file":"conflictResolutionPane.d.ts","sourceRoot":"","sources":["../../src/utils/conflictResolutionPane.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAO5C,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,QAAQ,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,QAAQ,CAAC,CA0InB"}
@@ -82,15 +82,25 @@ export async function createConflictResolutionPane(options) {
82
82
  .replace(/"/g, '\\"')
83
83
  .replace(/`/g, '\\`')
84
84
  .replace(/\$/g, '\\$');
85
- const claudeCmd = `claude "${escapedPrompt}" --permission-mode=acceptEdits`;
85
+ const claudeCmd = `claude "${escapedPrompt}" --dangerously-skip-permissions`;
86
86
  await tmuxService.sendShellCommand(paneInfo, claudeCmd);
87
87
  await tmuxService.sendTmuxKeys(paneInfo, 'Enter');
88
88
  // Auto-approve trust prompts for Claude (workspace trust, not edit permissions)
89
- // Note: --permission-mode=acceptEdits handles edit permissions, but not workspace trust
89
+ // Note: --dangerously-skip-permissions handles edit permissions, but not workspace trust
90
90
  autoApproveTrustPrompt(paneInfo).catch(() => {
91
91
  // Ignore errors in background monitoring
92
92
  });
93
93
  }
94
+ else if (agent === 'codex') {
95
+ const escapedPrompt = prompt
96
+ .replace(/\\/g, '\\\\')
97
+ .replace(/"/g, '\\"')
98
+ .replace(/`/g, '\\`')
99
+ .replace(/\$/g, '\\$');
100
+ const codexCmd = `codex "${escapedPrompt}" --dangerously-bypass-approvals-and-sandbox`;
101
+ await tmuxService.sendShellCommand(paneInfo, codexCmd);
102
+ await tmuxService.sendTmuxKeys(paneInfo, 'Enter');
103
+ }
94
104
  else if (agent === 'opencode') {
95
105
  await tmuxService.sendShellCommand(paneInfo, 'opencode');
96
106
  await tmuxService.sendTmuxKeys(paneInfo, 'Enter');
@@ -1 +1 @@
1
- {"version":3,"file":"conflictResolutionPane.js","sourceRoot":"","sources":["../../src/utils/conflictResolutionPane.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conflictResolutionPane.js","sourceRoot":"","sources":["../../src/utils/conflictResolutionPane.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { type SpawnOptions } from 'child_process';
2
+ export interface ExecAsyncOptions extends Omit<SpawnOptions, 'stdio'> {
3
+ /** Timeout in milliseconds. Default: 30000 (30s) */
4
+ timeout?: number;
5
+ /** If true, resolve with empty string on error instead of rejecting */
6
+ silent?: boolean;
7
+ }
8
+ /**
9
+ * Async wrapper around child_process.spawn that returns stdout as a string.
10
+ * This is the non-blocking replacement for execSync.
11
+ *
12
+ * @param command - The command to execute (can include spaces)
13
+ * @param options - Spawn options plus timeout and silent flags
14
+ * @returns Promise resolving to trimmed stdout
15
+ *
16
+ * @example
17
+ * // Basic usage
18
+ * const output = await execAsync('tmux list-panes');
19
+ *
20
+ * @example
21
+ * // With timeout
22
+ * const output = await execAsync('git status', { timeout: 5000 });
23
+ *
24
+ * @example
25
+ * // Silent mode (returns empty string on error)
26
+ * const output = await execAsync('tmux has-session -t foo', { silent: true });
27
+ */
28
+ export declare function execAsync(command: string, options?: ExecAsyncOptions): Promise<string>;
29
+ /**
30
+ * Execute multiple commands in parallel, returning all results.
31
+ * Uses Promise.allSettled so one failure doesn't fail all.
32
+ *
33
+ * @param commands - Array of commands to execute
34
+ * @param options - Options applied to all commands
35
+ * @returns Array of results (either string or Error)
36
+ *
37
+ * @example
38
+ * const [dims, panes] = await execAsyncParallel([
39
+ * 'tmux display-message -p "#{window_width}x#{window_height}"',
40
+ * 'tmux list-panes -F "#{pane_id}"'
41
+ * ]);
42
+ */
43
+ export declare function execAsyncParallel(commands: string[], options?: ExecAsyncOptions): Promise<Array<string | Error>>;
44
+ /**
45
+ * Execute multiple commands in parallel, returning results only on full success.
46
+ * If any command fails, the entire call rejects.
47
+ *
48
+ * @param commands - Array of commands to execute
49
+ * @param options - Options applied to all commands
50
+ * @returns Array of stdout strings in order
51
+ *
52
+ * @example
53
+ * const [opt1, opt2, opt3] = await execAsyncAll([
54
+ * 'tmux set-option -t sess pane-border-status top',
55
+ * 'tmux set-option -t sess pane-border-style "fg=colour240"',
56
+ * 'tmux set-option -t sess pane-border-format " #{pane_title} "'
57
+ * ]);
58
+ */
59
+ export declare function execAsyncAll(commands: string[], options?: ExecAsyncOptions): Promise<string[]>;
60
+ /**
61
+ * Race multiple equivalent commands, returning the first successful result.
62
+ * Useful for API fallbacks or trying multiple approaches.
63
+ *
64
+ * @param commands - Array of commands to race
65
+ * @param options - Options applied to all commands
66
+ * @returns First successful stdout
67
+ * @throws If all commands fail
68
+ *
69
+ * @example
70
+ * // Try multiple git commands, use first that succeeds
71
+ * const branch = await execAsyncRace([
72
+ * 'git symbolic-ref refs/remotes/origin/HEAD',
73
+ * 'git show-ref --verify refs/heads/main',
74
+ * 'git branch --show-current'
75
+ * ], { silent: false });
76
+ */
77
+ export declare function execAsyncRace(commands: string[], options?: Omit<ExecAsyncOptions, 'silent'>): Promise<string>;
78
+ //# sourceMappingURL=execAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execAsync.d.ts","sourceRoot":"","sources":["../../src/utils/execAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;IACnE,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA+DjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAQhC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,MAAM,CAAC,CAMjB"}
@@ -0,0 +1,141 @@
1
+ import { spawn } from 'child_process';
2
+ /**
3
+ * Async wrapper around child_process.spawn that returns stdout as a string.
4
+ * This is the non-blocking replacement for execSync.
5
+ *
6
+ * @param command - The command to execute (can include spaces)
7
+ * @param options - Spawn options plus timeout and silent flags
8
+ * @returns Promise resolving to trimmed stdout
9
+ *
10
+ * @example
11
+ * // Basic usage
12
+ * const output = await execAsync('tmux list-panes');
13
+ *
14
+ * @example
15
+ * // With timeout
16
+ * const output = await execAsync('git status', { timeout: 5000 });
17
+ *
18
+ * @example
19
+ * // Silent mode (returns empty string on error)
20
+ * const output = await execAsync('tmux has-session -t foo', { silent: true });
21
+ */
22
+ export function execAsync(command, options = {}) {
23
+ const { timeout = 30000, silent = false, ...spawnOptions } = options;
24
+ return new Promise((resolve, reject) => {
25
+ const proc = spawn(command, [], {
26
+ shell: true,
27
+ ...spawnOptions,
28
+ stdio: ['pipe', 'pipe', 'pipe'],
29
+ });
30
+ let stdout = '';
31
+ let stderr = '';
32
+ let timedOut = false;
33
+ let timeoutId;
34
+ if (timeout > 0) {
35
+ timeoutId = setTimeout(() => {
36
+ timedOut = true;
37
+ proc.kill('SIGTERM');
38
+ }, timeout);
39
+ }
40
+ proc.stdout?.on('data', (data) => {
41
+ stdout += data.toString();
42
+ });
43
+ proc.stderr?.on('data', (data) => {
44
+ stderr += data.toString();
45
+ });
46
+ proc.on('error', (error) => {
47
+ if (timeoutId)
48
+ clearTimeout(timeoutId);
49
+ if (silent) {
50
+ resolve('');
51
+ }
52
+ else {
53
+ reject(error);
54
+ }
55
+ });
56
+ proc.on('close', (code) => {
57
+ if (timeoutId)
58
+ clearTimeout(timeoutId);
59
+ if (timedOut) {
60
+ if (silent) {
61
+ resolve('');
62
+ }
63
+ else {
64
+ reject(new Error(`Command timed out after ${timeout}ms: ${command}`));
65
+ }
66
+ return;
67
+ }
68
+ if (code === 0) {
69
+ resolve(stdout.trim());
70
+ }
71
+ else {
72
+ if (silent) {
73
+ resolve('');
74
+ }
75
+ else {
76
+ const errorMessage = stderr.trim() || `Command failed with exit code ${code}`;
77
+ reject(new Error(errorMessage));
78
+ }
79
+ }
80
+ });
81
+ });
82
+ }
83
+ /**
84
+ * Execute multiple commands in parallel, returning all results.
85
+ * Uses Promise.allSettled so one failure doesn't fail all.
86
+ *
87
+ * @param commands - Array of commands to execute
88
+ * @param options - Options applied to all commands
89
+ * @returns Array of results (either string or Error)
90
+ *
91
+ * @example
92
+ * const [dims, panes] = await execAsyncParallel([
93
+ * 'tmux display-message -p "#{window_width}x#{window_height}"',
94
+ * 'tmux list-panes -F "#{pane_id}"'
95
+ * ]);
96
+ */
97
+ export async function execAsyncParallel(commands, options = {}) {
98
+ const results = await Promise.allSettled(commands.map(cmd => execAsync(cmd, options)));
99
+ return results.map(result => result.status === 'fulfilled' ? result.value : result.reason);
100
+ }
101
+ /**
102
+ * Execute multiple commands in parallel, returning results only on full success.
103
+ * If any command fails, the entire call rejects.
104
+ *
105
+ * @param commands - Array of commands to execute
106
+ * @param options - Options applied to all commands
107
+ * @returns Array of stdout strings in order
108
+ *
109
+ * @example
110
+ * const [opt1, opt2, opt3] = await execAsyncAll([
111
+ * 'tmux set-option -t sess pane-border-status top',
112
+ * 'tmux set-option -t sess pane-border-style "fg=colour240"',
113
+ * 'tmux set-option -t sess pane-border-format " #{pane_title} "'
114
+ * ]);
115
+ */
116
+ export async function execAsyncAll(commands, options = {}) {
117
+ return Promise.all(commands.map(cmd => execAsync(cmd, options)));
118
+ }
119
+ /**
120
+ * Race multiple equivalent commands, returning the first successful result.
121
+ * Useful for API fallbacks or trying multiple approaches.
122
+ *
123
+ * @param commands - Array of commands to race
124
+ * @param options - Options applied to all commands
125
+ * @returns First successful stdout
126
+ * @throws If all commands fail
127
+ *
128
+ * @example
129
+ * // Try multiple git commands, use first that succeeds
130
+ * const branch = await execAsyncRace([
131
+ * 'git symbolic-ref refs/remotes/origin/HEAD',
132
+ * 'git show-ref --verify refs/heads/main',
133
+ * 'git branch --show-current'
134
+ * ], { silent: false });
135
+ */
136
+ export async function execAsyncRace(commands, options = {}) {
137
+ // Use Promise.any to get first success
138
+ // Each command must NOT be silent so failures actually reject
139
+ return Promise.any(commands.map(cmd => execAsync(cmd, { ...options, silent: false })));
140
+ }
141
+ //# sourceMappingURL=execAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execAsync.js","sourceRoot":"","sources":["../../src/utils/execAsync.ts"],"names":[],"mappings":"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"}
@@ -2,5 +2,5 @@
2
2
  * Auto-generated AGENTS.md content
3
3
  * DO NOT EDIT MANUALLY - run 'pnpm generate:hooks-docs' to regenerate
4
4
  */
5
- export declare const AGENTS_MD = "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.\n\n## What You're Working On\n\nYou are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent (Claude Code or opencode).\n\n## Your Goal\n\nCreate executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.\n\n## Quick Start\n\n1. **Create a hook file**: `touch .dmux-hooks/worktree_created`\n2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`\n3. **Add shebang**: Start with `#!/bin/bash`\n4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.\n5. **Test it**: Set env vars manually and run the script\n\n## Hook Execution Model\n\n- **Non-blocking**: Hooks run in background (detached processes)\n- **Silent failures**: Hook errors are logged but don't stop dmux\n- **Environment-based**: All context passed via environment variables\n- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team\n- **Priority resolution**: `.dmux-hooks/` \u2192 `.dmux/hooks/` \u2192 `~/.dmux/hooks/`\n\n## Available Hooks\n\n### Pane Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |\n| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |\n| `worktree_created` | After full setup | Install deps, copy configs, setup git |\n| `before_pane_close` | Before closing | Save state, backup uncommitted work |\n| `pane_closed` | After closed | Cleanup resources, analytics, notifications |\n\n### Worktree Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |\n| `worktree_removed` | After worktree removed | Cleanup external references |\n\n### Merge Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `pre_merge` | Before merge operation | Run final tests, create backups |\n| `post_merge` | After successful merge | Deploy, close issues, notify team |\n\n### Interactive Hooks (with HTTP callbacks)\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `run_test` | When tests triggered | Run test suite, report status via HTTP |\n| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |\n\n\n## Environment Variables\n\n### Always Available\n```bash\nDMUX_ROOT=\"/path/to/project\" # Project root directory\nDMUX_SERVER_PORT=\"3142\" # HTTP server port\n```\n\n### Pane Context (most hooks)\n```bash\nDMUX_PANE_ID=\"dmux-1234567890\" # dmux pane identifier\nDMUX_SLUG=\"fix-auth-bug\" # Branch/worktree name\nDMUX_PROMPT=\"Fix authentication bug\" # User's prompt\nDMUX_AGENT=\"claude\" # Agent type (claude|opencode)\nDMUX_TMUX_PANE_ID=\"%38\" # tmux pane ID\n```\n\n### Worktree Context\n```bash\nDMUX_WORKTREE_PATH=\"/path/.dmux/worktrees/fix-auth-bug\"\nDMUX_BRANCH=\"fix-auth-bug\" # Same as slug\n```\n\n### Merge Context\n```bash\nDMUX_TARGET_BRANCH=\"main\" # Branch being merged into\n```\n\n## HTTP Callback API\n\nInteractive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.\n\n### Update Test Status\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"output\": \"optional test output\"}'\n\n# Status values: \"running\" | \"passed\" | \"failed\"\n```\n\n### Update Dev Server\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"url\": \"http://localhost:3000\"}'\n\n# Status values: \"running\" | \"stopped\"\n# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)\n```\n\n## Common Patterns\n\n### Pattern 1: Install Dependencies\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\ncd \"$DMUX_WORKTREE_PATH\"\n\nif [ -f \"pnpm-lock.yaml\" ]; then\n pnpm install --prefer-offline &\nelif [ -f \"package-lock.json\" ]; then\n npm install &\nelif [ -f \"yarn.lock\" ]; then\n yarn install &\nelif [ -f \"Gemfile\" ]; then\n bundle install &\nelif [ -f \"requirements.txt\" ]; then\n pip install -r requirements.txt &\nelif [ -f \"Cargo.toml\" ]; then\n cargo build &\nfi\n```\n\n### Pattern 2: Copy Configuration\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\n# Copy environment file\nif [ -f \"$DMUX_ROOT/.env.local\" ]; then\n cp \"$DMUX_ROOT/.env.local\" \"$DMUX_WORKTREE_PATH/.env.local\"\nfi\n\n# Copy other config files\nfor file in .env.development .npmrc .yarnrc; do\n if [ -f \"$DMUX_ROOT/$file\" ]; then\n cp \"$DMUX_ROOT/$file\" \"$DMUX_WORKTREE_PATH/$file\"\n fi\ndone\n```\n\n### Pattern 3: Run Tests with Status Updates\n```bash\n#!/bin/bash\n# .dmux-hooks/run_test\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\"\n\n# Update: starting\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\"}' > /dev/null\n\n# Run tests and capture output\nOUTPUT_FILE=\"/tmp/dmux-test-$DMUX_PANE_ID.txt\"\nif pnpm test > \"$OUTPUT_FILE\" 2>&1; then\n STATUS=\"passed\"\nelse\n STATUS=\"failed\"\nfi\n\n# Get output (truncate if too long)\nOUTPUT=$(head -c 5000 \"$OUTPUT_FILE\")\n\n# Update: complete\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"$(jq -n --arg status \"$STATUS\" --arg output \"$OUTPUT\" '{status: $status, output: $output}')\" > /dev/null\n\nrm -f \"$OUTPUT_FILE\"\n```\n\n### Pattern 4: Dev Server with Tunnel\n```bash\n#!/bin/bash\n# .dmux-hooks/run_dev\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\"\n\n# Start dev server in background\nLOG_FILE=\"/tmp/dmux-dev-$DMUX_PANE_ID.log\"\npnpm dev > \"$LOG_FILE\" 2>&1 &\nDEV_PID=$!\n\n# Wait for server to start\nsleep 5\n\n# Detect port from logs\nPORT=$(grep -oP 'localhost:Kd+' \"$LOG_FILE\" | head -1)\n[ -z \"$PORT\" ] && PORT=3000\n\n# Optional: Create tunnel with cloudflared\nif command -v cloudflared &> /dev/null; then\n TUNNEL=$(cloudflared tunnel --url \"http://localhost:$PORT\" 2>&1 | grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)\n URL=\"${TUNNEL:-http://localhost:$PORT}\"\nelse\n URL=\"http://localhost:$PORT\"\nfi\n\n# Report status\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"{\"status\": \"running\", \"url\": \"$URL\"}\" > /dev/null\n\necho \"[Hook] Dev server running at $URL (PID: $DEV_PID)\"\n```\n\n### Pattern 5: Post-Merge Deployment\n```bash\n#!/bin/bash\n# .dmux-hooks/post_merge\n\nset -e\ncd \"$DMUX_ROOT\"\n\n# Only deploy from main/master\nif [ \"$DMUX_TARGET_BRANCH\" != \"main\" ] && [ \"$DMUX_TARGET_BRANCH\" != \"master\" ]; then\n exit 0\nfi\n\n# Push to remote\ngit push origin \"$DMUX_TARGET_BRANCH\"\n\n# Trigger deployment (example: Vercel)\nif [ -n \"$VERCEL_TOKEN\" ]; then\n curl -s -X POST \"https://api.vercel.com/v1/deployments\" -H \"Authorization: Bearer $VERCEL_TOKEN\" -H \"Content-Type: application/json\" -d '{\"name\": \"my-project\"}' > /dev/null\nfi\n\n# Close GitHub issue if prompt contains #123\nISSUE=$(echo \"$DMUX_PROMPT\" | grep -oP '#Kd+' | head -1)\nif [ -n \"$ISSUE\" ] && command -v gh &> /dev/null; then\n gh issue close \"$ISSUE\" -c \"Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH\" 2>/dev/null || true\nfi\n```\n\n## Best Practices\n\n1. **Always start with shebang**: `#!/bin/bash`\n2. **Set error handling**: `set -e` (exit on error)\n3. **Make executable**: `chmod +x .dmux-hooks/hook_name`\n4. **Background long operations**: Append `&` to avoid blocking\n5. **Check for required tools**: `command -v tool &> /dev/null`\n6. **Log for debugging**: `echo \"[Hook] message\" >> \"$DMUX_ROOT/.dmux/hooks.log\"`\n7. **Handle missing vars gracefully**: `[ -z \"$VAR\" ] && exit 0`\n8. **Use silent curl**: `curl -s` to avoid noise in logs\n9. **Clean up temp files**: Remove files in `/tmp/`\n10. **Test before committing**: Run hooks manually with mock env vars\n\n## Testing Hooks\n\n### Manual Testing\n```bash\n# 1. Set environment variables\nexport DMUX_ROOT=\"$(pwd)\"\nexport DMUX_PANE_ID=\"test-pane\"\nexport DMUX_SLUG=\"test-branch\"\nexport DMUX_WORKTREE_PATH=\"$(pwd)\"\nexport DMUX_SERVER_PORT=\"3142\"\nexport DMUX_AGENT=\"claude\"\nexport DMUX_PROMPT=\"Test prompt\"\n\n# 2. Run hook directly\n./.dmux-hooks/worktree_created\n\n# 3. Check exit code\necho $? # Should be 0 for success\n```\n\n### Syntax Check\n```bash\n# Check for syntax errors without running\nbash -n ./.dmux-hooks/worktree_created\n```\n\n### Shellcheck (if available)\n```bash\nshellcheck ./.dmux-hooks/worktree_created\n```\n\n## Project Context Analysis\n\nBefore creating hooks, analyze these files in the project:\n\n### Package Manager Detection\n```bash\n# Check which package manager is used\nif [ -f \"pnpm-lock.yaml\" ]; then\n # Use: pnpm install, pnpm test, pnpm dev\nelif [ -f \"package-lock.json\" ]; then\n # Use: npm install, npm test, npm run dev\nelif [ -f \"yarn.lock\" ]; then\n # Use: yarn install, yarn test, yarn dev\nfi\n```\n\n### Test Command Discovery\n```bash\n# Read package.json to find test command\ncat package.json | grep '\"test\"'\n# Or with jq:\njq -r '.scripts.test' package.json\n```\n\n### Dev Command Discovery\n```bash\n# Read package.json to find dev command\ncat package.json | grep '\"dev\"'\n# Or with jq:\njq -r '.scripts.dev' package.json\n```\n\n### Environment Variables\n```bash\n# Check for .env files to copy\nls -la | grep '.env'\n```\n\n### Build System\n```bash\n# Detect build system\nif [ -f \"vite.config.ts\" ]; then\n # Vite project\nelif [ -f \"next.config.js\" ]; then\n # Next.js project\nelif [ -f \"nuxt.config.ts\" ]; then\n # Nuxt project\nfi\n```\n\n## Common Mistakes to Avoid\n\n\u274C **Blocking operations**: `sleep 60` (blocks dmux)\n\u2705 **Background long tasks**: `slow_operation &`\n\n\u274C **Hardcoded paths**: `/Users/me/project`\n\u2705 **Use variables**: `\"$DMUX_ROOT\"`\n\n\u274C **Assuming tools exist**: `pnpm install`\n\u2705 **Check first**: `command -v pnpm && pnpm install`\n\n\u274C **No error handling**: Script fails silently\n\u2705 **Set error mode**: `set -e` or check exit codes\n\n\u274C **Forgetting executable bit**: Hook won't run\n\u2705 **Make executable**: `chmod +x`\n\n\u274C **Noisy output**: Clutters dmux logs\n\u2705 **Silent operations**: `curl -s`, `> /dev/null 2>&1`\n\n\u274C **Not testing**: Deploy and hope\n\u2705 **Test manually**: Run with mock env vars first\n\n## Debugging\n\nIf a hook isn't working:\n\n1. **Check if file exists**: `ls -la .dmux-hooks/`\n2. **Check permissions**: Should show `x` in `rwxr-xr-x`\n3. **Check syntax**: `bash -n .dmux-hooks/hook_name`\n4. **Test manually**: Set env vars and run\n5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix\n6. **Simplify**: Remove complex parts, test basic version\n7. **Check tool availability**: `command -v required_tool`\n\n### Debug Mode\n```bash\n#!/bin/bash\n# Add to top of hook for debugging\nset -x # Print each command before executing\nset -e # Exit on error\n\n# Your hook logic here\n```\n\n## Summary Checklist\n\nWhen creating a new hook:\n\n- [ ] Create file in `.dmux-hooks/`\n- [ ] Add shebang: `#!/bin/bash`\n- [ ] Make executable: `chmod +x`\n- [ ] Add `set -e` for error handling\n- [ ] Use environment variables (never hardcode paths)\n- [ ] Background long operations with `&`\n- [ ] Check for required tools before using\n- [ ] Test manually with mock env vars\n- [ ] Add comments explaining what it does\n- [ ] Commit to version control\n\n## Getting Help\n\n- **Full documentation**: See `HOOKS.md` in project root\n- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`\n- **Examples**: Check `.dmux-hooks/examples/` directory\n- **dmux API**: See `API.md` for REST endpoints\n\n---\n\n*This documentation was auto-generated from dmux source code.*\n*Version: 2025-12-22*\n";
5
+ export declare const AGENTS_MD = "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.\n\n## What You're Working On\n\nYou are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent (Claude Code or opencode).\n\n## Your Goal\n\nCreate executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.\n\n## Quick Start\n\n1. **Create a hook file**: `touch .dmux-hooks/worktree_created`\n2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`\n3. **Add shebang**: Start with `#!/bin/bash`\n4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.\n5. **Test it**: Set env vars manually and run the script\n\n## Hook Execution Model\n\n- **Non-blocking**: Hooks run in background (detached processes)\n- **Silent failures**: Hook errors are logged but don't stop dmux\n- **Environment-based**: All context passed via environment variables\n- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team\n- **Priority resolution**: `.dmux-hooks/` \u2192 `.dmux/hooks/` \u2192 `~/.dmux/hooks/`\n\n## Available Hooks\n\n### Pane Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |\n| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |\n| `worktree_created` | After full setup | Install deps, copy configs, setup git |\n| `before_pane_close` | Before closing | Save state, backup uncommitted work |\n| `pane_closed` | After closed | Cleanup resources, analytics, notifications |\n\n### Worktree Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |\n| `worktree_removed` | After worktree removed | Cleanup external references |\n\n### Merge Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `pre_merge` | Before merge operation | Run final tests, create backups |\n| `post_merge` | After successful merge | Deploy, close issues, notify team |\n\n### Interactive Hooks (with HTTP callbacks)\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `run_test` | When tests triggered | Run test suite, report status via HTTP |\n| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |\n\n\n## Environment Variables\n\n### Always Available\n```bash\nDMUX_ROOT=\"/path/to/project\" # Project root directory\nDMUX_SERVER_PORT=\"3142\" # HTTP server port\n```\n\n### Pane Context (most hooks)\n```bash\nDMUX_PANE_ID=\"dmux-1234567890\" # dmux pane identifier\nDMUX_SLUG=\"fix-auth-bug\" # Branch/worktree name\nDMUX_PROMPT=\"Fix authentication bug\" # User's prompt\nDMUX_AGENT=\"claude\" # Agent type (claude|opencode)\nDMUX_TMUX_PANE_ID=\"%38\" # tmux pane ID\n```\n\n### Worktree Context\n```bash\nDMUX_WORKTREE_PATH=\"/path/.dmux/worktrees/fix-auth-bug\"\nDMUX_BRANCH=\"fix-auth-bug\" # Same as slug\n```\n\n### Merge Context\n```bash\nDMUX_TARGET_BRANCH=\"main\" # Branch being merged into\n```\n\n## HTTP Callback API\n\nInteractive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.\n\n### Update Test Status\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"output\": \"optional test output\"}'\n\n# Status values: \"running\" | \"passed\" | \"failed\"\n```\n\n### Update Dev Server\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"url\": \"http://localhost:3000\"}'\n\n# Status values: \"running\" | \"stopped\"\n# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)\n```\n\n## Common Patterns\n\n### Pattern 1: Install Dependencies\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\ncd \"$DMUX_WORKTREE_PATH\"\n\nif [ -f \"pnpm-lock.yaml\" ]; then\n pnpm install --prefer-offline &\nelif [ -f \"package-lock.json\" ]; then\n npm install &\nelif [ -f \"yarn.lock\" ]; then\n yarn install &\nelif [ -f \"Gemfile\" ]; then\n bundle install &\nelif [ -f \"requirements.txt\" ]; then\n pip install -r requirements.txt &\nelif [ -f \"Cargo.toml\" ]; then\n cargo build &\nfi\n```\n\n### Pattern 2: Copy Configuration\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\n# Copy environment file\nif [ -f \"$DMUX_ROOT/.env.local\" ]; then\n cp \"$DMUX_ROOT/.env.local\" \"$DMUX_WORKTREE_PATH/.env.local\"\nfi\n\n# Copy other config files\nfor file in .env.development .npmrc .yarnrc; do\n if [ -f \"$DMUX_ROOT/$file\" ]; then\n cp \"$DMUX_ROOT/$file\" \"$DMUX_WORKTREE_PATH/$file\"\n fi\ndone\n```\n\n### Pattern 3: Run Tests with Status Updates\n```bash\n#!/bin/bash\n# .dmux-hooks/run_test\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\"\n\n# Update: starting\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\"}' > /dev/null\n\n# Run tests and capture output\nOUTPUT_FILE=\"/tmp/dmux-test-$DMUX_PANE_ID.txt\"\nif pnpm test > \"$OUTPUT_FILE\" 2>&1; then\n STATUS=\"passed\"\nelse\n STATUS=\"failed\"\nfi\n\n# Get output (truncate if too long)\nOUTPUT=$(head -c 5000 \"$OUTPUT_FILE\")\n\n# Update: complete\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"$(jq -n --arg status \"$STATUS\" --arg output \"$OUTPUT\" '{status: $status, output: $output}')\" > /dev/null\n\nrm -f \"$OUTPUT_FILE\"\n```\n\n### Pattern 4: Dev Server with Tunnel\n```bash\n#!/bin/bash\n# .dmux-hooks/run_dev\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\"\n\n# Start dev server in background\nLOG_FILE=\"/tmp/dmux-dev-$DMUX_PANE_ID.log\"\npnpm dev > \"$LOG_FILE\" 2>&1 &\nDEV_PID=$!\n\n# Wait for server to start\nsleep 5\n\n# Detect port from logs\nPORT=$(grep -oP 'localhost:Kd+' \"$LOG_FILE\" | head -1)\n[ -z \"$PORT\" ] && PORT=3000\n\n# Optional: Create tunnel with cloudflared\nif command -v cloudflared &> /dev/null; then\n TUNNEL=$(cloudflared tunnel --url \"http://localhost:$PORT\" 2>&1 | grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)\n URL=\"${TUNNEL:-http://localhost:$PORT}\"\nelse\n URL=\"http://localhost:$PORT\"\nfi\n\n# Report status\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"{\"status\": \"running\", \"url\": \"$URL\"}\" > /dev/null\n\necho \"[Hook] Dev server running at $URL (PID: $DEV_PID)\"\n```\n\n### Pattern 5: Post-Merge Deployment\n```bash\n#!/bin/bash\n# .dmux-hooks/post_merge\n\nset -e\ncd \"$DMUX_ROOT\"\n\n# Only deploy from main/master\nif [ \"$DMUX_TARGET_BRANCH\" != \"main\" ] && [ \"$DMUX_TARGET_BRANCH\" != \"master\" ]; then\n exit 0\nfi\n\n# Push to remote\ngit push origin \"$DMUX_TARGET_BRANCH\"\n\n# Trigger deployment (example: Vercel)\nif [ -n \"$VERCEL_TOKEN\" ]; then\n curl -s -X POST \"https://api.vercel.com/v1/deployments\" -H \"Authorization: Bearer $VERCEL_TOKEN\" -H \"Content-Type: application/json\" -d '{\"name\": \"my-project\"}' > /dev/null\nfi\n\n# Close GitHub issue if prompt contains #123\nISSUE=$(echo \"$DMUX_PROMPT\" | grep -oP '#Kd+' | head -1)\nif [ -n \"$ISSUE\" ] && command -v gh &> /dev/null; then\n gh issue close \"$ISSUE\" -c \"Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH\" 2>/dev/null || true\nfi\n```\n\n## Best Practices\n\n1. **Always start with shebang**: `#!/bin/bash`\n2. **Set error handling**: `set -e` (exit on error)\n3. **Make executable**: `chmod +x .dmux-hooks/hook_name`\n4. **Background long operations**: Append `&` to avoid blocking\n5. **Check for required tools**: `command -v tool &> /dev/null`\n6. **Log for debugging**: `echo \"[Hook] message\" >> \"$DMUX_ROOT/.dmux/hooks.log\"`\n7. **Handle missing vars gracefully**: `[ -z \"$VAR\" ] && exit 0`\n8. **Use silent curl**: `curl -s` to avoid noise in logs\n9. **Clean up temp files**: Remove files in `/tmp/`\n10. **Test before committing**: Run hooks manually with mock env vars\n\n## Testing Hooks\n\n### Manual Testing\n```bash\n# 1. Set environment variables\nexport DMUX_ROOT=\"$(pwd)\"\nexport DMUX_PANE_ID=\"test-pane\"\nexport DMUX_SLUG=\"test-branch\"\nexport DMUX_WORKTREE_PATH=\"$(pwd)\"\nexport DMUX_SERVER_PORT=\"3142\"\nexport DMUX_AGENT=\"claude\"\nexport DMUX_PROMPT=\"Test prompt\"\n\n# 2. Run hook directly\n./.dmux-hooks/worktree_created\n\n# 3. Check exit code\necho $? # Should be 0 for success\n```\n\n### Syntax Check\n```bash\n# Check for syntax errors without running\nbash -n ./.dmux-hooks/worktree_created\n```\n\n### Shellcheck (if available)\n```bash\nshellcheck ./.dmux-hooks/worktree_created\n```\n\n## Project Context Analysis\n\nBefore creating hooks, analyze these files in the project:\n\n### Package Manager Detection\n```bash\n# Check which package manager is used\nif [ -f \"pnpm-lock.yaml\" ]; then\n # Use: pnpm install, pnpm test, pnpm dev\nelif [ -f \"package-lock.json\" ]; then\n # Use: npm install, npm test, npm run dev\nelif [ -f \"yarn.lock\" ]; then\n # Use: yarn install, yarn test, yarn dev\nfi\n```\n\n### Test Command Discovery\n```bash\n# Read package.json to find test command\ncat package.json | grep '\"test\"'\n# Or with jq:\njq -r '.scripts.test' package.json\n```\n\n### Dev Command Discovery\n```bash\n# Read package.json to find dev command\ncat package.json | grep '\"dev\"'\n# Or with jq:\njq -r '.scripts.dev' package.json\n```\n\n### Environment Variables\n```bash\n# Check for .env files to copy\nls -la | grep '.env'\n```\n\n### Build System\n```bash\n# Detect build system\nif [ -f \"vite.config.ts\" ]; then\n # Vite project\nelif [ -f \"next.config.js\" ]; then\n # Next.js project\nelif [ -f \"nuxt.config.ts\" ]; then\n # Nuxt project\nfi\n```\n\n## Common Mistakes to Avoid\n\n\u274C **Blocking operations**: `sleep 60` (blocks dmux)\n\u2705 **Background long tasks**: `slow_operation &`\n\n\u274C **Hardcoded paths**: `/Users/me/project`\n\u2705 **Use variables**: `\"$DMUX_ROOT\"`\n\n\u274C **Assuming tools exist**: `pnpm install`\n\u2705 **Check first**: `command -v pnpm && pnpm install`\n\n\u274C **No error handling**: Script fails silently\n\u2705 **Set error mode**: `set -e` or check exit codes\n\n\u274C **Forgetting executable bit**: Hook won't run\n\u2705 **Make executable**: `chmod +x`\n\n\u274C **Noisy output**: Clutters dmux logs\n\u2705 **Silent operations**: `curl -s`, `> /dev/null 2>&1`\n\n\u274C **Not testing**: Deploy and hope\n\u2705 **Test manually**: Run with mock env vars first\n\n## Debugging\n\nIf a hook isn't working:\n\n1. **Check if file exists**: `ls -la .dmux-hooks/`\n2. **Check permissions**: Should show `x` in `rwxr-xr-x`\n3. **Check syntax**: `bash -n .dmux-hooks/hook_name`\n4. **Test manually**: Set env vars and run\n5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix\n6. **Simplify**: Remove complex parts, test basic version\n7. **Check tool availability**: `command -v required_tool`\n\n### Debug Mode\n```bash\n#!/bin/bash\n# Add to top of hook for debugging\nset -x # Print each command before executing\nset -e # Exit on error\n\n# Your hook logic here\n```\n\n## Summary Checklist\n\nWhen creating a new hook:\n\n- [ ] Create file in `.dmux-hooks/`\n- [ ] Add shebang: `#!/bin/bash`\n- [ ] Make executable: `chmod +x`\n- [ ] Add `set -e` for error handling\n- [ ] Use environment variables (never hardcode paths)\n- [ ] Background long operations with `&`\n- [ ] Check for required tools before using\n- [ ] Test manually with mock env vars\n- [ ] Add comments explaining what it does\n- [ ] Commit to version control\n\n## Getting Help\n\n- **Full documentation**: See `HOOKS.md` in project root\n- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`\n- **Examples**: Check `.dmux-hooks/examples/` directory\n- **dmux API**: See `API.md` for REST endpoints\n\n---\n\n*This documentation was auto-generated from dmux source code.*\n*Version: 2026-02-17*\n";
6
6
  //# sourceMappingURL=generated-agents-doc.d.ts.map
@@ -425,6 +425,6 @@ When creating a new hook:
425
425
  ---
426
426
 
427
427
  *This documentation was auto-generated from dmux source code.*
428
- *Version: 2025-12-22*
428
+ *Version: 2026-02-17*
429
429
  `;
430
430
  //# sourceMappingURL=generated-agents-doc.js.map
@@ -1,17 +1,38 @@
1
+ /**
2
+ * Detects the main/master branch name for the repository (async version)
3
+ * Uses Promise.any for efficient fallback - first successful result wins
4
+ */
5
+ export declare function getMainBranchAsync(): Promise<string>;
1
6
  /**
2
7
  * Detects the main/master branch name for the repository
8
+ * @deprecated Use getMainBranchAsync for non-blocking operation
3
9
  */
4
10
  export declare function getMainBranch(): string;
11
+ /**
12
+ * Gets the current branch name (async version)
13
+ */
14
+ export declare function getCurrentBranchAsync(cwd?: string): Promise<string>;
5
15
  /**
6
16
  * Gets the current branch name
17
+ * @deprecated Use getCurrentBranchAsync for non-blocking operation
7
18
  */
8
19
  export declare function getCurrentBranch(cwd?: string): string;
20
+ /**
21
+ * Checks if there are uncommitted changes in the repository (async version)
22
+ */
23
+ export declare function hasUncommittedChangesAsync(cwd?: string): Promise<boolean>;
9
24
  /**
10
25
  * Checks if there are uncommitted changes in the repository
26
+ * @deprecated Use hasUncommittedChangesAsync for non-blocking operation
11
27
  */
12
28
  export declare function hasUncommittedChanges(cwd?: string): boolean;
29
+ /**
30
+ * Gets the list of conflicted files (async version)
31
+ */
32
+ export declare function getConflictedFilesAsync(cwd?: string): Promise<string[]>;
13
33
  /**
14
34
  * Gets the list of conflicted files
35
+ * @deprecated Use getConflictedFilesAsync for non-blocking operation
15
36
  */
16
37
  export declare function getConflictedFiles(cwd?: string): string[];
17
38
  /**
@@ -24,9 +45,15 @@ export interface OrphanedWorktree {
24
45
  branch: string;
25
46
  hasUncommittedChanges: boolean;
26
47
  }
48
+ /**
49
+ * Gets a list of orphaned worktrees (async version)
50
+ * Uses parallel operations for better performance with many worktrees
51
+ */
52
+ export declare function getOrphanedWorktreesAsync(projectRoot: string, activePaneSlugs: string[]): Promise<OrphanedWorktree[]>;
27
53
  /**
28
54
  * Gets a list of orphaned worktrees - worktrees that exist in .dmux/worktrees
29
55
  * but don't have an active pane tracking them
56
+ * @deprecated Use getOrphanedWorktreesAsync for non-blocking operation
30
57
  */
31
58
  export declare function getOrphanedWorktrees(projectRoot: string, activePaneSlugs: string[]): OrphanedWorktree[];
32
59
  //# sourceMappingURL=git.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA+CtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAW3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBzD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,gBAAgB,EAAE,CAwEpB"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAmC1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA+CtC;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMzE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAW3D;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAY7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBzD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAmE7B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,gBAAgB,EAAE,CAwEpB"}
package/dist/utils/git.js CHANGED
@@ -1,8 +1,51 @@
1
1
  import { execSync } from 'child_process';
2
2
  import * as fs from 'fs';
3
+ import * as fsPromises from 'fs/promises';
3
4
  import * as path from 'path';
5
+ import { execAsync, execAsyncRace } from './execAsync.js';
6
+ /**
7
+ * Detects the main/master branch name for the repository (async version)
8
+ * Uses Promise.any for efficient fallback - first successful result wins
9
+ */
10
+ export async function getMainBranchAsync() {
11
+ // Try the most reliable method first
12
+ try {
13
+ const originHead = await execAsync('git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null', { silent: true });
14
+ if (originHead) {
15
+ const match = originHead.match(/refs\/remotes\/origin\/(.+)/);
16
+ if (match) {
17
+ return match[1];
18
+ }
19
+ }
20
+ }
21
+ catch {
22
+ // Continue to fallbacks
23
+ }
24
+ // Race between checking main and master
25
+ try {
26
+ return await execAsyncRace([
27
+ 'git show-ref --verify --quiet refs/heads/main && echo main',
28
+ 'git show-ref --verify --quiet refs/heads/master && echo master',
29
+ ]);
30
+ }
31
+ catch {
32
+ // Neither exists, try current branch
33
+ }
34
+ try {
35
+ const branches = await execAsync('git branch --list', { silent: true });
36
+ const match = branches.match(/^\* (.+)$/m);
37
+ if (match) {
38
+ return match[1].trim();
39
+ }
40
+ }
41
+ catch {
42
+ // Failed to get any branch
43
+ }
44
+ return 'main'; // Default fallback
45
+ }
4
46
  /**
5
47
  * Detects the main/master branch name for the repository
48
+ * @deprecated Use getMainBranchAsync for non-blocking operation
6
49
  */
7
50
  export function getMainBranch() {
8
51
  try {
@@ -51,8 +94,20 @@ export function getMainBranch() {
51
94
  }
52
95
  return 'main'; // Default fallback
53
96
  }
97
+ /**
98
+ * Gets the current branch name (async version)
99
+ */
100
+ export async function getCurrentBranchAsync(cwd) {
101
+ try {
102
+ return await execAsync('git branch --show-current', { cwd, silent: true });
103
+ }
104
+ catch {
105
+ return 'main';
106
+ }
107
+ }
54
108
  /**
55
109
  * Gets the current branch name
110
+ * @deprecated Use getCurrentBranchAsync for non-blocking operation
56
111
  */
57
112
  export function getCurrentBranch(cwd) {
58
113
  try {
@@ -66,8 +121,21 @@ export function getCurrentBranch(cwd) {
66
121
  return 'main';
67
122
  }
68
123
  }
124
+ /**
125
+ * Checks if there are uncommitted changes in the repository (async version)
126
+ */
127
+ export async function hasUncommittedChangesAsync(cwd) {
128
+ try {
129
+ const status = await execAsync('git status --porcelain', { cwd, silent: true });
130
+ return status.trim().length > 0;
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
69
136
  /**
70
137
  * Checks if there are uncommitted changes in the repository
138
+ * @deprecated Use hasUncommittedChangesAsync for non-blocking operation
71
139
  */
72
140
  export function hasUncommittedChanges(cwd) {
73
141
  try {
@@ -82,8 +150,25 @@ export function hasUncommittedChanges(cwd) {
82
150
  return false;
83
151
  }
84
152
  }
153
+ /**
154
+ * Gets the list of conflicted files (async version)
155
+ */
156
+ export async function getConflictedFilesAsync(cwd) {
157
+ try {
158
+ const status = await execAsync('git status --porcelain', { cwd, silent: true });
159
+ return status
160
+ .split('\n')
161
+ .filter(line => line.startsWith('UU ') || line.startsWith('AA '))
162
+ .map(line => line.substring(3).trim())
163
+ .filter(Boolean);
164
+ }
165
+ catch {
166
+ return [];
167
+ }
168
+ }
85
169
  /**
86
170
  * Gets the list of conflicted files
171
+ * @deprecated Use getConflictedFilesAsync for non-blocking operation
87
172
  */
88
173
  export function getConflictedFiles(cwd) {
89
174
  try {
@@ -102,9 +187,74 @@ export function getConflictedFiles(cwd) {
102
187
  return [];
103
188
  }
104
189
  }
190
+ /**
191
+ * Gets a list of orphaned worktrees (async version)
192
+ * Uses parallel operations for better performance with many worktrees
193
+ */
194
+ export async function getOrphanedWorktreesAsync(projectRoot, activePaneSlugs) {
195
+ const worktreesDir = path.join(projectRoot, '.dmux', 'worktrees');
196
+ try {
197
+ await fsPromises.access(worktreesDir);
198
+ }
199
+ catch {
200
+ return [];
201
+ }
202
+ const orphaned = [];
203
+ try {
204
+ const entries = await fsPromises.readdir(worktreesDir, { withFileTypes: true });
205
+ // Process worktrees in parallel for better performance
206
+ const worktreePromises = entries
207
+ .filter(entry => entry.isDirectory() && !activePaneSlugs.includes(entry.name))
208
+ .map(async (entry) => {
209
+ const slug = entry.name;
210
+ const worktreePath = path.join(worktreesDir, slug);
211
+ const gitFile = path.join(worktreePath, '.git');
212
+ // Check if it's a valid git worktree
213
+ try {
214
+ await fsPromises.access(gitFile);
215
+ }
216
+ catch {
217
+ return null;
218
+ }
219
+ // Get last modified time
220
+ let lastModified = new Date(0);
221
+ try {
222
+ const [stats, gitStats] = await Promise.all([
223
+ fsPromises.stat(worktreePath),
224
+ fsPromises.stat(gitFile)
225
+ ]);
226
+ lastModified = stats.mtime > gitStats.mtime ? stats.mtime : gitStats.mtime;
227
+ }
228
+ catch {
229
+ // Use default date if stat fails
230
+ }
231
+ // Get branch name and check for changes in parallel
232
+ const [branch, hasChanges] = await Promise.all([
233
+ getCurrentBranchAsync(worktreePath).then(b => b || slug),
234
+ hasUncommittedChangesAsync(worktreePath)
235
+ ]);
236
+ return {
237
+ slug,
238
+ path: worktreePath,
239
+ lastModified,
240
+ branch,
241
+ hasUncommittedChanges: hasChanges,
242
+ };
243
+ });
244
+ const results = await Promise.all(worktreePromises);
245
+ orphaned.push(...results.filter((r) => r !== null));
246
+ // Sort by most recently modified first
247
+ orphaned.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
248
+ }
249
+ catch {
250
+ // Return empty array if directory read fails
251
+ }
252
+ return orphaned;
253
+ }
105
254
  /**
106
255
  * Gets a list of orphaned worktrees - worktrees that exist in .dmux/worktrees
107
256
  * but don't have an active pane tracking them
257
+ * @deprecated Use getOrphanedWorktreesAsync for non-blocking operation
108
258
  */
109
259
  export function getOrphanedWorktrees(projectRoot, activePaneSlugs) {
110
260
  const worktreesDir = path.join(projectRoot, '.dmux', 'worktrees');