Documentation
¶
Overview ¶
Package core — AgentDetect MCP tool.
Mirrors the `clawtool agents detect <agent>` CLI verb (commit ef4c698) on the MCP transport. Returns the same structured snapshot — {adapter, detected, claimed, exit_code} — so MCP clients can probe a host adapter without shelling out to the CLI.
Use case: an LLM running inside one host (e.g. claude-code) wants to verify clawtool's adapter is configured + claimed before issuing dispatch commands. Today that requires either shelling out via `Bash clawtool agents detect …` or reading `agents status --json`. This tool short-circuits both.
Read-only; no side-effects. Same exit-code contract as the CLI:
0 — adapter detected on this host AND claimed by clawtool 1 — adapter detected, NOT claimed (or transient Status err) 2 — adapter NOT detected on this host
Package core — AgentNew MCP tool. Mirrors `clawtool agent new` so a model can scaffold a Claude Code subagent persona from inside a conversation. Both surfaces share the same template renderer (internal/agentgen) so the output is byte-identical.
Terminology reminder (operator's 2026-04-27 ruling):
- **agent** = a USER-DEFINED PERSONA (this tool scaffolds one)
- **instance** = a configured upstream CLI bridge (claude / codex / gemini / opencode / hermes / openclaw / ...)
Don't confuse this with the legacy AgentList tool (agents_tool.go), which currently still surfaces *instances* under the legacy "agent" name. That rename is tracked separately.
Package core — SendMessage and AgentList MCP tools (ADR-014 Phase 1).
SendMessage routes a prompt to the resolved agent's transport and buffers the streaming reply for the MCP response. Full HTTP-grade streaming arrives with `clawtool serve` in Phase 2; the MCP wire here is request/response so we accept the buffer cap.
AgentList exposes the supervisor's registry snapshot — same shape as `clawtool send --list` and `GET /v1/agents`. Mirrors the v0.9 `RecipeList` pattern (read-only, structured, BaseResult-shaped).
Package core — atomic.go: shared file-mutation primitives for Edit and Write. These helpers guarantee no partial-write artifacts on crash and give us a single place to add safety polish (line-ending preservation, BOM handling) consistently across both tools.
Per ADR-007 we do not use a third-party "atomic write" library — Go's stdlib (`os.WriteFile` + `os.Rename`) is enough when used correctly. The platform invariant we rely on: rename(2) on the same filesystem is atomic, so writers never see a half-written file at the target path.
Package core — AutodevStart / AutodevStop / AutodevStatus MCP tools.
MCP mirror of the `clawtool autodev` CLI verbs. Same flag file (~/.config/clawtool/autodev.enabled) and counter (~/.config/clawtool/autodev.counter); CLI and MCP are interchangeable surfaces for arming / disarming the Stop-hook self-trigger loop.
Why expose these as MCP tools (the operator can already use the CLI / slash commands): a chat-driving model needs an addressable way to say "keep working until I tell you stop" without making the operator switch to a terminal. The MCP path is the one-message control loop; the CLI is the same primitive for shells / scripts / cron.
Package core — AutopilotAdd / AutopilotNext / AutopilotDone / AutopilotSkip / AutopilotList / AutopilotStatus MCP tools.
MCP mirror of the `clawtool autopilot` CLI verbs. Same TOML store (~/.config/clawtool/autopilot/queue.toml), same wire shape; CLI and MCP are interchangeable surfaces for the self-direction backlog. Operators / agents can mix-and-match.
Why the cross-disambiguation matters: the surface looks adjacent to SendMessage / Spawn / TaskWait, but it's solving a different problem. SendMessage dispatches to a peer agent (codex / gemini / opencode). Autopilot is the SAME agent picking up its own backlog. The descriptions explicitly call this out so a calling model doesn't reach for SendMessage when it should be calling AutopilotNext.
Package core implements clawtool's canonical core tools per ADR-005.
Quality bar reminder: each core tool must measurably beat the corresponding native built-in across the major agents. For Bash:
- timeout-safe: output is captured even when the process is killed
- predictable cwd: defaults to $HOME, never the daemon's cwd
- structured result: stdout/stderr/exit_code/duration_ms/timed_out returned as JSON even on timeout
v0.1 implements timeout-safe + structured result + cwd. Secret redaction and per-session command history land in v0.2.
Package core — Bash background-mode task registry (ADR-021 phase B, Codex's "long-running" recommendation). Mirrors BIAM's task vocabulary (pending / active / done / failed / cancelled) without reusing the SQLite store: bash subprocess output is volatile, signing every stdout chunk via Ed25519 (which BIAM would do) is the wrong default. Process-local in-memory registry, lifetime = clawtool serve process.
Package core — MCP surface for Bash background tasks. The underlying registry is in bash_bg.go; this file is the wiring layer mapping {BashOutput, BashKill} onto Get/Kill helpers and rendering the snapshot under the standard core-tool envelope.
Package core — Bridge* MCP tools (ADR-014 Phase 1).
Mirrors `clawtool bridge add/list/remove/upgrade` over MCP so a model can install / inspect / uninstall bridges mid-conversation ("kanka gemini bridge'i kur"). Same dispatch path as the CLI — both end up calling setup.Apply on the bridge's recipe.
Package core — BrowserFetch retrieves a URL through a real browser engine (Obscura, Chromium-via-CDP) so SPA / JS-rendered content lands in the agent's context. Sister tool to WebFetch (server-side via Mozilla Readability), which can't render React / Next.js / hydrated SPAs.
Per ADR-007 we wrap mature engines: Obscura (V8 + Chrome DevTools Protocol, Apache 2.0). We never re-implement page loading. clawtool adds: agent-friendly polish (size cap, structured result, optional JS evaluator, optional CSS-selector wait, post-render readability pass for clean prose).
Stateless: each call spins a fresh browser context. For interactive multi-step flows (login + cookie + click + capture) use BrowserAction.
Package core — BrowserScrape parallelises BrowserFetch across many URLs by wrapping `obscura scrape <url...> --concurrency N --eval ... --format json`. Use case: "give me the rendered headline from these 50 SPA blog posts", "bulk-snapshot a competitor's site map", etc.
Per ADR-007 we wrap Obscura's scrape subcommand (Apache-2.0 Rust engine, V8 + CDP) — clawtool never re-implements parallel fetching. Stateless: each URL gets its own browser context, no cookies, no shared session. For interactive work use BrowserAction.
Package core — Commit MCP tool. Wraps internal/checkpoint's Commit primitive (ADR-022) so an agent can land a Conventional Commits-validated, Co-Authored-By-blocked commit through one tool call instead of three Bash invocations.
This tool is what closes the operator's earlier gap: agents shell out to `Bash git commit -m "feat: …"` because there's no Commit tool, the messages aren't always conventional-shaped, and Bash has no way to refuse a Co-Authored-By trailer. Commit makes the right path the easy path.
Pre-commit guardrails layered through (in order):
- Repo check — bails with a clear error if cwd isn't a Git repo.
- internal/rules.Evaluate at EventPreCommit — operator's declarative invariants (e.g. "skill routing-map row updated" when a core tool changed). A Verdict.IsBlocked() = true is a hard refusal.
- internal/checkpoint.ValidateMessage — Conventional Commits + Co-Authored-By block.
- Optional dirtiness guard — refuses to commit if the working tree still has unstaged changes after staging (catches "you forgot to stage X" mid-flight).
Package core — Edit performs a precise search-and-replace on an existing file with safety polish:
- uniqueness check by default (refuses ambiguous edits)
- atomic temp+rename so a crash never leaves a half-written file
- line-ending preserve (LF / CRLF / CR detected from current content)
- BOM preserve
- binary refusal (symmetric with Read)
Per ADR-007 we wrap stdlib `os` for I/O and add our own polish layer. The search-and-replace shape mirrors what Claude Code's native Edit uses today (old_string / new_string / replace_all) — agents that learnt that interface get the same affordances against clawtool's stronger invariants.
Package core — Glob is the canonical wrapper around bmatcuk/doublestar.
Per ADR-007 we don't write a glob engine. doublestar is the de-facto double-star (`**`) glob library in Go, used by GoReleaser, k6, etc. This file's value is the polish layer: cwd-aware path resolution, uniform structured output, hard cap to protect agent context, and platform-stable separators (the wrapper always returns forward-slash paths regardless of OS — agents expect that).
ADR-021 phase B added .gitignore-aware traversal — when cwd is a Git worktree we ask `git ls-files --cached --others --exclude-standard -z` for the candidate set then run doublestar over it, which gives us the same ignore semantics as ripgrep (and keeps the operator's expected ".git/, vendor/, node_modules/ ignored by default" behaviour).
Package core — Grep wraps ripgrep when present, falls back to system grep.
Per ADR-007 we curate ripgrep as the default engine: it has the correct .gitignore semantics, --type aliases, fast Aho-Corasick matching, and a stable JSON output that is straightforward to parse. The fallback is system grep (-rn) so clawtool's Grep is never unavailable.
Output is uniform across engines so the agent never has to know which one ran. The `engine` field in the result lets users / tests verify.
Package core — IdeateRun / IdeateApply MCP tools.
MCP mirror of the `clawtool ideate` CLI. IdeateRun is read-only — it surveys repo signals and returns Idea candidates without touching the autopilot queue. IdeateApply does the same survey then pushes each surviving Idea onto the autopilot backlog at status=proposed; an operator running AutopilotAccept (or `clawtool autopilot accept <id>`) is the only path from proposed to pending.
This separation matches the v0.22.108 description-anatomy guidance: the model picks IdeateRun when it wants to *learn* what's wrong, IdeateApply when the operator has already greenlit pushing the findings into the queue. They share a runtime; the difference is purely whether the queue gets written.
Package core — typed manifest of clawtool's MCP tools (#173, the "Tool Manifest Registry" refactor).
BuildManifest assembles a *registry.Manifest with one ToolSpec per shipped tool. server.go reads this manifest at boot and invokes each ToolSpec.Register; there is no separate per-tool init wiring. Adding a new tool is one ToolSpec entry plus one RegisterX function — no surface_drift_test edits required since the manifest is the single source of truth (Bash / Read / Edit / Write / Grep / Glob / WebFetch / WebSearch / ToolSearch) get the same treatment.
Why incremental: a single big-bang manifest migration carries the risk that one register-fn signature mismatch (or one missed gate) breaks every tool at once. Doing it six tools at a time, with the surface_drift_test guarding cross-plane invariants, makes each step audit-able and rollback-able.
Why the youngest first: they have the freshest test coverage and the smallest blast radius if a migration mistake slips through. By the time we reach the older core (Bash / Read / Edit / Write) the registry harness is battle-tested.
Package core — Mcp* MCP tools (ADR-019). v0.17 fills in `McpNew` (real generator wrapper), `McpList` (real walker), and keeps thin stubs for `McpRun` / `McpBuild` / `McpInstall` that point at the CLI shortcut (those are inherently filesystem-side operations the model doesn't usually drive).
Package core — Portal* MCP tools (ADR-018). Read-only surface in v0.16.1: PortalList, PortalUse, PortalWhich, PortalUnset, PortalRemove, plus a deferred-feature stub for PortalAsk so the shape is discoverable before the v0.16.2 CDP driver lands.
PortalAdd is intentionally CLI-only — it spawns $EDITOR which has no meaning in an MCP context. Operators add portals from the terminal; agents discover and use them through MCP.
Package core — Read returns file content with stable line cursors, deterministic line counts, and per-format dispatch.
Per ADR-007 we wrap mature engines instead of writing parsers:
- text → stdlib bufio (line-walked, single-pass)
- pdf → pdftotext (poppler-utils) shell-out
- ipynb → native JSON cell parse
- docx → pandoc shell-out (universal office converter)
- xlsx → github.com/xuri/excelize/v2 (Microsoft/Alibaba/Oracle in prod)
- csv / tsv → stdlib encoding/csv (header + bounded preview)
- html → github.com/go-shiori/go-readability (Mozilla Readability port)
- json / yaml / toml / xml → text passthrough with format tag
- binary → refused with structured error
Adding a new format means: extend detectFormat, add a reader function, update CoreToolDocs's description, ship tests for the format. The readResult shape stays uniform so the agent never has to branch on which engine ran.
Package core — Recipe* MCP tools mirror the `clawtool recipe …` CLI surface so a model can run setup tasks from inside a conversation. Same registry, same Detect/Apply/Verify cycle.
Three tools per ADR-013:
RecipeList — enumerate recipes, optionally filter by category.
RecipeStatus — Detect output for one recipe or all of them.
RecipeApply — full Detect→Prereqs→Apply→Verify against a repo,
with structured options.
All three return BaseResult-shaped output (pretty text + structured JSON) so chat UIs render them the same way as Bash/Read/etc.
Package core — secret redaction for tool result envelopes (octopus pattern, mcp-server/src/index.ts:107). Every error envelope clawtool returns to a peer agent or surfaces in stderr/stdout passes through redactSecrets first, so a tool that wraps an upstream error message containing `Authorization: Bearer ghp_…` or `OPENAI_API_KEY=sk-…` doesn't re-export the credential to whoever asked.
The patterns deliberately err on the side of over-redacting: false positives (a value that LOOKS like a key but isn't) get replaced with [REDACTED]; the operator can re-investigate by re-running with `clawtool serve --debug` and reading the daemon log directly. False negatives (a real secret leaking through) are the unacceptable failure mode.
Package core — RulesAdd MCP tool. Operator wants agents to be able to add rules from any context without hand-editing .clawtool/rules.toml. This tool wraps internal/rules.AppendRule with an explicit scope (user vs. local) so the file ends up in the right place.
Companion to the `clawtool rules new` CLI verb — both go through internal/rules.AppendRule, so the on-disk shape is byte-identical regardless of which surface added the rule.
Package core — RulesCheck MCP tool. Surfaces the rules engine (internal/rules) so an agent can ask "are the operator's invariants satisfied right now?" without first having to call the unattended-mode supervisor or wait for pre_commit time.
This tool is read-only: it loads .clawtool/rules.toml (or the XDG fallback), evaluates against a caller-supplied Context, and returns the Verdict (results + warnings + blocked). It does NOT hook into Edit/Write/Bash automatically — rule enforcement at tool-call time lands when the Tool Manifest Registry refactor (#173) gives us a middleware seam.
Package core — Sandbox* MCP tools (ADR-020). v0.18 shipped the read-only surface (List / Show / Doctor); ADR-020 §"MCP-side SandboxRun" (resolved post-v0.22) reverses the original "no-MCP" stance and adds SandboxRun so chat-driven callers (Claude / Codex / Gemini) can run a one-shot command inside a named profile without dropping the operator to a shell.
SandboxRun is the chat-side analogue of `clawtool sandbox run` — both delegate into sandbox.RunOneShot so the wire shape + engine wrap ordering stay identical across surfaces.
Package core — SemanticSearch MCP tool (ADR-014 T6, design from the 2026-04-26 multi-CLI fan-out).
Concept queries ("how is auth rotated?") that Grep can't reach because the literal token isn't there. We wrap chromem-go's in-memory vector store + the configured embedding provider (OpenAI default, Ollama override). One Store per repo, lazily built on first Search call so cold-boot doesn't pay the embedding cost when the tool isn't being used.
Coexistence with Grep: Grep stays the literal regex tool; this is the conceptual one. Tool descriptions carry the routing hint so ToolSearch ranks each correctly per query.
Package core — session-scoped read tracking for the Read-before-Write guardrail (ADR-021). MCP session id is the key; we look it up via server.ClientSessionFromContext, never from a tool argument (Codex flagged this — model-supplied session ids can't be trusted).
Package core — SetContext / GetContext MCP tools (octopus pattern: "ambient editor context"). Lets an agent (or an IDE integration that drives clawtool's MCP surface) tell the daemon "right now I'm editing X line Y, the user's intent is Z" — and have other tools / agents query that state without re-asking.
Why this exists: clawtool sits between many agents and many tools, but the BIAM dispatch surface is request/response — there's no shared scratchpad for "things that are true right now in the user's editor." Without this every tool re-derives context from the prompt, and a second agent that wants to act on the same state has to be told it explicitly. SetContext is the small, boring storage layer that closes that gap.
Not a CRDT, not a long-term store. The data lives in a process- local map keyed by session ID; daemon restart wipes it. That's the right scope for "what is the user looking at this minute" — older state would mislead more than it helps.
SkillList / SkillLoad MCP tools — the on-demand skill mount pattern (ADR-029 phase 3, task #208).
claude.ai mounts /mnt/skills/public/<name>/SKILL.md into the container's filesystem; the model issues `view` / `read` to pull a skill into the current turn's context. The clawtool equivalent: SkillList enumerates installed Agent Skills, SkillLoad returns one skill's full content (frontmatter + markdown). Same on-demand semantic, different transport (MCP tool call vs filesystem read).
Skill discovery roots (resolved on each call so re-installs without restart pick up new skills):
- `./.claude/skills/<name>/SKILL.md` (project)
- `~/.claude/skills/<name>/SKILL.md` (user)
- `$CLAWTOOL_SKILLS_DIR/<name>/SKILL.md` (override; tests)
Lookup precedence: project beats user beats override.
Package core — SkillNew MCP tool. Mirrors `clawtool skill new` so a model can scaffold a Claude Code skill from inside a conversation, without the user dropping to a shell. Both surfaces share the same template renderer (passed in at registration so we don't reach across packages — this file stays a leaf).
Spec compliance: agentskills.io. SKILL.md gets YAML frontmatter with `name` + `description` (required) plus optional `triggers`, followed by the body template. Same shape as the CLI emits.
Package core — SourceCheck MCP tool.
Mirrors the `clawtool source check [<instance>] [--json]` CLI verb (commit ddabc05) on the MCP transport. Returns the same {name, ready, missing[]} array shape so MCP-only callers can probe whether a source's required env vars resolve via the secrets store — without shelling out to the CLI.
Use case: an installer / bootstrap agent (typically running as a clawtool MCP client) wants to verify GitHub / Slack / Postgres credentials are configured BEFORE issuing dispatch commands that depend on the source. The CLI verb requires `Bash clawtool source check …` round-trips; the MCP tool short-circuits.
Read-only; no side-effects, no auth-sensitive data emitted (only env-var NAMES, never values). Operators can call it freely.
Package core — SourceRegistry MCP tool.
Mirrors the `clawtool source registry [--limit N] [--url URL] [--json]` CLI verb (commit cdecb8c) on the MCP transport. An agent (typically running as a clawtool MCP client) can probe the official MCP Registry directly — no shell-out, no CLAWTOOL_PORTAL or token plumbing needed because the registry is anonymous read-only.
Use case: an installer/bootstrap agent wants to discover what MCP servers exist in the upstream ecosystem before issuing `source add` against the embedded catalog. The CLI verb requires `Bash clawtool source registry --json` round-trips; the MCP tool short-circuits.
Read-only; no side-effects. The registry endpoint is the official `https://registry.modelcontextprotocol.io` host by default; agents can override via `url` for testing or private mirrors.
Package core — TaskReply MCP tool (the back-channel that closes the BIAM fan-in loop). When clawtool dispatches a heavy task to a peer agent (codex / gemini / opencode / claude) via SendMessage --bidi, the runner buffers the upstream's stdout into ONE 4 MiB result envelope. For audits / synthesis / multi-finding work the reply is too large for the caller's MCP response cap and clawtool has to spill it to a file.
TaskReply lets the dispatched agent push structured replies back in chunks while it works:
- Subprocess spawn injects CLAWTOOL_TASK_ID + CLAWTOOL_FROM_INSTANCE env vars (see internal/agents/biam/runner.go).
- The peer's MCP client has clawtool registered as a server (via `clawtool agent claim <family>`), so it can call mcp__clawtool__TaskReply directly.
- Each call appends one envelope to the parent task. The caller's TaskGet / TaskWait sees the chunks land in real time without ever buffering a 300 KB blob into the wire response.
Idempotent — duplicate idempotency_key inserts are silently dropped at the store layer. Read-only signing identity is the daemon's own (tasks aren't cross-host today; A2A wraps that later). Token gate matches the rest of the BIAM surface — when the store isn't initialised, the handler returns the standard errBIAMNotInit error so the caller knows to launch `clawtool serve` first.
Package core — TaskNotify MCP tool. Edge-triggered completion push that pairs with SendMessage(bidi=true). Subscribes to the in-process biam.Notifier so the caller wakes the instant ANY of the watched tasks reaches a terminal state — no SQLite poll, no external CLI hooks.
Architecture: the runner publishes a *biam.Task to Notifier when it flips a row to a terminal state (see internal/agents/biam/ runner.go). Here we register one channel per task_id, then `select` across all of them + the timeout context. First task wins; the rest stay subscribed until the caller polls them with TaskGet (their slot decays at next Publish or process exit).
Already-terminal tasks: we eagerly check the store BEFORE blocking, so a TaskNotify call against a task that already finished returns immediately rather than waiting for a Publish that already happened.
Package core — TaskGet / TaskWait / TaskList MCP tools (ADR-015 Phase 1). Surface the BIAM SQLite store the supervisor's async runner persists into, so a calling model can:
- Fire SendMessage with bidi=true → receive task_id immediately.
- Continue its own work without blocking on the upstream.
- Pull back via TaskGet (snapshot) / TaskWait (block until terminal) when it actually needs the result.
All three tools are read-only and stateless beyond the BIAM store.
Package core — ToolSearch is the discovery primitive that makes a 50+ tool catalog usable per ADR-005. The agent calls ToolSearch with a natural-language query, gets ranked candidates, then binds to the right tool with its full schema via the regular tools/list output.
Package core — UnattendedVerify MCP tool. Mirror of the `clawtool unattended verify <session_id>` CLI verb so an agent can audit a past unattended-mode session for tamper-evidence without shelling out. Reads the JSONL audit log, walks every {event, sig} row, and verifies the Ed25519 signature against the local BIAM identity's public key.
Why a tool, not a script: agents that get woken up on a watch event (PR merged, CI failed) frequently want to confirm "the log of what I did last time is still intact" before chaining new dispatches on top. Forcing them through Bash to invoke the CLI surface costs a process-spawn round-trip per check; the in-process tool keeps that under a millisecond.
Package core — Verify MCP tool (ADR-014 T4, design from the 2026-04-26 multi-CLI fan-out).
Verify runs a repo's tests / lints / typechecks via whichever runner the repo declares (Make, pnpm, npm, go, pytest, ruby, cargo, just) and returns one structured pass/fail per check. Per ADR-007 we wrap maintained runners — `go test -json`, `pytest --json-report`, `cargo test --message-format json` — and fall back to the runner's plain output when the structured form isn't available on this host.
Buffered single payload (not stream): callers want the full pass/fail summary, not the live log fire hose. Bash already streams when that's what's wanted.
Package core — Version MCP tool.
Exposes version.BuildInfo over the MCP transport so a connected agent (claude-code, codex, gemini, opencode) can ask "what clawtool am I talking to?" without shelling out to `clawtool version --json`. Mirrors the HTTP `/v1/health` build surface (commit 54bf658) and the CLI `clawtool version --json` flag (commit 239eede), so all three wire-protocol consumers see identical shape.
Read-only; no side-effects, no auth-sensitive data. Operators can call it freely. The tool's only argument-less; the response embeds version.BuildInfo via struct embedding so the JSON keys (`name`, `version`, `go_version`, `platform`, `commit`, `modified`) match the rest of the surface verbatim.
Package core — WebFetch retrieves a URL and renders the body in the best shape for an AI agent: clean article text for HTML, raw text for plain-text MIME types, structured rejection for binaries.
Per ADR-007 we wrap two mature engines:
- net/http stdlib client for transport (proxy, TLS, redirect handling are all stock — battle-tested across Go's user base);
- github.com/go-shiori/go-readability for HTML extraction (Mozilla Readability port, the same algorithm Firefox Reader View ships).
What clawtool adds: agent-friendly polish — a hard body cap so a runaway page can't blow context, structured result with content-type-aware `format`, citation metadata (final URL after redirects, fetched_at).
Package core — SSRF guard for WebFetch (ADR-021 phase B).
Without this, an agent could ask WebFetch for `http://169.254.169.254/` (AWS metadata), `http://localhost:5432/` (the operator's local Postgres), or any RFC1918 address (the operator's internal network). The guard blocks resolution to those address ranges BEFORE the GET is issued, and re-checks every redirect target so a public 302→private redirect chain is rejected too.
Per ADR-007 we don't ship our own DNS resolver — net.LookupIP is canonical. We only own the address-range allow/deny logic.
Package core — WebSearch is a pluggable web-search primitive. clawtool itself does no crawling or ranking; it adapts whichever search backend the user has configured (Brave today; Tavily / SearXNG planned) into a uniform `{results, backend, …}` shape.
Per ADR-007 we wrap, never reinvent. The backend interface is small on purpose so adding a new provider is one file (see websearch_brave.go for the canonical example).
Package core — Write creates or overwrites a whole file with given content. Sister tool to Edit; the boundary is intentional:
- Edit modifies a substring of an existing file. Refuses if the file is missing.
- Write replaces or creates the whole file. If the file already exists and has detectable line endings, those endings are preserved by default so existing tooling (CR LF on Windows, etc.) keeps working.
Per ADR-007 we wrap stdlib `os` for I/O. The polish layer is the same atomic-write primitive Edit uses, plus a parent-directory auto-create so agents don't need a separate `mkdir` step before writing.
Index ¶
- Variables
- func BiamStore() *biam.Store
- func BuildManifest() *registry.Manifest
- func CoreToolDocs() []search.Doc
- func HashFile(path string) (string, error)
- func HashString(s string) string
- func RegisterAgentDetectTool(s *server.MCPServer)
- func RegisterAgentNew(s *server.MCPServer)
- func RegisterAgentTools(s *server.MCPServer)
- func RegisterAutodevTools(s *server.MCPServer)
- func RegisterAutopilotTools(s *server.MCPServer)
- func RegisterBash(s *server.MCPServer)
- func RegisterBashKill(s *server.MCPServer)
- func RegisterBashOutput(s *server.MCPServer)
- func RegisterBridgeTools(s *server.MCPServer)
- func RegisterBrowserFetch(s *server.MCPServer)
- func RegisterBrowserScrape(s *server.MCPServer)
- func RegisterCommit(s *server.MCPServer)
- func RegisterEdit(s *server.MCPServer)
- func RegisterGlob(s *server.MCPServer)
- func RegisterGrep(s *server.MCPServer)
- func RegisterIdeatorTools(s *server.MCPServer)
- func RegisterMcpTools(s *server.MCPServer)
- func RegisterPortalAliases(s *server.MCPServer, cfg config.Config)
- func RegisterPortalTools(s *server.MCPServer)
- func RegisterRead(s *server.MCPServer)
- func RegisterRecipeTools(s *server.MCPServer)
- func RegisterRulesAdd(s *server.MCPServer)
- func RegisterRulesCheck(s *server.MCPServer)
- func RegisterSandboxTools(s *server.MCPServer)
- func RegisterSemanticSearch(s *server.MCPServer)
- func RegisterSetContext(s *server.MCPServer)
- func RegisterSkillList(s *server.MCPServer)
- func RegisterSkillLoad(s *server.MCPServer)
- func RegisterSkillNew(s *server.MCPServer)
- func RegisterSourceCheckTool(s *server.MCPServer)
- func RegisterSourceRegistryTool(s *server.MCPServer)
- func RegisterTaskNotify(s *server.MCPServer)
- func RegisterTaskReply(s *server.MCPServer)
- func RegisterTaskTools(s *server.MCPServer)
- func RegisterToolSearch(s *server.MCPServer, idx *search.Index)
- func RegisterUnattendedVerify(s *server.MCPServer)
- func RegisterVerify(s *server.MCPServer)
- func RegisterVersionTool(s *server.MCPServer)
- func RegisterWebFetch(s *server.MCPServer)
- func RegisterWebSearch(s *server.MCPServer, store *secrets.Store)
- func RegisterWrite(s *server.MCPServer)
- func ResetBashTasksForTest()
- func ResetContextsForTest()
- func ResetSessionsForTest()
- func SetAutoLintEnabled(enabled bool)
- func SetBiamStore(s *biam.Store)
- func SubmitBackgroundBash(parent context.Context, command, cwd string, timeoutMs int) (string, error)
- type Backend
- type BaseResult
- type BashTask
- type BashTaskSnapshot
- type BashTaskStatus
- type BashTaskStore
- type BrowserFetchResult
- type BrowserScrapeResult
- type BrowserScrapeRow
- type EditResult
- type EditorContext
- type Engine
- type GlobResult
- type GrepMatch
- type GrepResult
- type LineEndings
- type ReadRecord
- type ReadResult
- type Renderer
- type SearchOptions
- type SemanticSearchResult
- type SessionKey
- type SessionState
- type ToolSearchResult
- type VerifyCheck
- type VerifyResult
- type WebFetchResult
- type WebSearchHit
- type WebSearchResult
- type WriteResult
Constants ¶
This section is empty.
Variables ¶
var BashTasks = &BashTaskStore{tasks: map[string]*BashTask{}}
BashTasks is the singleton. Tests use ResetBashTasksForTest.
var ErrBlockedAddress = errors.New("WebFetch refused: target resolves to a private / loopback / link-local / cloud-metadata address (SSRF guard)")
ErrBlockedAddress is the sentinel returned when the resolved IP falls into a deny range. Caller surfaces it verbatim.
var ErrMissingAPIKey = errors.New("missing API key")
ErrMissingAPIKey is returned by backends when their required API key is not present in either the secrets store or process env.
var Sessions = &SessionState{ reads: map[SessionKey]map[string]ReadRecord{}, }
Sessions is the process-wide singleton. Tests reset via ResetSessionsForTest.
Functions ¶
func BiamStore ¶ added in v0.22.135
BiamStore returns the process-wide BIAM store, or nil if the daemon never wired one (CLI / test paths). Callers that need the store for a read-only path (e.g. /v1/biam/subscribe's task-existence check) consult this getter instead of importing the unexported package var.
func BuildManifest ¶ added in v0.21.0
BuildManifest returns the typed manifest of every clawtool MCP tool. Caller (server.go in Step 3) walks it via manifest.Apply(s, runtime, cfg.IsEnabled).
Step 2 scope: 6 specs (Commit, RulesCheck, AgentNew, BashOutput, BashKill, TaskNotify). Each spec's Register fn adapts the existing RegisterX(s) signature to the registry.RegisterFn shape (s, runtime).
Specs added but Register-not-wired-yet are LEGAL — Apply silently skips them. We use that to document the older tools in the same manifest BEFORE migrating them, so search-index consumers (Step 4 work) can already see the canonical entry.
func CoreToolDocs ¶
CoreToolDocs returns search.Doc descriptors for every clawtool core tool. Step 4 of #173 collapsed the duplicated entry list into a delegate over BuildManifest().SearchDocs(nil) so the manifest is now the single source of truth. Kept as a public shim so the surface_drift_test (which iterates by spec name) stays a one-liner; internal callers go to the manifest directly.
func HashFile ¶ added in v0.20.0
HashFile returns SHA-256 of the file's raw bytes as hex. Helper used by Read / Write / Edit; centralised so the format stays consistent across tools.
func HashString ¶ added in v0.20.0
HashString computes SHA-256 of a string. Used for range_hash after format-aware decoding (PDF / DOCX / XLSX) so the hash captures the canonical text we returned to the agent, not the raw bytes.
func RegisterAgentDetectTool ¶ added in v0.22.40
RegisterAgentDetectTool adds the `AgentDetect` MCP tool to s. Wired from manifest.go via registry.ToolSpec.Register so the surface-drift test catches missing routing-rows / allowed-tools entries automatically.
func RegisterAgentNew ¶ added in v0.20.0
RegisterAgentNew adds the AgentNew tool to s. Template + helpers come from internal/agentgen so this MCP surface and the `clawtool agent new` CLI emit byte-identical files.
func RegisterAgentTools ¶ added in v0.20.0
RegisterAgentTools adds SendMessage + AgentList to the MCP server.
func RegisterAutodevTools ¶ added in v0.22.154
RegisterAutodevTools wires AutodevStart, AutodevStop, AutodevStatus onto the MCP server. Idempotent.
func RegisterAutopilotTools ¶ added in v0.22.118
RegisterAutopilotTools wires the seven tools onto the MCP server. Idempotent — calling twice replaces by name.
func RegisterBash ¶
RegisterBash adds the Bash tool to the given MCP server.
func RegisterBashKill ¶ added in v0.20.0
RegisterBashKill exposes KillBashTask over MCP as BashKill. The snapshot is returned post-cancel so the caller sees the terminal status (or `cancelled` if the kill won the race against a quick exit).
func RegisterBashOutput ¶ added in v0.20.0
RegisterBashOutput exposes GetBashTask over MCP as BashOutput.
func RegisterBridgeTools ¶ added in v0.20.0
RegisterBridgeTools adds BridgeList/Add/Remove/Upgrade to s.
func RegisterBrowserFetch ¶ added in v0.20.0
RegisterBrowserFetch wires the BrowserFetch MCP tool.
func RegisterBrowserScrape ¶ added in v0.20.0
RegisterBrowserScrape wires the BrowserScrape MCP tool.
func RegisterCommit ¶ added in v0.20.0
RegisterCommit wires the Commit MCP tool. Idempotent.
func RegisterEdit ¶
RegisterEdit adds the Edit tool to the given MCP server.
func RegisterGlob ¶
RegisterGlob adds the Glob tool to the given MCP server.
func RegisterGrep ¶
RegisterGrep adds the Grep tool to the given MCP server.
func RegisterIdeatorTools ¶ added in v0.22.119
RegisterIdeatorTools wires IdeateRun + IdeateApply onto the MCP server. Idempotent — calling twice replaces by name.
func RegisterMcpTools ¶ added in v0.20.0
RegisterMcpTools wires the Mcp* surface (ADR-019). McpNew runs the real generator. McpList walks the on-disk markers. McpRun / McpBuild / McpInstall are CLI-side filesystem operations and surface a hint to use the shell command — that's the natural path for a model giving advice rather than driving the build.
func RegisterPortalAliases ¶ added in v0.20.0
RegisterPortalAliases scans cfg.Portals and binds a thin wrapper `<name>__ask` for each one. Same wire-naming convention as internal/sources/manager.go aggregation. Each alias forwards to PortalAsk with the portal name pre-bound, so the calling model can do `my_deepseek__ask({"prompt":"..."})` without remembering the generic shape.
func RegisterPortalTools ¶ added in v0.20.0
RegisterPortalTools wires the Portal* MCP surface. Always registered; missing config produces empty results, not boot failure.
func RegisterRead ¶
RegisterRead adds the Read tool to the given MCP server.
func RegisterRecipeTools ¶ added in v0.9.0
RegisterRecipeTools adds the three Recipe* MCP tools to s. The registry must already be populated (typically via blank import of internal/setup/recipes).
func RegisterRulesAdd ¶ added in v0.21.4
RegisterRulesAdd wires the RulesAdd tool. Idempotent.
func RegisterRulesCheck ¶ added in v0.20.0
RegisterRulesCheck wires the RulesCheck tool. Idempotent.
func RegisterSandboxTools ¶ added in v0.20.0
func RegisterSemanticSearch ¶ added in v0.20.0
RegisterSemanticSearch wires the tool. Always registered; missing embedding key surfaces as a per-call error, not a boot failure.
func RegisterSetContext ¶ added in v0.22.36
RegisterSetContext registers SetContext + GetContext on the MCP server. The pair is wired together because they share storage — a runtime that opted into one without the other would surface a write-only or read-only context which is rarely useful.
func RegisterSkillList ¶ added in v0.21.6
RegisterSkillList exposes installed skills on the MCP plane. CLI has `clawtool skill list` already; this lets a model enumerate skills before deciding which one to SkillLoad.
func RegisterSkillLoad ¶ added in v0.21.6
RegisterSkillLoad adds the SkillLoad tool. Pairs with the pre-existing SkillNew (CLI scaffolder) and with the new SkillList tool so a model can discover-then-load.
func RegisterSkillNew ¶ added in v0.9.0
RegisterSkillNew adds the SkillNew tool to s. Template + helpers come from internal/skillgen so this MCP surface and the `clawtool skill new` CLI emit byte-identical output.
func RegisterSourceCheckTool ¶ added in v0.22.40
RegisterSourceCheckTool adds the `SourceCheck` MCP tool to s. Wired from manifest.go via registry.ToolSpec.Register so the surface-drift test catches missing routing-rows / allowed-tools entries automatically.
func RegisterSourceRegistryTool ¶ added in v0.22.44
RegisterSourceRegistryTool adds the `SourceRegistry` MCP tool to s. Wired from manifest.go via registry.ToolSpec.Register so the surface-drift test catches missing routing-rows / allowed-tools entries automatically.
func RegisterTaskNotify ¶ added in v0.20.0
RegisterTaskNotify wires the TaskNotify tool. Idempotent.
func RegisterTaskReply ¶ added in v0.22.28
RegisterTaskReply wires the TaskReply tool. Idempotent.
func RegisterTaskTools ¶ added in v0.20.0
RegisterTaskTools wires TaskGet / TaskWait / TaskList. Idempotent — safe to call when the BIAM store wasn't initialised; per-call handlers surface the "not configured" error.
func RegisterToolSearch ¶
RegisterToolSearch adds the ToolSearch tool to the given MCP server, closing over the index built at startup.
func RegisterUnattendedVerify ¶ added in v0.22.132
RegisterUnattendedVerify wires the UnattendedVerify tool. Idempotent.
func RegisterVerify ¶ added in v0.20.0
RegisterVerify wires the Verify MCP tool.
func RegisterVersionTool ¶ added in v0.22.40
RegisterVersionTool adds the `Version` MCP tool to s. Wired from manifest.go via the registry.ToolSpec.Register hook so the gating behaviour (this tool is always-on / no policy gate) stays consistent with the rest of the registry.
func RegisterWebFetch ¶
RegisterWebFetch adds the WebFetch tool to the given MCP server.
func RegisterWebSearch ¶
RegisterWebSearch adds the WebSearch tool to the given MCP server. The secrets-store reference is captured so per-call backend resolution can pick up updated API keys without restart.
func RegisterWrite ¶
RegisterWrite adds the Write tool to the given MCP server.
func ResetBashTasksForTest ¶ added in v0.20.0
func ResetBashTasksForTest()
ResetBashTasksForTest wipes the registry. Test-only.
func ResetContextsForTest ¶ added in v0.22.36
func ResetContextsForTest()
ResetContextsForTest wipes the store. Test-only helper.
func ResetSessionsForTest ¶ added in v0.20.0
func ResetSessionsForTest()
ResetSessionsForTest clears the registry. Test-only escape hatch matching the pattern in agents/supervisor.go.
func SetAutoLintEnabled ¶ added in v0.20.0
func SetAutoLintEnabled(enabled bool)
SetAutoLintEnabled lets server.go's boot path flip the flag based on config.AutoLint.Enabled. Idempotent.
func SetBiamStore ¶ added in v0.20.0
SetBiamStore registers the process-wide BIAM store. Idempotent.
func SubmitBackgroundBash ¶ added in v0.20.0
func SubmitBackgroundBash(parent context.Context, command, cwd string, timeoutMs int) (string, error)
SubmitBackgroundBash spawns the command, registers a task, and returns the task_id. The goroutine reading stdout/stderr keeps running after the call returns; consumers poll via TaskGet until status is terminal.
Types ¶
type Backend ¶
type Backend interface {
Name() string
Search(ctx context.Context, query string, limit int, opts SearchOptions) ([]WebSearchHit, error)
}
Backend abstracts a web-search provider. Implementations must be safe to invoke from multiple goroutines and complete within the supplied context's deadline.
SearchOptions carries the optional, provider-neutral filters from ADR-021 phase B. Backends translate what they support and ignore the rest — the operator sees a uniform request shape across providers, the unsupported ones degrade silently to "behave as though the filter wasn't supplied".
type BaseResult ¶ added in v0.9.0
type BaseResult struct {
Operation string `json:"-"`
Engine string `json:"engine,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
ErrorReason string `json:"error_reason,omitempty"`
}
BaseResult holds the fields and rendering helpers every tool result shares. Each tool's *Result struct embeds this so the JSON shape stays uniform (timing, error, engine surfaced the same way everywhere) and Render() implementations stay short — each one is just "header + body + footer" composed from BaseResult helpers and the tool-specific data.
Operation is JSON-omitted; it's a presentation concern (the header verb), not a wire field.
func (BaseResult) ErrorLine ¶ added in v0.9.0
func (b BaseResult) ErrorLine(target string) string
ErrorLine renders the canonical failure one-liner. Every tool that fails uses this — keeps "✗ <verb> — <reason>" consistent across the whole catalog. Reason is redacted for known secret shapes (API keys, bearer tokens, cookies) so an upstream error message that includes a credential doesn't leak to the peer. See internal/tools/core/redact.go for the canonical patterns.
func (BaseResult) FooterLine ¶ added in v0.9.0
func (b BaseResult) FooterLine(extras ...string) string
FooterLine joins extras with " · " and appends the duration. Used at the bottom of multi-line results (after content).
func (BaseResult) HeaderLine ¶ added in v0.9.0
func (b BaseResult) HeaderLine(title string) string
HeaderLine renders the canonical multi-line header used by tools that return content (Bash, Read, Grep). Engine — when set — is shown in brackets so the caller always knows which backend ran.
func (BaseResult) IsError ¶ added in v0.9.0
func (b BaseResult) IsError() bool
IsError is the universal failure predicate.
func (BaseResult) SuccessLine ¶ added in v0.9.0
func (b BaseResult) SuccessLine(target string, extras ...string) string
SuccessLine is the canonical single-line success format used by stateless tools (Edit, Write). Variadic extras are joined with " · " and the duration is appended automatically.
type BashTask ¶ added in v0.20.0
type BashTask struct {
ID string
Command string
Cwd string
StartedAt time.Time
FinishedAt time.Time
TimeoutMs int
// contains filtered or unexported fields
}
BashTask carries one background bash invocation's state. Output buffers grow without bound by design — the operator can always kill the task when the live tail gets noisy. We cap at 4 MiB per stream to match the BIAM body cap.
func (*BashTask) Snapshot ¶ added in v0.20.0
func (t *BashTask) Snapshot() BashTaskSnapshot
Snapshot returns the current state under the task's lock.
type BashTaskSnapshot ¶ added in v0.20.0
type BashTaskSnapshot struct {
ID string `json:"task_id"`
Command string `json:"command"`
Cwd string `json:"cwd,omitempty"`
Status BashTaskStatus `json:"status"`
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
ExitCode int `json:"exit_code"`
TimedOut bool `json:"timed_out"`
StartedAt time.Time `json:"started_at"`
FinishedAt time.Time `json:"finished_at,omitempty"`
}
snapshot returns a read-only view safe to ship over MCP.
func GetBashTask ¶ added in v0.20.0
func GetBashTask(id string) (BashTaskSnapshot, bool)
GetBashTask returns the snapshot for id. ok=false when no task matches.
func KillBashTask ¶ added in v0.20.0
func KillBashTask(id string) (BashTaskSnapshot, bool)
KillBashTask cancels the task's context, which propagates SIGKILL to the whole process group via ApplyGroupWithCtxCancel. No-op when the task is already terminal. Returns ok=false for unknown IDs.
func ListBashTasks ¶ added in v0.20.0
func ListBashTasks(limit int) []BashTaskSnapshot
ListBashTasks returns every recorded task, newest first. Bounded by limit (0 = no cap).
type BashTaskStatus ¶ added in v0.20.0
type BashTaskStatus string
BashTaskStatus mirrors BIAM's lifecycle so an agent that knows TaskGet's vocabulary doesn't need a second mental model.
const ( BashTaskActive BashTaskStatus = "active" BashTaskDone BashTaskStatus = "done" BashTaskFailed BashTaskStatus = "failed" BashTaskCancelled BashTaskStatus = "cancelled" )
type BashTaskStore ¶ added in v0.20.0
type BashTaskStore struct {
// contains filtered or unexported fields
}
BashTaskStore is the process-wide registry. Concurrent reads + writes are guarded by an RWMutex so TaskGet / TaskList stay fast under load.
type BrowserFetchResult ¶ added in v0.20.0
type BrowserFetchResult struct {
BaseResult
URL string `json:"url"`
FinalURL string `json:"final_url,omitempty"`
Format string `json:"format"` // "html" | "text" | "eval"
Title string `json:"title,omitempty"`
Byline string `json:"byline,omitempty"`
SiteName string `json:"site_name,omitempty"`
Content string `json:"content"`
EvalResult string `json:"eval_result,omitempty"`
SizeBytes int `json:"size_bytes"`
FetchedAt string `json:"fetched_at"`
Truncated bool `json:"truncated"`
}
BrowserFetchResult mirrors WebFetchResult so an agent can swap one for the other without rewriting downstream parsing. Adds EvalResult for callers that pass `eval` (raw stdout slice from obscura).
func (BrowserFetchResult) Render ¶ added in v0.20.0
func (r BrowserFetchResult) Render() string
Render keeps parity with WebFetchResult: framed body + footer.
type BrowserScrapeResult ¶ added in v0.20.0
type BrowserScrapeResult struct {
BaseResult
Results []BrowserScrapeRow `json:"results"`
Total int `json:"total"`
Failed int `json:"failed"`
Truncated bool `json:"truncated"`
FetchedAt string `json:"fetched_at"`
}
BrowserScrapeResult lists per-URL outcomes plus aggregate counts.
func (BrowserScrapeResult) Render ¶ added in v0.20.0
func (r BrowserScrapeResult) Render() string
Render lists one row per URL.
type BrowserScrapeRow ¶ added in v0.20.0
type BrowserScrapeRow struct {
URL string `json:"url"`
Result string `json:"result,omitempty"`
Error string `json:"error,omitempty"`
}
BrowserScrapeRow is one URL's outcome. `Result` carries the eval'd value (or rendered text); `Error` is set on per-URL failure so the rest of the batch keeps going.
type EditResult ¶
type EditResult struct {
BaseResult
Path string `json:"path"`
Replaced bool `json:"replaced"`
OccurrencesReplaced int `json:"occurrences_replaced"`
SizeBytesBefore int64 `json:"size_bytes_before"`
SizeBytesAfter int64 `json:"size_bytes_after"`
LineEndings string `json:"line_endings"`
LintFindings []lint.Finding `json:"lint_findings,omitempty"`
// HashBefore / HashAfter let the model verify exactly what
// changed (ADR-021). Both are SHA-256 hex of the file's raw
// bytes — pre-edit and post-edit.
HashBefore string `json:"hash_before,omitempty"`
HashAfter string `json:"hash_after,omitempty"`
// DiffUnified is a tiny `diff -u`-style patch of the change.
// Always populated on a successful edit; empty when the edit
// was a no-op or failed.
DiffUnified string `json:"diff_unified,omitempty"`
}
EditResult is the uniform shape returned to the agent.
func (EditResult) Render ¶ added in v0.9.0
func (r EditResult) Render() string
Render satisfies the Renderer contract. Single-line success/failure; stateless tools don't need a multi-line body.
type EditorContext ¶ added in v0.22.36
type EditorContext struct {
FilePath string `json:"file_path,omitempty"`
StartLine int `json:"start_line,omitempty"`
EndLine int `json:"end_line,omitempty"`
ProjectRoot string `json:"project_root,omitempty"`
Intent string `json:"intent,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
}
EditorContext is the per-session ambient state every agent / tool call can read or write. All fields are optional; SetContext merges the supplied keys into the existing state instead of overwriting wholesale, so an agent that only updates the cursor position doesn't have to re-supply file_path + intent every call.
func CurrentContext ¶ added in v0.22.36
func CurrentContext(session string) EditorContext
CurrentContext returns a snapshot of the named session's context for in-process callers (other tool handlers that want to read context without going through the MCP envelope). Pure Go API; no JSON round-trip.
func (EditorContext) IsZero ¶ added in v0.22.36
func (c EditorContext) IsZero() bool
IsZero reports whether the context has no meaningful fields set. Used by GetContext to render "(no context set)" rather than an empty struct.
type Engine ¶
type Engine struct {
Name string // canonical name, e.g. "ripgrep"
Bin string // resolved absolute path, empty if absent
}
Engine describes one detected upstream binary that clawtool wraps.
Per ADR-007, clawtool curates and wraps best-in-class engines. Detection runs once on startup so wrapper tools can pick the best available engine without re-shelling-out for every call.
func LookupEngine ¶
LookupEngine returns the cached engine entry for a given binary name. The Bin field is empty if the engine is not present on this system.
type GlobResult ¶
type GlobResult struct {
BaseResult
Matches []string `json:"matches"`
MatchesCount int `json:"matches_count"`
Truncated bool `json:"truncated"`
Cwd string `json:"cwd"`
Pattern string `json:"pattern"`
RespectGitignore bool `json:"respect_gitignore"`
IncludeHidden bool `json:"include_hidden"`
}
GlobResult is the uniform shape returned to the agent.
func (GlobResult) Render ¶ added in v0.9.0
func (r GlobResult) Render() string
Render satisfies the Renderer contract. One match per line so the chat looks like running `find` or `fd` in a terminal.
type GrepMatch ¶
type GrepMatch struct {
Path string `json:"path"`
Line int `json:"line"`
Column int `json:"column"`
Text string `json:"text"`
Before []string `json:"before,omitempty"`
After []string `json:"after,omitempty"`
}
GrepMatch is a single hit. Line and column are 1-indexed for human readability and to match conventional editor jumping. Before/After arrive populated only when the caller asked for context lines.
type GrepResult ¶
type GrepResult struct {
BaseResult
Matches []GrepMatch `json:"matches"`
MatchesCount int `json:"matches_count"`
Truncated bool `json:"truncated"`
Cwd string `json:"cwd"`
Pattern string `json:"pattern"`
}
GrepResult is the uniform shape returned regardless of engine.
func (GrepResult) Render ¶ added in v0.9.0
func (r GrepResult) Render() string
Render satisfies the Renderer contract. Output mirrors ripgrep's standard `path:line:col: text` so a developer reading the chat sees the same shape they'd see in a terminal.
type LineEndings ¶
type LineEndings string
LineEndings identifies the dominant line-ending convention of a file.
const ( LineEndingsLF LineEndings = "lf" LineEndingsCRLF LineEndings = "crlf" LineEndingsCR LineEndings = "cr" // ancient Mac LineEndingsUnknown LineEndings = "unknown" )
type ReadRecord ¶ added in v0.20.0
type ReadRecord struct {
Path string `json:"path"`
FileHash string `json:"file_hash"` // SHA-256 of raw bytes
RangeHash string `json:"range_hash,omitempty"` // SHA-256 of returned line range
LineStart int `json:"line_start,omitempty"`
LineEnd int `json:"line_end,omitempty"`
ReadAt time.Time `json:"read_at"`
}
ReadRecord captures what a Read tool call observed about a path at a single point in time. Edit + Write consult these to verify the agent has seen the file AND the file hasn't drifted since.
type ReadResult ¶
type ReadResult struct {
BaseResult
Path string `json:"path"`
Content string `json:"content"`
LineStart int `json:"line_start"`
LineEnd int `json:"line_end"`
TotalLines int `json:"total_lines"`
SizeBytes int64 `json:"size_bytes"`
Format string `json:"format"`
Truncated bool `json:"truncated"`
// FileHash is SHA-256 of the file's raw bytes (hex). Edit /
// Write check this against the recorded read-time hash to
// detect "file changed since you last looked" (ADR-021).
FileHash string `json:"file_hash,omitempty"`
// RangeHash is SHA-256 of the canonical returned content
// (after format-aware decoding for PDF / DOCX / XLSX). Lets
// range-based Edits prove they're operating on the slice
// the model just saw.
RangeHash string `json:"range_hash,omitempty"`
// Sheets is populated only for spreadsheet formats; lets the agent
// page through workbook structure without re-reading the file.
Sheets []string `json:"sheets,omitempty"`
}
ReadResult is the uniform shape across all formats. Embeds BaseResult so common fields (engine, duration, error) and their rendering helpers are inherited.
func (ReadResult) Render ¶ added in v0.9.0
func (r ReadResult) Render() string
Render satisfies the Renderer contract. The body is the file content framed by horizontal rules; header carries path and engine, footer carries cursor + size.
type Renderer ¶ added in v0.9.0
type Renderer interface {
Render() string
}
Renderer is the contract every tool result implements. The MCP dispatch helper below relies on it exclusively; tools that don't implement it would fall through to JSON marshaling, but every core tool overrides it.
type SearchOptions ¶ added in v0.20.0
type SearchOptions struct {
IncludeDomains []string // e.g. ["docs.python.org", "go.dev"]
ExcludeDomains []string // e.g. ["pinterest.com"]
Recency string // "24h" | "1w" | "1m" | "1y" | "" (empty = no filter)
Country string // ISO 3166-1 alpha-2 (e.g. "US", "TR"); empty = backend default
Topic string // free-form classifier the backend may honour
}
SearchOptions are the optional filters layered on top of (query, limit). Each backend maps these to its own API: Brave uses goggles for site filters + freshness for recency; Tavily uses include_domains / exclude_domains / topic / time_range; Google CSE uses sort=date + as_sitesearch.
type SemanticSearchResult ¶ added in v0.20.0
type SemanticSearchResult struct {
BaseResult
Repo string `json:"repo"`
Query string `json:"query"`
Results []index.Result `json:"results"`
}
SemanticSearchResult is the MCP response shape.
func (SemanticSearchResult) Render ¶ added in v0.20.0
func (r SemanticSearchResult) Render() string
Render satisfies Renderer. One result per line in the human form, score in parentheses. Path:lines: snippet first 80 chars.
type SessionKey ¶ added in v0.20.0
type SessionKey string
SessionKey is the trusted MCP session identifier. "anonymous" when the transport doesn't supply one (typical stdio).
func SessionKeyFromContext ¶ added in v0.20.0
func SessionKeyFromContext(ctx context.Context) SessionKey
SessionKeyFromContext extracts the trusted MCP session id from a tool handler's ctx. Falls back to "anonymous" so unit tests (and stdio sessions without a transport-supplied id) still get a meaningful key.
type SessionState ¶ added in v0.20.0
type SessionState struct {
// contains filtered or unexported fields
}
SessionState is the process-local read registry. Concurrent callers share one instance via Sessions.
func (*SessionState) ReadOf ¶ added in v0.20.0
func (s *SessionState) ReadOf(sid SessionKey, path string) (ReadRecord, bool)
ReadOf returns the latest record for (session, path).
func (*SessionState) RecordRead ¶ added in v0.20.0
func (s *SessionState) RecordRead(sid SessionKey, r ReadRecord)
RecordRead stores a Read observation. Idempotent — re-reading the same path overwrites the prior record.
type ToolSearchResult ¶
type ToolSearchResult struct {
BaseResult
Query string `json:"query"`
Results []any `json:"results"`
TotalIndexed int `json:"total_indexed"`
TypeFilter string `json:"type_filter,omitempty"`
DetailLevel string `json:"detail_level,omitempty"`
}
ToolSearchResult is the JSON envelope returned to the agent. Results is a slice of detail-level-specific entries; the concrete shape (name-only / name+desc / full schema) is chosen at handler time based on the operator's `detail_level` arg. We carry it as `[]any` rather than generic `map` so the on-wire JSON keeps stable field order per detail level.
func (ToolSearchResult) Render ¶ added in v0.9.0
func (r ToolSearchResult) Render() string
Render satisfies the Renderer contract. Each hit is rendered as "[score] name (type) — description" so the agent and the user see a plausible top-N list rather than raw JSON. The renderer type-switches on the concrete hit shape so detail_level=name (which has no Type / Description) still produces a readable summary line.
type VerifyCheck ¶ added in v0.20.0
type VerifyCheck struct {
Name string `json:"name"`
Status string `json:"status"` // "pass" | "fail" | "timeout" | "skipped"
DurationMs int64 `json:"duration_ms"`
Summary string `json:"summary,omitempty"`
DetailsLogExcerpt string `json:"details_log_excerpt,omitempty"`
}
VerifyCheck is one per-runner result. `DetailsLogExcerpt` is the last verifyMaxLogExcerpt bytes of combined stdout+stderr — enough for an agent to read the last failing assertion without blowing the response budget.
type VerifyResult ¶ added in v0.20.0
type VerifyResult struct {
BaseResult
Repo string `json:"repo"`
Checks []VerifyCheck `json:"checks"`
Overall string `json:"overall"` // "pass" | "fail"
}
VerifyResult is the uniform response. `Overall` is "pass" iff every check passed; one fail flips the whole result.
func (VerifyResult) Render ¶ added in v0.20.0
func (r VerifyResult) Render() string
Render satisfies the Renderer contract. One line per check + a final overall verdict.
type WebFetchResult ¶
type WebFetchResult struct {
BaseResult
URL string `json:"url"`
FinalURL string `json:"final_url"`
Status int `json:"status"`
ContentType string `json:"content_type"`
Format string `json:"format"` // "html" | "text" | "binary-rejected"
Title string `json:"title,omitempty"`
Byline string `json:"byline,omitempty"`
SiteName string `json:"site_name,omitempty"`
Content string `json:"content"`
SizeBytes int `json:"size_bytes"`
FetchedAt string `json:"fetched_at"`
Truncated bool `json:"truncated"`
}
WebFetchResult is the uniform shape returned to the agent.
func (WebFetchResult) Render ¶ added in v0.9.0
func (r WebFetchResult) Render() string
Render satisfies the Renderer contract. Header carries the URL + status + format; body is the extracted article (or raw text); footer notes truncation when applicable.
type WebSearchHit ¶
type WebSearchHit struct {
Title string `json:"title"`
URL string `json:"url"`
Snippet string `json:"snippet,omitempty"`
}
WebSearchHit is one ranked result from any backend.
type WebSearchResult ¶
type WebSearchResult struct {
BaseResult
Query string `json:"query"`
Results []WebSearchHit `json:"results"`
ResultsCount int `json:"results_count"`
Truncated bool `json:"truncated"`
}
WebSearchResult is the uniform result envelope the agent receives. Backend lives in BaseResult.Engine because the engine concept is the same — which backend ran this query — and consolidating in the embedded struct keeps every tool's "who did the work" field in one place across the catalog.
func (WebSearchResult) Render ¶ added in v0.9.0
func (r WebSearchResult) Render() string
Render satisfies the Renderer contract. Header carries query + backend; body lists `[N] title — url` rows so a developer scans results the same way they would in a browser results page.
type WriteResult ¶
type WriteResult struct {
BaseResult
Path string `json:"path"`
BytesWritten int64 `json:"bytes_written"`
Created bool `json:"created"`
LineEndings string `json:"line_endings"`
LintFindings []lint.Finding `json:"lint_findings,omitempty"`
}
WriteResult is the uniform shape returned to the agent.
func (WriteResult) Render ¶ added in v0.9.0
func (r WriteResult) Render() string
Render satisfies the Renderer contract. The Operation field switches between "Write" and "Create" based on whether the file existed beforehand — agents glance-read whether something was clobbered.
Source Files
¶
- agent_detect_tool.go
- agent_tool.go
- agents_tool.go
- atomic.go
- autodev_tool.go
- autopilot_tool.go
- bash.go
- bash_bg.go
- bash_bg_tool.go
- bridges_tool.go
- browser_fetch.go
- browser_scrape.go
- commit_tool.go
- edit.go
- engines.go
- exec.go
- exec_unix.go
- glob.go
- grep.go
- ideator_tool.go
- manifest.go
- mcp_tool.go
- portal_tool.go
- pretty.go
- read.go
- read_html.go
- read_office.go
- read_pdf_ipynb.go
- read_structured.go
- recipes_tool.go
- redact.go
- rules_add_tool.go
- rules_tool.go
- sandbox_tool.go
- semsearch.go
- session_state.go
- setcontext_tool.go
- skill_load_tool.go
- skill_tool.go
- source_check_tool.go
- source_registry_tool.go
- task_reply_tool.go
- tasknotify_tool.go
- tasks_tool.go
- toolsearch.go
- unattended_verify_tool.go
- verify.go
- version_tool.go
- webfetch.go
- webfetch_ssrf.go
- websearch.go
- websearch_brave.go
- write.go