diff --git a/libs/platform/src/editor.ts b/libs/platform/src/editor.ts index a29608d7..a2210385 100644 --- a/libs/platform/src/editor.ts +++ b/libs/platform/src/editor.ts @@ -13,6 +13,7 @@ import { homedir } from 'os'; import { join } from 'path'; import { access } from 'fs/promises'; import type { EditorInfo } from '@automaker/types'; +import { createLogger } from '@automaker/utils'; const execFileAsync = promisify(execFile); @@ -20,6 +21,9 @@ const execFileAsync = promisify(execFile); const isWindows = process.platform === 'win32'; const isMac = process.platform === 'darwin'; +// Logger for editor detection +const logger = createLogger('editor'); + // Cache with TTL for editor detection let cachedEditors: EditorInfo[] | null = null; let cacheTimestamp: number = 0; @@ -118,6 +122,43 @@ const SUPPORTED_EDITORS: EditorDefinition[] = [ }, ]; +/** + * Check if Xcode is fully installed (not just Command Line Tools) + * xed command requires full Xcode.app, not just CLT + */ +async function isXcodeFullyInstalled(): Promise { + if (!isMac) return false; + + try { + // Check if xcode-select points to full Xcode, not just CommandLineTools + const { stdout } = await execFileAsync('xcode-select', ['-p']); + const devPath = stdout.trim(); + + // Full Xcode path: /Applications/Xcode.app/Contents/Developer + // Command Line Tools: /Library/Developer/CommandLineTools + const isPointingToXcode = devPath.includes('Xcode.app'); + + if (!isPointingToXcode && devPath.includes('CommandLineTools')) { + // Check if xed command exists (indicates CLT are installed) + const xedExists = await commandExists('xed'); + + // Check if Xcode.app actually exists + const xcodeAppPath = await findMacApp('Xcode'); + + if (xedExists && xcodeAppPath) { + logger.warn( + 'Xcode is installed but xcode-select is pointing to Command Line Tools. ' + + 'To use Xcode as an editor, run: sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer' + ); + } + } + + return isPointingToXcode; + } catch { + return false; + } +} + /** * Try to find an editor - checks CLI first, then macOS app bundle * Returns EditorInfo if found, null otherwise @@ -128,6 +169,13 @@ async function findEditor(definition: EditorDefinition): Promise