Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/iloom-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,32 @@ iloom respects these environment variables:

---

## Platform Support

Terminal window launching (`il start` opening Claude, dev-server, and shell tabs) is supported on the following platforms:

| Platform | Terminal Emulator | Tab Colors | Tab Titles |
|----------|-------------------|------------|------------|
| macOS | Terminal.app | Yes (background) | No |
| macOS | iTerm2 | Yes (background) | Yes |
| WSL | Windows Terminal (`wt.exe`) | Yes (`--tabColor`) | Yes |
| Linux | gnome-terminal | No | Yes |
| Linux | konsole | No | Yes |
| Linux | xterm (fallback) | No | Yes (window title) |

**WSL Notes:**
- Windows Terminal must be installed (available from the [Microsoft Store](https://aka.ms/terminal))
- `wt.exe` is automatically available on `PATH` inside WSL when Windows Terminal is installed
- The WSL distribution is detected from the `WSL_DISTRO_NAME` environment variable
- Tab colors are applied via the `--tabColor` flag at launch time

**Linux Notes:**
- Terminal emulators are detected in preference order: gnome-terminal, konsole, xterm
- gnome-terminal supports opening multiple tabs in a single invocation
- Background colors are not controllable via CLI on most Linux terminals

---

## Additional Resources

- [Main README](../README.md) - Overview and quick start
Expand Down
79 changes: 40 additions & 39 deletions src/lib/LoomManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,46 +345,8 @@ export class LoomManager {
}
}

// 11.5. Launch workspace components based on individual flags
const enableClaude = input.options?.enableClaude !== false
const enableCode = input.options?.enableCode !== false
const enableDevServer = input.options?.enableDevServer !== false
const enableTerminal = input.options?.enableTerminal ?? false
const oneShot = input.options?.oneShot ?? 'default'
const setArguments = input.options?.setArguments
const executablePath = input.options?.executablePath

// Only launch if at least one component is enabled
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
const { LoomLauncher } = await import('./LoomLauncher.js')
const { ClaudeContextManager } = await import('./ClaudeContextManager.js')

// Create ClaudeContextManager with shared SettingsManager to ensure CLI overrides work
const claudeContext = new ClaudeContextManager(undefined, undefined, this.settings)
const launcher = new LoomLauncher(claudeContext, this.settings)

await launcher.launchLoom({
enableClaude,
enableCode,
enableDevServer,
enableTerminal,
worktreePath,
branchName,
port,
capabilities,
workflowType: input.type === 'branch' ? 'regular' : input.type,
identifier: input.identifier,
...(issueData?.title && { title: issueData.title }),
oneShot,
...(setArguments && { setArguments }),
...(executablePath && { executablePath }),
sourceEnvOnStart: settingsData.sourceEnvOnStart ?? false,
colorTerminal: input.options?.colorTerminal ?? settingsData.colors?.terminal ?? true,
colorHex: colorData.hex,
})
}

// 12. Write loom metadata (spec section 3.1)
// Must happen BEFORE launching terminals so that `il spin` can read the session ID
// Derive description from issue/PR title or branch name
const description = issueData?.title ?? branchName

Expand Down Expand Up @@ -449,6 +411,45 @@ export class LoomManager {
}
await this.metadataManager.writeMetadata(worktreePath, metadataInput)

// 11.5. Launch workspace components based on individual flags
const enableClaude = input.options?.enableClaude !== false
const enableCode = input.options?.enableCode !== false
const enableDevServer = input.options?.enableDevServer !== false
const enableTerminal = input.options?.enableTerminal ?? false
const oneShot = input.options?.oneShot ?? 'default'
const setArguments = input.options?.setArguments
const executablePath = input.options?.executablePath

// Only launch if at least one component is enabled
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
const { LoomLauncher } = await import('./LoomLauncher.js')
const { ClaudeContextManager } = await import('./ClaudeContextManager.js')

// Create ClaudeContextManager with shared SettingsManager to ensure CLI overrides work
const claudeContext = new ClaudeContextManager(undefined, undefined, this.settings)
const launcher = new LoomLauncher(claudeContext, this.settings)

await launcher.launchLoom({
enableClaude,
enableCode,
enableDevServer,
enableTerminal,
worktreePath,
branchName,
port,
capabilities,
workflowType: input.type === 'branch' ? 'regular' : input.type,
identifier: input.identifier,
...(issueData?.title && { title: issueData.title }),
oneShot,
...(setArguments && { setArguments }),
...(executablePath && { executablePath }),
sourceEnvOnStart: settingsData.sourceEnvOnStart ?? false,
colorTerminal: input.options?.colorTerminal ?? settingsData.colors?.terminal ?? true,
colorHex: colorData.hex,
})
}

// 13. Create and return loom metadata
const loom: Loom = {
id: this.generateLoomId(input),
Expand Down
20 changes: 19 additions & 1 deletion src/lib/TerminalColorManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ import { TerminalColorManager } from './TerminalColorManager.js'
import { execa } from 'execa'
import { generateColorFromBranchName } from '../utils/color.js'
import { logger } from '../utils/logger.js'
import { isWSL } from '../utils/platform-detect.js'

// Mock execa
vi.mock('execa')

// Mock platform-detect
vi.mock('../utils/platform-detect.js', () => ({
isWSL: vi.fn().mockReturnValue(false),
}))

// Mock logger
vi.mock('../utils/logger.js', () => ({
logger: {
Expand Down Expand Up @@ -147,14 +153,26 @@ describe('TerminalColorManager', () => {
await expect(manager.applyTerminalColor('feature/test-branch')).resolves.not.toThrow()
})

it('should log warning about limited Linux support', async () => {
it('should log warning about limited Linux support on native Linux', async () => {
vi.mocked(isWSL).mockReturnValue(false)

await manager.applyTerminalColor('feature/test-branch')

expect(logger.warn).toHaveBeenCalledWith(
expect.stringContaining('limited support on Linux')
)
})

it('should log debug message about tab colors on WSL', async () => {
vi.mocked(isWSL).mockReturnValue(true)

await manager.applyTerminalColor('feature/test-branch')

expect(logger.debug).toHaveBeenCalledWith(
expect.stringContaining('Windows Terminal tab colors are applied at launch time')
)
expect(logger.warn).not.toHaveBeenCalled()
})
})

describe('applyTerminalColor - Windows', () => {
Expand Down
22 changes: 15 additions & 7 deletions src/lib/TerminalColorManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { execa } from 'execa'
import { generateColorFromBranchName } from '../utils/color.js'
import { logger } from '../utils/logger.js'
import { isWSL } from '../utils/platform-detect.js'

/**
* Platform type for color application
Expand Down Expand Up @@ -76,15 +77,22 @@ export class TerminalColorManager {

/**
* Apply terminal color on Linux
* Limited support - graceful degradation with warning
* On WSL, tab colors are applied at launch time via Windows Terminal's --tabColor flag.
* On native Linux, terminal background colors have limited CLI support.
*/
private async applyLinuxColor(_rgb: { r: number; g: number; b: number }): Promise<void> {
logger.warn(
'Terminal background colors have limited support on Linux. ' +
'VSCode title bar colors will still be applied. ' +
'Future versions may add support for specific terminal emulators.'
)
// Future: Detect terminal emulator (gnome-terminal, konsole, etc.) and apply accordingly
if (isWSL()) {
logger.debug(
'Windows Terminal tab colors are applied at launch time via --tabColor. ' +
'VSCode title bar colors will still be applied.'
)
} else {
logger.warn(
'Terminal background colors have limited support on Linux. ' +
'VSCode title bar colors will still be applied. ' +
'Future versions may add support for specific terminal emulators.'
)
}
}

/**
Expand Down
Loading