* Check if Claude Desktop app is installed. * On macOS, checks for /Applications/Claude.app. * On Linux, checks if xdg-open can handle claude:// protocol. * On Windows, checks if the protocol handler exists. * In dev mode, always returns true (assumes dev Desktop is running).
()
| 48 | * In dev mode, always returns true (assumes dev Desktop is running). |
| 49 | */ |
| 50 | async function isDesktopInstalled(): Promise<boolean> { |
| 51 | // In dev mode, assume the dev Desktop app is running |
| 52 | if (isDevMode()) { |
| 53 | return true |
| 54 | } |
| 55 | |
| 56 | const platform = process.platform |
| 57 | |
| 58 | if (platform === 'darwin') { |
| 59 | // Check for Claude.app in /Applications |
| 60 | return pathExists('/Applications/Claude.app') |
| 61 | } else if (platform === 'linux') { |
| 62 | // Check if xdg-mime can find a handler for claude:// |
| 63 | // Note: xdg-mime returns exit code 0 even with no handler, so check stdout too |
| 64 | const { code, stdout } = await execFileNoThrow('xdg-mime', [ |
| 65 | 'query', |
| 66 | 'default', |
| 67 | 'x-scheme-handler/claude', |
| 68 | ]) |
| 69 | return code === 0 && stdout.trim().length > 0 |
| 70 | } else if (platform === 'win32') { |
| 71 | // On Windows, try to query the registry for the protocol handler |
| 72 | const { code } = await execFileNoThrow('reg', [ |
| 73 | 'query', |
| 74 | 'HKEY_CLASSES_ROOT\\claude', |
| 75 | '/ve', |
| 76 | ]) |
| 77 | return code === 0 |
| 78 | } |
| 79 | |
| 80 | return false |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Detect the installed Claude Desktop version. |
no test coverage detected