Skip to content

Commit 7e91ec6

Browse files
authored
Merge pull request #950 from web3dev1337/fix/commander-open-autostart
fix: auto-start commander on panel open
2 parents fad5813 + 43b6c79 commit 7e91ec6

2 files changed

Lines changed: 81 additions & 17 deletions

File tree

client/commander-panel.js

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class CommanderPanel {
99
this.orchestrator = orchestrator;
1010
this.isVisible = false;
1111
this.isRunning = false;
12+
this.isStarting = false;
13+
this.startCommanderPromise = null;
1214
// Always use same-origin API requests; the dev server proxies `/api` to the backend.
1315
this.serverUrl = window.location.origin;
1416
this.terminal = null;
@@ -114,7 +116,7 @@ class CommanderPanel {
114116
<div class="commander-terminal" id="commander-terminal">
115117
<div class="commander-placeholder">
116118
<p>Commander is a Claude Code terminal for orchestrating your sessions.</p>
117-
<p>Click <strong>▶️ Start</strong> to launch the terminal, then <strong>Start Claude</strong> to begin.</p>
119+
<p>Opening Commander starts it automatically. Claude will launch as soon as the terminal is ready.</p>
118120
</div>
119121
</div>
120122
`;
@@ -139,6 +141,29 @@ class CommanderPanel {
139141
this.orchestrator?.applyUiVisibility?.();
140142
}
141143

144+
setPlaceholderMessages(lines = []) {
145+
if (this.terminal) return;
146+
147+
const container = document.getElementById('commander-terminal');
148+
if (!container) return;
149+
150+
const messages = Array.isArray(lines) && lines.length
151+
? lines
152+
: [
153+
'Commander is a Claude Code terminal for orchestrating your sessions.',
154+
'Opening Commander starts it automatically. Claude will launch as soon as the terminal is ready.'
155+
];
156+
157+
const placeholder = document.createElement('div');
158+
placeholder.className = 'commander-placeholder';
159+
messages.forEach((message) => {
160+
const paragraph = document.createElement('p');
161+
paragraph.textContent = message;
162+
placeholder.appendChild(paragraph);
163+
});
164+
container.replaceChildren(placeholder);
165+
}
166+
142167
/**
143168
* Initialize XTerm.js terminal
144169
*/
@@ -545,7 +570,10 @@ class CommanderPanel {
545570
updateStatusBadge() {
546571
const badge = document.getElementById('commander-status-badge');
547572
if (badge) {
548-
if (this.isRunning) {
573+
if (this.isStarting) {
574+
badge.textContent = 'Starting';
575+
badge.className = 'commander-status starting';
576+
} else if (this.isRunning) {
549577
badge.textContent = 'Running';
550578
badge.className = 'commander-status online';
551579
} else {
@@ -581,11 +609,14 @@ class CommanderPanel {
581609
const status = await this.checkStatus();
582610

583611
if (!status.running) {
584-
// Commander terminal not running - start everything
612+
this.isStarting = true;
613+
this.updateStatusBadge();
614+
this.setPlaceholderMessages([
615+
'Commander is starting.',
616+
'Claude will launch automatically as soon as the terminal is ready.'
617+
]);
618+
585619
await this.startCommander();
586-
setTimeout(() => {
587-
this.startClaude('fresh');
588-
}, 1500);
589620
} else if (!this.terminal) {
590621
// Terminal not initialized locally - set it up
591622
this.initTerminal();
@@ -615,22 +646,50 @@ class CommanderPanel {
615646
* Start the Commander terminal
616647
*/
617648
async startCommander() {
618-
try {
619-
const response = await fetch(`${this.serverUrl}/api/commander/start`, {
620-
method: 'POST'
621-
});
649+
if (this.startCommanderPromise) {
650+
return this.startCommanderPromise;
651+
}
622652

623-
if (response.ok) {
624-
const result = await response.json();
625-
if (result.success) {
653+
this.isStarting = true;
654+
this.updateStatusBadge();
655+
656+
this.startCommanderPromise = (async () => {
657+
try {
658+
const response = await fetch(`${this.serverUrl}/api/commander/start`, {
659+
method: 'POST'
660+
});
661+
const result = response.ok
662+
? await response.json()
663+
: { success: false, error: `Request failed (${response.status})` };
664+
665+
if (result.success || result.error === 'Already running') {
626666
this.isRunning = true;
627-
this.updateStatusBadge();
628667
this.initTerminal();
668+
return result;
629669
}
670+
671+
this.isRunning = false;
672+
this.setPlaceholderMessages([
673+
'Commander could not be started.',
674+
String(result.error || 'Close and reopen the panel to try again.')
675+
]);
676+
return result;
677+
} catch (error) {
678+
console.error('Failed to start commander:', error);
679+
this.isRunning = false;
680+
this.setPlaceholderMessages([
681+
'Commander could not be started.',
682+
'Close and reopen the panel to try again.'
683+
]);
684+
return { success: false, error: error.message };
685+
} finally {
686+
this.isStarting = false;
687+
this.updateStatusBadge();
688+
this.startCommanderPromise = null;
630689
}
631-
} catch (error) {
632-
console.error('Failed to start commander:', error);
633-
}
690+
})();
691+
692+
return this.startCommanderPromise;
634693
}
635694

636695
/**

client/styles.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10496,6 +10496,11 @@ body.dependency-onboarding-active #dependency-setup-modal {
1049610496
color: var(--accent-success);
1049710497
}
1049810498

10499+
.commander-status.starting {
10500+
background: rgba(210, 153, 34, 0.2);
10501+
color: var(--accent-warning, #d29922);
10502+
}
10503+
1049910504
.commander-status.offline {
1050010505
background: rgba(248, 81, 73, 0.2);
1050110506
color: var(--accent-danger);

0 commit comments

Comments
 (0)