/** * After settings are written, make the mod plugins loadable the way a person * would (ADR-404): refresh (or add) the `ruflo` marketplace clone, then * `claude plugin install --scope ` for each plugin the clone * carries. The refreshed clone is what makes a plugin load; the install adds * a cached copy (and the `claude plugin list` entry) that survives a later * stale clone. * * Fixed argv through execFile, never a shell; each step bounded. The `add` * step passes `--scope` so the marketplace is declared in the same settings * file ruflo already wrote, not in user settings. `~/.claude.json` is never * touched by ruflo. No `-y`: a marketplace-declared command is never accepted * on a person's behalf. */ import { type MarketplaceEntry, type ModPlugin, type Scope } from './install.js'; import { type ReadFs } from './plugin-resolve.js'; export declare const MARKETPLACE_TIMEOUT_MS = 150000; export declare const INSTALL_TIMEOUT_MS = 60000; export interface ExecResult { code: number; stdout: string; stderr: string; } export type Exec = (file: string, args: readonly string[], opts: { cwd: string; timeout: number; env: NodeJS.ProcessEnv; }) => Promise; export declare const nodeExec: Exec; /** The `claude` a shell would run, when it can be exec'd without a shell. */ export declare function findClaudeBinary(env: NodeJS.ProcessEnv, home: string): string | null; export type StepState = 'ok' | 'failed' | 'pending'; export interface RepairStep { argv: string[]; state: StepState; output: string; } export interface RepairOptions { projectRoot: string; scope: Scope; /** Claude Code's config directory, read after the marketplace step to see what the clone carries. */ configDir: string; claude: string; plugins?: readonly ModPlugin[]; /** The marketplace the settings declare (default github ruvnet/ruflo). */ marketplace?: MarketplaceEntry; exec?: Exec; env?: NodeJS.ProcessEnv; fs?: ReadFs; /** * ADR-509 ยง2.2: called once the marketplace step has refreshed the clone and * before any `claude plugin install`; a plugin id it returns is not installed * (its step is a failure naming the reason). */ beforeInstall?: (clone: string | null) => { blocked: ReadonlyMap; }; } /** * `update` when Claude Code already knows ruflo by the wanted source; else * `add` it at the scope, which also switches a ruflo marketplace known by * another source (Claude Code keeps one per config dir). */ export declare function marketplaceArgv(scope: Scope, known: boolean, wanted?: MarketplaceEntry): string[]; export declare function uninstallArgv(id: string, scope: Scope): string[]; export declare function installArgv(id: string, scope: Scope): string[]; /** * Marketplace first (a failure there stops everything: nothing below can * work); then one install per plugin, every failure collected. A plugin the * refreshed clone does not carry is pending when not required, a failure when * required. */ export declare function repairPluginInstall(opts: RepairOptions): Promise<{ ok: boolean; steps: RepairStep[]; }>; /** `claude plugin uninstall` for each id, every failure collected. */ export declare function uninstallPlugins(opts: { projectRoot: string; scope: Scope; ids: readonly string[]; claude: string; exec?: Exec; env?: NodeJS.ProcessEnv; }): Promise<{ ok: boolean; steps: RepairStep[]; }>; //# sourceMappingURL=plugin-repair.d.ts.map