/**
 * Interactive setup wizard — the one-line onboarding experience.
 *
 * `npx instar` or `instar setup` walks through everything:
 *   1. Project detection + naming
 *   2. Secret management (Bitwarden / local encrypted / manual)
 *   3. Telegram setup (primary communication channel)
 *   4. User setup (name, email, permissions)
 *   5. Scheduler + first job (optional)
 *   6. Start server
 *
 * Launches a Claude Code session that walks you through setup
 * conversationally. Claude Code is a hard requirement — Instar's
 * entire runtime depends on it.
 *
 * No flags needed. No manual config editing. Just answers.
 */
/**
 * Codex model used by setup-wizard and secret-setup micro-sessions when
 * the host framework is codex-cli. Codex CLI's bundled default
 * (gpt-5.2-codex) was retired from ChatGPT-subscription accounts on
 * 2026-04-14 and is API-only since. The wizard targets the subscription
 * path by default, so we pin to a model empirically confirmed-working on
 * ChatGPT auth (see src/providers/adapters/openai-codex/models.ts for
 * the full availability matrix).
 *
 * Exported for the tests-suite canary that asserts this constant is
 * passed to every codex spawn in setup.ts.
 */
export declare const WIZARD_CODEX_MODEL = "gpt-5.3-codex";
/**
 * Launch the conversational setup wizard via Claude Code.
 * Claude Code is required — there is no fallback.
 */
/**
 * Decide what the framework prompt should do given which binaries were
 * detected. Pure function so the decision is unit-testable without
 * spawning readline.
 *
 *   - both installed                → 'prompt'    (ask the user)
 *   - only claude-code installed    → 'claude-code'  (no point asking)
 *   - only codex-cli installed      → 'codex-cli'    (no point asking)
 *   - neither installed             → 'prompt'    (let the user pick;
 *                                       checkFrameworkPrerequisite will
 *                                       then surface the right install
 *                                       message for their choice)
 */
export declare function resolveFrameworkPromptBehavior(claudeDetected: boolean, codexDetected: boolean): 'prompt' | 'claude-code' | 'codex-cli';
export declare function runSetup(opts?: {
    framework?: 'claude-code' | 'codex-cli' | 'gemini-cli' | 'pi-cli';
}): Promise<void>;
/**
 * Idempotently register the Playwright MCP server in
 * ~/.codex/config.toml so codex-runtime agentic sessions can drive
 * browser automation (used by the v1.2.17 Telegram setup primary
 * path). Skips silently if Codex isn't installed (no config dir).
 *
 * TOML is appended hand-rolled rather than parsed: we just check
 * for the section header and add it if missing. Codex's config is
 * regular TOML; an extra section at EOF is a no-op for unrelated
 * config values.
 *
 * Exported for unit testing.
 */
export declare function ensureCodexPlaywrightMcp(): void;
/**
 * Install auto-start so the agent's lifeline process starts on login.
 * macOS: LaunchAgent plist in ~/Library/LaunchAgents/
 * Linux: systemd user service in ~/.config/systemd/user/
 *
 * Returns true if auto-start was installed successfully.
 */
/**
 * Whether the real `launchctl bootout/bootstrap` (loading a plist into the live
 * user launchd) is allowed. Skipped under a test runner (vitest auto-sets
 * `VITEST`) or when `INSTAR_SKIP_LAUNCHCTL_LOAD` is set — so a unit test that
 * exercises the plist-WRITING path (e.g. the init→join handoff test) never
 * loads a tmpdir-pointed plist into the operator's real launchd and leaves
 * stale `status 78` entries behind (test-hygiene fix, MM-Bootstrap Track C
 * follow-up). The plist file is still written/removed; only the live load is
 * gated, so the unit-under-test (the plist content) is unaffected.
 */
export declare function launchctlLoadAllowed(): boolean;
export declare function installAutoStart(projectName: string, projectDir: string, hasTelegram: boolean): boolean;
/**
 * Remove auto-start for a project.
 */
export declare function uninstallAutoStart(projectName: string): boolean;
/**
 * Pick the most durable node path from candidates.
 *
 * Prefers stable, non-versioned paths (e.g. /opt/homebrew/bin/node) over
 * version-specific paths (e.g. /opt/homebrew/opt/node@20/bin/node) because
 * version-specific paths disappear when that version is uninstalled — causing
 * the symlink to break and the agent to become unrecoverable.
 *
 * ABI-AWARENESS (the recurring-SQLite-bane fix): when `nativeModulePath`
 * is given and exists, candidates are first filtered to those that can
 * actually LOAD that native module. This prevents the durability heuristic
 * from picking a node major (e.g. Node 25 via the stable /opt/homebrew/bin
 * symlink) that has no matching better-sqlite3 prebuilt and won't compile
 * from source — the failure that broke SQLite on every `brew upgrade`.
 * Durability is still preferred, but only WITHIN the ABI-compatible set.
 * If NO candidate is compatible, we fall back to the durability-only choice
 * (better a present-but-degraded node than no node at all).
 */
/**
 * Pure, testable core of durable-node selection.
 *
 * @param candidates   ordered candidate node paths
 * @param isUsable     predicate: does this path exist + run? (IO injected)
 * @param isCompatible optional predicate: can this node load the native
 *                     module? When provided and at least one candidate is
 *                     compatible, the pool is narrowed to compatible nodes
 *                     BEFORE the durability heuristic runs. When NO candidate
 *                     is compatible, the durability-only pool is used (better
 *                     a present-but-degraded node than none).
 */
export declare function selectDurableNode(candidates: string[], isUsable: (nodePath: string) => boolean, isCompatible?: (nodePath: string) => boolean): string | undefined;
/**
 * Create or update a stable node symlink at .instar/bin/node.
 *
 * The plist references this symlink instead of a hardcoded node path.
 * This way, when node moves (NVM switch, homebrew upgrade), we only
 * need to update the symlink — not regenerate the entire plist.
 *
 * Returns the symlink path.
 */
export declare function ensureStableNodeSymlink(projectDir: string): string;
/**
 * Generate and install boot wrapper scripts that resolve the shadow install
 * binary at runtime. This ensures machine reboots pick up the auto-updated
 * version instead of the version that was global at setup time.
 *
 * The shadow install is the sole source of truth — no fallback to global.
 * If the shadow install is missing, the wrapper fails loudly instead of
 * silently running a stale global binary (which causes version confusion).
 *
 * Two wrappers are generated:
 *   - instar-boot.sh  — bash wrapper for manual use / Linux systemd
 *   - instar-boot.js  — Node.js wrapper for macOS launchd (avoids /bin/bash TCC)
 *
 * On macOS, launchd spawns /bin/bash without Full Disk Access permissions,
 * causing "Operation not permitted" when accessing project directories.
 * Using node directly as the plist entry point bypasses this because
 * user-installed binaries (homebrew, nvm) are not subject to TCC restrictions.
 */
export declare function installBootWrapper(projectDir: string): {
    sh: string;
    js: string;
};
/**
 * Ensure the boot wrapper exists on disk, regenerating it if missing.
 *
 * The boot wrapper is what launchd exec's — if it's gone, launchd can't
 * bring the agent back after any restart. The wrapper itself can't
 * regenerate itself (chicken-and-egg), but any running process that
 * descends from it can, which closes the loop for future restarts.
 *
 * Returns `true` if a wrapper was written (was missing), `false` if
 * it was already present and nothing was done.
 */
export declare function ensureBootWrapper(projectDir: string): boolean;
/**
 * Install the user-level fleet watchdog (singleton per machine).
 *
 * The fleet watchdog supervises ALL instar agents on the machine. It runs every
 * 5 minutes under launchd, detects crash-looping agents, attempts self-heal
 * (shadow-install reinstall, node-symlink repair, stale-lock cleanup), and
 * escalates to the user via a healthy peer agent's /attention endpoint when
 * self-heal fails N cycles in a row.
 *
 * This is idempotent: writes the latest script + plist regardless of prior state,
 * then reloads the launchd job. Safe to call from every agent setup — the script
 * is per-machine and the launchd label `ai.instar.watchdog` is unique.
 *
 * Returns true if writes occurred, false if no-op.
 */
export declare function installFleetWatchdog(): boolean;
interface NonInteractiveOptions {
    name?: string;
    user?: string;
    telegramToken?: string;
    telegramGroup?: string;
    whatsappBackend?: string;
    whatsappPhone?: string;
    whatsappPhoneNumberId?: string;
    whatsappAccessToken?: string;
    whatsappVerifyToken?: string;
    scenario?: string;
}
/**
 * Run setup without the LLM wizard. Requires all necessary flags.
 * Returns exit code 0 on success, throws on failure.
 */
export declare function runNonInteractiveSetup(opts: NonInteractiveOptions): Promise<void>;
export {};
//# sourceMappingURL=setup.d.ts.map