feat: add npx CLI entry point with install, runtime, and IDE detection commands

Replaces the old git-clone installer with a direct npm package copy workflow.
Supports 13 IDE auto-detection targets, runtime delegation to Bun worker,
and pure Node.js install path (no Bun required for installation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-02-26 23:45:00 -05:00
parent e2a230286d
commit 85eb796b18
8 changed files with 1320 additions and 0 deletions
+174
View File
@@ -0,0 +1,174 @@
/**
* IDE Auto-Detection
*
* Detects which AI coding IDEs / tools are installed on the system by
* probing known config directories and checking for binaries in PATH.
*
* Pure Node.js — no Bun APIs used.
*/
import { execSync } from 'child_process';
import { existsSync, readdirSync } from 'fs';
import { homedir } from 'os';
import { join } from 'path';
import { IS_WINDOWS } from '../utils/paths.js';
// ---------------------------------------------------------------------------
// IDE type and metadata
// ---------------------------------------------------------------------------
export interface IDEInfo {
/** Machine-readable identifier. */
id: string;
/** Human-readable label for display in prompts. */
label: string;
/** Whether the IDE was detected on this system. */
detected: boolean;
/** Whether claude-mem has implemented setup for this IDE. */
supported: boolean;
/** Short hint text shown in the multi-select. */
hint?: string;
}
// ---------------------------------------------------------------------------
// PATH helper
// ---------------------------------------------------------------------------
function isCommandInPath(command: string): boolean {
try {
const whichCommand = IS_WINDOWS ? 'where' : 'which';
execSync(`${whichCommand} ${command}`, { stdio: 'pipe' });
return true;
} catch {
return false;
}
}
// ---------------------------------------------------------------------------
// VS Code extension directory scanner
// ---------------------------------------------------------------------------
function hasVscodeExtension(extensionNameFragment: string): boolean {
const extensionsDirectory = join(homedir(), '.vscode', 'extensions');
if (!existsSync(extensionsDirectory)) return false;
try {
const entries = readdirSync(extensionsDirectory);
return entries.some((entry) => entry.toLowerCase().includes(extensionNameFragment.toLowerCase()));
} catch {
return false;
}
}
// ---------------------------------------------------------------------------
// Detection map
// ---------------------------------------------------------------------------
/**
* Detect all known IDEs and return an array of `IDEInfo` objects.
* Each entry indicates whether the IDE was found and whether claude-mem
* currently supports setting it up.
*/
export function detectInstalledIDEs(): IDEInfo[] {
const home = homedir();
return [
{
id: 'claude-code',
label: 'Claude Code',
detected: existsSync(join(home, '.claude')),
supported: true,
hint: 'recommended',
},
{
id: 'gemini-cli',
label: 'Gemini CLI',
detected: existsSync(join(home, '.gemini')),
supported: false,
hint: 'coming soon',
},
{
id: 'opencode',
label: 'OpenCode',
detected:
existsSync(join(home, '.config', 'opencode')) || isCommandInPath('opencode'),
supported: false,
hint: 'coming soon',
},
{
id: 'openclaw',
label: 'OpenClaw',
detected: existsSync(join(home, '.openclaw')),
supported: false,
hint: 'coming soon',
},
{
id: 'windsurf',
label: 'Windsurf',
detected: existsSync(join(home, '.codeium', 'windsurf')),
supported: false,
hint: 'coming soon',
},
{
id: 'codex-cli',
label: 'Codex CLI',
detected: existsSync(join(home, '.codex')),
supported: false,
hint: 'coming soon',
},
{
id: 'cursor',
label: 'Cursor',
detected: existsSync(join(home, '.cursor')),
supported: true,
},
{
id: 'copilot-cli',
label: 'Copilot CLI',
detected: isCommandInPath('copilot'),
supported: false,
hint: 'coming soon',
},
{
id: 'antigravity',
label: 'Antigravity',
detected: existsSync(join(home, '.gemini', 'antigravity')),
supported: false,
hint: 'coming soon',
},
{
id: 'goose',
label: 'Goose',
detected:
existsSync(join(home, '.config', 'goose')) || isCommandInPath('goose'),
supported: false,
hint: 'coming soon',
},
{
id: 'crush',
label: 'Crush',
detected: isCommandInPath('crush'),
supported: false,
hint: 'coming soon',
},
{
id: 'roo-code',
label: 'Roo Code',
detected: hasVscodeExtension('roo-code'),
supported: false,
hint: 'coming soon',
},
{
id: 'warp',
label: 'Warp',
detected: existsSync(join(home, '.warp')) || isCommandInPath('warp'),
supported: false,
hint: 'coming soon',
},
];
}
/**
* Return only the IDEs that were detected on this system.
*/
export function getDetectedIDEs(): IDEInfo[] {
return detectInstalledIDEs().filter((ide) => ide.detected);
}