import { type ModuleSnapshot } from "../modules/runtime.js";
import type { GatewayScope } from "./scoped-gateway.js";
import { type CodexServerEntry } from "./codex-servers.js";
export declare const peerForcedCommand = "command=\"sh ~/.local/share/phren/bridge/dispatch-scoped peer\"";
export declare const forcedCommand = "command=\"sh ~/.local/share/phren/bridge/dispatch\"";
/** A scoped key's forced command. A separate script, so a key added before
 * the Hook can serve its scope fails closed instead of reaching `dispatch`. */
export declare const scopedForcedCommand: (scope: GatewayScope) => string;
export declare function upgradeKeys(text: string): {
    text: string;
    changed: number;
};
/** The existing LaunchAgent's own EnvironmentVariables beyond phren's, read
 * with plutil. A missing or unreadable plist has none. */
export declare function extraLaunchAgentEnvironment(file: string, read?: (file: string) => Promise<string>): Promise<Record<string, string>>;
export interface LaunchAgentValues {
    label: string;
    node: string;
    program: string;
    path: string;
    root: string;
    herdr: string;
    store: string;
    profile: string;
}
/** The Hook's LaunchAgent: phren's own environment first, then every kept key. */
export declare function launchAgentXml(values: LaunchAgentValues, extra?: Record<string, string>): string;
/** The forwarder the forced command uses for the phone's byte pipe. */
export type GatewayKind = "socat" | "nc" | "node";
export interface GatewayEnvironment {
    root: string;
    herdr: string;
    store: string;
    profile: string;
    node: string;
    bundle: string;
    socket: string;
    timing: string;
}
/** Pick the cheapest reliable forwarder at install time: socat, then an nc that
 *  understands Unix sockets, then the node gateway that always works. */
export declare function detectGateway(env?: NodeJS.ProcessEnv): Promise<GatewayKind>;
/** The POSIX sh forced command: the phone's byte pipe goes straight to the Hook
 *  socket through a tiny forwarder, so a loaded machine never pays for a fresh
 *  node process; every other SSH command falls through to the node gateway. */
export declare function gatewayScript(gateway: GatewayKind, environment: GatewayEnvironment): string;
/** The enroll script, for an SSH session the user signed into with a password
 *  (the phone's "Password" sign-in): it adds one restricted phone key, then the
 *  phone connects with that key. It is never the forced command, so a phone key
 *  cannot use it to add more keys. */
export declare function enrollScript(environment: Pick<GatewayEnvironment, "root" | "herdr" | "store" | "profile" | "node" | "bundle">): string;
/** The scoped keys' forced command: always the node gateway (never the raw
 *  socat/nc pipe), told which scope the key holds. An unknown scope or an older
 *  bundle without `ssh-scoped` refuses. */
export declare function scopedGatewayScript(environment: Omit<GatewayEnvironment, "socket" | "timing">): string;
export declare const scopedGatewayPath: (root?: string) => string;
/** The commands that restart the Hook in `domain`, printed when launchd refuses. */
export declare function launchCommands(domain: string, plist: string): string[];
/** How long install waits for Codex turns that would stop with the Hook. */
export declare const CODEX_TURN_WAIT_MS: number;
/** Codex workers still running inside the Hook's service (started by a Hook
 * from before each server got its own scope) stop with it, mid-turn or not.
 * Say which, and wait up to `waitMs` for the running turns to finish. */
export declare function waitForCodexWorkers(waitMs?: number, inService?: () => Promise<CodexServerEntry[]>, log?: (line: string) => void, pollMs?: number): Promise<void>;
export declare function install(version: string, noService?: boolean, force?: boolean): Promise<void>;
export declare function uninstall(): Promise<void>;
interface SettingsEdit {
    file: string;
    before?: string;
    after: string;
}
export declare function planAgentHooks(program: string, remove?: boolean, modules?: ModuleSnapshot, fastClaude?: boolean): Promise<SettingsEdit[]>;
/** The first line of every plugin copy phren wrote; a copy without it belongs to the user. */
export declare const OPENCODE_PLUGIN_MARKER = "// Installed by Phren Hook";
/** Whether to (re)write the installed plugin: a missing copy, or one phren wrote that is now out of date. */
export declare function opencodePluginNeedsWrite(existing: string | undefined, source: string): boolean;
export declare function rollback(): Promise<void>;
export declare function reconcileModuleHooks(store: string, profile?: string): Promise<void>;
export {};
