tmuxes 0.1.9 → 0.1.11

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 (142) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +283 -296
  3. package/{server/bin → bin}/tmuxes.js +36 -36
  4. package/dist/agentHooks.js +91 -0
  5. package/dist/agentHooks.js.map +1 -0
  6. package/dist/agentOutput.js +30 -0
  7. package/dist/agentOutput.js.map +1 -0
  8. package/dist/agentState.js +45 -0
  9. package/dist/agentState.js.map +1 -0
  10. package/dist/config.js +32 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/exe.js +37 -0
  13. package/dist/exe.js.map +1 -0
  14. package/dist/exec.js +43 -0
  15. package/dist/exec.js.map +1 -0
  16. package/dist/files.js +308 -0
  17. package/dist/files.js.map +1 -0
  18. package/dist/foldersStore.js +103 -0
  19. package/dist/foldersStore.js.map +1 -0
  20. package/dist/index.js +117 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/logger.js +16 -0
  23. package/dist/logger.js.map +1 -0
  24. package/{server/src/monitor.ts → dist/monitor.js} +9 -10
  25. package/dist/monitor.js.map +1 -0
  26. package/dist/openBrowser.js +31 -0
  27. package/dist/openBrowser.js.map +1 -0
  28. package/{server/src/platform.ts → dist/platform.js} +5 -4
  29. package/dist/platform.js.map +1 -0
  30. package/dist/rest/router.js +198 -0
  31. package/dist/rest/router.js.map +1 -0
  32. package/dist/targetCommand.js +60 -0
  33. package/dist/targetCommand.js.map +1 -0
  34. package/dist/targets.js +131 -0
  35. package/dist/targets.js.map +1 -0
  36. package/dist/tmux/builder.js +174 -0
  37. package/dist/tmux/builder.js.map +1 -0
  38. package/dist/tmux/formats.js +61 -0
  39. package/dist/tmux/formats.js.map +1 -0
  40. package/dist/tmux/sessions.js +157 -0
  41. package/dist/tmux/sessions.js.map +1 -0
  42. package/dist/validate.js +65 -0
  43. package/dist/validate.js.map +1 -0
  44. package/dist/windowsSsh.js +209 -0
  45. package/dist/windowsSsh.js.map +1 -0
  46. package/dist/winshell/manager.js +267 -0
  47. package/dist/winshell/manager.js.map +1 -0
  48. package/dist/ws/protocol.js +4 -0
  49. package/dist/ws/protocol.js.map +1 -0
  50. package/dist/ws/sshState.js +35 -0
  51. package/dist/ws/sshState.js.map +1 -0
  52. package/dist/ws/terminalSession.js +204 -0
  53. package/dist/ws/terminalSession.js.map +1 -0
  54. package/dist/ws/wsServer.js +151 -0
  55. package/dist/ws/wsServer.js.map +1 -0
  56. package/dist/wsl.js +35 -0
  57. package/dist/wsl.js.map +1 -0
  58. package/package.json +61 -28
  59. package/public/assets/index-D_X5SnGx.css +1 -0
  60. package/public/assets/index-Dl69CPyt.js +44 -0
  61. package/{client → public}/index.html +13 -12
  62. package/.node-version +0 -1
  63. package/.nvmrc +0 -1
  64. package/.tmp-npm-cache/_cacache/content-v2/sha512/43/27/5e000b8b9c56a6ccc66f709485499f4304e2cb1982582ba571321c07b3ef56fcabd2c671898cc8003365a0485b6fd8e73e7b17b073cec0f7d1628c1a99df +0 -0
  65. package/.tmp-npm-cache/_cacache/content-v2/sha512/51/cf/4301295d74559ed494bae160d54d8741077f89faebb311882ac065019246951e7b53f3dcb913793c42b331e14c7070c4810c3cdc27a427d103a7db4614e0 +0 -0
  66. package/.tmp-npm-cache/_cacache/content-v2/sha512/c3/4d/d68a454a916e74c2617f586fbf770981b33811d667c2547eb0e9fc21938f4ee7e98f1ceee4bde8ad8815b5f6efe21b60eee798837d68f51a3340d7e5bb7a +0 -0
  67. package/.tmp-npm-cache/_cacache/content-v2/sha512/fe/40/2abfbefc96299e8bf714aa91d62607190ae299e102cf5933db2e2904640d65d25d67dbbb6fa2ddc92a17f00b9dbfdf2e37487f67d96ec36c64a285b59a7d +0 -0
  68. package/.tmp-npm-cache/_cacache/index-v5/27/fe/81a3de6ce7ae3d1e41a3421de20c5629998c4ee5d0ffe2037630f03b03b2 +0 -4
  69. package/.tmp-npm-cache/_cacache/index-v5/65/22/dd66711f62681fce09aabb2357a2907b4a0c778ac5227c4baf9603fd86e8 +0 -4
  70. package/.tmp-npm-cache/_update-notifier-last-checked +0 -0
  71. package/AGENTS.md +0 -15
  72. package/CLAUDE.md +0 -3
  73. package/README.en.md +0 -304
  74. package/SECURITY.md +0 -31
  75. package/client/package.json +0 -29
  76. package/client/src/App.tsx +0 -123
  77. package/client/src/activity.ts +0 -5
  78. package/client/src/api.ts +0 -130
  79. package/client/src/attention.tsx +0 -157
  80. package/client/src/components/FileExplorer.tsx +0 -156
  81. package/client/src/components/FileViewer.tsx +0 -194
  82. package/client/src/components/SessionRow.tsx +0 -108
  83. package/client/src/components/SessionTree.tsx +0 -197
  84. package/client/src/components/SettingsButton.tsx +0 -122
  85. package/client/src/components/Sidebar.tsx +0 -96
  86. package/client/src/components/StatusBanner.tsx +0 -31
  87. package/client/src/components/TargetGroup.tsx +0 -275
  88. package/client/src/components/TerminalPanel.tsx +0 -192
  89. package/client/src/folders.ts +0 -245
  90. package/client/src/hooks/useTerminal.ts +0 -67
  91. package/client/src/hooks/useTmuxSocket.ts +0 -65
  92. package/client/src/i18n.ts +0 -213
  93. package/client/src/main.tsx +0 -17
  94. package/client/src/settings.tsx +0 -87
  95. package/client/src/styles.css +0 -723
  96. package/client/src/types.ts +0 -93
  97. package/client/src/util.ts +0 -65
  98. package/client/tsconfig.json +0 -13
  99. package/client/vite.config.ts +0 -15
  100. package/fig/fig1.png +0 -0
  101. package/scripts/prepack.mjs +0 -35
  102. package/server/package.json +0 -61
  103. package/server/src/agentHooks.ts +0 -120
  104. package/server/src/agentOutput.ts +0 -36
  105. package/server/src/agentState.ts +0 -70
  106. package/server/src/config.ts +0 -31
  107. package/server/src/exe.ts +0 -34
  108. package/server/src/exec.ts +0 -61
  109. package/server/src/files.ts +0 -330
  110. package/server/src/foldersStore.ts +0 -114
  111. package/server/src/index.ts +0 -114
  112. package/server/src/logger.ts +0 -16
  113. package/server/src/openBrowser.ts +0 -28
  114. package/server/src/rest/router.ts +0 -290
  115. package/server/src/targetCommand.ts +0 -79
  116. package/server/src/targets.ts +0 -152
  117. package/server/src/tmux/builder.ts +0 -198
  118. package/server/src/tmux/formats.ts +0 -95
  119. package/server/src/tmux/sessions.ts +0 -204
  120. package/server/src/validate.ts +0 -79
  121. package/server/src/windowsSsh.ts +0 -239
  122. package/server/src/winshell/manager.ts +0 -296
  123. package/server/src/ws/protocol.ts +0 -15
  124. package/server/src/ws/sshState.ts +0 -36
  125. package/server/src/ws/terminalSession.ts +0 -207
  126. package/server/src/ws/wsServer.ts +0 -153
  127. package/server/src/wsl.ts +0 -38
  128. package/server/test/agentHooks.test.ts +0 -66
  129. package/server/test/agentOutput.test.ts +0 -26
  130. package/server/test/agentState.test.ts +0 -24
  131. package/server/test/builder.test.ts +0 -162
  132. package/server/test/files.test.ts +0 -81
  133. package/server/test/formats.test.ts +0 -123
  134. package/server/test/monitor.test.ts +0 -25
  135. package/server/test/validate.test.ts +0 -71
  136. package/server/test/wsl.test.ts +0 -18
  137. package/server/tsconfig.json +0 -9
  138. package/server/vitest.config.ts +0 -12
  139. package/start.cmd +0 -30
  140. package/start.command +0 -20
  141. package/start.sh +0 -20
  142. package/tsconfig.base.json +0 -19
@@ -1,37 +1,37 @@
1
1
  #!/usr/bin/env node
2
- // tmuxes — web UI to manage tmux sessions (local / SSH / WSL).
3
- // Parses a couple of flags, sets the env the server reads, then launches it.
4
-
5
- const args = process.argv.slice(2);
6
-
7
- if (args.includes('--help') || args.includes('-h')) {
8
- console.log(`tmuxes — one browser tab to run and supervise tmux sessions (local · SSH · WSL)
9
-
10
- Usage:
11
- tmuxes [options]
12
-
13
- Options:
14
- --port <n> Port to listen on (default 7420, env TMUXES_PORT)
15
- --no-open Do not open the browser
16
- -h, --help Show this help
17
-
18
- Binds to 127.0.0.1 only (no-auth local UI). Then open http://127.0.0.1:7420
19
- (opens automatically unless --no-open). Requires tmux on the host you connect to.`);
20
- process.exit(0);
21
- }
22
-
23
- function flag(name) {
24
- const i = args.indexOf(name);
25
- return i >= 0 ? args[i + 1] : undefined;
26
- }
27
-
28
- const port = flag('--port');
29
- if (port) process.env.TMUXES_PORT = port;
30
-
31
- // Open the browser by default (the "one-click run" experience), unless the
32
- // user opted out or already set TMUXES_OPEN.
33
- if (!args.includes('--no-open') && process.env.TMUXES_OPEN === undefined) {
34
- process.env.TMUXES_OPEN = '1';
35
- }
36
-
37
- await import('../dist/index.js');
2
+ // tmuxes — web UI to manage tmux sessions (local / SSH / WSL).
3
+ // Parses a couple of flags, sets the env the server reads, then launches it.
4
+
5
+ const args = process.argv.slice(2);
6
+
7
+ if (args.includes('--help') || args.includes('-h')) {
8
+ console.log(`tmuxes — one browser tab to run and supervise tmux sessions (local · SSH · WSL)
9
+
10
+ Usage:
11
+ tmuxes [options]
12
+
13
+ Options:
14
+ --port <n> Port to listen on (default 7420, env TMUXES_PORT)
15
+ --no-open Do not open the browser
16
+ -h, --help Show this help
17
+
18
+ Binds to 127.0.0.1 only (no-auth local UI). Then open http://127.0.0.1:7420
19
+ (opens automatically unless --no-open). Requires tmux on the host you connect to.`);
20
+ process.exit(0);
21
+ }
22
+
23
+ function flag(name) {
24
+ const i = args.indexOf(name);
25
+ return i >= 0 ? args[i + 1] : undefined;
26
+ }
27
+
28
+ const port = flag('--port');
29
+ if (port) process.env.TMUXES_PORT = port;
30
+
31
+ // Open the browser by default (the "one-click run" experience), unless the
32
+ // user opted out or already set TMUXES_OPEN.
33
+ if (!args.includes('--no-open') && process.env.TMUXES_OPEN === undefined) {
34
+ process.env.TMUXES_OPEN = '1';
35
+ }
36
+
37
+ await import('../dist/index.js');
@@ -0,0 +1,91 @@
1
+ import { agentHookCommand, } from './agentState.js';
2
+ function isDisabled() {
3
+ const v = process.env.TMUXES_NO_AUTOHOOK;
4
+ return v === '1' || v === 'true';
5
+ }
6
+ function baseName(token) {
7
+ return (token.split(/[\\/]/).pop() || '').toLowerCase().replace(/\.(exe|cmd|bat)$/, '');
8
+ }
9
+ export function detectAgentKind(command) {
10
+ if (isDisabled())
11
+ return undefined;
12
+ const trimmed = command.trim();
13
+ if (!trimmed)
14
+ return undefined;
15
+ const m = /^(\S+)(\s+[\s\S]*)?$/.exec(trimmed);
16
+ if (!m)
17
+ return undefined;
18
+ switch (baseName(m[1])) {
19
+ case 'claude':
20
+ return 'claude';
21
+ case 'codex':
22
+ return 'codex';
23
+ default:
24
+ return undefined;
25
+ }
26
+ }
27
+ function hook(kind, state, reason, event) {
28
+ return { type: 'command', command: agentHookCommand(kind, state, reason, event) };
29
+ }
30
+ function claudeSettings() {
31
+ return JSON.stringify({
32
+ hooks: {
33
+ UserPromptSubmit: [{ hooks: [hook('claude', 'running', '', 'UserPromptSubmit')] }],
34
+ PreToolUse: [{ matcher: '', hooks: [hook('claude', 'running', '', 'PreToolUse')] }],
35
+ PostToolUse: [{ matcher: '', hooks: [hook('claude', 'running', '', 'PostToolUse')] }],
36
+ PermissionRequest: [
37
+ { matcher: '', hooks: [hook('claude', 'waiting', 'decision', 'PermissionRequest')] },
38
+ ],
39
+ Notification: [
40
+ {
41
+ matcher: 'permission_prompt',
42
+ hooks: [hook('claude', 'waiting', 'decision', 'Notification.permission_prompt')],
43
+ },
44
+ {
45
+ matcher: 'elicitation_dialog',
46
+ hooks: [hook('claude', 'waiting', 'decision', 'Notification.elicitation_dialog')],
47
+ },
48
+ ],
49
+ Stop: [{ hooks: [hook('claude', 'idle', 'done', 'Stop')] }],
50
+ StopFailure: [{ hooks: [hook('claude', 'idle', 'error', 'StopFailure')] }],
51
+ SessionEnd: [{ hooks: [hook('claude', 'idle', 'done', 'SessionEnd')] }],
52
+ },
53
+ });
54
+ }
55
+ function tomlString(v) {
56
+ return `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
57
+ }
58
+ function codexHookConfig(event, cmd, opts = {}) {
59
+ const matcher = opts.matcher === undefined ? '' : `matcher=${tomlString(opts.matcher)},`;
60
+ return `hooks.${event}=[{${matcher}hooks=[{type="command",command=${tomlString(cmd)}}]}]`;
61
+ }
62
+ function codexConfigArgs() {
63
+ const configs = [
64
+ codexHookConfig('UserPromptSubmit', agentHookCommand('codex', 'running', '', 'UserPromptSubmit')),
65
+ codexHookConfig('PreToolUse', agentHookCommand('codex', 'running', '', 'PreToolUse'), {
66
+ matcher: '',
67
+ }),
68
+ codexHookConfig('PostToolUse', agentHookCommand('codex', 'running', '', 'PostToolUse'), {
69
+ matcher: '',
70
+ }),
71
+ codexHookConfig('PermissionRequest', agentHookCommand('codex', 'waiting', 'decision', 'PermissionRequest'), { matcher: '' }),
72
+ codexHookConfig('Stop', agentHookCommand('codex', 'idle', 'done', 'Stop')),
73
+ ];
74
+ return configs.map((c) => `-c '${c}'`).join(' ');
75
+ }
76
+ export function augmentAgentCommand(command) {
77
+ const kind = detectAgentKind(command);
78
+ if (!kind)
79
+ return { command };
80
+ const trimmed = command.trim();
81
+ const m = /^(\S+)(\s+[\s\S]*)?$/.exec(trimmed);
82
+ if (!m)
83
+ return { command };
84
+ const prog = m[1];
85
+ const rest = m[2] ?? '';
86
+ if (kind === 'claude') {
87
+ return { kind, command: `${prog} --settings '${claudeSettings()}'${rest}` };
88
+ }
89
+ return { kind, command: `${prog} ${codexConfigArgs()}${rest}` };
90
+ }
91
+ //# sourceMappingURL=agentHooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentHooks.js","sourceRoot":"","sources":["../src/agentHooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ const ERROR_PATTERNS = [
2
+ {
3
+ event: 'CodexStreamDisconnected',
4
+ kinds: ['codex'],
5
+ re: /stream disconnected before completion.*error sending request for url.*\/codex\/responses/i,
6
+ },
7
+ {
8
+ event: 'StreamDisconnected',
9
+ re: /stream disconnected before completion/i,
10
+ },
11
+ ];
12
+ function normalizeTerminalText(text) {
13
+ return text
14
+ .replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, '')
15
+ .replace(/\s+/g, ' ')
16
+ .trim();
17
+ }
18
+ export function classifyAgentTerminalError(text, kind) {
19
+ const normalized = normalizeTerminalText(text);
20
+ if (!normalized)
21
+ return undefined;
22
+ for (const pattern of ERROR_PATTERNS) {
23
+ if (pattern.kinds && !pattern.kinds.includes(kind))
24
+ continue;
25
+ if (pattern.re.test(normalized))
26
+ return pattern.event;
27
+ }
28
+ return undefined;
29
+ }
30
+ //# sourceMappingURL=agentOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentOutput.js","sourceRoot":"","sources":["../src/agentOutput.ts"],"names":[],"mappings":"AAQA,MAAM,cAAc,GAA2B;IAC7C;QACE,KAAK,EAAE,yBAAyB;QAChC,KAAK,EAAE,CAAC,OAAO,CAAC;QAChB,EAAE,EAAE,2FAA2F;KAChG;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,EAAE,EAAE,wCAAwC;KAC7C;CACF,CAAC;AAEF,SAAS,qBAAqB,CAAC,IAAY;IACzC,OAAO,IAAI;SACR,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;SACzC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAY,EAAE,IAAe;IACtE,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7D,IAAI,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC;IACxD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,45 @@
1
+ export const AGENT_OPTION = '@tmuxes_agent';
2
+ function isAgentKind(v) {
3
+ return v === 'claude' || v === 'codex';
4
+ }
5
+ function isAgentState(v) {
6
+ return v === 'running' || v === 'waiting' || v === 'idle';
7
+ }
8
+ function isAttentionReason(v) {
9
+ return v === 'decision' || v === 'done' || v === 'error';
10
+ }
11
+ function cleanToken(v) {
12
+ return v.replace(/[^A-Za-z0-9_.-]/g, '_');
13
+ }
14
+ export function agentValue(kind, state, reason, event, nonce) {
15
+ return [
16
+ kind,
17
+ state,
18
+ reason,
19
+ cleanToken(event),
20
+ nonce.replace(/:/g, '_'),
21
+ ].join(':');
22
+ }
23
+ export function agentInitialValue(kind) {
24
+ return agentValue(kind, 'idle', '', 'launch', String(Date.now()));
25
+ }
26
+ export function agentHookCommand(kind, state, reason, event) {
27
+ return `tmux set-option -q ${AGENT_OPTION} ${agentValue(kind, state, reason, event, '$(date +%s).$$')}`;
28
+ }
29
+ export function parseAgentValue(raw) {
30
+ if (!raw)
31
+ return undefined;
32
+ const [kind, state, reason, event, ...nonceParts] = raw.split(':');
33
+ if (!isAgentKind(kind) || !isAgentState(state))
34
+ return undefined;
35
+ const snap = { agentKind: kind, agentState: state };
36
+ if (isAttentionReason(reason))
37
+ snap.attentionReason = reason;
38
+ if (event)
39
+ snap.agentEvent = event;
40
+ const nonce = nonceParts.join(':');
41
+ if (nonce)
42
+ snap.agentNonce = nonce;
43
+ return snap;
44
+ }
45
+ //# sourceMappingURL=agentState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentState.js","sourceRoot":"","sources":["../src/agentState.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAE5C,SAAS,WAAW,CAAC,CAAS;IAC5B,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,OAAO,CAAC;AACzC,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,MAAM,CAAC;AAC5D,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAS;IAClC,OAAO,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,CAAC;AAC3D,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,IAAe,EACf,KAAiB,EACjB,MAA4B,EAC5B,KAAa,EACb,KAAa;IAEb,OAAO;QACL,IAAI;QACJ,KAAK;QACL,MAAM;QACN,UAAU,CAAC,KAAK,CAAC;QACjB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;KACzB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAe;IAC/C,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAe,EACf,KAAiB,EACjB,MAA4B,EAC5B,KAAa;IAEb,OAAO,sBAAsB,YAAY,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC;AAC1G,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAuB;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACjE,MAAM,IAAI,GAAkB,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACnE,IAAI,iBAAiB,CAAC,MAAM,CAAC;QAAE,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;IAC7D,IAAI,KAAK;QAAE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IACnC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK;QAAE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IACnC,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,32 @@
1
+ /** Central configuration. Localhost-only by design — see README/SECURITY. */
2
+ export const config = {
3
+ /** Bind address. Intentionally not configurable: this is a no-auth local shell UI. */
4
+ host: '127.0.0.1',
5
+ port: Number(process.env.TMUXES_PORT ?? 7420),
6
+ /** ssh timeouts (seconds). */
7
+ ssh: {
8
+ /** Management calls fail fast so the UI never hangs. */
9
+ connectTimeoutMgmt: 8,
10
+ /** Interactive attach is allowed a little longer. */
11
+ connectTimeoutTty: 10,
12
+ /** Keep the OpenSSH control master alive for long-lived SSH reuse. */
13
+ controlPersist: 'yes',
14
+ },
15
+ /**
16
+ * Allowed WebSocket Origins. The WS upgrade bypasses Express middleware, so
17
+ * we enforce this in the upgrade handler to block DNS-rebind / cross-site WS
18
+ * hijack. Empty/absent Origin (non-browser clients) is allowed.
19
+ */
20
+ isAllowedOrigin(origin) {
21
+ if (!origin)
22
+ return true;
23
+ try {
24
+ const { hostname } = new URL(origin);
25
+ return hostname === '127.0.0.1' || hostname === 'localhost' || hostname === '[::1]';
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ },
31
+ };
32
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,sFAAsF;IACtF,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC;IAE7C,8BAA8B;IAC9B,GAAG,EAAE;QACH,wDAAwD;QACxD,kBAAkB,EAAE,CAAC;QACrB,qDAAqD;QACrD,iBAAiB,EAAE,EAAE;QACrB,sEAAsE;QACtE,cAAc,EAAE,KAAK;KACtB;IAED;;;;OAIG;IACH,eAAe,CAAC,MAA0B;QACxC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;YACrC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,OAAO,CAAC;QACtF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACO,CAAC"}
package/dist/exe.js ADDED
@@ -0,0 +1,37 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { isAbsolute, join, delimiter } from 'node:path';
3
+ import { isWindows } from './platform.js';
4
+ /**
5
+ * Resolve a command name to a full path for node-pty on Windows.
6
+ *
7
+ * Unlike child_process.spawn, node-pty's ConPTY path does NOT search PATH or
8
+ * append a PATHEXT extension, so `pty.spawn('ssh', …)` fails with
9
+ * "File not found". We resolve the executable ourselves (PATH + common system
10
+ * locations). On POSIX, execvp already searches PATH, so the name is returned
11
+ * unchanged.
12
+ */
13
+ export function resolveExecutable(file) {
14
+ if (!isWindows)
15
+ return file;
16
+ if (isAbsolute(file) && existsSync(file))
17
+ return file;
18
+ const hasExt = /\.[A-Za-z0-9]+$/.test(file);
19
+ const exts = hasExt ? [''] : (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM').split(';');
20
+ const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\Windows';
21
+ const dirs = [
22
+ ...(process.env.PATH || '').split(delimiter),
23
+ join(sysRoot, 'System32'),
24
+ join(sysRoot, 'System32', 'OpenSSH'), // ssh.exe ships here, not always on PATH
25
+ ];
26
+ for (const dir of dirs) {
27
+ if (!dir)
28
+ continue;
29
+ for (const ext of exts) {
30
+ const candidate = join(dir, file + ext);
31
+ if (existsSync(candidate))
32
+ return candidate;
33
+ }
34
+ }
35
+ return file; // fall back; node-pty surfaces a clear error if truly missing
36
+ }
37
+ //# sourceMappingURL=exe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exe.js","sourceRoot":"","sources":["../src/exe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtD,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,qBAAqB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,aAAa,CAAC;IAC9E,MAAM,IAAI,GAAG;QACX,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,yCAAyC;KAChF,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;YACxC,IAAI,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,CAAC,8DAA8D;AAC7E,CAAC"}
package/dist/exec.js ADDED
@@ -0,0 +1,43 @@
1
+ import { spawn } from 'node:child_process';
2
+ /**
3
+ * Run a command as an argv array with NO shell. Never rejects — a nonzero exit
4
+ * or spawn error resolves with the captured output so callers can interpret it
5
+ * (e.g. tmux "no server running" is a normal empty case, not a throw).
6
+ */
7
+ export function runCommand(file, args, opts = {}) {
8
+ const encoding = opts.encoding ?? 'utf8';
9
+ return new Promise((resolve) => {
10
+ const child = spawn(file, args, { shell: false });
11
+ const outChunks = [];
12
+ const errChunks = [];
13
+ let settled = false;
14
+ const timer = opts.timeoutMs
15
+ ? setTimeout(() => {
16
+ child.kill('SIGKILL');
17
+ }, opts.timeoutMs)
18
+ : null;
19
+ child.stdout.on('data', (d) => outChunks.push(d));
20
+ child.stderr.on('data', (d) => errChunks.push(d));
21
+ if (opts.input !== undefined) {
22
+ child.stdin.on('error', () => {
23
+ /* ignore EPIPE if the child exits early */
24
+ });
25
+ child.stdin.end(opts.input);
26
+ }
27
+ const done = (code, signal, extraErr) => {
28
+ if (settled)
29
+ return;
30
+ settled = true;
31
+ if (timer)
32
+ clearTimeout(timer);
33
+ const stderr = Buffer.concat(errChunks).toString(encoding) + (extraErr ?? '');
34
+ resolve({ code, signal, stdout: Buffer.concat(outChunks).toString(encoding), stderr });
35
+ };
36
+ child.on('error', (err) => {
37
+ // e.g. ENOENT when ssh/tmux/wsl.exe is missing — surface as a failed result.
38
+ done(null, null, err.message);
39
+ });
40
+ child.on('close', (code, signal) => done(code, signal));
41
+ });
42
+ }
43
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAiB3C;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAc,EAAE,OAAmB,EAAE;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAClD,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS;YAC1B,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE;gBACd,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;YACpB,CAAC,CAAC,IAAI,CAAC;QAET,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC3B,2CAA2C;YAC7C,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,IAAmB,EAAE,MAA6B,EAAE,QAAiB,EAAE,EAAE;YACrF,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YAC9E,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzF,CAAC,CAAC;QAEF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,6EAA6E;YAC7E,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC"}