import { type CliContext } from '../context.js'; import type { ClaudeInvoker } from '../invoker.js'; export interface DoctorCheck { name: string; ok: boolean; detail: string; /** Commands that would resolve this, shown together at the end. */ fix?: string[]; /** Worth mentioning, but not a failure (e.g. an optional integration is off). */ note?: boolean; } export interface DoctorDeps { /** Tracked file list (defaults to `git ls-files`); injected in tests. */ gitTrackedFiles?: () => string[]; /** Claude resolver (defaults to getClaude); injected in tests. */ resolveClaude?: () => ClaudeInvoker; /** Browser debug-port reachability probe; injected in tests. */ checkBrowserPort?: (port: number) => Promise; /** Shell-profile resolver for the shim check; injected in tests. */ resolveShimProfile?: () => string | null; /** Skip checks that need the network (used by tests and offline runs). */ skipNetwork?: boolean; /** Injected in tests for the identity check. */ fetchImpl?: typeof fetch; } /** Fail if any credential or profile file is tracked in git. */ export declare function auditGitSafety(trackedFiles: string[]): DoctorCheck; /** The transparent `claude` shim: installed, and safe to uninstall ccx under? */ export declare function auditShim(context: CliContext, deps?: DoctorDeps): DoctorCheck; /** * Is ccx visible while Claude is running? * * The shim is transparent by design, so nothing on screen says ccx is on. The * status line is the one place that can, which makes "is it wired up" worth * reporting rather than leaving someone to wonder whether switching is * happening at all. */ export declare function auditStatusline(context: CliContext): DoctorCheck; /** Session history: ccx must SHARE ~/.claude/projects, never fork it. */ export declare function auditSharedHistory(context: CliContext): DoctorCheck; /** Account health: REAL login state per account (probed), naming who needs login. */ export declare function auditAccounts(context: CliContext): Promise; /** * Confirm each profile holds the account it claims to. This is the only check * that can catch profiles that have been scrambled or that share one login, * because local files report the recorded identity, not the token's owner. */ export declare function auditIdentities(context: CliContext, deps?: DoctorDeps): Promise; /** * Do any two profiles hold the same login? * * Checked locally and without the network, because this is the state that * destroys accounts: renewing a shared login ends it for the other profile. It * needs to be visible immediately, not only when a network check is possible. */ export declare function auditSharedLogins(context: CliContext): DoctorCheck; /** * Cap state: informational, unless nothing is left to run on. * * "Left to run on" counts the accounts that could ACTUALLY start a session, not * the enabled ones. An account whose login the token endpoint has refused is * still enabled and cannot be used, so counting it hid the situation this check * exists for: every usable account capped while a couple of dead profiles made * the total look healthy. That is exactly the state it reported "ok" in. */ export declare function auditCaps(context: CliContext): DoctorCheck; /** Informational: report which installed editors are pointed at ccx. */ export declare function auditEditor(context: CliContext): DoctorCheck; export declare function runDoctor(context: CliContext, deps?: DoctorDeps): Promise<{ checks: DoctorCheck[]; ok: boolean; }>; /** Print the doctor report and return 0 when all checks pass, 1 otherwise. */ export declare function doctorCommand(context: CliContext, deps?: DoctorDeps): Promise;