Skip to content

Tools

The catalog of tools kin can call — what each one does, its risk kind, and whether it runs without asking.

Adding a tool? See Extending kin — tools, kinds, and profiles for the step-by-step walkthrough (subclass Tool, set kind, implement async run(args, ctx), route untrusted output through frame_untrusted, register in default_registry(), add tests/test_harness/ coverage).

How tools map to permissions

Every tool declares a risk kindread, edit, shell, meta, mcp, network, or outpost — and the active mode maps that kind to a decision. So whether a tool auto-runs, asks, or is refused depends on the mode, not just the tool. Read and meta tools never prompt; edits auto-apply in auto and ask in strict; shell runs sandboxed in auto, while in strict it auto-allows only commands proven read-only and asks otherwise. (The workflow tool sets its kind to ask directly, so it always asks — you approve the model-authored script before it runs.) See Modes & permissions for the full matrix.

The "auto-approves?" column below describes strict mode (the ask-first posture); in auto — the launch default — edits auto-apply and shell runs sandboxed.

Filesystem

Dedicated read tools so the model can navigate without going through gated shell. Edits are atomic and return a unified diff.

Tool What it does Kind Auto-approves?
read_file Read a text file, PDF, Word (.docx) or Excel (.xlsx) document, or image (PNG/JPEG/GIF/WebP returned as image blocks; SVG as text), with line numbers. Macros in .docm/.xlsm are ignored, not analyzed. Defaults to the first 2,000 lines; page with offset/limit. read Yes
write_file Create or overwrite a file atomically (temp file + rename). Returns a unified diff. edit Asks
edit_file Replace an exact old_string with new_string (must match exactly and be unique unless replace_all). Returns a unified diff. edit Asks
ls List a directory's entries (directories first, with sizes). Workspace-confined. read Yes
glob Find files by glob pattern (**/*.py), newest first. Workspace-confined. read Yes
grep Search file contents by regular expression; returns path:line: text. Workspace-confined. read Yes

Diagnostics after edit

write_file and edit_file append a lint pass's output when it fails — v1 covers .py via ruff check (an opt-in ty typecheck pass layers on top, default off — see diagnostics_ty). A clean pass appends nothing; a failing one appends diagnostics (ruff): N issue(s) plus up to 20 lines / 2000 chars of output, so the model can often self-correct in the same turn without a separate shell call. shutil.which-gated (a project without ruff installed degrades to a silent no-op) and bounded by a 10s timeout — diagnostics can never fail or delay-block a write. This is a subprocess pass, not an embedded LSP (see DR 0066 for why). On by default; KIN_DIAGNOSTICS=0 / diagnostics_after_edit = false disables it.

Notebooks

Jupyter .ipynb tools using nbformat. Edits address cells by a stable cell_id from read_notebook.

Tool What it does Kind Auto-approves?
read_notebook Read a notebook as structured cells (source, cell_id, execution_count, outputs). Matplotlib image/png outputs return as image blocks. read Yes
edit_notebook Edit a cell in place by cell_id, or append a new cell. Preserves nbformat metadata and untouched execution counts. edit Asks

Shell

One gated shell tool, plus a background trio for long-running processes.

Tool What it does Kind Auto-approves?
shell Run a bash command, foreground or (with run_in_background) detached. shell Only if provably read-only
shell_list List live background shells and their last output line. meta Yes
shell_output Read a background shell's output by shell_id; wait=true blocks until it exits. meta Yes
shell_kill Kill a background shell by id. meta Yes

A foreground shell auto-runs only when the command classifier proves it read-only; otherwise it asks. See The shell allowlist.

Code interpreter (Python)

A stateful Python REPL for iterative computation and data work — one persistent interpreter per session, so variables, imports, and files survive across calls (the difference from running python -c through shell, which forgets everything between calls). The value of a trailing expression is echoed like a REPL.

Tool What it does Kind Auto-approves?
run_code Run Python in the session's persistent kernel. Exceptions come back as a readable traceback and the kernel (with its state) survives; a timeout (default 30 s, max 600 s) kills the kernel — state lost, next call starts fresh. shell Never in strict (arbitrary code is never provably safe); sandboxed in auto
run_code_reset Kill the kernel; the next run_code call starts a fresh interpreter. The escape hatch for memory growth or a polluted environment. meta Yes

run_code shares the shell kind on purpose: in auto mode the kernel is spawned inside the same OS sandbox shell commands run under (writes confined to the workspace, network off, secrets scrubbed from its environment — see Auto mode & the OS sandbox); in strict mode it always asks; it is refused while planning. Under KIN_SANDBOX=container (Outpost) it runs unwrapped in-container like shell does. It is not the workflow tool — that runs an in-process orchestration script that fans out subagents; run_code is the OS-sandboxed subprocess for the code itself.

Both tools are stdlib-only and registered by default; set KIN_RUN_CODE=0 (or run_code_enabled = false) to remove them.

Planning & interaction

Harness-internal tools that plan, ask you, or hand off a finished plan. See Planning for the lifecycle.

Tool What it does Kind Auto-approves?
todos Update the turn's task list (a full rewrite each call); drives the pinned task panel. meta Yes
ask Ask you a question and wait — single-select, multi-select, or free text. meta Yes
write_plan Write (or revise) the plan file under .kin/plans/. Usually called by the planner subagenttask(subagent_type='planner', ...) — for non-trivial changes; the top-level model can also call it inline for a small fully-converged one-file change (see Planning). The first call in a planning sequence auto-enters the read-only planning freeze on the top-level session; only a human leaves it (via present_plan's modal or a bare /plan). meta Yes (capability reduction)
present_plan Present the tracked plan file (read fresh off disk) for approval — only your choice at the modal (or a bare /plan) lifts the planning freeze. The modal offers three choices — approve & execute (keep context), approve, clear & re-inject (reseed just the plan + an execution preamble), or review first (the model dispatches an adversarial critic subagent itself, applies fixes with write_plan, and re-presents — staying frozen). meta Yes (it is the approval flow)

Settings

Tools that let kin help tune your settings mid-conversation — the same diff-approval gate as the artifact editor, but reachable by the model. The model can only ever write sampling/model knobs; containment knobs (mode / sandbox* / shell_allowlist) and secrets/endpoints (api_key / base_url / brave_api_key) are refused. See Modes & permissions § Model-writable settings and turn the guidance on with /settings.

Tool What it does Kind Auto-approves?
read_settings Read the live settings — sampling/model values plus which knobs are changeable. Credentials are masked to [SET]/[NOT SET]; each knob is tagged model-writable / human-only. Includes a short settings guide. read Yes
propose_settings Propose a partial patch of sampling/model settings (temperature, top_p, top_k, max_tokens, context_window, enable_thinking, effort, cache_ttl, model). You review a diff and approve before anything is written; the change applies to new sessions. Any containment/secret/endpoint key is refused with a banner naming it. The effort knob is the per-serve picker vocabulary (Anthropic 5-value, OpenAI 3-value, Z.ai 7-value, Qwen 3-value) that the /effort command dispatches live — reasoning_effort is intentionally human-only so the picker stays the single cross-wire source of truth. Top-level only (a subagent can't propose); frozen during planning. meta Asks (you approve the diff)

Delegation

Tools that spin up isolated work or load reusable prompts.

Tool What it does Kind Auto-approves?
task Delegate a focused job to a subagent with its own isolated context. Set run_in_background=true to detach and follow up via agent_list / agent_output / agent_kill. meta Yes (spawn only)
agent_list List every agent (foreground + background) — id, fg/bg marker, status, profile, output line. meta Yes
agent_output Read an agent's buffered output by agent_id; wait=true blocks until it finishes. meta Yes
agent_kill Kill an agent by id — works on a running foreground child too (cancels the child, not the parent). Idempotent on a finished agent. meta Yes
agent_message Send the next instruction to an idle subagent (running agent can't be messaged — wait with agent_output(wait=true)). Foreground returns ONLY the new turn's prose (the full transcript is on the row, readable via agent_output); set run_in_background=true to detach (fires a fresh subagent_completed reminder on the next user turn). meta Yes
tasks Maintain a session-long DAG of work items (add / update / complete / remove / list / blocked). Cycle-checked; auto-unblocks downstream on complete. meta Yes
skill List available skills, or load a named skill's instructions into the conversation. meta Yes
workflow Run a model-authored async def main() that fans out subagents over deterministic control flow; only its returned string re-enters context. Read/analysis fan-out, or parallel edits via isolation: "worktree"; supports structured schema output and within-run resume (resume_from_run_id). Capped at 6 concurrent / 64 total agents per run (the caps are also stated to the model in the tool description). ask Asks (you approve the script)

See Subagents, Workflows (fan-out orchestration), Agents (foreground + background subagents + --agent) and Tasks for detail.

One opt-in search_workspace tool — a ranked, chunk-aware full-text search over the workspace's file content, the complement to exact-match grep. See Workspace search for how it works.

Tool What it does Kind Auto-approves?
search_workspace Ranked (BM25) full-text search over chunked workspace content; returns path:line hits best-first. Filters by path prefix and kind (markdown / text). Query must be ≥ 3 characters. read Yes

search_workspace is registered only when search_enabled is set (KIN_SEARCH_ENABLED=1 or the search_enabled key — off by default), so the model isn't shown it unless you opt in. It's a local stdlib SQLite FTS5 index — zero new dependencies, no network, no egress. The index DB lives outside the workspace under ~/.kin/index/ (so it's never committed or surprise-tracked); secret files (.env, ~/.ssh, .mcp.json, …) and .gitignored paths are excluded from both the index and the results. Because results are in-workspace content the model already reads freely, they carry the same trust as grep output. See Workspace search.

Memory

One memory tool over the persistent cross-session store under ~/.kin/memory/ — Anthropic's memory-tool command set, so models trained against it drive it natively. See Memory for categories, recall, and the end-of-run reflection pass.

Tool What it does Kind Auto-approves?
memory view / create / str_replace / insert / delete / rename over markdown files under the virtual /memories root. create overwrites; delete/rename refuse the root itself; every path is canonicalized and confined to the memory root. edit view always; mutations auto-apply in auto, ask in strict

memory is registered by default; memory_enabled = false / KIN_MEMORY=0 unregisters it (project-ok — the knob only removes the tool; containment lives in the path guard). Mutations are confined to the memory root instead of the workspace — that root is the global-only memory_dir setting. See Memory.

Web

web_fetch is always available. The two Brave-backed tools are registered only when BRAVE_API_KEY is set, so the model is never shown a tool it cannot use.

Tool What it does Kind Auto-approves?
web_fetch Fetch a URL and return its main content as markdown (or extracted PDF text). SSRF-safe. read Yes
web_search Search the web (Brave) and return a list of results. Requires BRAVE_API_KEY. read Yes
web_context Search and return model-ready, re-ranked context chunks (Brave LLM Context). Requires BRAVE_API_KEY. read Yes
cite_check Check a batch of cited URLs for liveness (HEAD-first, no body downloads) with a Wayback-snapshot substitute for dead ones. Same SSRF guard as web_fetch. read Yes

See Web tools for enabling Brave and choosing between them, and Deep research for the citation-liveness gate cite_check backs.

Browser

A text-only headless browser (Playwright + Chromium, one per session) for pages that need interaction or JavaScript rendering — the model reads ARIA snapshots and acts on elements by role + accessible name. No vision, no screenshots, no JS execution.

Tool What it does Kind Auto-approves?
browser One tool, an action enum: navigate / snapshot / click / fill / select / press / back / close. Every state-changing action returns the fresh page snapshot. http/https only, SSRF-guarded navigations, no downloads. browser Yes in auto (asks in strict)

Registered only when the optional browser extra is installed (uv sync --extra browser + uv run playwright install chromium); KIN_BROWSER=0 / browser_enabled = false unregisters it. Denied while planning. See Browser for the action reference, the safety boundary (and its documented limit), and the browser_allow_private local-dev escape hatch.

Remote (SSH)

One opt-in ssh tool for remote ops / deploys — the single controlled network hole that runs outside the auto-mode OS sandbox.

Tool What it does Kind Auto-approves?
ssh Run a command on a remote host over SSH. Structured args only — host (required) / user / port / command; there are no raw flags. Honors your ~/.ssh/config (host aliases, IdentityFile, ProxyJump/bastions). mcp Never (always asks)

The ssh tool is registered only when an ssh_hosts allowlist is set (global-only — see settings), so the model is never shown it unless you opt in, and host must be on that allowlist. It always asks for approval (its mcp kind), and it is refused while planning. Because it runs outside the sandbox, its safety rests on the structured-args contract: the argv is built from a fixed set of hardening -o flags plus only your four fields, validated to reject injection (newlines, %-tokens, shell metacharacters, and a leading - in host/user that ssh would otherwise parse as an option) before anything spawns. See Auto mode & the OS sandbox.

Git network ops (push / pull / fetch)

Local git (status/add/commit/branch) already works through shell. Auto mode's OS sandbox runs shell with network off, so git push/pull/fetch can't succeed through it even after approval — these three tools run the network op outside the sandbox instead, with structured args (no raw command/flags field), the same shape as ssh. Unlike ssh, they are always registered — a git remote/branch is a charset-restricted bare name, not an arbitrary host, so there's no opt-in allowlist to gate.

Tool What it does Kind Auto-approves?
git-push Push to a remote. remote (optional) / branch (optional, requires remote) / force (optional — always --force-with-lease, never raw --force). mcp Never (always asks)
git-pull Fetch + merge/rebase from a remote. remote / branch (same pairing rule) / rebase (optional, --rebase). mcp Never (always asks)
git-fetch Fetch refs without touching the working tree. remote / branch (same pairing rule) / all (optional, --all). network Yes in auto (asks in strict)

git-push and git-pull reuse the mcp kind (always ask, denied while planning), same reasoning as ssh. git-fetch gets the lighter network kind instead — it doesn't mutate the working tree or push anything out, so it auto-allows in auto mode (still asks in strict, still denied while planning: fetch writes .git/objects and updates remote-tracking refs, a real side effect). See Modes & permissions for the network kind, and Auto mode & the OS sandbox for why these run outside the sandbox at all.

Every argv is built element-by-element (shell=False) from only remote/branch/one flag, validated against an anchored allowlist before anything spawns — a leading - (option injection), control characters, %, \, :, and @ are all refused, which also kills ext::/file:///user@host: transport syntax outright. "Always allow" is scoped to remote+branch+the one risky flag (not just the tool name), so approving one push can't silently authorize a push to a different branch or with force=true. git-clone is deferred — it writes a new directory, a workspace-escape question the other three don't have.

Outpost

A tool pair speaking to your Outpost's v1 HTTP API — the always-on automation layer (scheduler, job runs, inbox) kin can check on and drive from the local loop. outpost reads; outpost-send acts.

Tool What it does Kind Auto-approves?
outpost Read the automation layer: jobs (list runs, cursor-paginated), job (one job + its runs), report (a run's markdown report), inbox (open items awaiting an answer), schedules (standing/upcoming schedules). Structured args only — op + that op's fields. outpost Yes in auto (asks in strict)
outpost-send Act on the automation layer: submit (hand off a new job — workspace + prompt, optional deliver_matrix to deliver over Matrix), answer (answer an open inbox item), cancel (cancel a job). mcp Never (always asks)

jobs and schedules answer different questions — jobs is a runs-backed listing ("what ran"), schedules reads schedule definitions directly ("what's due to run": standing cron/every jobs regardless of enabled state, plus a future one-shot). A standing schedule that hasn't fired yet is invisible to jobs; use schedules for "what's scheduled today"/cron questions. Like inbox, schedules needs the operator scope on your Outpost service (set from the Developers portal) — a non-operator token gets refused.

Both tools register only when outpost_url and outpost_token are both set (global-only — see settings), so the model is never shown a tool it can't back. outpost gets its own outpost kind — the same lighter, auto-allow-in-auto treatment as git-fetch, but a dedicated kind because the transport is bearer-authed HTTP to a remote, operator-owned service rather than a local git subprocess. outpost-send reuses the mcp kind (the ssh/git-push precedent) since it mutates real state on the remote scheduler — spawning a job, resuming a halted run, or killing one. Both are refused while planning. Every response — a job's metadata, a run's report, an inbox question — is framed as untrusted data before it re-enters context: a cloud run's output is still untrusted input to the local loop, even though the Outpost itself is yours.

Note

Journals written before three tool renames reference view_file, view_notebook, and exit_plan. The registry keeps dispatch-only aliases (view_fileread_file, view_notebookread_notebook, exit_planpresent_plan) so an old session still resumes, while the model only ever sees the current names. See Sessions.