feat: add terminal type selection in directory picker

Add CSS styling for the terminal type dropdown that was already
implemented in the JavaScript but wasn't visible due to missing styles.

The dropdown allows users to choose between:
- Standard Shell (bash/zsh) - default
- Claude Code CLI - runs claude --dangerously-skip-permissions

When Claude Code CLI is selected:
- Session picker is skipped (not needed)
- Terminal automatically launches with claude --dangerously-skip-permissions
- Mode is automatically set to 'session'

Changes:
- Add .terminal-type-selection, .terminal-type-select styles to terminal.css
- Match existing modal styling (background, borders, focus states)
- JavaScript was already implemented from previous work

Resolves: "Claude Code CLI still not appears under terminal > new terminal"

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
uroma
2026-01-19 18:22:11 +00:00
Unverified
parent df10f31f6c
commit 9e289cb0a1
2 changed files with 98 additions and 16 deletions

View File

@@ -284,12 +284,14 @@
} }
.recent-directories, .recent-directories,
.custom-directory { .custom-directory,
.terminal-type-selection {
margin-bottom: 20px; margin-bottom: 20px;
} }
.recent-directories label, .recent-directories label,
.custom-directory label { .custom-directory label,
.terminal-type-selection label {
display: block; display: block;
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
@@ -298,6 +300,28 @@
text-transform: uppercase; text-transform: uppercase;
} }
.terminal-type-select {
width: 100%;
padding: 10px 12px;
background: #1a1a1a;
border: 1px solid #333;
border-radius: 6px;
color: #e0e0e0;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
}
.terminal-type-select:hover {
border-color: #555;
}
.terminal-type-select:focus {
outline: none;
border-color: #4a9eff;
box-shadow: 0 0 0 3px rgba(74, 158, 255, 0.1);
}
.directory-list { .directory-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -166,19 +166,25 @@ class TerminalManager {
sessionId = null, sessionId = null,
mode = 'mixed', mode = 'mixed',
silent = false, silent = false,
skipSessionPicker = false skipSessionPicker = false,
terminalType = null
} = options; } = options;
// Show directory picker if no working directory provided // Show directory picker if no working directory provided
const selectedDir = workingDir || await this.showDirectoryPicker(); const selection = workingDir
? { directory: workingDir, terminalType: terminalType || 'standard' }
: await this.showDirectoryPicker();
if (!selectedDir) { if (!selection) {
return null; return null;
} }
const { directory: selectedDir, terminalType: selectedTerminalType } = selection;
// If no session provided and not skipping picker, show session picker // If no session provided and not skipping picker, show session picker
let sessionSelection = null; let sessionSelection = null;
if (!sessionId && !skipSessionPicker) { if (!sessionId && !skipSessionPicker && selectedTerminalType !== 'claude-cli') {
// Skip session picker if Claude Code CLI terminal is selected
sessionSelection = await this.showSessionPicker(); sessionSelection = await this.showSessionPicker();
// If user cancelled session picker, still create terminal but without session // If user cancelled session picker, still create terminal but without session
// sessionSelection will be null or { sessionId: string, source: 'web'|'local' } or { sessionId: 'new', source: 'new' } // sessionSelection will be null or { sessionId: string, source: 'web'|'local' } or { sessionId: 'new', source: 'new' }
@@ -213,15 +219,25 @@ class TerminalManager {
// Switch to new terminal // Switch to new terminal
this.switchToTerminal(terminalId); this.switchToTerminal(terminalId);
// Handle terminal type specific initialization
if (selectedTerminalType === 'claude-cli') {
// Wait a moment for terminal to be ready
await new Promise(resolve => setTimeout(resolve, 500));
// Launch Claude CLI with skip permissions flag
await this.launchCommand(terminalId, 'claude --dangerously-skip-permissions\n');
await this.setMode(terminalId, 'session');
if (!silent) {
showToast('Claude Code CLI terminal created', 'success');
}
} else if (sessionSelection && sessionSelection.sessionId) {
// Auto-launch Claude CLI if session was selected // Auto-launch Claude CLI if session was selected
if (sessionSelection && sessionSelection.sessionId) {
if (sessionSelection.sessionId !== 'new') { if (sessionSelection.sessionId !== 'new') {
await this.launchClaudeCLI(terminalId, sessionSelection.sessionId, sessionSelection.source); await this.launchClaudeCLI(terminalId, sessionSelection.sessionId, sessionSelection.source);
} else { } else {
// Launch Claude CLI without session for new session // Launch Claude CLI without session for new session
await this.launchClaudeCLI(terminalId, null, 'new'); await this.launchClaudeCLI(terminalId, null, 'new');
} }
}
if (!silent) { if (!silent) {
const sessionMsg = sessionSelection && sessionSelection.sessionId && sessionSelection.sessionId !== 'new' const sessionMsg = sessionSelection && sessionSelection.sessionId && sessionSelection.sessionId !== 'new'
@@ -229,6 +245,11 @@ class TerminalManager {
: sessionSelection && sessionSelection.sessionId === 'new' ? ' (New Session)' : ''; : sessionSelection && sessionSelection.sessionId === 'new' ? ' (New Session)' : '';
showToast(`Terminal created${sessionMsg}`, 'success'); showToast(`Terminal created${sessionMsg}`, 'success');
} }
} else {
if (!silent) {
showToast('Terminal created', 'success');
}
}
return terminalId; return terminalId;
} catch (error) { } catch (error) {
@@ -281,6 +302,17 @@ class TerminalManager {
<label>Custom Path</label> <label>Custom Path</label>
<input type="text" class="directory-input" placeholder="Enter absolute path..." value="${escapeHtml(recentDirs[0])}"> <input type="text" class="directory-input" placeholder="Enter absolute path..." value="${escapeHtml(recentDirs[0])}">
</div> </div>
<div class="terminal-type-selection">
<label>Terminal Type</label>
<select class="terminal-type-select">
<option value="standard">Standard Shell (bash/zsh)</option>
<option value="claude-cli">Claude Code CLI (with --dangerously-skip-permissions)</option>
</select>
<small style="display: block; margin-top: 0.5rem; color: var(--text-secondary);">
Standard Shell: Regular terminal with bash/zsh<br>
Claude Code CLI: Automatically starts with claude --dangerously-skip-permissions
</small>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn-secondary btn-cancel">Cancel</button> <button class="btn-secondary btn-cancel">Cancel</button>
@@ -293,8 +325,10 @@ class TerminalManager {
setTimeout(() => modal.classList.add('visible'), 10); setTimeout(() => modal.classList.add('visible'), 10);
const input = modal.querySelector('.directory-input'); const input = modal.querySelector('.directory-input');
const terminalTypeSelect = modal.querySelector('.terminal-type-select');
const createBtn = modal.querySelector('.btn-create'); const createBtn = modal.querySelector('.btn-create');
let selectedDir = recentDirs[0]; let selectedDir = recentDirs[0];
let selectedTerminalType = 'standard';
// Handle directory selection // Handle directory selection
modal.querySelectorAll('.directory-item').forEach(item => { modal.querySelectorAll('.directory-item').forEach(item => {
@@ -311,17 +345,22 @@ class TerminalManager {
selectedDir = input.value; selectedDir = input.value;
}); });
// Handle terminal type selection
terminalTypeSelect.addEventListener('change', () => {
selectedTerminalType = terminalTypeSelect.value;
});
// Handle enter key // Handle enter key
input.addEventListener('keypress', (e) => { input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
resolve(selectedDir); resolve({ directory: selectedDir, terminalType: selectedTerminalType });
cleanup(); cleanup();
} }
}); });
// Handle create // Handle create
createBtn.addEventListener('click', () => { createBtn.addEventListener('click', () => {
resolve(selectedDir); resolve({ directory: selectedDir, terminalType: selectedTerminalType });
cleanup(); cleanup();
}); });
@@ -583,6 +622,25 @@ class TerminalManager {
} }
} }
/**
* Launch a command in the terminal
*/
async launchCommand(terminalId, command) {
const terminal = this.terminals.get(terminalId);
if (!terminal || !terminal.ws || terminal.ws.readyState !== WebSocket.OPEN) {
console.error('[TerminalManager] Terminal not ready for command launch');
return;
}
// Send command to terminal
terminal.ws.send(JSON.stringify({
type: 'input',
data: command
}));
console.log(`[TerminalManager] Launched command in terminal ${terminalId}: ${command.trim()}`);
}
/** /**
* Extract project name from session metadata * Extract project name from session metadata
*/ */