← Reference

Tools

Every tool the agent can call.

Full notes from the app

Tools are registered into the global ToolRegistry. Permission rules can selectively allow/deny per-tool.

67 entries · kcode 0.4.0

67 shown
ToolLibraryWhat it does
Bash
bashtool-bashExecute a bash command through the native shell-host, which runs the in-process brush interpreter (a hard fork — no /bin/bash). Shell state persists across calls like one continuous terminal — each run's cd and exported-env changes (including sourced venv activations) carry into the next call's seed (fresh_state: true opts out; tool_bash.persist_shell_state = false disables). Output is captured in full; a command that exceeds the timeout (120s default) keeps running in the background instead of being killed — the result carries background_exec_id to query/wait/kill via the shell_* tools. The result also carries env_changes, cwd_change, and redirects — the exported variables a command set (e.g. a sourced activate), where it cd'd, and the files it opened via redirection (resolved paths, so a runtime-computed target like > "$LOG" surfaces as the concrete file) — so the agent can carry that state into later commands, plus per-stage pipeline exits and the run's observed footprint: pipestatus (each stage's own exit code for a 2+-stage pipeline, bash $PIPESTATUS semantics — so under the default pipefail you see which stage failed), signal (terminating signal), max_rss_bytes, cpu_user_ms/cpu_system_ms, and distinct_endpoints (count of remote peers contacted; the full endpoint list stays on shell_wait/shell_poll/shell_state). A PTY command that stops at an interactive prompt is handed back immediately — waiting_for_input: true + the detected prompt text + background_exec_id — so the agent answers via shell_write_stdin within seconds instead of burning the full timeout. Pass use_pty: true to run under a pseudo-terminal (so isatty() is true) for tools that refuse to run, colorize, or prompt without a TTY — this merges stdout and stderr into one stream. A sudo/su password ask ([sudo] password for …: / Password:) is the one prompt that does NOT come to the model: it pops a masked password dialog for the user, the answer is typed straight to the command's stdin, and the value is never logged, never in the tool result, never in the transcript; dismissing the dialog kills the command (headless runs fall back to the generic waiting_for_input hand-back). A backgrounded command is exit-watched by default (2026-08-11): when it exits, a pushed <cp:shell-exit> notification (exec id, exit code, output tail) wakes the session even from idle and continues a turn it lands in (cascade rule 5) — the agent continues with other work or ends its turn instead of blocking on shell_wait (one-shot per command; a shell_wait on a watched exec is refused). The one exception is a command parked at an interactive prompt: it is waiting for shell_write_stdin, not an exit, so there the watch stays opt-in via notify_on_exit: true.
shell_spawntool-bashStart a command in the background; returns an exec_id to query later. Accepts use_pty: true for a PTY-backed run (isatty() true), e.g. for a command that prompts. Accepts notify_on_exit: true for a pushed <cp:shell-exit> completion notice (exec id, exit code, output tail) instead of polling.
shell_statustool-bashCurrent status (running/exited/signaled/killed) of a spawned command.
shell_waittool-bashBlock until a command finishes (or times out); returns its outcome.
shell_write_stdintool-bashWrite text to a running command's stdin (e.g. answer an interactive prompt).
shell_signaltool-bashSend a signal (by number) to a command's process group.
shell_killtool-bashKill a command's whole process-group subtree.
shell_listtool-bashList all known commands and their statuses.
shell_polltool-bashLive onCommand snapshot of a running command: elapsed time, captured bytes, aggregate RSS/CPU/fd/thread counts, open network endpoints (sockets with local/remote address and TCP state), and a per-process breakdown (one sample per live pipeline stage — the brush engine spawns each stage, command-substitution, and subshell as its own observed process) — all sampled via proc-observe.
shell_plantool-bashbeforeCommand: analyze a command WITHOUT running it — resolved binary, read-only / sed-in-place flags, predicted side-effect class, and parses (the execution engine's own — brush's — verdict on whether the command will even parse). Returns a plan_id.
shell_proceedtool-bashAct on a plan from shell_plan: run it as-is (proceed), drop it (abort), or run a replacement (modify).
shell_whichtool-bashResolve a command to its binary path on PATH, with its --version line, flavor (gnu/busybox from the version line; bsd inferred for versionless system binaries on macOS — best-effort), canonical (the symlink-chain target when it differs, e.g. a Homebrew entry into its Cellar), and shim — when the path is a version-manager shim (asdf, mise, pyenv, rbenv, nodenv) the manager is named and the real binary it currently selects is reported via <manager> which.
shell_helptool-bashRun a command's --help, falling back to man when --help isn't supported, and return the text (best-effort, capped); the result names its source (--help or man).
shell_envtool-bashThe shell environment: PATH entries, $SHELL, and set env-var names (values omitted to avoid leaking secrets).
shell_projecttool-bashDetect project build files in the cwd (Makefile, package.json, Cargo.toml, justfile, go.mod, …) and parse the invocable targets for the dominant runners (Make targets, npm scripts, justfile recipes) so the agent knows what to run.
shell_quotetool-bashQuote a string into one safe shell token (POSIX single-quoting).
shell_escapetool-bashQuote a list of arguments and join them into one safe command string.
shell_globtool-bashExpand a glob pattern with bash-exact filename expansion (the owned brush engine) against the cwd; returns the matching paths (empty if none match).
shell_eventstool-bashDrain buffered shell events since the last poll (command started/exited, interactive prompts, host restarts).
shell_subscribetool-bashLimit which event classes shell_events buffers (started, exit_code, prompt, …); empty buffers all.
shell_statetool-bashObservability dashboard: a full snapshot per known command — status, elapsed time, captured bytes, per-pid RSS/CPU/fd/thread counts, and open network endpoints. (shell_list is the lightweight id-and-status listing.)
shell_output_headtool-bashFirst N lines of a command's captured output.
shell_output_tailtool-bashLast N lines of a command's captured output.
shell_output_slicetool-bashA byte range of a command's captured output.
shell_output_greptool-bashRegex search over a command's captured output (with context lines).
shell_output_bytestool-bashTotal captured bytes for a command's stream.
Fs
fs_readtool-fsRead a file's contents with line numbers. Supports optional offset (1-based) and limit (line count) for paginating large files. Repeat reads of an unchanged file return a short unchanged-since-last-read marker instead of re-streaming content; refresh=true forces the full content.
fs_writetool-fsOverwrite a file with new contents. Creates parent directories if missing. Overwriting an existing file requires the session to have read its current contents first; brand-new paths need no prior read.
fs_edittool-fsReplace old_string with new_string in a file. Set replace_all=true for global replacement. Read-before-edit is enforced: edits to files whose current contents the session never read, or that changed on disk since the read, are rejected with the remedy named.
apply_patchtool-fsApply a multi-file patch atomically (R#40). Grammar: *** Begin Patch, then *** Add File: (lines prefixed +), *** Delete File:, and *** Update File: (optional *** Move to: rename; hunks of space-prefixed context, - removals, + additions, @@ anchors), then *** End Patch. Hunks locate via the fs_edit fuzzy ladder; a failing hunk anywhere aborts the whole patch with zero writes. Existing files require a prior fs_read (read-before-write gate).
fs_globtool-fsList paths matching a glob pattern. Walks via the project gitignore-aware walker. Returns relative paths.
Grep
greptool-grepSearch code and text with regex patterns (ripgrep-backed). Returns matches as {file, line, match} entries.
Lsp
lsptool-lspCode-intelligence over project language servers: go_to_definition, find_references, workspace_symbol, hover, document_symbol, prepare_call_hierarchy, incoming_calls, outgoing_calls, prepare_rename, and the workspace-wide lsp_outline. Servers are spawned from the per-language [lsp_client.servers] map (defaults to rust-analyzer for Rust); an unconfigured language returns a validation error rather than failing the turn. In the GPU chat, results render as a per-operation view rather than raw JSON — a summary header (find_references · 3 references) over a location list, kind-labelled symbol rows (fn tick, struct SessionPresenter), a nested symbol tree for document_symbol/lsp_outline, cleaned hover markdown, or caller/callee rows for the call-hierarchy ops. Each result row that carries a file location is clickable — click it to open that file at its line in your editor (the same editor resolution as /files, via session_panels.files.editor; VS Code-family, Zed, and Sublime jump to the exact line, other editors open the file).
Web
web_fetchtool-webHTTP GET a URL and return its body as text (capped at 1 MiB). #151 An HTML response (detected by its Content-Type, not by sniffing the body) is converted to Markdown by default so the model reads prose instead of tag soup — <script>/<style> noise dropped, tables preserved; pass raw: true to get the original body untouched. Non-HTML content types (JSON, plain text, …) always pass through verbatim, and a conversion failure falls back to the raw body rather than losing content. The structured result carries content_type and format (markdown|raw).
web_searchtool-webSearch the web through a user-keyed search API — Brave, Tavily, or Exa — and return ranked results in one normalized shape (rank/title/url/snippet, plus published_date and score when the provider reports them — 2026-09-07), whichever backend serves it (P6). Registered only when tool_web.search_provider AND tool_web.search_api_key are both set: no key ⇒ the tool is absent from the agent's toolset entirely (and a key is never sent to a host you didn't name). Takes query (required), count (narrows, never widens, the tool_web.search_max_results cap), and — Tavily only — topic (general/news/finance), time_range (day/week/month/year) and include_domains (a domain list); an unknown topic/time_range is a validation error, never a silently dropped filter. With Tavily the request asks for tool_web.search_depth and, under tool_web.search_include_answer, a short written answer that leads the tool's text as Answer: (structured answer). Each hit's text names its publish date after the URL. Results with no URL are dropped; the model is pointed at web_fetch to read a result's page. Same Network permission posture as web_fetch. LLM-vendor-native server-side search (Anthropic/OpenAI) is the decided follow-on fallback for keyless setups — not built yet.
Vision
view_imagetool-visionLoad an image file from disk (PNG, JPEG, GIF, WebP, BMP, TIFF, ICO) so a vision-capable model can see it. Returns the image on the tool result plus its dimensions and mime; on a non-vision model the image is dropped with a short note. PDFs are rejected — convert to an image first.
Browser
browser_navigatetool-browserOpen a URL in the session's browser (#66) — a headless Chrome-family browser spawned per session on first use (a fresh ephemeral profile each time, killed with the session), shared by the agent's tools and any open /browser tile. Takes url (https://…, file://…, or a data: URL for small test pages). Requires a Chrome-family browser installed (Chrome, Chromium, Edge, Brave, Arc) — otherwise the call reports it plainly. Returns once the page's load event has fired (up to 15 s; a page that never fires it is still handed back), and a refused navigation — a DNS failure, a connection refused, a blocked scheme — is an error naming Chrome's reason rather than a silent success (2026-09-07: a browser_evaluate right after used to run against a page that had not loaded).
browser_clicktool-browserClick an element in the session's browser by CSS selector — a real DOM click, so links, buttons, and framework handlers all fire. Fails with a clear error when nothing matches. Part of the #66 browser stack (see browser_navigate).
browser_filltool-browserSet an input's value in the session's browser by CSS selector, firing input + change events so framework listeners (React/Vue) register it. Takes selector and text. Part of the #66 browser stack.
browser_evaluatetool-browserEvaluate a JavaScript expression in the session's browser page and return its JSON value (promises awaited; 30 s cap). Use for reading page state, extracting data, or custom interactions. The result carries the expression beside its value, so the chat's Evaluate block names what ran (2026-09-07). Read-only. Part of the #66 browser stack.
browser_screenshottool-browserCapture the session's browser viewport as a JPEG — saved under browser_host.screenshot_dir as <session>-<stamp>.jpg and named by path in the result (2026-09-07), shown to the model when vision-capable (the path and dimensions only otherwise), with the page URL/title alongside. The chat renders the capture inline labelled by its file, and the model can re-read the file with view_image. Read-only. Part of the #66 browser stack.
Memory
memory_savetool-memoryPersist a durable fact across sessions. kind is one of user (who the user is), feedback (how to work, with the why), project (goals/constraints not in the code), or reference (external pointers); plus a short kebab-case name, a one-line description (used to judge relevance on recall), and the body. Memories are keyed by name: re-saving a name updates it in place (never a duplicate), and if the body changed the result reports the memory it replaced. Optionally set confidence (0–1, default 1.0), source (user|model|tool), and scopeuser (default; global, travels across every project) or project (stored with this project only). Storage is kcode's SQLite KV, not files.
memory_searchtool-memoryRecall stored memories relevant to a query, returning each match's full body (plus confidence, source, and a written date) ranked by relevance × confidence × recency — a more-relevant, more-trusted, or more-recently-used match ranks higher. Recency tracks use: each recall marks the memory used, so one you rely on stays near the top. The written date is when the content was last written — plain information, not a freshness verdict; judge an old memory's claims against current code for yourself. limit caps the hits (default 8). By default it spans both scopes (each hit is tagged [project] when project-scoped); pass scope (user|project|all, default all) to narrow. The index of names + descriptions is already injected into the system prompt each session; this pulls the full content of the entries that matter for the task.
memory_listtool-memoryList stored memories (id, kind, name, description, confidence, source, scope), oldest first. Pass kind to filter to one category (user|feedback|project|reference), and/or scope (user|project|all, default all) to filter by store — spanning both scopes by default, tagging each project-scoped row [project]. Used to see what is remembered before saving a duplicate, or to find a name to update/delete.
memory_deletetool-memoryForget a stored memory by its name (the name you saved it under; memory_list shows the names) once it has turned out wrong or is no longer relevant. Pass scope (user|project, default user) to name which store to delete from.
Sessions
session_searchtool-sessionsEpisodic recall — search the actual content of past conversations (what was said or done), as opposed to memory_search which recalls curated durable facts. One tool, three shapes inferred from the args (no mode switch): pass query to match message text case-insensitively across every session (returns the top sessions, deduped by session, each with the matching snippet + its message index); pass session_id + around (a message index from a prior result) to read a window of messages around that point (re-anchor on the window's first/last index to page); or pass neither to browse recent sessions (id, title, project, created, message count), newest first. Backed by the session store's persisted per-session message buffer (the same decode the /share exporter uses), so it covers every recorded session; a per-session decoded cache keyed by a blob fingerprint keeps warm queries in-memory. No LLM is involved — every result is real message text.
session_managertool-sessionsList, rename, and delete past sessions. LIST (default, or action: "list") — scoped to the current project by default, project: "all" for every project, or project: <path> for one; returns each session's id, title, project, model, and created date, newest first. RENAME — action: "rename" with session_id + title. DELETE — action: "delete" with session_id (permanent). All sessions live in the one user-scope store, so listing spans projects with no cross-DB access (2026-08-31). Reading a session's contents is session_search; resuming one onto the grid is the recall switcher — this tool only lists and manages the records.
Skills
skill_managetool-skillsProcedural memory — author the agent's own skills (how to do a kind of task, captured once done successfully). Actions via the action arg: create (a new dir-form SKILL.md from name + description + body; refuses to overwrite and refuses a built-in name), edit (replace a skill's whole SKILL.md), patch (find-and-replace oldnew, which must match exactly once), delete (remove a skill — confined to the skills root: refuses a built-in name, a path outside the root, or a symlinked skill directory), and list (the skills under each root with their descriptions). scope picks where: user (default; <data>/skills, global) or project (this repo's .kcode/skills). A skill written here hot-reloads into the live session, so it is runnable immediately via run_skill / /<name>. Guide-only skills only — the Area-11 script-skill machinery (a bundled entry, capabilities, typed schemas) stays hand-authored. Reserve skills for repeatable procedures; use memory_save for a fact, session_search to recall a conversation.
Tasks
tasktool-tasksRecord and update the agent's task list for the current session — kcode's equivalent of claude-code's TodoWrite and opencode's todo. Send the ENTIRE list each call (todos: an array of {content, status, activeForm}); it replaces the session's list (full-list replace), so completed items must be re-sent or they drop off. status is pending, in_progress, or completed, with at most one in_progress at a time; activeForm is the present-tense label shown while an item runs (e.g. "Adding tests"). Backed by the session tasks store (the same store /tasks reads), so the list surfaces to the user in the GPU side panel (#183). Registered under both task and todo names so a model reaching for either finds it. An internal bookkeeping tool (2026-07-27): it mutates only kcode-managed session state, so the permission engine auto-grants it in every mode — it never raises a permission prompt, even in an untrusted project. In the GPU chat its result renders as a real checklist: a N done · N in progress · N pending summary line over rows with status-coloured glyphs, the in-progress row leading with its activeForm caption.
See /tasks todo
todotool-tasksAlias of task — the identical tool under the todo name that opencode and claude-code models expect. Same full-list-replace semantics; see task.
See /tasks task
Meta
meta_ask_user_questiontool-metaPause the turn and ask the user a structured, mixed-form question — options (each with an optional description), header, multi-select, free-text/number fields, and an 'Other' write-in — fielded by an interactive GPU modal. Returns the chosen option(s), any 'other' text, and any field values; headless returns cancelled so the agent never blocks.
set_timertool-metaThe agent's front door to the session loop scheduler — it schedules its own future turns, no user prompt needed. after (one-shot delay), every (recurring interval), and repeat (fire cap) take the same cadence syntax as /loop (10m, 1h30m, bare seconds); omit all three for an after-each-turn on-idle loop. An optional instruction is the prompt run on each fire (omitted = a plain continuation nudge). Returns a t<n> id (or a caller-supplied id) to cancel later. Autonomous by design: no caps or guardrails beyond the context window — the same daemon-owned scheduler the user's /loop drives. cron gives a wall-clock cadence (5-field expression, mutually exclusive with after/every); durable: true persists the timer in the project store — it re-arms on the next spawn/resume after a stop or daemon restart, and a fire point that fell in the away window surfaces as a missed-fire notification (skip-past), never a surprise turn.
cancel_timertool-metaCancel a timer the agent previously set with set_timer, by its id. Stops that loop without touching the user's /loop or any other agent timer (each is namespaced separately).
set_activitytool-metaThe agent declares what it is currently doing — a short intention line (text, required, max 80 chars) like "committing to git" or "searching for API docs". While the turn runs, the line replaces the generic "working"/"Working…" label on the session's Mission Control tile marker and the chat panel's pinned working strip, and lands on the /control timeline as an activity row. Turn-scoped: the display clears when the turn ends, so the agent re-declares as its focus changes. Reports are rate-capped per session (session_daemon.agent_activity_max_per_window per agent_activity_window_secs, default 20 per 60s); over-cap reports are silently dropped (a daemon warn log).
run_commandtool-metaThe agent runs one of a small curated allowlist of session commands on itself — the same actions a user reaches by typing a slash command. command is one of: compact (free context-window space now, like /compact — no value; publishes a request the agent-loop drains at the next round boundary and runs before the next provider call, so freed space benefits the very next step, and shows on the /control timeline as a <cp:compaction> event like any automatic one); model (switch model mid-session — value is a model id like claude-opus-4-8 or a display label like Claude Opus 4.8, resolved here so a bad name is an immediate tool error rather than a silent no-op); effort (set reasoning effort — value is minimal/low/medium/high); goal (set the session goal — value is the goal text, or omit/empty to clear it); rename (set the session's display title, like /renamevalue is the title, or omit/empty to reset to the automatic one); consolidate (distil durable facts from recent sessions into memory now, like /memory consolidate — no value; the daemon spawns a background memory-consolidator subagent, visible on the /control timeline, and always runs regardless of the automatic-runner toggle). model, effort, goal, and rename apply to the live session and persist to the registry exactly like the user's /model, /effort, /goal, /rename — except the agent's goal skips the kickoff turn (the agent is already running) while still arming the self-driving goal driver (#59). The change takes effect from the agent's next step. Folds in the former standalone compact tool. Autonomous by design — the agent decides when to free headroom, switch model, adjust effort, record a goal, retitle the session, or consolidate memory on a long run. It also fires an agent_invocable prompt-shortcut command (e.g. commit) by name: the command's body returns as the tool result for the agent to follow in-turn (the run_skill injection pattern), with value substituted for $ARGUMENTS. A command that does not set agent_invocable: true is refused.
fork_sessiontool-metaThe agent forks its own session — the twin of the user's /fork: the daemon copies the conversation's message buffer into a new live session in the same project, visible as a fresh Mission Control tile in any window showing the source session (an unshown source's fork stays switcher-reachable), inheriting the source's model/effort/autocompact params. title (optional) names the fork, else it falls back to the project directory; first_instruction (optional) is delivered to the fork as its first user message so it starts working immediately — omitted, the fork waits for the user. Fire-and-forget: the tool cannot return the new session's id and the agent cannot reach the fork afterwards; results surface to the user in the fork's tile plus a notification-center entry. Distinct from subagents (a fork is a full user-visible session sharing the chat history, not a scoped delegate with fresh context). Agent forks are rate-capped per source session (session_daemon.agent_fork_max_per_window per agent_fork_window_secs, default 3 per 600s); over-cap requests are dropped with a notification.
run_skilltool-metaThe agent invokes one of its skills on itself — the twin of run_command, the same thing a user reaches by typing /<skill>. After Area 10 the four prompt routines (commit, init, review, security-review) are commands fired via run_command, so run_skill serves only true skills — the Area 11 agent-capability bundles. A skill is an authored bundle: a SKILL.md guide plus optional code/templates, declared tool dependencies (tool-dependencies), a capability declaration ([capabilities], the plugin manifest shape), optional typed input_schema/output_schema, and a parallelizable flag. On invoke, the skill-runner prepares the environment — it takes the (base project, skill) concurrency lock (a non-parallelizable skill busy elsewhere fails fast), resolves the worktree-aware state home at <base>/.kcode/skill-state/<skill>/, and validates inputs against the declared input schema — then returns the prepared guide (with ${CLAUDE_SKILL_STATE} substituted) for the agent loop to drive step by step in-context (not a sub-agent). The state home, tool deps, and output schema ride the tool result; a declared output schema is validated before the result returns. The descriptor lists the available skills (and constrains skill to them); an unknown name is a tool error naming the valid ones.
Essentials Bundle
notifyessentials-bundleThe agent posts a message to the user's notification center — title (required) plus an optional body. The entry lands in the durable cross-project center (kind agent, glyph ◆, info blue) attributed to its plugin ("<title> — <body> (via kcode-notify)"), lights the right-edge seam like a completion (never outranking a blocked or errored session), and — because a reach-out exists to find the away user — escalates to a macOS banner when the kcode window is unfocused. Use it for milestones worth interrupting for (a long build finished, a decision is waiting), not progress chatter: agent notifies are rate-capped per session (session_daemon.agent_notify_max_per_window per agent_notify_window_secs, default 5 per 60s) and over-cap posts are silently dropped (a daemon warn log, never a notification about notifications). Not a native tool: it ships as the built-in kcode-notify Lua plugin bundle (the dogfooding proof that a real tool can be a plugin) whose handler calls the kcode.notify host API under the notify permission — blocklist kcode-notify in a project's plugin policy to remove it.
See /notifications fork_session
Subagent
spawn_subagenttool-subagentDelegate a focused task to a subagent. Runs one turn against the named AgentKind with its declared tool subset + permission mode, returning its final text. The child starts from the prompt it is given and nothing else — it does not see the parent's conversation, and nothing it does is written into the parent's transcript or --resume history. Its cost, tool sessions, and control-plane events still belong to the parent session. A model override (explicit argument or kind frontmatter) is validated at spawn against the resolved backend (2026-07-27): with a ChatGPT OAuth login, a model the Codex subscription backend can't serve is rejected up front with a tool error naming the servable set (e.g. gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex-spark) instead of failing mid-turn. In the GPU chat, spawn/await calls render as a subagent card — kind header, a two-line prompt preview, a spawned · join-N / N rounds meta line, and a foldable result preview — not raw JSON. An optional name gives the child a session-mailbox identity (addressable via send_message), and isolation: "worktree" runs it in a fresh checkout on a kcode-agent/<id> branch — kept and reported (path + branch) when it leaves changes behind, auto-removed otherwise (R#49). output_schema (R#40): a JSON Schema the child's final answer must satisfy — the child turn gains a synthetic submit_result tool and only concludes on a validating payload (5 invalid attempts fail the turn), returned as structured_output.
spawn_subagent_asynctool-subagentFire-and-forget variant of spawn_subagent. Returns a join_id; pair every spawn with one await_subagent. Enables parallel subagent dispatch. Accepts the same name (mailbox identity) and isolation: "worktree" (own checkout on a kcode-agent/<id> branch, kept on changes) parameters as spawn_subagent (R#48/R#49). output_schema (R#40): a JSON Schema the child's final answer must satisfy — the child turn gains a synthetic submit_result tool and only concludes on a validating payload (5 invalid attempts fail the turn), returned as structured_output.
spawn_worktree_sessiontool-subagentStart a long-lived worker session in its own git worktree of the parent's base repo (W2). Unlike spawn_subagent (one turn, disposable, result returned in-turn), the worker is a real session: its own tile and transcript, a fresh checkout on branch kcode/<slug> seeded from .worktreeinclude, its own isolation env ($PORT, KCODE_WORKTREE_* — the W1 slot overlay), and it keeps running after the call returns. task is delivered as the worker's first turn (a complete, self-contained brief — the worker cannot ask the parent questions); optional goal arms the #59 goal driver so the worker self-drives until it declares done/blocked. Returns { session_id, slug, branch, path }. Parent and worker coordinate over cross-session mail (W2b): the parent steers with send_message to the worker's slug, the worker reports with to: "parent", and mail wakes an idle recipient; results land as commits on the branch, and completion/needs-input also reach the user through the notification triggers. A worktree parent spawns siblings under its own base repo (never a worktree of a worktree), sharing one slot pool. Rate-capped per parent session (session_daemon.agent_worktree_max_per_window/agent_worktree_window_secs, defaults 3 per 600s); an over-cap or failed spawn returns as a readable tool error (request/response, unlike the fire-and-forget fork_session). Daemon sessions only — headless runs get a clear "needs the daemon" error.
await_subagenttool-subagentWait for a previously-spawned async subagent to finish and read its result. Each join_id may be awaited exactly once.
advisortool-subagentConsult a second opinion from a DIFFERENT model than the calling session. A fixed read-only sub-agent (the built-in advisor kind — reads code/files, never writes) that takes question plus a self-contained context (it cannot see the conversation) and returns an independent read. It always runs on the model pinned in subagent.advisor_model, which must differ from the session's current model (override else the default) — a same-model call is refused, and an unset pin reports that the user must set subagent.advisor_model rather than auto-picking (2026-08-20). Gated by subagent.advisor_enabled (default on); off removes the tool entirely. Its transcript row is inline (a normal settled row, not floating over the composer) and, when it finishes, shows a one-line summary of the advice it returned (2026-08-31).
Judge
emit_judge_verdicttool-judgeEmit a structured continue/stop verdict from the judge AgentKind at round-end. Drives continuation rule 9.
Mailbox
send_messagetool-mailboxSend a short message to another agent via the session mailbox (R#48). Address a named subagent (spawned with name), main (the primary agent), or * to broadcast — or another session (W2b): a live worktree worker by its slug, and, from inside a worker started by spawn_worktree_session, parent for the session that spawned it. Cross-session mail is daemon-routed into the target session's own mailbox and wakes the target when it is idle; it reaches live sessions only and is rate-capped (session_daemon.agent_mail_*). A name registered in this session wins over a matching slug. Used for mid-turn coordination between sibling subagents, subagent-to-main reporting, and parent↔worker steering.
check_inboxtool-mailboxRead (and clear) the calling agent's session mailbox. Returns the messages sent to this agent by other named agents since the last check (R#48) — including cross-session mail (W2b): a worker's message arrives from its slug, a spawning session's from parent.
manage_sessiontool-mailboxAct on another session — a fork, a worktree worker, or any sibling in the project (B). action: "status" reads the target's live state from the registry (working / idle / needs-input, context fullness, last activity); action: "steer" injects text into the target's next round (or a wake turn when idle) to redirect a running worker; action: "interrupt" cancels its in-flight turn. target is a session id, a worktree worker's slug, or a family relative read off the session's persisted origin: parent (the session that spawned this one), child (this session's most-recent child), or sibling (another live child of this session's parent). Unlike send_message, the daemon answers a manage ask directly — a definite outcome, not a message the target's model reads later. Rate-capped like the other cross-session tools (session_daemon.agent_mail_*).