#!/usr/bin/env bun import { APIError } from "@letta-ai/letta-client/core/error"; import type { AgentState } from "@letta-ai/letta-client/resources/agents/agents"; import type { Message } from "@letta-ai/letta-client/resources/agents/messages"; import { getResumeData, type ResumeData } from "./agent/check-approval"; import { getClient } from "./agent/client"; import { setAgentContext, setConversationId as setContextConversationId, } from "./agent/context"; import type { AgentProvenance } from "./agent/create"; import { getLettaCodeHeaders } from "./agent/http-headers"; import { ISOLATED_BLOCK_LABELS } from "./agent/memory"; import { getModelPresetUpdateForAgent, getModelUpdateArgs, getResumeRefreshArgs, resolveModel, } from "./agent/model"; import { updateAgentLLMConfig, updateAgentSystemPrompt } from "./agent/modify"; import { resolveSkillSourcesSelection } from "./agent/skillSources"; import { LETTA_CLOUD_API_URL } from "./auth/oauth"; import { type ParsedCliArgs, parseCliArgs, preprocessCliArgs, renderCliOptionsHelp, } from "./cli/args"; import { ConversationSelector } from "./cli/components/ConversationSelector"; import { normalizeConversationShorthandFlags, parseCsvListFlag, parseJsonArrayFlag, resolveImportFlagAlias, } from "./cli/flagUtils"; import { formatErrorDetails } from "./cli/helpers/errorFormatter"; import { ensureFileIndex } from "./cli/helpers/fileIndex"; import type { ApprovalRequest } from "./cli/helpers/stream"; import { ProfileSelectionInline } from "./cli/profile-selection"; import { validateConversationDefaultRequiresAgent, validateFlagConflicts, validateRegistryHandleOrThrow, } from "./cli/startupFlagValidation"; import { runSubcommand } from "./cli/subcommands/router"; import { permissionMode } from "./permissions/mode"; import { settingsManager } from "./settings-manager"; import { startStartupAutoUpdateCheck } from "./startup-auto-update"; import { telemetry } from "./telemetry"; import { loadTools } from "./tools/manager"; import { clearPersistedClientToolRules } from "./tools/toolset"; import { debugLog, debugWarn, isDebugEnabled } from "./utils/debug"; import { markMilestone } from "./utils/timing"; // Stable empty array constants to prevent new references on every render // These are used as fallbacks when resumeData is null, avoiding the React // anti-pattern of creating new [] on every render which triggers useEffect re-runs const EMPTY_APPROVAL_ARRAY: ApprovalRequest[] = []; const EMPTY_MESSAGE_ARRAY: Message[] = []; void ensureFileIndex(); function printHelp() { // Keep this plaintext (no colors) so output pipes cleanly const usage = ` Letta Code is a general purpose CLI for interacting with Letta agents USAGE # interactive TUI letta Resume last conversation for this project letta --new Create a new conversation (for concurrent sessions) letta --resume Open agent selector UI to pick agent/conversation letta --new-agent Create a new agent directly (skip profile selector) letta --agent Open a specific agent by ID # headless letta -p "..." One-off prompt in headless mode (no TTY UI) # maintenance letta update Manually check for updates and install if available letta memfs ... Memory filesystem subcommands (JSON-only) letta agents ... Agents subcommands (JSON-only) letta messages ... Messages subcommands (JSON-only) letta blocks ... Blocks subcommands (JSON-only) letta connect ... Connect providers from terminal OPTIONS ${renderCliOptionsHelp()} SUBCOMMANDS (JSON-only) letta memfs status --agent letta memfs diff --agent letta memfs resolve --agent --resolutions '' letta memfs backup --agent letta memfs backups --agent letta memfs restore --agent --from --force letta memfs export --agent --out letta agents list [--query | --name | --tags ] letta messages search --query [--all-agents] letta messages list [--agent ] letta blocks list --agent letta blocks copy --block-id [--label