mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
feat(ui): add shell instance count and improve welcome message
- Add instance count controls (+/- buttons) for Run Shell - Update runShell() to support launching multiple shell sessions - Update welcome message to explain persistent GNU Screen sessions - Add "Instance count" tooltips to both Claude and Shell controls Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+48
-25
@@ -184,7 +184,11 @@ class ClaudemanApp {
|
|||||||
|
|
||||||
showWelcome() {
|
showWelcome() {
|
||||||
this.terminal.writeln('\x1b[1;36m Claudeman Terminal\x1b[0m');
|
this.terminal.writeln('\x1b[1;36m Claudeman Terminal\x1b[0m');
|
||||||
this.terminal.writeln('\x1b[90m Click "Run Claude" or press Ctrl+Enter to begin\x1b[0m');
|
this.terminal.writeln('');
|
||||||
|
this.terminal.writeln('\x1b[90m Each instance opens a persistent GNU Screen session running Claude or Shell.\x1b[0m');
|
||||||
|
this.terminal.writeln('\x1b[90m Sessions stay alive for autonomous work, even if you close this browser.\x1b[0m');
|
||||||
|
this.terminal.writeln('');
|
||||||
|
this.terminal.writeln('\x1b[90m Press \x1b[1;37mCtrl+Enter\x1b[0m\x1b[90m to start Claude • Click \x1b[1;37mRun Shell\x1b[0m\x1b[90m for a terminal\x1b[0m');
|
||||||
this.terminal.writeln('');
|
this.terminal.writeln('');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -990,6 +994,19 @@ class ClaudemanApp {
|
|||||||
input.value = Math.max(1, current - 1);
|
input.value = Math.max(1, current - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shell count stepper functions
|
||||||
|
incrementShellCount() {
|
||||||
|
const input = document.getElementById('shellCount');
|
||||||
|
const current = parseInt(input.value) || 1;
|
||||||
|
input.value = Math.min(20, current + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementShellCount() {
|
||||||
|
const input = document.getElementById('shellCount');
|
||||||
|
const current = parseInt(input.value) || 1;
|
||||||
|
input.value = Math.max(1, current - 1);
|
||||||
|
}
|
||||||
|
|
||||||
async runClaude() {
|
async runClaude() {
|
||||||
const caseName = document.getElementById('quickStartCase').value || 'testcase';
|
const caseName = document.getElementById('quickStartCase').value || 'testcase';
|
||||||
const tabCount = Math.min(20, Math.max(1, parseInt(document.getElementById('tabCount').value) || 1));
|
const tabCount = Math.min(20, Math.max(1, parseInt(document.getElementById('tabCount').value) || 1));
|
||||||
@@ -1084,9 +1101,10 @@ class ClaudemanApp {
|
|||||||
|
|
||||||
async runShell() {
|
async runShell() {
|
||||||
const caseName = document.getElementById('quickStartCase').value || 'testcase';
|
const caseName = document.getElementById('quickStartCase').value || 'testcase';
|
||||||
|
const shellCount = Math.min(20, Math.max(1, parseInt(document.getElementById('shellCount').value) || 1));
|
||||||
|
|
||||||
this.terminal.clear();
|
this.terminal.clear();
|
||||||
this.terminal.writeln(`\x1b[1;33m Starting Shell in ${caseName}...\x1b[0m`);
|
this.terminal.writeln(`\x1b[1;33m Starting ${shellCount} Shell session(s) in ${caseName}...\x1b[0m`);
|
||||||
this.terminal.writeln('');
|
this.terminal.writeln('');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1107,34 +1125,39 @@ class ClaudemanApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const sessionName = `s${startNumber}-${caseName}`;
|
|
||||||
|
|
||||||
// Create session with shell mode
|
// Create multiple shell sessions
|
||||||
const createRes = await fetch('/api/sessions', {
|
for (let i = 0; i < shellCount; i++) {
|
||||||
method: 'POST',
|
const sessionName = `s${startNumber + i}-${caseName}`;
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ workingDir, mode: 'shell', name: sessionName })
|
|
||||||
});
|
|
||||||
const createData = await createRes.json();
|
|
||||||
if (!createData.success) throw new Error(createData.error);
|
|
||||||
|
|
||||||
const sessionId = createData.session.id;
|
// Create session with shell mode
|
||||||
|
const createRes = await fetch('/api/sessions', {
|
||||||
// Start shell
|
|
||||||
await fetch(`/api/sessions/${sessionId}/shell`, {
|
|
||||||
method: 'POST'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.activeSessionId = sessionId;
|
|
||||||
|
|
||||||
// Send resize
|
|
||||||
const dims = this.fitAddon.proposeDimensions();
|
|
||||||
if (dims) {
|
|
||||||
await fetch(`/api/sessions/${sessionId}/resize`, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ cols: dims.cols, rows: dims.rows })
|
body: JSON.stringify({ workingDir, mode: 'shell', name: sessionName })
|
||||||
});
|
});
|
||||||
|
const createData = await createRes.json();
|
||||||
|
if (!createData.success) throw new Error(createData.error);
|
||||||
|
|
||||||
|
const sessionId = createData.session.id;
|
||||||
|
|
||||||
|
// Start shell
|
||||||
|
await fetch(`/api/sessions/${sessionId}/shell`, {
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set active to last created
|
||||||
|
this.activeSessionId = sessionId;
|
||||||
|
|
||||||
|
// Send resize
|
||||||
|
const dims = this.fitAddon.proposeDimensions();
|
||||||
|
if (dims) {
|
||||||
|
await fetch(`/api/sessions/${sessionId}/resize`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ cols: dims.cols, rows: dims.rows })
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.terminal.focus();
|
this.terminal.focus();
|
||||||
|
|||||||
@@ -165,14 +165,19 @@
|
|||||||
<button class="btn-toolbar btn-claude" onclick="app.runClaude()" title="Run Claude (Ctrl+Enter)">
|
<button class="btn-toolbar btn-claude" onclick="app.runClaude()" title="Run Claude (Ctrl+Enter)">
|
||||||
Run Claude
|
Run Claude
|
||||||
</button>
|
</button>
|
||||||
<div class="tab-count-group" title="Number of tabs to open (1-10)">
|
<div class="tab-count-group" title="Instance count">
|
||||||
<button class="tab-count-btn" onclick="app.decrementTabCount()">−</button>
|
<button class="tab-count-btn" onclick="app.decrementTabCount()" title="Instance count">−</button>
|
||||||
<input type="number" id="tabCount" class="tab-count-input" value="1" min="1" max="20" readonly>
|
<input type="number" id="tabCount" class="tab-count-input" value="1" min="1" max="20" readonly title="Instance count">
|
||||||
<button class="tab-count-btn" onclick="app.incrementTabCount()">+</button>
|
<button class="tab-count-btn" onclick="app.incrementTabCount()" title="Instance count">+</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn-toolbar btn-shell" onclick="app.runShell()" title="Run Shell">
|
<button class="btn-toolbar btn-shell" onclick="app.runShell()" title="Run Shell">
|
||||||
Run Shell
|
Run Shell
|
||||||
</button>
|
</button>
|
||||||
|
<div class="tab-count-group" title="Instance count">
|
||||||
|
<button class="tab-count-btn" onclick="app.decrementShellCount()" title="Instance count">−</button>
|
||||||
|
<input type="number" id="shellCount" class="tab-count-input" value="1" min="1" max="20" readonly title="Instance count">
|
||||||
|
<button class="tab-count-btn" onclick="app.incrementShellCount()" title="Instance count">+</button>
|
||||||
|
</div>
|
||||||
<div class="case-select-group">
|
<div class="case-select-group">
|
||||||
<select id="quickStartCase" class="toolbar-select" title="Select case">
|
<select id="quickStartCase" class="toolbar-select" title="Select case">
|
||||||
<option value="testcase">testcase</option>
|
<option value="testcase">testcase</option>
|
||||||
|
|||||||
Reference in New Issue
Block a user