import type { AgentId } from '../types.js';
import { getShimsDir } from '../state.js';
export { getShimsDir };
export type ConflictStrategy = 'keep-dest' | 'overwrite' | 'ask-per-file';
export interface ConflictInfo {
    agent: AgentId;
    version: string;
    conflicts: string[];
}
/** Generate the shim script content for an agent. Resolves project/default version, auto-installs if missing, and execs the binary. */
/**
 * Current shim schema version. Bump whenever `generateShimScript` changes
 * in a way that requires existing on-disk shims to be regenerated (new
 * flags, fixed argument parsing, new hooks, etc.). `isShimCurrent` reads
 * this marker out of existing shims to decide whether to regenerate.
 *
 * History:
 *   v1 — initial shim (implicit, no marker).
 *   v2 — `--version=...` form in sync/refresh-rules calls; refresh-rules
 *        shim hook for non-@-capable agents.
 *   v3 — sync/refresh-rules flag renamed `--version` → `--agent-version`
 *        so it no longer collides with commander's top-level `--version`.
 *   v4 — project version marker changed from `.agents-version` to a
 *        root-level `agents.yaml`; shim now skips ~/.agents/agents.yaml
 *        when walking up for a project marker.
 *   v5 — emit CODEX_HOME for codex shims so the versioned config (permissions,
 *        sandbox_mode, rules/agents-deny.rules) is actually read by the codex
 *        binary instead of $HOME/.codex.
 *   v6 — hard-disable Codex startup update checks in the generated shims.
 *   v7 — rename `agents refresh-memory` invocation to `agents refresh-rules`
 *        and capability flag `memoryImports` → `rulesImports`.
 *   v8 — versions moved from ~/.agents-system/versions to ~/.agents/versions
 *        (two-repo split: system = shipped defaults, user = operational state).
 *   v9 — claude shim exports CLAUDE_CODE_OAUTH_TOKEN from per-version
 *        .oauth_token file on Linux (keychain-less sandbox fallback).
 *   v11 — when no default is set or the configured version is not installed,
 *         interactively propose the latest already-installed version.
 *   v12 — helper calls inside generated shims use the absolute agents-cli
 *         entrypoint instead of PATH-resolved `agents`.
 *   v13 — validate agents.yaml version strings before constructing binary paths.
 *   v14 — derive `configDirName` from `agentConfig.configDir` relative to $HOME
 *         instead of hardcoding `.${agent}`. Backwards-compatible for every
 *         existing agent (their configDir is `~/.{agent}`); enables nested
 *         layouts like Antigravity's `~/.gemini/antigravity-cli/`.
 *   v15 — remove foreground resource sync / rules refresh from launch shims.
 *         Version homes are reconciled by agents-cli management commands; the
 *         shim hot path only resolves a version and execs the agent binary.
 *   v16 — re-introduce project-scoped compile to the shim hot path via
 *         `agents sync --launch`. This stays fast (filesystem-only): compiles
 *         project rules, mirrors workspace resources, and synthesizes the
 *         scoped plugin marketplaces (agents-cli/agents-system/extras-<alias>/
 *         agents-project). Version-home reconciliation stays out of the hot
 *         path — management commands still own that.
 *   v17 — bash-side skip-fast sentinel under ~/.agents/.cache/launch-sync/.
 *         When the sentinel mtime is newer than every source dir, exec the
 *         agent binary directly without spawning node. Cuts steady-state
 *         hot-path latency from ~680ms (node startup + module init) to ~11ms
 *         (a few stat calls). Node writes the sentinel after each successful
 *         sync. Documented limitation: POSIX dir mtime only updates on
 *         top-level entry add/remove — deep edits to plugin contents won't
 *         trigger auto-resync, run `agents sync` for that.
 */
export declare const SHIM_SCHEMA_VERSION = 30;
/**
 * Generate the full bash shim script for the given agent. The returned string
 * is written to ~/.agents/shims/{cliCommand} and made executable.
 */
export declare function generateShimScript(agent: AgentId): string;
/**
 * Which shim files to materialize for a platform. Pure — testable on any host.
 *
 * POSIX writes the extensionless `#!/bin/bash` shim — the file PATH resolution
 * execs. Windows writes only the `.cmd` companion: PATHEXT makes it the runnable
 * form, and the bash file (mode 0o755 is a no-op there) is never executed — so
 * emitting it is dead weight that only ever confuses `where agents`.
 */
export declare function shimTargetsFor(platform: NodeJS.Platform): {
    bash: boolean;
    cmd: boolean;
};
/** Create the shim(s) for an agent. */
export declare function createShim(agent: AgentId): string;
/** The POSIX pass-through shim for a brand. */
export declare function generateBrandShim(name: string): string;
/** Write a brand's pass-through shim(s) onto PATH; returns the shim path. */
export declare function createBrandShim(name: string): string;
/** True when the file at the given path is an agents-cli brand shim. */
export declare function isBrandShim(filePath: string): boolean;
/** Remove a brand's shim companions. Returns true if anything was removed. */
export declare function removeBrandShim(name: string): boolean;
/**
 * The POSIX gh overload shim. Self-healing by construction: it resolves the real
 * gh (first `gh` on PATH that is not this shims dir) and execs it directly whenever
 * agents-cli is gone, the sentinel is already set (recursion), or the verb is
 * anything but `pr checks` — so a leftover/orphaned shim can never break `gh`.
 */
export declare function generateGhOverloadShim(): string;
/** True when the file is our gh overload shim (not a user's real gh). */
export declare function isGhOverloadShim(filePath: string): boolean;
/**
 * Create/refresh the gh overload shim so a user's `gh pr checks` transparently
 * escapes the GraphQL rate limit. POSIX only in v1 (Windows keeps native gh —
 * resolving the real gh without recursion needs a separate `.cmd` design).
 *
 * Skips (returns null) when there is no real `gh` to overload — shadowing a
 * non-existent binary would only turn a clean "command not found" into shim
 * output. Never clobbers a non-shim `gh` a user placed in the shims dir. If a real
 * gh later disappears, the shim itself fails loud with 127 rather than looping.
 */
export declare function ensureGhOverloadShim(): string | null;
/** Remove the gh overload shim — real gh returns immediately. Called on uninstall. */
export declare function removeGhOverloadShim(): boolean;
/** Remove the shim(s) for an agent. */
export declare function removeShim(agent: AgentId): boolean;
/**
 * Current versioned-alias schema. Bump whenever `generateVersionedAliasScript`
 * changes in a way that requires existing on-disk aliases to be regenerated.
 *
 * History:
 *   v1 — implicit (no marker); no CLAUDE_CONFIG_DIR export, so direct
 *        `claude@X` invocations leaked into ~/.claude (the default version's
 *        symlinked home) and `agents view` never saw the login.
 *   v2 — emit CLAUDE_CONFIG_DIR for claude aliases so each version has its
 *        own isolated config/OAuth slot; stamp a version marker so stale
 *        aliases can be detected and regenerated.
 *   v3 — emit CODEX_HOME for codex aliases so direct `codex@X` invocations
 *        read the versioned permissions/rules instead of $HOME/.codex.
 *   v4 — direct aliases read binaries and config homes from ~/.agents-system.
 *   v5 — hard-disable Codex startup update checks in versioned aliases.
 *   v6 — versions moved from ~/.agents-system/versions to ~/.agents/versions
 *        (two-repo split: system = shipped defaults, user = operational state).
 *   v7 — runtime state split into ~/.agents/.history and ~/.agents/.cache.
 *   v8 — resolve grok/kimi/droid binaries from their real install locations
 *        (~/.grok/downloads, ~/.kimi-code/bin, ~/.local/bin) instead of the
 *        hardcoded node_modules/.bin, which never exists for these three and
 *        made every versioned alias (the path `agents teams` pins to) fail
 *        with "<agent>@<version> not installed". Also emit GROK_HOME.
 *   v9 — kimi was wrong in v8: it npm-installs @moonshot-ai/kimi-code into
 *        node_modules/.bin/kimi (grok/droid ship native binaries elsewhere,
 *        kimi does not). The ~/.kimi-code/bin path never existed for an npm
 *        install and the `command -v kimi` fallback resolved to this alias's
 *        sibling dispatcher shim, re-exec-looping forever. Resolve kimi via the
 *        generic node_modules/.bin branch.
 *  v10 — guard grok's `command -v grok` fallback against resolving to our own
 *        shims dir (same infinite re-exec loop), mirroring droid.
 *  v11 — export DISABLE_AUTOUPDATER=1 for claude aliases so a pinned per-version
 *        install can't self-mutate via Claude Code's background auto-updater.
 *        Explicit user value wins.
 *  v12 — Windows: stop writing the extensionless bash alias next to the `.cmd`
 *        (and delete a lingering one). The version suffix contains dots, so
 *        cmd.exe and PowerShell treat `claude@2.1.201` as a complete filename
 *        with extension `.201`, exact-match the bash script AHEAD of PATHEXT
 *        probing, and ShellExecute it to the `.sh` editor association — the
 *        editor opens the script and the agent never launches. The `.cmd` is
 *        now the only Windows artifact and carries this alias marker so
 *        staleness checks read it directly.
 *  v13 — grok aliases resolve the binary from the versioned home's
 *        .grok/downloads first, then fall back to the global ~/.grok/downloads.
 *        The old template checked only the global dir, so a `grok@<version>`
 *        alias failed with "not installed" whenever the binary was staged into
 *        the versioned home (installer run with GROK_HOME set, or grok
 *        self-update under the shim).
 *  v16 — RUSH-2459: two compounding grok binary-resolution bugs fixed. (1) The
 *        "exact version match" grep ran against `ls`'s FULL PATH output, and
 *        the versioned home's own path always contains the version string
 *        (.../versions/grok/<version>/...), so it matched every candidate
 *        unconditionally and silently degraded to "whatever ls sorts first" —
 *        now matched against each candidate's basename instead. (2) When no
 *        filename genuinely carries the version, the fallback no longer
 *        trusts whatever sorts first: it rejects any grok-* candidate under
 *        1MB (real grok binaries are ~100MB+; a stray wrapper/alias script is
 *        a few hundred bytes) and prefers the most recently modified
 *        survivor. On yosemite-s0 both bugs fired together: a stale, unrelated
 *        grok-0.2.118-* file — a 99-byte wrapper that exec'd cursor-agent —
 *        sorted alphabetically before the real self-updated grok binary and
 *        was silently launched instead.
 */
export declare const VERSIONED_ALIAS_SCHEMA_VERSION = 18;
/**
 * Agents whose config directory can be relocated by an environment variable
 * (the per-agent `managedEnv` block in `generateVersionedAliasScript` below).
 *
 * Only these can be installed with `agents add --isolated`: the versioned alias
 * points that env var at the copy's private home, so the copy never reads or
 * writes the user's real `~/.<agent>`. Every other agent isolates ONLY by
 * adopting `~/.<agent>` via a symlink — which an isolated install deliberately
 * skips — so an isolated copy would silently fall back to (and mutate) the real
 * config dir. For those agents `--isolated` is refused up front.
 *
 * KEEP IN SYNC with the `managedEnv` switch in `generateVersionedAliasScript`.
 * The colocated test `shims.isolation-capability.test.ts` enforces this.
 */
export declare const CONFIG_ENV_ISOLATED_AGENTS: readonly AgentId[];
/**
 * Whether an agent supports a clean `--isolated` install — i.e. its config
 * location can be redirected by an env var so the isolated copy stays fully
 * separate from the user's real `~/.<agent>`. See {@link CONFIG_ENV_ISOLATED_AGENTS}.
 */
export declare function supportsIsolatedInstall(agent: AgentId): boolean;
/**
 * Generate a versioned alias script that directly execs a specific version.
 * e.g., claude@2.0.65 -> directly runs that version's binary
 */
export declare function generateVersionedAliasScript(agent: AgentId, version: string): string;
/**
 * Read the schema version of an on-disk versioned alias. Returns null if the
 * alias doesn't exist or is a pre-v2 alias (no marker — treated as stale).
 */
export declare function readVersionedAliasSchemaVersion(agent: AgentId, version: string): number | null;
/**
 * True if the on-disk versioned alias matches the current schema version.
 */
export declare function isVersionedAliasCurrent(agent: AgentId, version: string): boolean;
/**
 * Regenerate a versioned alias if missing or stale. Mirrors ensureShimCurrent
 * for the main shim — callers can surface a one-line notice when something
 * was upgraded.
 */
export declare function ensureVersionedAliasCurrent(agent: AgentId, version: string): 'created' | 'updated' | 'current';
/**
 * Get the filesystem path for a versioned alias script — the logical
 * (extensionless) launch name. On Windows this is not a real file (see
 * versionedAliasOnDiskFile); stat/read checks must use the on-disk path.
 */
export declare function getVersionedAliasPath(agent: AgentId, version: string): string;
/**
 * The file createVersionedAlias actually materializes for a platform:
 * `<cmd>@<version>.cmd` on Windows, the bare bash script on POSIX. Pure —
 * testable on any host. Mirrors onDiskShimFile for the main shim.
 */
export declare function versionedAliasOnDiskFile(cliCommand: string, version: string, platform: NodeJS.Platform): string;
/**
 * Create a versioned alias for a specific agent version.
 * e.g., claude@2.0.65
 *
 * Same platform split as createShim (shimTargetsFor): POSIX writes the
 * extensionless bash script; Windows writes ONLY the `.cmd`. Unlike the main
 * shim — where the bash file was merely dead weight — a bash alias next to the
 * versioned `.cmd` is actively harmful: the dotted version suffix makes
 * cmd.exe/PowerShell treat `claude@2.1.201` as a complete filename (extension
 * `.201`), so the exact match wins over PATHEXT probing and the shell
 * ShellExecutes the bash script to the `.sh` editor association — the editor
 * opens, the agent never launches. Any legacy bash alias is deleted here.
 */
export declare function createVersionedAlias(agent: AgentId, version: string): string;
/**
 * Remove a versioned alias for a specific agent version. Removes whichever
 * companions exist — the extensionless script (POSIX, or a legacy Windows
 * install that wrote it) AND the `.cmd` (Windows) — mirroring removeShim.
 */
export declare function removeVersionedAlias(agent: AgentId, version: string): boolean;
/**
 * Check if a versioned alias exists (the on-disk artifact for this platform).
 */
export declare function versionedAliasExists(agent: AgentId, version: string): boolean;
/** Get the agent's config directory path in HOME (e.g. ~/.claude). */
export declare function getAgentConfigPath(agent: AgentId): string;
/**
 * Read the user's configured Codex model from their active `~/.codex/config.toml`.
 *
 * Codex runs under a per-version `CODEX_HOME` (see `buildExecEnv`). A dispatch
 * pinned to a version whose home config lacks a top-level `model` key silently
 * falls back to Codex's built-in default (currently `gpt-5.3-codex`), which a
 * ChatGPT-tier account is not entitled to use — the run dies with HTTP 400
 * before doing any work. The user's model preference lives in whichever
 * version-home was active when they set it (`~/.codex` symlinks to it), so it is
 * NOT visible to a run pinned to a different version. Forwarding it via `--model`
 * keeps the user's "default model setup" regardless of the active version-home,
 * and is concurrency-safe (no file writes) when fanning out many parallel runs.
 *
 * Returns the top-level `model` only (ignores `[profile.*]` tables). Best-effort:
 * a missing/unreadable/unset config yields `undefined` (caller keeps prior behaviour).
 */
export declare function readCodexConfiguredModel(): string | undefined;
/** Best-effort account identity for a file-auth agent's credential directory; null when no decodable account claim exists. */
export declare function readAuthFileIdentity(agent: AgentId, configDir: string): string | null;
/** Carry the freshest existing account credential into `toConfigDir` so version switches don't log out file-auth agents. */
export declare function carryForwardAuthFiles(agent: AgentId, toConfigDir: string): void;
/** Switch the agent's config symlink to point at a specific version, backing up any real directory first. */
export declare function switchConfigSymlink(agent: AgentId, version: string): Promise<{
    success: boolean;
    backupPath?: string;
    error?: string;
}>;
/**
 * Switch home-level files (outside the config dir) to per-version symlinks.
 * e.g., ~/.claude.json -> ~/.agents/versions/claude/2.0.65/home/.claude.json
 *
 * Uses atomic rename to avoid data loss if another session is running.
 * On first migration (real file -> symlink), merges global auth into
 * ALL installed versions so they inherit the current account.
 */
export declare function switchHomeFileSymlinks(agent: AgentId, version: string): {
    switched: string[];
    errors: string[];
};
/**
 * Claude reads `.claude.json` at `$CLAUDE_CONFIG_DIR/.claude.json`. Our shim
 * points CLAUDE_CONFIG_DIR at `<ver>/home/.claude`, so Claude's real config
 * file lives at `<ver>/home/.claude/.claude.json` (INSIDE), while
 * `switchHomeFileSymlinks` manages `<ver>/home/.claude.json` (OUTSIDE).
 *
 * To keep both views consistent we make INSIDE a symlink to OUTSIDE. Claude's
 * atomic write (`Uf6`) resolves symlinks before the tmp+rename cycle, so the
 * symlink survives across writes and OUTSIDE remains the single source of
 * truth that agents-cli's home-file machinery already manages.
 *
 * This function idempotently reconciles one version:
 *   - INSIDE missing: create symlink -> `../.claude.json` (create OUTSIDE if needed).
 *   - INSIDE already symlink to OUTSIDE: no-op.
 *   - INSIDE is a real file: it's the authoritative auth state (Claude was
 *     writing to it). Move its content to OUTSIDE (merging with OUTSIDE,
 *     INSIDE wins for `oauthAccount`), then replace INSIDE with the symlink.
 *   - Symlink points elsewhere: replace it.
 */
export declare function ensureClaudeInsideSymlink(version: string): void;
/**
 * Get the current config symlink target version, if any.
 */
export declare function getConfigSymlinkVersion(agent: AgentId): string | null;
/** The on-disk shim filename for a platform: `<cmd>.cmd` on Windows, bare `<cmd>` on POSIX. */
export declare function onDiskShimFile(cliCommand: string, platform: NodeJS.Platform): string;
/** Check whether the on-disk shim exists for an agent. */
export declare function shimExists(agent: AgentId): boolean;
/** True when the on-disk shim's schema version matches the current schema. */
export declare function isShimCurrent(agent: AgentId): boolean;
/**
 * True when the agent shim's baked `AGENTS_BIN` is fine to keep: it either already
 * points at the install we'd generate now, OR points at some OTHER install that
 * still exists on disk (leave it — regenerating could ping-pong two live installs
 * sharing the shims dir). Returns FALSE only when the shim points at a DIFFERENT,
 * now-removed install — the exact drift a deleted dev build (`~/.local/agents-cli-dev`),
 * an old npm-global (`/opt/homebrew`), or a rotated version dir leaves behind. A shim
 * can pass the schema check (`isShimCurrent`) yet still carry that stale path.
 */
export declare function shimPointsAtLiveInstall(agent: AgentId): boolean;
/** Shim files in the shims dir, excluding the hooks/ subdir and @-versioned aliases. */
export declare function listShimFileNames(): string[];
/**
 * Prune a stale, orphaned shim: one that is NOT a managed agent shim and NOT a user
 * alias, whose baked `AGENTS_BIN` points at an install that no longer exists. These
 * are legacy `exec "$AGENTS_BIN" <cmd>` command shims (browser/secrets/sessions/…)
 * left behind by a removed install — the current source never generates them, and
 * they either die with `exit 127` or shadow the real package bin on PATH. Only
 * removed when the baked target is gone, so a working shim is never touched.
 * Returns true if removed.
 */
export declare function pruneOrphanedCommandShim(fileName: string): boolean;
/** Regenerate the shim if missing or older than the current schema; never downgrade a newer on-disk shim. */
export declare function ensureShimCurrent(agent: AgentId): 'created' | 'updated' | 'current';
/** Get the logical (extensionless) shim path for an agent. */
export declare function getShimPath(agent: AgentId): string;
/** Return the first executable on PATH that would shadow the managed shim, excluding the shim itself and legacy pre-split files. */
export declare function getPathShadowingExecutable(agent: AgentId, overrides?: {
    pathDirs?: string[];
    shimPath?: string;
}): string | null;
/**
 * Delete the legacy ~/.agents/shims/<cli> file if it exists, returning whether
 * anything was removed. Pre-split installs put shims under ~/.agents/shims/;
 * the new layout uses ~/.agents-system/shims/. The leftover file causes the
 * repair-prompt loop reported in PROJ-789 — `getPathShadowingExecutable` flags
 * it as a shadow but `addShimsToPath` only edits rc files, never the file
 * itself. Removing it ends the loop.
 */
export declare function removeLegacyUserShim(agent: AgentId, overrides?: {
    homeDir?: string;
}): boolean;
/**
 * Where an adopted launcher's provenance is recorded. Lives under durable
 * `.history` (NOT the regenerable `.cache`) so the reverse pointer to the native
 * binary survives a cache wipe — the shim reads it to fall through to the native
 * binary by absolute path when no managed version resolves. Two lines:
 * line 1 = original binary, line 2 = launcher path (for `--release`).
 */
export declare function getAdoptedRecordPath(agent: AgentId, historyDir?: string): string;
/**
 * The launcher a harness's own installer drops in an early-PATH dir. Detection
 * for adoption keys on the launcher *existing as a symlink resolving outside our
 * shims dir* — NOT on current PATH order. That's deliberate: the shim only loses
 * PATH races in non-interactive / GUI-launched shells, which an interactive
 * `agents` run can't observe via its own PATH. Keying on the durable symlink lets
 * auto-adoption fire for those users too. Returns the launcher path or null.
 */
export declare function findAdoptableLauncher(agent: AgentId, overrides?: {
    homeDir?: string;
    shimsDir?: string;
}): string | null;
export type AdoptResult = {
    adopted: true;
    launcher: string;
    original: string;
} | {
    adopted: false;
    reason: 'no-shadow' | 'already-adopted' | 'not-a-symlink' | 'unsafe-target' | 'error';
    launcher?: string;
};
/**
 * Adopt the harness's own launcher that shadows our shim on PATH.
 *
 * PATH-ordering fixes (editing rc files) can never reliably win: `~/.local/bin`
 * (where grok/droid/etc. self-install) is prepended in `.zshenv`/`.zprofile`
 * for *every* shell, while our shims prepend only lands in `.zshrc`
 * (interactive). No single rc file guarantees "last prepend wins" across zsh's
 * whole sourcing chain, so the shim loses in non-interactive / GUI-launched
 * contexts. Instead of fighting PATH order, we *become* the launcher: replace
 * the shadowing symlink with one pointing at our shim, and record the real
 * original so the shim falls through to it when no managed version is selected.
 *
 * Regression bounds:
 * - Only ever touches a **symlink** (never renames/deletes a real binary).
 * - Records the resolved original + launcher path for lossless restore
 *   (`releaseAdoptedLauncher`), in durable `.history` so a cache wipe can't
 *   orphan the reverse pointer.
 * - Idempotent: a no-op once the launcher already points at our shim.
 * - Never records our own shim as the "original" (would loop).
 */
export declare function adoptShadowingLauncher(agent: AgentId, overrides?: {
    shadowedBy?: string;
    shimsDir?: string;
    historyDir?: string;
}): AdoptResult;
/**
 * Undo `adoptShadowingLauncher`: repoint the launcher back at the recorded
 * original and drop the record. Reversible escape hatch for users who want the
 * native launcher to win. Returns the restored original path, or null if there
 * was nothing to release.
 */
export declare function releaseAdoptedLauncher(agent: AgentId, overrides?: {
    shimsDir?: string;
    historyDir?: string;
}): string | null;
export declare function hasAliasShadowingShim(agent: AgentId, overrides?: {
    homeDir?: string;
}): boolean;
/**
 * Check if shims directory is in PATH.
 */
export declare function isShimsInPath(): boolean;
export declare function stripShimPathLines(content: string, shimsDir: string): string;
/**
 * Get shell configuration instructions for adding shims to PATH.
 */
export declare function getPathSetupInstructions(): string;
interface ShimPathResult {
    success: boolean;
    alreadyPresent?: boolean;
    rcFile?: string;
    /** Human label of where the entry landed, e.g. `~/.zshrc` or `your user PATH`. */
    location?: string;
    /** Per-platform "how to pick it up" hint, e.g. `source ~/.zshrc` / open a new terminal. */
    reloadHint?: string;
    error?: string;
}
/**
 * Add the shims directory to PATH: edits the shell rc file on POSIX, or registers
 * it on the Windows User PATH (registry + WM_SETTINGCHANGE). Idempotent.
 */
export declare function addShimsToPath(overrides?: {
    homeDir?: string;
    shell?: string;
    shimsDir?: string;
}): ShimPathResult;
export declare function listAgentsWithInstalledVersions(): AgentId[];
/**
 * Thrown when an operation would carry an isolated-only agent across the isolation
 * boundary. Callers that can explain the situation catch it and print guidance; the
 * throw is what makes the boundary a property of the code rather than a convention
 * every future call site has to remember.
 */
export declare class IsolationBoundaryError extends Error {
    readonly agent: AgentId;
    readonly operation: string;
    constructor(agent: AgentId, operation: string);
}
/**
 * True when EVERY installed version of `agent` is isolated (and at least one is).
 *
 * This is the switch: installing with `--isolated` is itself the act of opting in,
 * so there is no mode to set and none to forget. It is per-agent, so an isolated
 * codex constrains nothing about claude. And the escape hatch is inherent — remove
 * the isolated copies and the agent is ordinary again, which means the state that
 * grants protection is the same state you delete to drop it.
 *
 * An agent with any NORMAL version is not protected: that install already owns the
 * launcher and the real `~/.<agent>`, so there is no boundary left to defend.
 */
export declare function isIsolationProtected(agent: AgentId): boolean;
/** Refuse `operation` when `agent` is isolated-only. */
export declare function assertIsolationBoundary(agent: AgentId, operation: string): void;
export declare function listAgentsWithNonIsolatedInstalledVersions(): AgentId[];
/**
 * Resource diff between two versions. Each field lists resources present in
 * the current version but missing from the target.
 */
export interface ResourceDiff {
    commands: string[];
    skills: string[];
    hooks: string[];
    memory: {
        file: string;
        currentLines: number;
        targetLines: number;
    }[];
    mcp: string[];
}
/**
 * Check if a ResourceDiff has any differences.
 */
export declare function hasResourceDiff(diff: ResourceDiff): boolean;
