mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
feat: add multi-tab feature to open 1-10 Claude sessions at once
- Add number input (1-10) next to "Run Claude" button in toolbar - When tabCount > 1, create sessions named "1-projectname", "2-projectname", etc. - All sessions share the same working directory (case folder) - First session is auto-selected after creation - Add CSS for small number input in toolbar Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+56
-17
@@ -678,32 +678,71 @@ class ClaudemanApp {
|
||||
|
||||
async runClaude() {
|
||||
const caseName = document.getElementById('quickStartCase').value || 'testcase';
|
||||
const tabCount = Math.min(10, Math.max(1, parseInt(document.getElementById('tabCount').value) || 1));
|
||||
|
||||
this.terminal.clear();
|
||||
this.terminal.writeln(`\x1b[1;32m Starting Claude in ${caseName}...\x1b[0m`);
|
||||
this.terminal.writeln(`\x1b[1;32m Starting ${tabCount} Claude session(s) in ${caseName}...\x1b[0m`);
|
||||
this.terminal.writeln('');
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/quick-start', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ caseName })
|
||||
});
|
||||
const data = await res.json();
|
||||
// Get case path first
|
||||
const caseRes = await fetch(`/api/cases/${caseName}`);
|
||||
const caseData = await caseRes.json();
|
||||
|
||||
if (!data.success) throw new Error(data.error);
|
||||
|
||||
this.activeSessionId = data.sessionId;
|
||||
this.loadQuickStartCases();
|
||||
|
||||
// Send resize
|
||||
const dims = this.fitAddon.proposeDimensions();
|
||||
if (dims) {
|
||||
await fetch(`/api/sessions/${data.sessionId}/resize`, {
|
||||
// Create the case if it doesn't exist
|
||||
if (!caseData.path) {
|
||||
const createCaseRes = await fetch('/api/cases', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ cols: dims.cols, rows: dims.rows })
|
||||
body: JSON.stringify({ name: caseName, description: '' })
|
||||
});
|
||||
const createCaseData = await createCaseRes.json();
|
||||
if (!createCaseData.success) throw new Error(createCaseData.error || 'Failed to create case');
|
||||
}
|
||||
|
||||
const workingDir = caseData.path || `${process.env.HOME}/claudeman-cases/${caseName}`;
|
||||
let firstSessionId = null;
|
||||
|
||||
// Create multiple sessions
|
||||
for (let i = 1; i <= tabCount; i++) {
|
||||
const sessionName = tabCount > 1 ? `${i}-${caseName}` : caseName;
|
||||
|
||||
// Create session
|
||||
const createRes = await fetch('/api/sessions', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ workingDir, name: sessionName })
|
||||
});
|
||||
const createData = await createRes.json();
|
||||
if (!createData.success) throw new Error(createData.error);
|
||||
|
||||
// Start interactive mode
|
||||
await fetch(`/api/sessions/${createData.session.id}/interactive`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
// Track first session
|
||||
if (i === 1) {
|
||||
firstSessionId = createData.session.id;
|
||||
}
|
||||
|
||||
this.terminal.writeln(`\x1b[90m Created session ${i}/${tabCount}: ${sessionName}\x1b[0m`);
|
||||
}
|
||||
|
||||
// Select the first session
|
||||
if (firstSessionId) {
|
||||
this.activeSessionId = firstSessionId;
|
||||
this.loadQuickStartCases();
|
||||
|
||||
// Send resize
|
||||
const dims = this.fitAddon.proposeDimensions();
|
||||
if (dims) {
|
||||
await fetch(`/api/sessions/${firstSessionId}/resize`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ cols: dims.cols, rows: dims.rows })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.terminal.focus();
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<button class="btn-toolbar btn-primary" onclick="app.runClaude()" title="Run Claude (Ctrl+Enter)">
|
||||
Run Claude
|
||||
</button>
|
||||
<input type="number" id="tabCount" class="toolbar-input-sm" value="1" min="1" max="10" title="Number of tabs to open (1-10)">
|
||||
<button class="btn-toolbar" onclick="app.runShell()" title="Run Shell">
|
||||
Shell
|
||||
</button>
|
||||
|
||||
@@ -539,6 +539,28 @@ body {
|
||||
max-width: 50vw;
|
||||
}
|
||||
|
||||
.toolbar-input-sm {
|
||||
padding: 0.3rem 0.4rem;
|
||||
background: var(--bg-input);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
color: var(--text);
|
||||
font-size: 0.75rem;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toolbar-input-sm:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.toolbar-input-sm::-webkit-inner-spin-button,
|
||||
.toolbar-input-sm::-webkit-outer-spin-button {
|
||||
opacity: 1;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#dirDisplay {
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
|
||||
Reference in New Issue
Block a user