| addExtension | Installs an extension into a scope from a folder or a git repository (url#ref, sha to pin a commit, and subdir for one inside it): copies its files (never runs a script), checks its manifest, and locks it, enabled, with the marketplace it came from when it did (origin, for a temporary folder, is what the lock says it came from). An extension with the same name in that scope is replaced; its data folder stays. With link, a folder is registered where it is instead, to develop it: not copied, and its files not checked. The packages its npx servers run are fetched into packages (#54), the agent's package cache (packageCacheDir(); by default the scope's). |
| addMarketplace | Adds a marketplace to the agent (its extensions folder, dir) from a folder, a git URL (#ref) or owner/repo, taking a copy; one with the same name is replaced. Asking the person first is the caller's: the kit's command asks them to type its name, unless it's official. |
| agentKitVersion | The version of agent-kit in use, read from its own package.json (next to dist/, or src/ under tsx), e.g. to show it in an agent's header or log. |
| askForChoice | A choice between options, through the port's askChoice() (or askDecision() with the options numbered in the prompt) and the response file, which takes the same answer: the numbers, or the person's own words. |
| askForDecision | Asks the human for a decision through two channels in parallel, whichever answers first wins: (1) the installed InteractionPort (the keyboard, for a person running the process in their own terminal, see tui/terminalInteraction.ts), and (2) a response file, for when something else (e.g. Claude Code, or a non-terminal host driving its own UI — an Electron main process, a Tauri sidecar) is piloting the run and has no interactive stdin to write to. |
| askForManualIntervention | Like askForDecision(), for a manual-intervention checkpoint (see tools/manualLogin.ts). |
| askForText | A free-text answer, through the port's askText() (or askDecision() when it has none) and the response file: trimmed, with its case kept. |
| awareness | The awareness (#43): the agent knows who it is and what it is at each moment of a session, and the person can ask it. A "Who you are" section, about_me (the session's facts, read anew on every call through ExtensionContext.session(), and the agent's guide), and the help skill, how the kit's chat is used, which doesn't change. It needs the spec's identity. |
| buildSessionOptions | Builds the options object passed to the Agent SDK's query() — everything about how the agent runs a session (system prompt, tools, MCP servers, hooks), independent of what is said to start it off (that's the caller's prompt, a plain string for a one-shot run or an AsyncIterable for a multi-turn chat). |
| checkFileScope | The reason to deny toolName with input under scope, or undefined to let it through. Tools other than Read/Write/Edit/Grep/Glob are never judged here, and a call without a path is left for the tool itself to reject. |
| checkPlanScope | The reason to deny toolName with input in plan mode, or undefined to let it through. Anything not known to only read is denied, so a tool nobody thought of can't change anything while the human reviews the plan. |
| checkRequirements | Checks an extension's requirements, all at once. |
| codeStoreDir | The agent's store of extensions' code, by content (#57): where a project's scope keeps its extensions' code. |
| createChatController | Opens the chat's session (the first run with a session opener, --continue picking the latest) and loads the history; start() then draws the run's conversation and sends the initial prompt, send() each line the person types. |
| createConsoleRenderer | The console rendering of runQuery()'s event stream, shared by runChatTui() and by any one-shot run that prints the same events. Streamed text rarely ends in a newline, so every other line (actions, notices, errors) starts by ending the current line only if it isn't already ended — never with a fixed "\n", which leaves a blank line between consecutive actions. |
| createDeferred | Externally-controllable promise — used to know when a chat turn has finished. |
| createFileKnowledgeStore | A KnowledgeStore over the markdown files of knowledgeDir. |
| createFileScopeGate | PreToolUse hook enforcing scope on Read/Write/Edit/Grep/Glob, for the main agent and its subagents alike. Bash, when a subagent has it, is not covered: it can reach any path, which is why Bash-granting features stay opt-in. |
| createFriendlyToolLabel | Builds a friendlyToolLabel(toolName, toolInput) — describe lets the host agent layer its own domain-specific cases (e.g. Playwright's browser_* tools) on top of this kit's generic ones; extraLocalServers names any additional MCP server (beyond this kit's own "approvals"/"manualLogin"/"time") whose tools should be unwrapped without a "[server] " prefix, e.g. "playwright". |
| createHumanApprovalServer | The tools that ask the person, in every mode but autonomous: request_human_approval (right before an action that publishes something visible to others and that's hard to undo), ask_human (a choice between options, in a panel, within the turn) and, when the session can be in plan mode (modeControl), present_plan, the kit's own way out of plan mode (ADR-023): the person runs the plan, keeps planning or cancels. |
| createInputQueue | User message queue backed by a single long-lived generator, for any multi-turn (chat-shaped) caller of query(). |
| createKnowledgeServer | The knowledge MCP server over store. |
| createManualLoginServer | Checkpoint tool for when the agent hits something it can't do itself (typically a login it has no credentials for, or one that fails unexpectedly). Pauses execution until a human confirms they've intervened by hand in whatever live interface the agent is driving (a browser window, say), and then lets the agent continue. There is deliberately no default wording: what counts as a manual intervention is entirely the domain's, so the concrete agent always supplies texts (see AgentSpec.manualInterventionTexts). |
| createModeControl | A ModeControl starting at initial (buildSessionOptions() returns one for its session). |
| createPlanGate | PreToolUse hook for "plan" mode: the agent only reads and plans (see checkPlanScope()). Registered for every session that can be in plan mode and deciding only while isActive() says it is; otherwise it gives no decision, so the call goes on as if it weren't there. It's the kit's own gate, not the SDK's permissionMode: "plan" (ADR-023). |
| createProgressView | The Ink counterpart of createConsoleRenderer() for one-shot ("run"-style) sessions: the same methods and the same text (so onWrite logs exactly what the console version would), plus a spinner with the current action, approval panels and a status bar. Checkpoints go through an Ink InteractionPort until close(). |
| createPromptLoader | Builds a loadPrompt(relativePath, vars) bound to rootDir — so each agent built on this kit supplies its own prompts directory (its own domain content) and gets the same {{key}} substitution/fail-loudly behavior for free. |
| createRunFolder | Creates a new, empty run folder under runsDir. |
| createRunStore | A SessionStore (the SDK's adapter for keeping transcripts elsewhere) that keeps one session in one run folder: conversation.jsonl for the main transcript, subagents/*.jsonl for each subagent's, and session.json with the session's id and which file is which subagent's. The SDK appends to it as the transcript grows and loads from it before resuming (confirmed empirically: a resumed session remembers the conversation, its subagents' transcripts included, even with the CLI's own copy deleted). The CLI still writes that copy under ~/.claude/projects/: it can't be turned off while a store is in use. |
| createSaveToSourcesServer | The tools that keep sourcesDir, the originals the agent reads but never edits (Write/Edit are scoped to the notes folder, see hooks/fileScopeGate.ts): save_to_sources, list_sources and download_to_sources, plus request_file and retire_source when a person can be asked. Nothing is ever overwritten or deleted; the bookkeeping is in sources.ts (this extension's). |
| createStepGate | PreToolUse hook for "interactive" mode: pauses before every action and asks for confirmation (by keyboard or by file, see humanInput.ts), like reviewing a plan step by step. |
| createSubagentBashGate | PreToolUse hook restricting the Bash tool to subagents only, never the main agent directly. See session.ts's buildSessionOptions(), which attaches this hook whenever AgentSpec.buildSubagents() returned something for this config. |
| createSubagentForegroundGate | PreToolUse hook forcing run_in_background: false on every Agent-tool call that spawns one of this session's own subagents. The Agent tool's own input schema defaults to background execution ("Agents run in the background by default", its own description says) unless the model explicitly opts out per call — confirmed empirically (in a real consuming agent) that with a less directive prompt, the model left it on that default, the main turn's "result" fired before the subagent had done anything at all, and the whole invocation was silently lost: no file written, no error, nothing — because the caller's message loop had no code watching for background-task completion (SDKTaskStartedMessage/SDKTaskUpdatedMessage/etc. are never handled). Setting background: false on the AgentDefinition itself (session.ts's agents: {...}) does NOT fix this — confirmed empirically it has no effect on which way the model's own per-call run_in_background input resolves. Rewriting the tool input here, before it ever executes, is the only lever that actually forces synchronous execution regardless of what the model asked for. |
| createSubagentTypeGate | PreToolUse hook restricting the Agent tool to the subagent types this session actually registered (session.ts's agents: {...}, from AgentSpec.buildSubagents()) — confirmed empirically that the Agent SDK also exposes a built-in "general-purpose" subagent_type regardless of what agents lists, and that spawning one that way inherits the whole session's own tools (including Bash, whenever any opt-in subagent turned it on) rather than the narrow AgentDefinition.tools each declared subagent actually declares. Without this hook, that built-in type is a way to route around subagentBashGate.ts entirely: once inside it, agent_id is set exactly like an intended subagent, so the Bash-from-main-thread check alone can't tell them apart — this is exactly what happened in practice in a real consuming agent (the model delegated a plain file deletion to a spontaneous "general-purpose" agent to get at Bash, instead of using its own tools and leaving the stray file alone). |
| createTranscriptLogger | Logs every tool call (request + result) as one JSON line, redacting secrets (e.g. a domain-specific password — see BaseSessionConfig.secrets) plus CLAUDE_CODE_OAUTH_TOKEN, which this kit always scrubs regardless of domain since it owns the auth-token concept (see claudeAuth.ts). |
| describeCapability | A capability's texts in language: English when it has none there, then any it has, then its id. |
| detectLanguage | resolveLanguage() with the running process's arguments, locale and environment. |
| ensureClaudeAuth | The terminal-facing counterpart to resolveClaudeAuth() (core/claudeAuth.ts), which only looks up a token. This one also gets you one: if resolveClaudeAuth(config) comes back empty, it prints why, offers to run "claude setup-token" interactively, and sets the result on process.env.CLAUDE_CODE_OAUTH_TOKEN for this run. Exits the process if the user declines or cancels — there's no agent to run without a token. |
| extensionCatalog | Everything the known marketplaces offer, matching words (in its name, description, category, tags or keywords) when given; its texts in language (the kit's by default). |
| extensionDataDir | An installed extension's data folder: ${CLAUDE_PLUGIN_DATA} in its servers' arguments and variables (a browser profile, a cache), in its scope, outside its plugin and its hash, so it's kept across sessions and updates. Created when a session starts it; removing the extension asks before deleting it. |
| extensionOptionStates | An installed extension's options, as they are now. |
| findPlugin | A plugin found in the known marketplaces: <name>@<marketplace>, or a name only one of them offers. |
| formFields | A form's fields from MCP's requestedSchema: an object of primitive properties. |
| getInteractionPort | The port checkpoints ask through right now, or null. |
| getLanguage | The language of the kit's texts right now. |
| getSharedReadline | The registered readline interface, or null. |
| getTheme | The theme in use right now. |
| inspectMarketplace | Reads a marketplace from a folder, a git URL (#ref) or owner/repo without adding it: what to show before asking. |
| installExtension | Installs a plugin of a known marketplace (<name>@<marketplace>, or a name only one offers) into a scope: the agent's by default (the project's when it has none), the packages its npx servers run into the agent's cache. Asking the person first, for one that isn't the agent's own (needsConfirmation()), is the caller's. |
| installFromMarketplace | Installs <plugin>@<marketplace> (or a plugin only one known marketplace offers) into a scope, locked with where it came from (the packages its npx servers run into options.packages, #54). Its name in the agent is its plugin.json's, as for any extension. |
| installTarget | How an install into scope is done: its npx packages into the agent's cache, and a project's code into the agent's store when the agent has a scope of its own. |
| isExitPromptError | True for the error @inquirer/prompts throws when the user cancels (Ctrl+C) a prompt. |
| isRemoteServer | Whether a server is remote (#61). |
| isSlug | Whether slug is lowercase ASCII words joined by hyphens. |
| knowledge | The built-in knowledge base (ADR-008, ADR-024): an interlinked wiki the agent keeps only through its knowledge_* tools, over a KnowledgeStore (the kit's over markdown files, or the agent's own). The host reads it through apis.knowledge.knowledgeStore. |
| knowledgePluginRoot | Absolute path of the knowledge base's plugin shipped with the kit, next to dist/ (or src/ under tsx). |
| knowledgePromptSection | The "Knowledge base" section appended to the system prompt: the layers and the working rules, listing pageTypes, for a knowledge base reached through the knowledge_* tools (ADR-024). With a sources folder, also how summaries and originals are matched (by the model, with the two extensions' tools: each owns its data, #30); the folder itself is the sources' section. preferences (the active preference pages) are listed by title, up to PREFERENCES_IN_PROMPT. |
| linkedIds | The ids every [text](id) link in markdown points to (links that look like page ids). |
| listInstalled | Every extension installed in the scopes, the project's first. |
| listMarketplaces | The marketplaces the agent knows, with their manifests when they can be read. |
| listRuns | The runs under runsDir that kept a conversation, newest first; runs without session.json are left out. |
| memory | The memory of the person (#34): what the agent learns about the person it works for, kept across all their projects in a folder of its own, reached only through its tools (recall, remember, forget). What it remembers must quote the person's own messages, which it hears through a UserPromptSubmit hook (and, for a resumed run, from the run's conversation). |
| messagesFor | A language's texts; any it lacks come from English (nested groups key by key). |
| packageCacheDir | Where an agent keeps the packages its extensions' npx servers run: in its scope (the project's when it has none), shared by both. |
| parseId | type/slug split, or null when it isn't one. |
| readConversation | The human's messages and the agent's replies in a run's conversation, in order. |
| readExtensionManifest | Reads an extension's manifest from its plugin. |
| readExternalManifest | Reads an extension's manifest, checking what the kit needs from it. |
| readMarketplaceManifest | Reads and checks a marketplace's .claude-plugin/marketplace.json. |
| remoteHosts | The hosts an extension's remote servers talk to, for the person to read before installing it. |
| remoteServerName | The name a session gives an extension's remote server: its own, prefixed with the extension's. The SDK's CLI keeps OAuth tokens by server name (confirmed empirically, CLI 2.1.300): a server named like one in the runner's own Claude Code would sign in with the runner's token. |
| removeExtension | Removes an extension from a scope (its files and its lock entry; a linked one's folder is left where it is), and its data folder with deleteData; false when it wasn't there. |
| removeMarketplace | Forgets a marketplace (its copy and its entry); the extensions installed from it stay. False when it wasn't known. |
| resolveClaudeAuth | Pure lookup, no I/O and no console output of any kind — safe to call from a headless/non-interactive consumer (a server, an Electron main process) as much as from a terminal one. |
| resolveLanguage | The language for the kit's texts and the agent's replies: --language=<code>, then the agent's option, then the system's language, then English. A code that is asked for but isn't supported falls through to the next source, with a warning. Pure: detectLanguage() fills the sources from the running process. |
| resolvePluginSource | Where a plugin's source points: a folder of the marketplace's copy, a git repository, an npm package or a zip. |
| restoreExtensions | Gets what a workspace's lock lists and this computer lacks (#57): each extension's code into the agent's store, from where it came (its marketplace, its git repository at its commit, its folder), checked against the lock's hash, and the packages its npx servers run into the agent's cache. It trusts nothing: the workspace still asks before they run. What can't be got says why (a marketplace the agent doesn't know, another version there now, a folder that isn't on this computer). |
| runChatInk | The Ink counterpart of runChatTui(), with the same options, session log and history file: history in the scrollback, the reply streaming in place, a spinner with the current action (and a subagent's), approval panels, "/command" completion and a status bar. Checkpoints go through an Ink InteractionPort while the chat runs, so no second stdin reader ever competes with Ink's; the response file keeps working as always. |
| runChatTui | A ready-to-run interactive terminal chat loop, assembled from this kit's own chat primitives: createInputQueue() feeds typed lines into a multi-turn query() session, runQuery()'s normalized event stream is rendered to the console (streamed text, friendly action labels via createFriendlyToolLabel(), turn failures), and this loop's own readline.Interface is registered via setSharedReadline() so any human-in-the-loop checkpoint the session hits (the interactive-mode step gate, or the guided-mode approval/ manual-login tools — see terminalInteraction.ts) prompts on the same interface instead of a second one fighting it for stdin's raw mode. |
| runExtensionCommand | The extension command an agent exposes in its own binary (#37), e.g. captain extension add ./jokebook --project: installs, removes, enables, disables and lists the extensions in its two scopes. Returns false when argv isn't this command (so the agent goes on), and sets process.exitCode to 1 on an error. |
| runQuery | Thin wrapper around the SDK's own query(): same two-argument shape (a plain string for a one-shot run, or an AsyncIterable<SDKUserMessage> — see createInputQueue() — for a multi-turn chat), translating its raw message stream into AgentEvents as described above. Every other control surface of the underlying Query (interrupt, close, supportedCommands) is passed through unchanged. |
| runWizard | Asks steps in order and resolves with every answer by step name. A step's message, choices or default can depend on earlier answers, and when skips it, so a consumer's whole interactive menu becomes a list of step definitions. |
| scopePrivateDir | Where a scope keeps what's the person's, not the workspace's: its extensions' data and secrets (#57). The agent's scope, its own folder; a project's, a folder of its own in the agent's (<agent scope>/.projects/<project>-<hash>/), so nothing private travels with a project. An agent without a scope of its own keeps it in the project's. |
| setExtensionEnabled | Enables or disables an installed extension in a scope; false when it isn't there. |
| setExtensionOptions | Sets an installed extension's options (#55), each from what the person typed (undefined clears it), checked against its userConfig: sensitive ones into the scope's secrets, the rest into its lock. A running session's servers take them when they start again. |
| setInteractionPort | Installs the port every checkpoint asks through (null: answer through the response file only). One per process. |
| setLanguage | Sets the language of the kit's texts directly (a host that resolved it itself, tests). |
| setSharedReadline | Registers the chat's readline interface, so checkpoints ask on it instead of opening a second one (null to unregister). |
| setTheme | The kit's default theme with overrides on top: only the roles given change. |
| sources | The sources folder: originals kept as obtained, read with Read and extract_text, added and retired only through its tools (sourceFiles). It knows nothing of a knowledge base (#30). |
| sourcesPromptSection | The "Sources" section appended to the system prompt whenever there's a sources folder, with or without a knowledge base: what the originals are and how they come and go. projectDir and sourcesDir give the folder's name as the model reads it. |
| summarizeToolResponse | Avoids bloating the transcript with large payloads (browser-tool screenshots/base64). |
| switchLanguage | Switches the kit's language on purpose, e.g. the person picked another in a chat (#47): from then on it wins over --language and config.language, until switched again. The session says so to the model when it opens next (the controller's setLanguage() reopens it). |
| togglePlanMode | What the chats' /plan does: switches control into plan mode, or, when it's already there, back to the mode it was entered from ("guided" if it started in plan mode). Returns the new mode, or null when this session can't be in plan mode (an autonomous one). |
| truncate | Cuts text to max characters, with "…" at the end. |
| truncatePath | Cuts a path to max characters from the front, with "…": unlike truncate() (which cuts the tail off long freeform text), a path's most useful part, the file name, is at the end. |
| trustWorkspace | Trusts a workspace's extensions (its project scope's, all or names) with the code its lock has now: what the person does when the chat asks, or with extension trust. The names trusted. |
| updateExtension | Updates an installed extension from the marketplace it came from: a fresh copy of the marketplace, then installed again in the same scope (its data and options kept). One that didn't come from a marketplace is installed again with extension add. |
| updateMarketplace | Takes a fresh copy of a known marketplace from where it came from. |
| withToolLabels | A formatAction that shows the tools in labels() with their label, and any other with formatAction (the kit's by default). labels is read on every call, so it can follow the session in use (/resume opens another). |
| withToolPhrases | A toolPhrase that counts the tools in labels() with their phrase, and any other with toolPhrase. |