aiwcli 0.15.5 → 0.15.7
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.
- package/README.md +6 -3
- package/dist/capabilities/branch/adapters.d.ts +2 -0
- package/dist/capabilities/branch/adapters.js +21 -0
- package/dist/capabilities/branch/contracts.d.ts +57 -0
- package/dist/capabilities/branch/contracts.js +1 -0
- package/dist/capabilities/branch/control-plane.d.ts +2 -0
- package/dist/capabilities/branch/control-plane.js +343 -0
- package/dist/capabilities/branch/runtime-core.d.ts +5 -0
- package/dist/capabilities/branch/runtime-core.js +36 -0
- package/dist/capabilities/installation/control-plane/clean-command.d.ts +41 -0
- package/dist/capabilities/installation/control-plane/clean-command.js +196 -0
- package/dist/capabilities/installation/control-plane/clear-command.d.ts +160 -0
- package/dist/capabilities/installation/control-plane/clear-command.js +1220 -0
- package/dist/capabilities/installation/control-plane/init-command.d.ts +81 -0
- package/dist/capabilities/installation/control-plane/init-command.js +449 -0
- package/dist/capabilities/launch/contracts.d.ts +51 -0
- package/dist/capabilities/launch/contracts.js +1 -0
- package/dist/capabilities/launch/control-plane/execute-launch.d.ts +2 -0
- package/dist/capabilities/launch/control-plane/execute-launch.js +222 -0
- package/dist/capabilities/launch/runtime-core/launch-options.d.ts +14 -0
- package/dist/capabilities/launch/runtime-core/launch-options.js +69 -0
- package/dist/cli/base-command.d.ts +18 -0
- package/dist/cli/base-command.js +55 -0
- package/dist/commands/branch.d.ts +0 -20
- package/dist/commands/branch.js +24 -416
- package/dist/commands/clean.d.ts +1 -41
- package/dist/commands/clean.js +1 -196
- package/dist/commands/clear.d.ts +1 -161
- package/dist/commands/clear.js +1 -1121
- package/dist/commands/init/index.d.ts +1 -98
- package/dist/commands/init/index.js +4 -478
- package/dist/commands/launch.d.ts +36 -11
- package/dist/commands/launch.js +135 -159
- package/dist/lib/base-command.d.ts +1 -114
- package/dist/lib/base-command.js +1 -153
- package/dist/lib/claude-settings-types.d.ts +31 -19
- package/dist/lib/context/context-formatter.d.ts +74 -0
- package/dist/lib/context/context-formatter.js +493 -0
- package/dist/lib/context/context-selector.d.ts +42 -0
- package/dist/lib/context/context-selector.js +451 -0
- package/dist/lib/context/context-store.d.ts +100 -0
- package/dist/lib/context/context-store.js +618 -0
- package/dist/lib/context/plan-manager.d.ts +54 -0
- package/dist/lib/context/plan-manager.js +282 -0
- package/dist/lib/context/task-tracker.d.ts +44 -0
- package/dist/lib/context/task-tracker.js +146 -0
- package/dist/lib/core-ide-base.d.ts +4 -0
- package/dist/lib/core-ide-base.js +77 -0
- package/dist/lib/core-installer.d.ts +5 -0
- package/dist/lib/core-installer.js +54 -0
- package/dist/lib/git-exclude-manager.d.ts +2 -2
- package/dist/lib/git-exclude-manager.js +3 -3
- package/dist/lib/hooks/hook-utils.d.ts +143 -0
- package/dist/lib/hooks/hook-utils.js +609 -0
- package/dist/lib/hooks/session-end-logic.d.ts +5 -0
- package/dist/lib/hooks/session-end-logic.js +63 -0
- package/dist/lib/hooks-merger.js +25 -19
- package/dist/lib/ide-path-resolver.d.ts +19 -7
- package/dist/lib/ide-path-resolver.js +25 -9
- package/dist/lib/install-state.d.ts +34 -0
- package/dist/lib/install-state.js +161 -0
- package/dist/lib/launch-options.d.ts +1 -0
- package/dist/lib/launch-options.js +1 -0
- package/dist/lib/lsp-patch.d.ts +12 -0
- package/dist/lib/lsp-patch.js +156 -0
- package/dist/lib/multiplexer.d.ts +57 -0
- package/dist/lib/multiplexer.js +19 -0
- package/dist/lib/multiplexers/psmux.d.ts +75 -0
- package/dist/lib/multiplexers/psmux.js +384 -0
- package/dist/lib/multiplexers/tmux.d.ts +44 -0
- package/dist/lib/multiplexers/tmux.js +262 -0
- package/dist/lib/mux-utils.d.ts +5 -0
- package/dist/lib/mux-utils.js +42 -0
- package/dist/lib/paths.d.ts +2 -2
- package/dist/lib/paths.js +2 -2
- package/dist/lib/platform-commands.d.ts +27 -0
- package/dist/lib/platform-commands.js +49 -0
- package/dist/lib/runtime/aiw-cli.d.ts +37 -0
- package/dist/lib/runtime/aiw-cli.js +74 -0
- package/dist/lib/runtime/atomic-write.d.ts +19 -0
- package/dist/lib/runtime/atomic-write.js +121 -0
- package/dist/lib/runtime/cli-args.d.ts +55 -0
- package/dist/lib/runtime/cli-args.js +185 -0
- package/dist/lib/runtime/constants.d.ts +56 -0
- package/dist/lib/runtime/constants.js +230 -0
- package/dist/lib/runtime/executable-policy.d.ts +16 -0
- package/dist/lib/runtime/executable-policy.js +57 -0
- package/dist/lib/runtime/git-state.d.ts +9 -0
- package/dist/lib/runtime/git-state.js +59 -0
- package/dist/lib/runtime/inference.d.ts +37 -0
- package/dist/lib/runtime/inference.js +262 -0
- package/dist/lib/runtime/lint-dispatch.d.ts +40 -0
- package/dist/lib/runtime/lint-dispatch.js +285 -0
- package/dist/lib/runtime/logger.d.ts +66 -0
- package/dist/lib/runtime/logger.js +201 -0
- package/dist/lib/runtime/models.d.ts +14 -0
- package/dist/lib/runtime/models.js +14 -0
- package/dist/lib/runtime/platform-adapter.d.ts +7 -0
- package/dist/lib/runtime/platform-adapter.js +21 -0
- package/dist/lib/runtime/preflight.d.ts +24 -0
- package/dist/lib/runtime/preflight.js +65 -0
- package/dist/lib/runtime/sentinel-ipc.d.ts +14 -0
- package/dist/lib/runtime/sentinel-ipc.js +67 -0
- package/dist/lib/runtime/state-io.d.ts +30 -0
- package/dist/lib/runtime/state-io.js +174 -0
- package/dist/lib/runtime/stop-words.d.ts +20 -0
- package/dist/lib/runtime/stop-words.js +150 -0
- package/dist/lib/runtime/subprocess-utils.d.ts +29 -0
- package/dist/lib/runtime/subprocess-utils.js +96 -0
- package/dist/lib/runtime/tmux-preflight.d.ts +13 -0
- package/dist/lib/runtime/tmux-preflight.js +78 -0
- package/dist/lib/runtime/utils.d.ts +54 -0
- package/dist/lib/runtime/utils.js +162 -0
- package/dist/lib/sentinel-wrapper.d.ts +9 -0
- package/dist/lib/sentinel-wrapper.js +20 -0
- package/dist/lib/shell-quoting.d.ts +5 -0
- package/dist/lib/shell-quoting.js +17 -0
- package/dist/lib/spawn-errors.d.ts +6 -0
- package/dist/lib/spawn-errors.js +15 -0
- package/dist/lib/spawn.js +5 -11
- package/dist/lib/template-installer.d.ts +4 -5
- package/dist/lib/template-installer.js +36 -34
- package/dist/lib/template-resolver.d.ts +6 -7
- package/dist/lib/template-resolver.js +26 -21
- package/dist/lib/template-settings-reconstructor.d.ts +7 -2
- package/dist/lib/template-settings-reconstructor.js +76 -45
- package/dist/lib/terminal-strategy.d.ts +11 -0
- package/dist/lib/terminal-strategy.js +49 -0
- package/dist/lib/terminal.d.ts +28 -0
- package/dist/lib/terminal.js +162 -112
- package/dist/lib/tmux-pane-placement.d.ts +17 -0
- package/dist/lib/tmux-pane-placement.js +58 -0
- package/dist/lib/tmux-primitives.d.ts +5 -0
- package/dist/lib/tmux-primitives.js +15 -0
- package/dist/lib/tmux-session.d.ts +32 -0
- package/dist/lib/tmux-session.js +86 -0
- package/dist/lib/tty-detection.js +1 -1
- package/dist/lib/types.d.ts +168 -0
- package/dist/lib/types.js +6 -0
- package/dist/lib/version.d.ts +1 -1
- package/dist/lib/version.js +1 -1
- package/dist/platform/launch.d.ts +10 -0
- package/dist/platform/launch.js +10 -0
- package/dist/templates/CLAUDE.md +31 -40
- package/dist/templates/cc-native/.claude/settings.json +27 -27
- package/dist/templates/cc-native/CC-NATIVE-README.md +1 -1
- package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +10 -9
- package/dist/templates/cc-native/_cc-native/CLAUDE.md +18 -18
- package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +3 -3
- package/dist/templates/cc-native/_cc-native/artifacts/lib/format.ts +14 -14
- package/dist/templates/cc-native/_cc-native/artifacts/lib/tracker.ts +1 -1
- package/dist/templates/cc-native/_cc-native/artifacts/lib/write.ts +3 -3
- package/dist/templates/cc-native/_cc-native/cc-native.config.json +3 -3
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +16 -15
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +3 -3
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +2 -2
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +2 -2
- package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +3 -3
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +2 -2
- package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +3 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +8 -8
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +4 -4
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +2 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +2 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +8 -8
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +3 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +2 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +3 -3
- package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +3 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/agent-selection.test.ts +345 -0
- package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/preflight.test.ts +344 -0
- package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +37 -15
- package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +16 -69
- package/dist/templates/cc-native/_cc-native/plan-review/lib/orchestrator.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/output-builder.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/plan-questions.ts +2 -2
- package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +56 -26
- package/dist/templates/cc-native/_cc-native/plan-review/lib/review-pipeline.ts +7 -7
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/agent.ts +4 -4
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +3 -3
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/index.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/claude-agent.ts +2 -2
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts +4 -4
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/gemini-agent.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/orchestrator-claude-agent.ts +5 -6
- package/dist/templates/core/.codex/workflows/codex.md +17 -0
- package/dist/templates/core/.codex/workflows/handoff.md +5 -0
- package/dist/templates/core/.codex/workflows/meta-plan.md +7 -0
- package/dist/templates/core/.cognition/AGENTS.md +5 -0
- package/dist/templates/core/.cognition/config.json +12 -0
- package/dist/templates/{_shared → core}/.windsurf/workflows/handoff.md +1 -1
- package/dist/templates/{_shared → core}/.windsurf/workflows/meta-plan.md +1 -1
- package/dist/templates/core/hooks-ts/_utils/git-state.ts +2 -0
- package/dist/templates/{_shared → core}/hooks-ts/archive_plan.ts +14 -23
- package/dist/templates/core/hooks-ts/codex_explorer.ts +160 -0
- package/dist/templates/{_shared → core}/hooks-ts/context_monitor.ts +23 -55
- package/dist/templates/{_shared → core}/hooks-ts/file-suggestion.ts +4 -3
- package/dist/templates/{_shared → core}/hooks-ts/lint_after_edit.ts +7 -9
- package/dist/templates/{_shared → core}/hooks-ts/pre_compact.ts +5 -5
- package/dist/templates/{_shared → core}/hooks-ts/session_end.ts +38 -78
- package/dist/templates/{_shared → core}/hooks-ts/session_start.ts +5 -5
- package/dist/templates/core/hooks-ts/task_create_capture.ts +32 -0
- package/dist/templates/{_shared → core}/hooks-ts/task_update_capture.ts +9 -24
- package/dist/templates/core/hooks-ts/user_prompt_submit.ts +46 -0
- package/dist/templates/{_shared → core}/lib-ts/CLAUDE.md +27 -16
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/headless.ts +3 -2
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/tmux.ts +44 -15
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/base-agent.ts +6 -4
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/execution-backend.ts +1 -1
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/index.ts +2 -2
- package/dist/templates/{_shared → core}/lib-ts/agent-exec/structured-output.ts +4 -5
- package/dist/templates/{_shared → core}/lib-ts/context/CLAUDE.md +9 -6
- package/dist/templates/{_shared → core}/lib-ts/context/context-formatter.ts +16 -21
- package/dist/templates/{_shared → core}/lib-ts/context/context-selector.ts +8 -6
- package/dist/templates/{_shared → core}/lib-ts/context/context-store.ts +32 -20
- package/dist/templates/{_shared → core}/lib-ts/context/plan-manager.ts +19 -15
- package/dist/templates/{_shared → core}/lib-ts/context/task-tracker.ts +3 -3
- package/dist/templates/core/lib-ts/hooks/context-monitor-logic.ts +32 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/hooks}/hook-utils.ts +168 -41
- package/dist/templates/core/lib-ts/hooks/prompt-binding-logic.ts +80 -0
- package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +93 -0
- package/dist/templates/core/lib-ts/package.json +19 -0
- package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +295 -0
- package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +106 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/atomic-write.ts +12 -7
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/cli-args.ts +8 -6
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/constants.ts +326 -324
- package/dist/templates/core/lib-ts/runtime/executable-policy.ts +89 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/git-state.ts +6 -4
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/inference.ts +59 -10
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/lint-dispatch.ts +25 -23
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/logger.ts +32 -29
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/models.ts +2 -2
- package/dist/templates/core/lib-ts/runtime/platform-adapter.ts +33 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/preflight.ts +4 -3
- package/dist/templates/core/lib-ts/runtime/sentinel-ipc.ts +91 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/state-io.ts +11 -7
- package/dist/templates/core/lib-ts/runtime/stop-words.ts +185 -0
- package/dist/templates/core/lib-ts/runtime/subprocess-utils.ts +147 -0
- package/dist/templates/core/lib-ts/runtime/tmux-preflight.ts +93 -0
- package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/utils.ts +4 -3
- package/dist/templates/{_shared → core}/lib-ts/templates/formatters.ts +7 -5
- package/dist/templates/{_shared → core}/lib-ts/templates/plan-context.ts +2 -1
- package/dist/templates/{_shared → core}/lib-ts/tsconfig.json +3 -1
- package/dist/templates/{_shared → core}/lib-ts/types.ts +78 -77
- package/dist/templates/core/scripts/resolve-run.ts +61 -0
- package/dist/templates/{_shared → core}/scripts/resolve_context.ts +3 -3
- package/dist/templates/{_shared → core}/scripts/status_line.ts +25 -20
- package/dist/templates/core/skills/codex/CLAUDE.md +78 -0
- package/dist/templates/{_shared → core}/skills/codex/SKILL.md +21 -18
- package/dist/templates/{_shared → core}/skills/codex/lib/codex-watcher.ts +76 -103
- package/dist/templates/{_shared → core}/skills/codex/scripts/launch-codex.ts +119 -133
- package/dist/templates/{_shared → core}/skills/codex/scripts/watch-codex.ts +6 -4
- package/dist/templates/core/skills/devin/CLAUDE.md +65 -0
- package/dist/templates/core/skills/devin/SKILL.md +73 -0
- package/dist/templates/core/skills/devin/lib/devin-watcher.ts +280 -0
- package/dist/templates/core/skills/devin/scripts/launch-devin.ts +257 -0
- package/dist/templates/{_shared → core}/skills/handoff-system/CLAUDE.md +436 -433
- package/dist/templates/{_shared → core}/skills/handoff-system/lib/document-generator.ts +9 -7
- package/dist/templates/{_shared → core}/skills/handoff-system/lib/handoff-reader.ts +6 -4
- package/dist/templates/{_shared → core}/skills/handoff-system/scripts/resume_handoff.ts +10 -8
- package/dist/templates/{_shared → core}/skills/handoff-system/scripts/save_handoff.ts +12 -10
- package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff-resume.md +2 -2
- package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff.md +6 -5
- package/dist/templates/{_shared → core}/skills/meta-plan/CLAUDE.md +2 -1
- package/dist/templates/{_shared → core}/skills/meta-plan/workflows/meta-plan.md +8 -7
- package/oclif.manifest.json +89 -13
- package/package.json +13 -12
- package/dist/templates/_shared/.claude/settings.json +0 -120
- package/dist/templates/_shared/.claude/skills/codex/SKILL.md +0 -35
- package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +0 -13
- package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +0 -13
- package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +0 -43
- package/dist/templates/_shared/.codex/workflows/codex.md +0 -11
- package/dist/templates/_shared/.codex/workflows/handoff.md +0 -226
- package/dist/templates/_shared/.codex/workflows/meta-plan.md +0 -347
- package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +0 -2
- package/dist/templates/_shared/hooks-ts/task_create_capture.ts +0 -48
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +0 -93
- package/dist/templates/_shared/lib-ts/base/launchers/tmux-launcher.ts +0 -173
- package/dist/templates/_shared/lib-ts/base/launchers/window-launcher.ts +0 -93
- package/dist/templates/_shared/lib-ts/base/launchers/wt-launcher.ts +0 -64
- package/dist/templates/_shared/lib-ts/base/pane-launcher.ts +0 -55
- package/dist/templates/_shared/lib-ts/base/sentinel-ipc.ts +0 -87
- package/dist/templates/_shared/lib-ts/base/stop-words.ts +0 -184
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +0 -249
- package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +0 -341
- package/dist/templates/_shared/lib-ts/base/tmux-pane-placement.ts +0 -78
- package/dist/templates/_shared/lib-ts/package.json +0 -20
- package/dist/templates/_shared/scripts/resolve-run.ts +0 -62
- package/dist/templates/_shared/skills/codex/CLAUDE.md +0 -70
- /package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/index.ts +0 -0
package/dist/lib/terminal.js
CHANGED
|
@@ -27,38 +27,68 @@
|
|
|
27
27
|
*
|
|
28
28
|
* @module lib/terminal
|
|
29
29
|
*/
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
30
|
+
import { spawn } from 'node:child_process';
|
|
31
|
+
import { existsSync } from 'node:fs';
|
|
32
|
+
import path from 'node:path';
|
|
33
|
+
import { cleanClaudeEnv } from './mux-utils.js';
|
|
34
|
+
import { isCommandAvailable } from './runtime/executable-policy.js';
|
|
35
|
+
import { isWindowsPlatform } from './runtime/platform-adapter.js';
|
|
36
|
+
import { findMsysBash } from './runtime/tmux-preflight.js';
|
|
37
|
+
import { escapeSingleQuotedPath } from './shell-quoting.js';
|
|
38
|
+
import { detectPowerShell, findAvailableLinuxTerminal, isWSL, resolveWindowsTerminalStrategy, } from './terminal-strategy.js';
|
|
39
|
+
/** @internal */
|
|
40
|
+
export function resolveTerminalPlatform(platform, isWSLResult) {
|
|
41
|
+
if (isWindowsPlatform(platform))
|
|
42
|
+
return 'windows';
|
|
43
|
+
if (platform === 'darwin')
|
|
44
|
+
return 'darwin';
|
|
45
|
+
if (isWSLResult)
|
|
46
|
+
return 'wsl';
|
|
47
|
+
return 'linux';
|
|
47
48
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
/** @internal */
|
|
50
|
+
export function buildMacTerminalSpawnArgs(cwd, command) {
|
|
51
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'bash');
|
|
52
|
+
const fullCommand = `cd '${escapedPath}' && ${command}`;
|
|
53
|
+
const escapedCommand = fullCommand.replaceAll('\\', '\\\\').replaceAll('"', String.raw `\"`);
|
|
54
|
+
return {
|
|
55
|
+
command: 'osascript',
|
|
56
|
+
args: ['-e', `tell application "Terminal" to do script "${escapedCommand}"`],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** @internal */
|
|
60
|
+
export function buildWindowsTerminalSpawnArgs(cwd, command, powershellCmd) {
|
|
61
|
+
return {
|
|
62
|
+
command: 'wt',
|
|
63
|
+
args: ['-d', cwd, powershellCmd, '-NoExit', '-Command', command],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** @internal */
|
|
67
|
+
export function buildPowerShellFallbackSpawnArgs(cwd, command, powershellCmd) {
|
|
68
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'powershell');
|
|
69
|
+
const psCommand = `Start-Process ${powershellCmd} -ArgumentList '-NoExit','-Command',"cd '${escapedPath}'; ${command}"`;
|
|
70
|
+
return {
|
|
71
|
+
command: powershellCmd,
|
|
72
|
+
args: ['-Command', psCommand],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** @internal */
|
|
76
|
+
export function buildLinuxTerminalSpawnArgs(cwd, command, terminalInfo) {
|
|
77
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'bash');
|
|
78
|
+
const fullCommand = `cd '${escapedPath}' && ${command}`;
|
|
79
|
+
return {
|
|
80
|
+
command: terminalInfo.cmd,
|
|
81
|
+
args: terminalInfo.getArgs(fullCommand),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** @internal */
|
|
85
|
+
export function buildWSLTerminalSpawnArgs(cwd, command) {
|
|
86
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'bash');
|
|
87
|
+
const bashCmd = `cd '${escapedPath}' && ${command}; exec bash`;
|
|
88
|
+
return {
|
|
89
|
+
command: 'wt.exe',
|
|
90
|
+
args: ['wsl.exe', '--', 'bash', '-c', bashCmd],
|
|
91
|
+
};
|
|
62
92
|
}
|
|
63
93
|
/**
|
|
64
94
|
* Launch PowerShell fallback when Windows Terminal is not available.
|
|
@@ -70,13 +100,12 @@ function detectPowerShell() {
|
|
|
70
100
|
*/
|
|
71
101
|
async function launchPowerShellFallback(cwd, command, powershellCmd, debugLog) {
|
|
72
102
|
return new Promise((resolve) => {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const terminal = spawn(powershellCmd, ['-Command', psCommand], {
|
|
103
|
+
const spawnArgs = buildPowerShellFallbackSpawnArgs(cwd, command, powershellCmd);
|
|
104
|
+
debugLog?.(`Launching PowerShell fallback with command: ${spawnArgs.args[1]}`);
|
|
105
|
+
const terminal = spawn(spawnArgs.command, spawnArgs.args, {
|
|
77
106
|
detached: true,
|
|
78
107
|
stdio: 'ignore',
|
|
79
|
-
env:
|
|
108
|
+
env: cleanClaudeEnv(),
|
|
80
109
|
});
|
|
81
110
|
terminal.on('error', (err) => {
|
|
82
111
|
resolve({ success: false, error: `Failed to launch PowerShell: ${err.message}` });
|
|
@@ -90,32 +119,91 @@ async function launchPowerShellFallback(cwd, command, powershellCmd, debugLog) {
|
|
|
90
119
|
*
|
|
91
120
|
* @param cwd - Working directory
|
|
92
121
|
* @param command - Command to execute
|
|
122
|
+
* @param shellPreference - Preferred shell for Windows launches
|
|
93
123
|
* @param debugLog - Optional debug logging function
|
|
94
124
|
*/
|
|
95
|
-
async function launchWindowsTerminal(cwd, command, debugLog) {
|
|
96
|
-
const powershellCmd = detectPowerShell();
|
|
97
|
-
debugLog?.(`Detected PowerShell: ${powershellCmd}`);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
async function launchWindowsTerminal(cwd, command, shellPreference, debugLog) {
|
|
126
|
+
const powershellCmd = detectPowerShell(isCommandAvailable);
|
|
127
|
+
debugLog?.(`Detected PowerShell: ${powershellCmd}; shell preference: ${shellPreference}`);
|
|
128
|
+
const gitBashPath = findMsysBash();
|
|
129
|
+
const minttyPath = gitBashPath
|
|
130
|
+
? path.join(path.dirname(gitBashPath), 'mintty.exe')
|
|
131
|
+
: null;
|
|
132
|
+
const hasMintty = Boolean(minttyPath && existsSync(minttyPath));
|
|
133
|
+
const strategyOrder = resolveWindowsTerminalStrategy(shellPreference, gitBashPath, hasMintty, powershellCmd);
|
|
134
|
+
const tryStrategy = async (strategy) => {
|
|
135
|
+
if (strategy === 'powershell-fallback') {
|
|
136
|
+
debugLog?.('Using PowerShell fallback launcher');
|
|
137
|
+
return launchPowerShellFallback(cwd, command, powershellCmd, debugLog);
|
|
138
|
+
}
|
|
139
|
+
if (strategy === 'mintty') {
|
|
140
|
+
if (!minttyPath || !gitBashPath) {
|
|
141
|
+
return { success: false, error: 'mintty or Git Bash not found' };
|
|
111
142
|
}
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'bash');
|
|
144
|
+
const bashCmd = `cd '${escapedPath}' && ${command}; exec bash`;
|
|
145
|
+
debugLog?.(`Using mintty for Windows terminal: ${minttyPath}`);
|
|
146
|
+
return new Promise((resolve) => {
|
|
147
|
+
const terminal = spawn(minttyPath, [gitBashPath, '-lc', bashCmd], {
|
|
148
|
+
detached: true,
|
|
149
|
+
stdio: 'ignore',
|
|
150
|
+
env: cleanClaudeEnv(),
|
|
151
|
+
windowsHide: true,
|
|
152
|
+
});
|
|
153
|
+
terminal.on('error', (err) => {
|
|
154
|
+
resolve({ success: false, error: `mintty launch failed: ${err.message}` });
|
|
155
|
+
});
|
|
156
|
+
terminal.unref();
|
|
157
|
+
resolve({ success: true });
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (strategy === 'git-bash-in-wt') {
|
|
161
|
+
if (!gitBashPath) {
|
|
162
|
+
return { success: false, error: 'Git Bash not found' };
|
|
114
163
|
}
|
|
164
|
+
const escapedPath = escapeSingleQuotedPath(cwd, 'bash');
|
|
165
|
+
const bashCmd = `cd '${escapedPath}' && ${command}; exec bash`;
|
|
166
|
+
debugLog?.(`Using Git Bash for Windows terminal: ${gitBashPath}`);
|
|
167
|
+
return new Promise((resolve) => {
|
|
168
|
+
const terminal = spawn('wt', ['-d', cwd, gitBashPath, '-lc', bashCmd], {
|
|
169
|
+
detached: true,
|
|
170
|
+
stdio: 'ignore',
|
|
171
|
+
env: cleanClaudeEnv(),
|
|
172
|
+
});
|
|
173
|
+
terminal.on('error', (err) => {
|
|
174
|
+
resolve({ success: false, error: `Git Bash launch via wt failed: ${err.message}` });
|
|
175
|
+
});
|
|
176
|
+
terminal.unref();
|
|
177
|
+
resolve({ success: true });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
debugLog?.('Using Windows Terminal with PowerShell');
|
|
181
|
+
return new Promise((resolve) => {
|
|
182
|
+
const spawnArgs = buildWindowsTerminalSpawnArgs(cwd, command, powershellCmd);
|
|
183
|
+
const terminal = spawn(spawnArgs.command, spawnArgs.args, {
|
|
184
|
+
detached: true,
|
|
185
|
+
stdio: 'ignore',
|
|
186
|
+
env: cleanClaudeEnv(),
|
|
187
|
+
});
|
|
188
|
+
terminal.on('error', (err) => {
|
|
189
|
+
resolve({ success: false, error: `Failed to launch terminal: ${err.message}` });
|
|
190
|
+
});
|
|
191
|
+
terminal.unref();
|
|
192
|
+
resolve({ success: true });
|
|
115
193
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
194
|
+
};
|
|
195
|
+
const tryStrategies = async (index = 0) => {
|
|
196
|
+
const strategy = strategyOrder[index];
|
|
197
|
+
if (!strategy) {
|
|
198
|
+
return { success: false, error: 'Failed to launch Windows terminal with all available strategies' };
|
|
199
|
+
}
|
|
200
|
+
const result = await tryStrategy(strategy);
|
|
201
|
+
if (result.success)
|
|
202
|
+
return result;
|
|
203
|
+
debugLog?.(`Strategy ${strategy} failed: ${result.error}`);
|
|
204
|
+
return tryStrategies(index + 1);
|
|
205
|
+
};
|
|
206
|
+
return tryStrategies();
|
|
119
207
|
}
|
|
120
208
|
/**
|
|
121
209
|
* Launch macOS Terminal.app with command.
|
|
@@ -126,16 +214,12 @@ async function launchWindowsTerminal(cwd, command, debugLog) {
|
|
|
126
214
|
*/
|
|
127
215
|
async function launchMacTerminal(cwd, command, debugLog) {
|
|
128
216
|
return new Promise((resolve) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
// Escape double quotes and backslashes for AppleScript context
|
|
133
|
-
const escapedCommand = fullCommand.replaceAll('\\', '\\\\').replaceAll('"', String.raw `\"`);
|
|
134
|
-
debugLog?.(`Launching macOS Terminal with command: ${fullCommand}`);
|
|
135
|
-
const terminal = spawn('osascript', ['-e', `tell application "Terminal" to do script "${escapedCommand}"`], {
|
|
217
|
+
const spawnArgs = buildMacTerminalSpawnArgs(cwd, command);
|
|
218
|
+
debugLog?.(`Launching macOS Terminal with command: cd '${escapeSingleQuotedPath(cwd, 'bash')}' && ${command}`);
|
|
219
|
+
const terminal = spawn(spawnArgs.command, spawnArgs.args, {
|
|
136
220
|
detached: true,
|
|
137
221
|
stdio: 'ignore',
|
|
138
|
-
env:
|
|
222
|
+
env: cleanClaudeEnv(),
|
|
139
223
|
});
|
|
140
224
|
terminal.on('error', (err) => {
|
|
141
225
|
resolve({ success: false, error: `Failed to launch Terminal.app: ${err.message}` });
|
|
@@ -144,56 +228,24 @@ async function launchMacTerminal(cwd, command, debugLog) {
|
|
|
144
228
|
resolve({ success: true });
|
|
145
229
|
});
|
|
146
230
|
}
|
|
147
|
-
/**
|
|
148
|
-
* Linux terminal emulator configurations.
|
|
149
|
-
*/
|
|
150
|
-
const LINUX_TERMINALS = [
|
|
151
|
-
{ cmd: 'gnome-terminal', getArgs: (command) => ['--', 'bash', '-c', `${command}; exec bash`] },
|
|
152
|
-
{ cmd: 'konsole', getArgs: (command) => ['-e', `bash -c "${command}; exec bash"`] },
|
|
153
|
-
{ cmd: 'xterm', getArgs: (command) => ['-e', `bash -c "${command}; exec bash"`] },
|
|
154
|
-
{ cmd: 'x-terminal-emulator', getArgs: (command) => ['-e', `bash -c "${command}; exec bash"`] },
|
|
155
|
-
];
|
|
156
|
-
/**
|
|
157
|
-
* Find the first available Linux terminal emulator.
|
|
158
|
-
* Checks gnome-terminal, konsole, xterm, x-terminal-emulator in order.
|
|
159
|
-
*
|
|
160
|
-
* @returns Terminal configuration if found, null otherwise
|
|
161
|
-
*/
|
|
162
|
-
function findAvailableLinuxTerminal() {
|
|
163
|
-
for (const terminal of LINUX_TERMINALS) {
|
|
164
|
-
try {
|
|
165
|
-
execSync(`which ${terminal.cmd}`, { stdio: 'ignore' });
|
|
166
|
-
return terminal;
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
// Terminal not found, try next
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
function isWSL() {
|
|
176
|
-
return Boolean(process.env['WSL_DISTRO_NAME']);
|
|
177
|
-
}
|
|
178
231
|
/**
|
|
179
232
|
* Launch Windows Terminal (wt.exe) from WSL, running the command inside a new bash session.
|
|
180
233
|
*
|
|
181
234
|
* Uses wt.exe → wsl.exe → bash so the new terminal inherits the correct WSL distro.
|
|
182
|
-
* Claude Code nesting-detection vars are stripped via
|
|
235
|
+
* Claude Code nesting-detection vars are stripped via cleanClaudeEnv().
|
|
183
236
|
*
|
|
184
237
|
* @param cwd - Working directory (WSL path)
|
|
185
238
|
* @param command - Command to execute
|
|
186
239
|
* @param debugLog - Optional debug logging function
|
|
187
240
|
*/
|
|
188
241
|
async function launchWSLTerminal(cwd, command, debugLog) {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
debugLog?.(`Launching WSL via wt.exe with command: ${bashCmd}`);
|
|
242
|
+
const spawnArgs = buildWSLTerminalSpawnArgs(cwd, command);
|
|
243
|
+
debugLog?.(`Launching WSL via wt.exe with command: ${spawnArgs.args[4]}`);
|
|
192
244
|
return new Promise((resolve) => {
|
|
193
|
-
const proc = spawn(
|
|
245
|
+
const proc = spawn(spawnArgs.command, spawnArgs.args, {
|
|
194
246
|
detached: true,
|
|
195
247
|
stdio: 'ignore',
|
|
196
|
-
env:
|
|
248
|
+
env: cleanClaudeEnv(),
|
|
197
249
|
});
|
|
198
250
|
proc.on('error', (err) => {
|
|
199
251
|
resolve({ success: false, error: `wt.exe failed: ${err.message}` });
|
|
@@ -212,23 +264,21 @@ async function launchWSLTerminal(cwd, command, debugLog) {
|
|
|
212
264
|
*/
|
|
213
265
|
async function launchLinuxTerminal(cwd, command, debugLog) {
|
|
214
266
|
// Find available terminal first (synchronous)
|
|
215
|
-
const terminal = findAvailableLinuxTerminal();
|
|
267
|
+
const terminal = findAvailableLinuxTerminal(isCommandAvailable);
|
|
216
268
|
if (!terminal) {
|
|
217
269
|
return {
|
|
218
270
|
error: 'No supported terminal emulator found. Please install gnome-terminal, konsole, or xterm.',
|
|
219
271
|
success: false,
|
|
220
272
|
};
|
|
221
273
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const fullCommand = `cd '${escapedPath}' && ${command}`;
|
|
225
|
-
debugLog?.(`Launching ${terminal.cmd} with command: ${fullCommand}`);
|
|
274
|
+
const spawnArgs = buildLinuxTerminalSpawnArgs(cwd, command, terminal);
|
|
275
|
+
debugLog?.(`Launching ${terminal.cmd} with command: cd '${escapeSingleQuotedPath(cwd, 'bash')}' && ${command}`);
|
|
226
276
|
// Launch terminal (single async operation)
|
|
227
277
|
return new Promise((resolve) => {
|
|
228
|
-
const proc = spawn(
|
|
278
|
+
const proc = spawn(spawnArgs.command, spawnArgs.args, {
|
|
229
279
|
detached: true,
|
|
230
280
|
stdio: 'ignore',
|
|
231
|
-
env:
|
|
281
|
+
env: cleanClaudeEnv(),
|
|
232
282
|
});
|
|
233
283
|
proc.on('error', (err) => {
|
|
234
284
|
resolve({ error: `Failed to launch ${terminal.cmd}: ${err.message}`, success: false });
|
|
@@ -269,12 +319,12 @@ async function launchLinuxTerminal(cwd, command, debugLog) {
|
|
|
269
319
|
* ```
|
|
270
320
|
*/
|
|
271
321
|
export async function launchTerminal(options) {
|
|
272
|
-
const { cwd, command, debugLog } = options;
|
|
322
|
+
const { cwd, command, debugLog, windowsShellPreference = 'default' } = options;
|
|
273
323
|
const { platform } = process;
|
|
274
324
|
debugLog?.(`Launching terminal in ${cwd} with command: ${command}`);
|
|
275
325
|
debugLog?.(`Platform: ${platform}`);
|
|
276
|
-
if (platform
|
|
277
|
-
return launchWindowsTerminal(cwd, command, debugLog);
|
|
326
|
+
if (isWindowsPlatform(platform)) {
|
|
327
|
+
return launchWindowsTerminal(cwd, command, windowsShellPreference, debugLog);
|
|
278
328
|
}
|
|
279
329
|
if (platform === 'darwin') {
|
|
280
330
|
return launchMacTerminal(cwd, command, debugLog);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSP split algorithm for tmux pane placement.
|
|
3
|
+
* Extracted from template core/lib-ts/base/tmux-pane-placement.ts.
|
|
4
|
+
*/
|
|
5
|
+
export type TmuxSplitFlag = '-h' | '-v';
|
|
6
|
+
export interface TmuxPaneInfo {
|
|
7
|
+
active: boolean;
|
|
8
|
+
height: number;
|
|
9
|
+
paneId: string;
|
|
10
|
+
width: number;
|
|
11
|
+
}
|
|
12
|
+
export interface PlacementResult {
|
|
13
|
+
splitFlag: TmuxSplitFlag;
|
|
14
|
+
targetPane: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function listPanes(tmuxPath: string): Promise<TmuxPaneInfo[]>;
|
|
17
|
+
export declare function findBestSplit(panes: TmuxPaneInfo[]): null | PlacementResult;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSP split algorithm for tmux pane placement.
|
|
3
|
+
* Extracted from template core/lib-ts/base/tmux-pane-placement.ts.
|
|
4
|
+
*/
|
|
5
|
+
import { execFileAsync } from './runtime/subprocess-utils.js';
|
|
6
|
+
const LIST_PANES_FORMAT = '#{pane_id} #{pane_width} #{pane_height} #{pane_active}';
|
|
7
|
+
export async function listPanes(tmuxPath) {
|
|
8
|
+
const result = await execFileAsync(tmuxPath, ['list-panes', '-F', LIST_PANES_FORMAT], {
|
|
9
|
+
timeout: 3000,
|
|
10
|
+
});
|
|
11
|
+
if (result.exitCode !== 0)
|
|
12
|
+
return [];
|
|
13
|
+
const panes = [];
|
|
14
|
+
for (const rawLine of result.stdout.split(/\r?\n/)) {
|
|
15
|
+
const line = rawLine.trim();
|
|
16
|
+
if (!line)
|
|
17
|
+
continue;
|
|
18
|
+
const parts = line.split(/\s+/);
|
|
19
|
+
if (parts.length < 4)
|
|
20
|
+
continue;
|
|
21
|
+
const paneId = parts[0] ?? '';
|
|
22
|
+
const width = Number.parseInt(parts[1] ?? '', 10);
|
|
23
|
+
const height = Number.parseInt(parts[2] ?? '', 10);
|
|
24
|
+
const activeRaw = parts[3] ?? '';
|
|
25
|
+
if (!paneId || !Number.isFinite(width) || !Number.isFinite(height))
|
|
26
|
+
continue;
|
|
27
|
+
panes.push({
|
|
28
|
+
paneId,
|
|
29
|
+
width,
|
|
30
|
+
height,
|
|
31
|
+
active: activeRaw === '1',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return panes;
|
|
35
|
+
}
|
|
36
|
+
export function findBestSplit(panes) {
|
|
37
|
+
if (panes.length === 0)
|
|
38
|
+
return null;
|
|
39
|
+
let best = panes[0];
|
|
40
|
+
let bestArea = best.width * best.height;
|
|
41
|
+
for (let i = 1; i < panes.length; i++) {
|
|
42
|
+
const pane = panes[i];
|
|
43
|
+
if (!pane)
|
|
44
|
+
continue;
|
|
45
|
+
const area = pane.width * pane.height;
|
|
46
|
+
if (area > bestArea) {
|
|
47
|
+
best = pane;
|
|
48
|
+
bestArea = area;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const CELL_ASPECT_RATIO = 2;
|
|
52
|
+
const visualWidth = best.width;
|
|
53
|
+
const visualHeight = best.height * CELL_ASPECT_RATIO;
|
|
54
|
+
return {
|
|
55
|
+
targetPane: best.paneId,
|
|
56
|
+
splitFlag: visualWidth >= visualHeight ? '-h' : '-v',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { quoteForSh } from './shell-quoting.js';
|
|
2
|
+
/** Fixed tmux server socket. Multiple named sessions share one server. */
|
|
3
|
+
export declare const TMUX_SOCKET_PATH: string;
|
|
4
|
+
/** Convert Windows path to MSYS2 POSIX path for tmux args. C:\foo\bar → /c/foo/bar */
|
|
5
|
+
export declare function toMsysPosixPath(winPath: string): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export { quoteForSh } from './shell-quoting.js';
|
|
4
|
+
/** Fixed tmux server socket. Multiple named sessions share one server. */
|
|
5
|
+
export const TMUX_SOCKET_PATH = path.join(os.tmpdir(), 'aiwcli-tmux.sock');
|
|
6
|
+
/** Convert Windows path to MSYS2 POSIX path for tmux args. C:\foo\bar → /c/foo/bar */
|
|
7
|
+
export function toMsysPosixPath(winPath) {
|
|
8
|
+
if (process.platform !== 'win32')
|
|
9
|
+
return winPath;
|
|
10
|
+
const normalized = winPath.replaceAll('\\', '/');
|
|
11
|
+
const match = normalized.match(/^([A-Za-z]):\/(.*)/u);
|
|
12
|
+
if (!match)
|
|
13
|
+
return normalized;
|
|
14
|
+
return `/${match[1].toLowerCase()}/${match[2]}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface TmuxSessionOptions {
|
|
2
|
+
/** Prepend tmux mouse enable command (default true). */
|
|
3
|
+
enableMouse?: boolean;
|
|
4
|
+
/** Platform override for deterministic tests. */
|
|
5
|
+
platform?: NodeJS.Platform | undefined;
|
|
6
|
+
/** Optional prompt text to deliver as a positional arg via temp file. */
|
|
7
|
+
promptText?: string | undefined;
|
|
8
|
+
reattach?: boolean;
|
|
9
|
+
sessionName: string;
|
|
10
|
+
/** CLI args (e.g. ['--dangerously-skip-permissions']). */
|
|
11
|
+
toolArgs: string[];
|
|
12
|
+
/** Absolute path to tool binary (or bare command name on Unix). */
|
|
13
|
+
toolPath: string;
|
|
14
|
+
}
|
|
15
|
+
export type TmuxColorMode = 'c256' | 'truecolor';
|
|
16
|
+
export declare function buildTmuxRuntimeBootstrapCommands(platform?: NodeJS.Platform, enableMouse?: boolean): string[];
|
|
17
|
+
/** Color mode policy for tmux-launched sessions. */
|
|
18
|
+
export declare function resolveTmuxColorMode(platform?: NodeJS.Platform): TmuxColorMode;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the absolute path to a tool binary (e.g. 'claude', 'codex').
|
|
21
|
+
* On Windows prefers .exe, then extensionless, then .cmd.
|
|
22
|
+
* Returns null when the tool is not on PATH.
|
|
23
|
+
*/
|
|
24
|
+
export declare function findToolPath(name: string): null | string;
|
|
25
|
+
/** Build the shell command string from structured options. */
|
|
26
|
+
export declare function buildShellCommand(opts: TmuxSessionOptions): string;
|
|
27
|
+
/**
|
|
28
|
+
* Best-effort configure tmux session: mouse, scrollback, 256-color, and truecolor.
|
|
29
|
+
* Batches all settings into a single tmux invocation using \; command separator.
|
|
30
|
+
* Unix only — Windows uses psmux (native ConPTY handles mouse/color natively).
|
|
31
|
+
*/
|
|
32
|
+
export declare function configureTmuxSession(): void;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { writeFileSync } from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { resolveExecutable } from './runtime/executable-policy.js';
|
|
6
|
+
import { isNonWindowsPlatform, resolveTmuxColorModeForPlatform, } from './runtime/platform-adapter.js';
|
|
7
|
+
import { quoteForSh } from './tmux-primitives.js';
|
|
8
|
+
export function buildTmuxRuntimeBootstrapCommands(platform = process.platform, enableMouse = true) {
|
|
9
|
+
const commands = [];
|
|
10
|
+
if (enableMouse) {
|
|
11
|
+
commands.push('tmux set-option -g mouse on >/dev/null 2>&1 || true');
|
|
12
|
+
}
|
|
13
|
+
// Increase scrollback buffer from default 2000
|
|
14
|
+
commands.push('tmux set-option -g history-limit 50000 >/dev/null 2>&1 || true');
|
|
15
|
+
// Configure terminal overrides for truecolor on Unix.
|
|
16
|
+
// Note: default-terminal is set before session creation.
|
|
17
|
+
// Windows uses psmux (native ConPTY) which handles color/cursor natively.
|
|
18
|
+
if (isNonWindowsPlatform(platform)) {
|
|
19
|
+
commands.push('tmux set -a terminal-overrides ",xterm*:Tc,alacritty:Tc" >/dev/null 2>&1 || true');
|
|
20
|
+
}
|
|
21
|
+
return commands;
|
|
22
|
+
}
|
|
23
|
+
/** Color mode policy for tmux-launched sessions. */
|
|
24
|
+
export function resolveTmuxColorMode(platform = process.platform) {
|
|
25
|
+
return resolveTmuxColorModeForPlatform(platform);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the absolute path to a tool binary (e.g. 'claude', 'codex').
|
|
29
|
+
* On Windows prefers .exe, then extensionless, then .cmd.
|
|
30
|
+
* Returns null when the tool is not on PATH.
|
|
31
|
+
*/
|
|
32
|
+
export function findToolPath(name) {
|
|
33
|
+
return resolveExecutable(name, { windowsProfile: 'exeThenExtensionlessThenCmd' });
|
|
34
|
+
}
|
|
35
|
+
/** Build the shell command string from structured options. */
|
|
36
|
+
export function buildShellCommand(opts) {
|
|
37
|
+
const { toolPath, toolArgs, promptText, enableMouse = true, platform = process.platform } = opts;
|
|
38
|
+
const colorMode = resolveTmuxColorMode(platform);
|
|
39
|
+
const parts = buildTmuxRuntimeBootstrapCommands(platform, enableMouse);
|
|
40
|
+
const cmdParts = [];
|
|
41
|
+
cmdParts.push(quoteForSh(toolPath));
|
|
42
|
+
for (const arg of toolArgs) {
|
|
43
|
+
cmdParts.push(quoteForSh(arg));
|
|
44
|
+
}
|
|
45
|
+
// Deliver prompt via temp file — avoids nested bash→tmux→sh quoting
|
|
46
|
+
if (promptText) {
|
|
47
|
+
const tmpFile = path.join(os.tmpdir(), `aiwcli-prompt-${Date.now()}-${process.pid}.txt`);
|
|
48
|
+
writeFileSync(tmpFile, promptText, { encoding: 'utf8', mode: 0o600 });
|
|
49
|
+
const bootstrap = `Read startup instructions from this file path before taking action: ${tmpFile}. Use that file as the initial context.`;
|
|
50
|
+
cmdParts.push(quoteForSh(bootstrap));
|
|
51
|
+
}
|
|
52
|
+
// Export COLORTERM only when truecolor is intentionally enabled.
|
|
53
|
+
if (colorMode === 'truecolor') {
|
|
54
|
+
parts.push('export COLORTERM=truecolor');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
parts.push('unset COLORTERM');
|
|
58
|
+
}
|
|
59
|
+
parts.push(`exec ${cmdParts.join(' ')}`);
|
|
60
|
+
return parts.join('; ');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Best-effort configure tmux session: mouse, scrollback, 256-color, and truecolor.
|
|
64
|
+
* Batches all settings into a single tmux invocation using \; command separator.
|
|
65
|
+
* Unix only — Windows uses psmux (native ConPTY handles mouse/color natively).
|
|
66
|
+
*/
|
|
67
|
+
export function configureTmuxSession() {
|
|
68
|
+
if (!isNonWindowsPlatform())
|
|
69
|
+
return;
|
|
70
|
+
try {
|
|
71
|
+
execSync('tmux set-option -g mouse on \\; ' +
|
|
72
|
+
'set-option -g history-limit 50000 \\; ' +
|
|
73
|
+
'set -g default-terminal "tmux-256color" \\; ' +
|
|
74
|
+
'set -a terminal-overrides ",xterm*:Tc,alacritty:Tc"', { stdio: 'ignore', timeout: 3000 });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Fallback: tmux-256color may not be in terminfo — try screen-256color
|
|
78
|
+
try {
|
|
79
|
+
execSync('tmux set-option -g mouse on \\; ' +
|
|
80
|
+
'set-option -g history-limit 50000 \\; ' +
|
|
81
|
+
'set -g default-terminal "screen-256color" \\; ' +
|
|
82
|
+
'set -a terminal-overrides ",xterm*:Tc,alacritty:Tc"', { stdio: 'ignore', timeout: 3000 });
|
|
83
|
+
}
|
|
84
|
+
catch { /* best-effort */ }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -36,7 +36,7 @@ export function shouldUseColors(proc = process) {
|
|
|
36
36
|
const env = proc.env ?? process.env;
|
|
37
37
|
const noColor = env.NO_COLOR;
|
|
38
38
|
const forceColor = env.FORCE_COLOR;
|
|
39
|
-
// NO_COLOR takes precedence (
|
|
39
|
+
// NO_COLOR takes precedence (unknown value disables colors)
|
|
40
40
|
if (noColor !== undefined) {
|
|
41
41
|
return false;
|
|
42
42
|
}
|