diff --git a/packages/mosaic/src/runtime/detector.ts b/packages/mosaic/src/runtime/detector.ts index ba5265d..c80167c 100644 --- a/packages/mosaic/src/runtime/detector.ts +++ b/packages/mosaic/src/runtime/detector.ts @@ -33,6 +33,12 @@ const RUNTIME_DEFS: Record< versionFlag: 'version', installHint: 'See https://opencode.ai for install instructions', }, + pi: { + label: 'Pi', + command: 'pi', + versionFlag: '--version', + installHint: 'npm install -g @mariozechner/pi-coding-agent', + }, }; export function detectRuntime(name: RuntimeName): RuntimeInfo { diff --git a/packages/mosaic/src/runtime/installer.ts b/packages/mosaic/src/runtime/installer.ts index 065497e..078a235 100644 --- a/packages/mosaic/src/runtime/installer.ts +++ b/packages/mosaic/src/runtime/installer.ts @@ -7,6 +7,7 @@ export function formatInstallInstructions(name: RuntimeName): string { claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode', + pi: 'Pi', }; return `To install ${labels[name]}:\n ${hint}`; } diff --git a/packages/mosaic/src/runtime/mcp-config.ts b/packages/mosaic/src/runtime/mcp-config.ts index 852767d..b014c36 100644 --- a/packages/mosaic/src/runtime/mcp-config.ts +++ b/packages/mosaic/src/runtime/mcp-config.ts @@ -16,6 +16,8 @@ export function configureMcpForRuntime(runtime: RuntimeName): void { return configureCodexMcp(); case 'opencode': return configureOpenCodeMcp(); + case 'pi': + return configurePiMcp(); } } @@ -69,6 +71,31 @@ function configureCodexMcp(): void { writeFileSync(configPath, content, 'utf-8'); } +function configurePiMcp(): void { + const settingsPath = join(homedir(), '.pi', 'agent', 'settings.json'); + ensureDir(settingsPath); + + let data: Record = {}; + if (existsSync(settingsPath)) { + try { + data = JSON.parse(readFileSync(settingsPath, 'utf-8')) as Record; + } catch { + // Start fresh if corrupt + } + } + + if ( + !data['mcpServers'] || + typeof data['mcpServers'] !== 'object' || + Array.isArray(data['mcpServers']) + ) { + data['mcpServers'] = {}; + } + (data['mcpServers'] as Record)['sequential-thinking'] = MCP_ENTRY; + + writeFileSync(settingsPath, JSON.stringify(data, null, 2) + '\n', 'utf-8'); +} + function configureOpenCodeMcp(): void { const configPath = join(homedir(), '.config', 'opencode', 'config.json'); ensureDir(configPath); diff --git a/packages/mosaic/src/stages/runtime-setup.ts b/packages/mosaic/src/stages/runtime-setup.ts index cd689fe..472cf0a 100644 --- a/packages/mosaic/src/stages/runtime-setup.ts +++ b/packages/mosaic/src/stages/runtime-setup.ts @@ -4,7 +4,7 @@ import { detectRuntime, type RuntimeInfo } from '../runtime/detector.js'; import { formatInstallInstructions } from '../runtime/installer.js'; import { configureMcpForRuntime } from '../runtime/mcp-config.js'; -const RUNTIME_NAMES: RuntimeName[] = ['claude', 'codex', 'opencode']; +const RUNTIME_NAMES: RuntimeName[] = ['claude', 'codex', 'opencode', 'pi']; export async function runtimeSetupStage(p: WizardPrompter, state: WizardState): Promise { p.separator(); diff --git a/packages/mosaic/src/types.ts b/packages/mosaic/src/types.ts index 0e494ee..e5c50ab 100644 --- a/packages/mosaic/src/types.ts +++ b/packages/mosaic/src/types.ts @@ -1,7 +1,7 @@ export type WizardMode = 'quick' | 'advanced'; export type InstallAction = 'fresh' | 'keep' | 'reconfigure' | 'reset'; export type CommunicationStyle = 'direct' | 'friendly' | 'formal'; -export type RuntimeName = 'claude' | 'codex' | 'opencode'; +export type RuntimeName = 'claude' | 'codex' | 'opencode' | 'pi'; export interface SoulConfig { agentName?: string;