/**
 * Helpers shared by PreToolUse "wrap" hosts (cursor, codebuddy).
 *
 * These hosts intercept a host-level Bash/Shell tool call, wrap its command
 * line with `tokenjuice wrap -- <host-shell> -lc '<original>'`, and return a
 * host-shaped response so the agent's tool output flows through tokenjuice's
 * compaction path.
 *
 * The wire-format response (`updated_input` vs. `hookSpecificOutput`) is
 * host-specific and stays in the per-host module. Everything else — resolving
 * the installed tokenjuice launcher, picking a host shell, quoting the
 * wrapped command, detecting already-wrapped commands — is host-agnostic and
 * lives here.
 */
export type WrapLauncherOptions = {
    /** When true, bypass the `PATH` lookup for an installed tokenjuice binary and route through the caller's build. */
    local?: boolean;
    /** Override the binary/entrypoint path. Defaults to `process.argv[1]`. */
    binaryPath?: string;
    /** Override the node executable used when dispatching a `.js` entrypoint. Defaults to `process.execPath`. */
    nodePath?: string;
};
export type BuildWrapLauncherHookCommandOptions = WrapLauncherOptions & {
    /** Host-specific CLI subcommand name, e.g. `"cursor-pre-tool-use"` or `"codebuddy-pre-tool-use"`. */
    subcommand: string;
    /** Error context used when `binaryPath` cannot be resolved. */
    hostName: string;
};
export declare function isRecord(value: unknown): value is Record<string, unknown>;
export declare function isExecutableFile(path: string): Promise<boolean>;
export declare function pathExists(path: string): Promise<boolean>;
/**
 * Walk `PATH` and return the first executable `tokenjuice` (or Windows
 * variant) found. Empty segments and missing entries are skipped.
 */
export declare function resolveInstalledTokenjuicePath(): Promise<string | undefined>;
/**
 * Resolve a single shell candidate string to an executable path. Accepts
 * either an absolute path (checked directly) or a bare name (walked against
 * `PATH`). Returns `undefined` when the candidate is unusable.
 */
export declare function resolveShellPath(shell: string): Promise<string | undefined>;
/**
 * Try each candidate in order and return the first one that resolves. Callers
 * pass the host-specific ordering (e.g. for codebuddy:
 * `[tool_input.shell, TOKENJUICE_CODEBUDDY_SHELL, SHELL, "bash", "sh"]`).
 *
 * `undefined` / empty / whitespace-only candidates are skipped silently so
 * callers can pass the raw env-var values without filtering first.
 */
export declare function resolveHostShell(candidates: (string | undefined)[]): Promise<string | undefined>;
/**
 * Build the command stored in a PreToolUse hook entry, shaped like:
 *
 *     <launcher-command> <subcommand> --wrap-launcher <launcher>
 *
 * Where `<launcher-command>` is either the launcher executable itself or
 * `<node-path> <launcher-js-path>` when the launcher points at a `.js`
 * entrypoint (so cursor/codebuddy can invoke a repo-local build without
 * chmod'ing the script).
 */
export declare function buildWrapLauncherHookCommand(options: BuildWrapLauncherHookCommandOptions): Promise<string>;
/**
 * Build the command the host should ask the agent to run — the original
 * command routed through `tokenjuice wrap` and the selected host shell:
 *
 *     <launcher-command> wrap -- <shell-path> -lc '<original>'
 *
 * `wrapLauncher` comes from the PreToolUse hook's `--wrap-launcher` argv so
 * the dispatched binary matches the one the host installed.
 */
export declare function buildWrappedCommand(params: {
    wrapLauncher: string;
    shellPath: string;
    command: string;
    source?: string;
    nodePath?: string;
}): string;
/**
 * Detect whether a command has already been wrapped by tokenjuice. Matches
 * three shapes:
 *
 *   `tokenjuice wrap ...`                     — bare executable on PATH
 *   `/abs/path/to/tokenjuice wrap ...`        — absolute launcher (pnpm link,
 *                                               homebrew, etc.)
 *   `node /some/dist/cli/main.js ... wrap`    — node-dispatched local build
 *
 * Avoids double-wrapping when a tool call is already routed through tokenjuice
 * (e.g. the user invoked `tokenjuice wrap --raw -- <cmd>` explicitly).
 */
export declare function commandAlreadyWrapped(command: string): boolean;
