/** A single install method. Exactly one of the keys (npm/brew/script/binary) is set. */
export type InstallMethod = {
    npm: string;
} | {
    brew: string;
} | {
    script: string;
} | {
    binary: BinarySpec;
};
/** Per-platform binary download spec. Keys are `<os>-<arch>` (e.g. darwin-arm64). */
export interface BinarySpec {
    [platform: string]: {
        url: string;
        /** Path inside the archive (relative). Required when url is a .tar.gz/.zip. */
        extract?: string;
    };
}
/**
 * How to verify a CLI is installed. Structured so we can dispatch to spawnSync
 * with an argv array — never through a shell.
 *
 * `which` — just check PATH for `cmd`.
 * `version` — spawn `cmd` with `args` and require exit 0.
 */
export type CheckSpec = {
    kind: 'which';
    cmd: string;
} | {
    kind: 'version';
    cmd: string;
    args: string[];
};
/** Parsed CLI manifest. */
export interface CliManifest {
    /** Name as it appears on the command line (e.g. "higgsfield"). */
    name: string;
    /** One-line summary shown in `agents cli list`. */
    description?: string;
    /** Project homepage; used in detail view + post-install messaging. */
    homepage?: string;
    /** Structured check spec; never a raw shell command. */
    check: CheckSpec;
    /** Install methods tried in order; first one whose tool is available is used. */
    install: InstallMethod[];
    /** Message printed after successful install — typically auth instructions. */
    postInstall?: string;
    /** Origin layer this manifest was resolved from. */
    source: string;
    /** Absolute path to the yaml file. */
    path: string;
}
/** A validation problem in a CLI manifest. */
export interface CliManifestError {
    /** Filename that failed to parse. */
    file: string;
    /** Human-readable reason. */
    reason: string;
}
/**
 * Parse a `check:` field into a CheckSpec. Accepts either a structured object
 * (`{ kind: 'which'|'version', cmd, args? }`) or a legacy whitespace-separated
 * string. String form is split on whitespace and each token is validated against
 * SAFE_CHECK_TOKEN — manifests cannot smuggle in shell metacharacters.
 */
export declare function parseCheckSpec(raw: unknown, defaultName: string): CheckSpec;
/**
 * Parse a single CLI manifest from its YAML contents.
 * Returns a manifest on success; throws on schema violations so callers can
 * decide whether to surface or swallow the error per file.
 */
export declare function parseCliManifest(contents: string, opts: {
    name: string;
    source: string;
    path: string;
}): CliManifest;
/**
 * Discover all CLI manifests resolvable from the current cwd. Returns valid
 * manifests and any parse errors separately so the CLI can show both.
 */
export declare function listCliManifests(cwd?: string): {
    manifests: CliManifest[];
    errors: CliManifestError[];
};
/** Resolve a single CLI manifest by name. Returns null when not declared. */
export declare function resolveCliManifest(name: string, cwd?: string): CliManifest | null;
export declare function hasCommand(cmd: string): boolean;
/**
 * Run the manifest's check. Dispatches on CheckSpec.kind — never invokes a
 * shell, never interpolates strings into a command line.
 */
export declare function isCliInstalled(manifest: CliManifest): boolean;
/**
 * Async, non-blocking sibling of {@link isCliInstalled}. Same dispatch and
 * Windows-shim retry, but over `execFile` so many manifests can be checked
 * concurrently — the fix for RUSH-2136, where `agents doctor --json` ran a dozen+
 * blocking 10s-timeout `spawnSync` checks SERIALLY (measured ~136s on an idle
 * box). `execFile`'s `timeout` still SIGKILLs a wedged check, so a single
 * hanging probe can't stall the whole set past 10s.
 */
export declare function isCliInstalledAsync(manifest: CliManifest): Promise<boolean>;
/**
 * Pick the first install method whose required host tool is available.
 * Returns null when none of the declared methods can run on this host.
 */
export declare function selectInstallMethod(manifest: CliManifest): InstallMethod | null;
/** Render a CheckSpec back to a human-readable command string (display only). */
export declare function describeCheck(check: CheckSpec): string;
/** Short description of a method for display. */
export declare function describeMethod(method: InstallMethod): string;
export interface InstallResult {
    manifest: CliManifest;
    /** Method that was attempted (null if no compatible method existed). */
    method: InstallMethod | null;
    /** True when the post-install `check` passed. */
    installed: boolean;
    /** stdout/stderr captured from the install command, for surfacing on failure. */
    output?: string;
    /** Set when the install runner threw or exited non-zero. */
    error?: string;
}
/**
 * Resolve the directory a `binary` install method downloads/extracts into.
 *
 * `/usr/local/bin` used to be hardcoded here, which fails on Apple Silicon
 * Macs where that directory is root-owned and not user-writable (Homebrew
 * moved on to /opt/homebrew but left /usr/local/bin behind). Resolution
 * order:
 *  1. `AGENTS_CLI_BIN_DIR` — explicit override, used as-is when set.
 *  2. `~/.local/bin` — the XDG user-bin dir already used for shims (see
 *     posixpath.ts / shims.ts); created with mkdir -p if missing.
 *  3. `/usr/local/bin` — last resort, for hosts where it's still writable.
 *     When it isn't either, throw an actionable error naming the env var and
 *     ~/.local/bin instead of letting curl/tar fail with a bare EACCES.
 *
 * Called once per install/dry-run so the same directory is used everywhere
 * that method is described or executed.
 */
export declare function resolveBinDir(): string;
/**
 * Display-only rendering of how a method would be run, for `--dry-run` and
 * status output. Not used by installCli — execution goes through runInstallMethod
 * which dispatches to spawnSync with argv arrays.
 */
export declare function buildInstallCommand(method: InstallMethod): string;
/**
 * Install a single CLI by running its first compatible method. Streams the
 * underlying command's output to the parent terminal so users see brew/npm
 * progress live. Verifies success by re-running `check`.
 */
export declare function installCli(manifest: CliManifest, opts?: {
    dryRun?: boolean;
}): InstallResult;
export interface CliStatus {
    manifest: CliManifest;
    installed: boolean;
}
/** Convenience: list all manifests + their installed-on-host status. */
export declare function listCliStatus(cwd?: string): {
    statuses: CliStatus[];
    errors: CliManifestError[];
};
/**
 * Async sibling of {@link listCliStatus} that probes every manifest CONCURRENTLY
 * (RUSH-2136). The sync version runs each blocking `spawnSync` check one after
 * another, so a dozen host CLIs whose checks are slow serialize into a
 * multi-minute stall on `agents doctor --json`. This awaits them in parallel, so
 * total wall time is the slowest single check (bounded at 10s), not their sum.
 */
export declare function listCliStatusAsync(cwd?: string): Promise<{
    statuses: CliStatus[];
    errors: CliManifestError[];
}>;
