Mirrors Paperclip's per-adapter ensureCommandResolvable pattern as a single
fail-fast gate at the top of `setup onboard`. Probes {claude, codex, gemini,
pi} via commandExists; throws NoAgentCliError if none resolve. Also surfaces
all four in `setup verify` alongside the existing CODEX check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 1 failed | 846 passed (847)
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
/**
|
|
* setup/agent-cli-check.ts — Detect agent CLIs available on PATH.
|
|
*
|
|
* Clawdie's runtime drives one of several local agent CLIs (claude, codex,
|
|
* gemini, pi). At least one must be resolvable on PATH for onboarding to
|
|
* succeed. This mirrors Paperclip's per-adapter `ensureCommandResolvable`
|
|
* pattern, but as a single fail-fast check at the top of `setup onboard`.
|
|
*
|
|
* No "hello probe" yet — `command -v` is enough; all four were validated
|
|
* end-to-end in doc/AGENT-CLI-VALIDATION.md.
|
|
*/
|
|
import { commandExists } from './platform.js';
|
|
|
|
export interface AgentCli {
|
|
name: string;
|
|
command: string;
|
|
present: boolean;
|
|
}
|
|
|
|
export const AGENT_CLIS: ReadonlyArray<{ name: string; command: string }> = [
|
|
{ name: 'claude', command: 'claude' },
|
|
{ name: 'codex', command: 'codex' },
|
|
{ name: 'gemini', command: 'gemini' },
|
|
{ name: 'pi', command: 'pi' },
|
|
];
|
|
|
|
export function detectAgentClis(): AgentCli[] {
|
|
return AGENT_CLIS.map(({ name, command }) => ({
|
|
name,
|
|
command,
|
|
present: commandExists(command),
|
|
}));
|
|
}
|
|
|
|
export class NoAgentCliError extends Error {
|
|
constructor() {
|
|
super(
|
|
[
|
|
'No agent CLI found on PATH.',
|
|
'Clawdie needs at least one of: claude, codex, gemini, pi.',
|
|
'Install via the ISO npm-globals bundle (claude/gemini/pi) or `pkg install codex`.',
|
|
'See doc/AGENT-CLI-VALIDATION.md for the validated install paths.',
|
|
].join(' '),
|
|
);
|
|
this.name = 'NoAgentCliError';
|
|
}
|
|
}
|
|
|
|
export function requireAtLeastOneAgentCli(): AgentCli[] {
|
|
const clis = detectAgentClis();
|
|
if (!clis.some((c) => c.present)) {
|
|
throw new NoAgentCliError();
|
|
}
|
|
return clis;
|
|
}
|