Tools and safety model
Feature docs index · Repository README
Choose a tool below, then check its path, output, and credential limits before use. Shell guardrails are not an OS sandbox.
| Tool | Contract |
|---|---|
read | Read known local files or internal resources. Local output supplies tags and line anchors for hash_edit; see reading files. |
bash / shell | Run non-interactive commands in the active cwd with configurable preflight, timeout, and bounded output. The host shell has no OS sandbox; see environment profiles. |
hash_edit | Apply hashline patches to existing UTF-8 files using latest current-session read tags, line anchors, stale-tag recovery, optional block ops, whole-file MV, and regular-file-only REM. Use for anchored changes to existing files. |
write | Create or fully replace a file; both path and content are required. Empty content is allowed, replacement is atomic, parent directories are created recursively, UTF-8 content is capped at 1 MiB, and final symlink targets are rejected. Relative paths resolve from cwd; absolute behavior follows capabilities.tools.write.absolute_paths. Use for new files or complete replacements. |
grep | Bounded, in-process content search with OR patterns, ranked/raw modes, pagination, and partial-scan metadata. No external rg is needed. |
find | Fuzzy path discovery with pagination and Git/Perforce ignore rules; directory listings are cached, not file contents. |
list_files | Return raw shallow direct child files/directories; does not read or honor ignore files. find and grep use shared git/P4-aware traversal where applicable. |
ast_grep | Embedded AST search, read-only rewrite previews, and outlines; no external CLI needed. Directory requests use shared Git/Perforce-aware walking of visible regular files. Explicit file requests bypass ignore filters but retain path checks. Empty visible worksets return successful no-match. |
view_image | Inspect one local image through a configured vision model. Requires absolute path and prompt; supports png, jpg, jpeg, gif, and webp; enforces max_image_bytes; sends image bytes only to configured capabilities.tools.view_image.vision_model (openai-codex/openai Responses API, Anthropic Messages API, or OpenAI-compatible custom provider). Never falls back to active chat model. |
subagents | Run independent delegated tasks in bounded parallel child sessions, optionally selecting a discovered subagent identity. |
web | Public research and programming documentation. search accepts a query; open accepts a public URL or cached reference. See below. |
Shell commands
bash requires command and a nonblank intent that briefly explains why the command is needed. The transcript card shows intent above command, then result summary. timeout is optional (1–300 seconds, default 30). Runtime aliases shell and cmd also require intent.
AST search and outlines
ast_grep defaults to operation: "search". Search requires pattern and accepts optional rewrite for a read-only diff preview. Use operation: "outline" to inspect symbols before reading source.
Neither operation needs an installed CLI. Embedded AST libraries infer language from file extension unless you supply one. Project configs and custom grammars are not loaded.
- Search returns
path:line:textwith 1-based lines. Rewrite previews identify each match by path, line, and exact end-exclusive byte range, then show removed-lines and replacement+lines. Surrounding text remains unchanged, and files are never written. Overlapping matches produce independent previews, not one combined patch. limitbounds returned lines (default 100, maximum 500); output is capped at 64 KiB. A boundary can cut a preview short, so checktruncatedbefore using it.- Pattern and rewrite each accept up to 4 KiB. Search accepts complete UTF-8 files up to 256 KiB, visits at most 10,000 files, and reads at most 128 MiB per call. Syntax trees are limited to 16,384 nodes and depth 64; patterns to 256 nodes. Replacement allocation estimates are capped at 1 MiB before expansion.
files_skipped,partial, andtruncatedreport oversized, unreadable, non-UTF-8, or overly complex files. - Parsing, including pattern parsing, checks cancellation and a shared 30-second deadline. Traversal checks each AST node before matching. A single bounded library match/replacement or filesystem operation cannot be interrupted mid-call. No detached workers are created. Unknown file types are skipped. In mixed-language searches, a pattern that cannot compile for one language makes results partial. Supply a language for strict pattern validation.
- Outline shares search's complete-file, file-count, scan-byte, and syntax-tree limits. Bundled rules cover Rust, TypeScript/TSX, JavaScript, Python, Go, Kotlin, Java, and Swift. Other languages are ignored.
{"operation":"outline","path":"src","language":"rust","limit":30}
- For outline, omit
patternandrewriteor set them to JSONnull. Other values, including empty strings and placeholders, are rejected. Outline-only fields areitems(structureby default, orexports,imports,all),view(digestby default, ornames,signatures,expanded),name(Rust regex over top-level name/signature/first source line),symbol_type(comma-separated lower camel case types), andpub_members(default false). For search, omit these fields or set them tonull;pub_members: falsedoes not count as absent. Filters do not select members directly. Name/type filters are capped at 512 bytes. - All fields except
operationtreatnullas omission. Search still requires a nonemptypattern. If supplied,operationmust besearchoroutline. Providers that require every key can use"pattern":null,"rewrite":nullfor outline and null outline-only fields for search. Invalid mode-specific arguments report offending fields with an omit-or-null example. - Explicit
structure/digestdefaults retain internal symbols for directory and file requests.namesomits members and computes only names, though name filtering still computes signatures.signaturesincludes top-level signatures;digestadds member names;expandedadds member signatures. - Each output line is a complete JSON object with
path,language, anditem. Items contain names, types, signatures, export/import flags, ranges, and direct members selected by the view. Lines and columns are 1-based; range ends are exclusive. Byte offsets are omitted. limitcounts top-level entries, not members or source lines (default 100, maximum 500). A parent and its selected members are kept or omitted together. Returned entry text is capped at 64 KiB.- Outline checks cancellation and the shared 30-second deadline before and after each extraction iterator step and before accepting output. One step may traverse the remaining bounded file tree and collect direct members. Individual library calls, including compilation of fixed bundled rules, and filesystem operations cannot stop mid-call. The deadline is cooperative, not a strict timeout. No child processes or detached workers are created.
- Check
symbols_returned,files_skipped,partial, andtruncated. Byte and entry limits retain only complete earlier entries; deadlines return partial failure. Empty outlines succeed. Project or ancestorsgconfig.yml, custom language libraries, and custom outline rules are never loaded. Only approved regular files are read under the same path and read checks as search.
URL routing
Use the narrowest tool that meets the request:
| Need | Tool | Use |
|---|---|---|
| Public unauthenticated plain text, Markdown, JSON, or HTML ordinary GET | web open | Bounded native fetch/readability; no JavaScript or interaction. |
| Public research and page text | web | Search and open; no browser interaction or CSS extraction. |
| Custom or non-public HTTP work | bash | Custom methods, headers, bodies, redirect control, binary downloads, private/local services, or an explicit request. |
URL open applies bounded readability extraction to substantial HTML and converts short HTML to Markdown. Never block or rewrite curl.
web contract
Use one operation per call. Omit unused fields or set them to null:
{"operation":"search","query":"Rust official release notes","limit":5,"domainFilter":["rust-lang.org","-old.rust-lang.org"],"recencyFilter":"month"}
{"operation":"open","url":"https://www.rust-lang.org/"}
{"operation":"open","reference":"web:<reference from a result>"}
- With active
openai-codex, search uses the active model and existing Codex OAuth/refresh athttps://chatgpt.com/backend-api/codex/responseswith nativeweb_search. Other providers use Exa/searchand require environment-onlyEXA_API_KEY. URL open fetches directly without credentials or an Exa key. Search backends do not fall back to each other or MCP. - Codex returns a labeled model-generated synthesis with URL citations, not page extracts. It creates no cached references; open cited URLs separately for page text.
limitrequests a source count but does not enforce it. Codex rejectsdomainFilterandrecencyFilter; omit both. The filtered example above applies only to Exa. - Codex search requires
response.completed, rejects failed or incomplete streams, and caps streams at 2 MiB. It reuses the provider's blocking transport, cancellation, byte-idle and semantic-progress watchdogs, and session-expiry refresh. Tool output remains capped at 48 KiB. - Query: 1 to 512 characters after trimming. URL: at most 2,048 UTF-8 bytes. Search results: 1 to 10, default 5.
- Search-only
domainFilteraccepts at most 20 bare ASCII domains (253 characters per domain, 63 per label). Prefix-to exclude. Schemes, ports, paths, whitespace, empty labels, and leading/trailing label hyphens are rejected. Entries are trimmed. Includes/excludes map to ExaincludeDomains/excludeDomains.recencyFilteracceptsday,week,month, oryear, mapped tostartPublishedDateat the current UTC date minus 1, 7, 30, or 365 days. It filters publication date, not crawl freshness. For open, omit filters or set them to null. Aliases and query batches are unsupported. - Only public HTTP(S) URLs are accepted. Credentials and sensitive URL parameters are rejected. URL open uses the DNS-pinned transport in
url_fetch.rs, which rejects private/local destinations and redirects. Exa result URLs are also validated; Exa controls retrieval of search extracts. - Exa search text requests are capped at 10,000 characters per page and responses at 2 MiB, with 5s/20s connect/request timeouts. Direct URL open downloads at most 512 KiB with 5s/15s connect/request timeouts and a 5,000-token text budget. Both check cancellation, cache at most 40,000 bytes per page, and cap output at 48 KiB with truncation metadata.
- Exa search shows source URLs, stable references, and bounded excerpts. Cached open returns stored text.
- Runtime stores up to 64 immutable page snapshots and evicts the oldest. Runtime clones share this cache. Sessions do not persist or restore it. An expired or unknown reference fails without network work; reopen the public URL for a new reference.
- URL open makes a direct GET and returns readable text, which may omit page content. Cached open returns the same snapshot without refreshing. Output gives no publication, crawl, or fetch timestamps; do not infer them from a reference.
Visible tool output
Mission Control shows pending and completed tool activity with safe status, metadata, and bounded output. Pending write/hash_edit entries do not include file contents or replacement payloads. web shows query/result/truncation metadata and redacts credential-shaped text. read shows requested paths. Subagent summaries omit raw child output. Shared summaries live in src/output/tool_summary.rs.
When opt-in LSP edit injection has fresh diagnostics, they are appended to the successful write/hash_edit tool result. Mission Control may show successful hash_edit changes as a bounded changed-line transcript preview and a larger activity-detail diff. Both are display-only, not provider tool results or JSONL session data.
subagents displays a bounded aggregate summary rather than raw child output.
Reading files
Use paths for known local files or skills:
{ "paths": ["README.md:1-200"] }
- Provider-facing schema requires
paths, accepting 1 to 8 entries. Runtime validation rejects missing, empty, blank, or unknown-file inputs. - Recognized read targets: local files,
skill://<name>skill definitions, andskill://<name>/<relative-reference>skill reference files. Other resource schemes are unsupported. HTTP(S) targets fail with guidance to usewebopen. - String selector suffixes:
:N,:-M,:N-M,:N+,:N+K,:raw, and compounds such as:raw:50-100. Selectors apply independently to each target. - Each local file remains limited to 1 MiB and UTF-8 text. Local files without a selector return up to 400 lines; use line selectors to choose another range.
- Multi-file output uses
--- FILE: <requested path> ---sections. File-specific errors appear asERROR:sections, and successful file sections remain visible when another requested file fails. - Complete multi-file
ToolResult.contentis capped at 1 MiB measured as UTF-8 bytes, including file headers, separators, file content, andERROR:text. readdoes not search, expand globs, or discover files. Usefindfor fuzzy path discovery orgrepfor content search, thenreadknown paths/resources.- Local file reads default to hashline output:
[path#TAG]header plus 1-indexedLINE:TEXTrows. :rawbypasses hashline formatting for plain text (path:raw,path:raw:20-40); it does not bypass byte caps or path/skill protections.- Skill reference reads are limited to discovered/enabled skills. References must be relative, cannot contain
.., cannot target symlinks or directories, must remain under the canonical skill directory, and must be UTF-8 under the 1 MiB read cap. hash_editanchors must use the newest tag and visible line numbers from the most recentreador successfulhash_editresponse for that file. Stale-tag failures mean re-read first, then retry with fresh anchors.
Finding paths
Discover paths without reading contents:
{ "query": "lib", "kind": "mixed", "path": "src", "limit": 20, "offset": 0 }
Rules:
queryis required, trimmed, and limited to 512 characters.kinddefaults tofiles;directoriesresults end with/in output, andmixedcan return both files and directories.limitdefaults to 50 and is capped at 200;offsetsupports pagination.pathis optional and must resolve to an existing directory. Relative paths stay within cwd; absolute paths outside cwd requirecapabilities.tools.find.absolute_paths(defaulttrue). Output is slash-normalized, cwd-relative for paths within cwd and absolute for outside paths.findis read-only, uses the shared workspace walker, and does not replacegrepcontent search.- Each scan cooperatively checks cancellation, visits at most 100,000 entries (including the root), and has a 10-second deadline. Filesystem calls can exceed a cooperative deadline. Narrow
pathwhen a scan is partial. scan_completeandtotal_matched_exactidentify exhaustive scans. Partial scans rank only observed matches, settruncated: trueandindex_ready: false, and reporthas_more: null;total_matchedis then a lower bound.entries_scanned,entry_limit_reached,timed_out,walk_errors, andwalk_entries_omittedexplain incomplete traversal. Paging does not resume a partial scan.- Workspace walking honors standard hidden/
.ignore/Git filters plus Perforce defaults and configuration. It prunes ignored directories before scanning and feedsfind,grep, and directory-modeast_grep;list_filesintentionally remains a raw shallow listing. - Perforce resolution follows
P4CONFIG→P4ENVIRO→ process environment → Windows user/system registry.P4IGNOREaccepts ordered semicolon-separated relative or absolute rule files; unset values use.p4ignorefollowed byp4ignore.txt. Non-macOS POSIX systems defaultP4ENVIROto$HOME/.p4enviro; Windows and macOS require it explicitly..p4rootis always excluded;.p4configand configuredP4CONFIGfilename are excluded when configuration discovery is active. P4 rule/config reads are bounded. macOSp4 setpreferences are not read directly; expose those values throughP4CONFIG,P4ENVIRO, or process environment. fs_cachestores directory listings only, keyed by path plus directory mtime with TTL expiry. It does not cache file bytes or provider-visible tool output.
Searching contents
{ "patterns": ["fn run"], "path": "src", "limit": 20, "context": 2 }
grepis fully in-process Rust search; it does not spawnrgor require search credentials.patternsis required, accepts 1 to 8 exact strings, and uses OR semantics.- Each pattern is matched as a case-sensitive regex after common brace/parenthesis repairs; failed compilation falls back to literal matching. The original pattern bytes are preserved for matching diagnostics and display.
- Ranked mode is the default: it emits
grouped_v1path headers,[def-like],[match], and[import]primary labels, and deduplicated context rows. Raw mode emits flat deterministicpath:line:contentrows and uses one extra match as a pagination lookahead. limitandoffsetapply to primary matching lines;contextadds at most 20 lines on either side and does not consume the primary limit. Ranked mode keeps at most five primary hits per file and reports omitted hits withtruncatedandper_filemetadata.- Reads are capped at 4 MiB per file and 128 MiB per invocation; traversal is capped at 10,000 files and 10 seconds. The provider-visible output is capped at 65,536 UTF-8 bytes and records are added atomically.
- Hidden, ignored,
.git,target, binary, special, and unreadable files are skipped as applicable. Metadata reports scan byte/file limits, per-file limits, recovery skips, binary/invalid-UTF-8 counts, matcher adjustments/fallbacks, exact-match status, and truncation reasons.
Editing files
Anchor patches to the latest read tags:
{ "input": "[README.md#A1B2]\nSWAP 10.=10:\n+new line" }
Rules:
- Each file section starts
[PATH#TAG];TAGmust come from latest current-session hashlinereadoutput or previous successfulhash_editresponse. - Supported ops:
SWAP,SWAP.BLK,DEL,DEL.BLK,INS.PRE,INS.POST,INS.BLK.POST,INS.HEAD,INS.TAIL,MV, andREM. - Body-taking ops end with
:and accept only+TEXTrows. Literal leading plus/minus content still needs the body prefix:++value,+- item. - Stale tag or surprising result: re-read file, then reissue patch with fresh tag/line anchors.
hash_editdoes not create new files; usewritefor creation.
Inspecting images
Configure an explicit vision provider/model before use:
{
"capabilities": {
"tools": {
"view_image": {
"vision_model": {
"provider": "local-vision",
"model": "vision-model-id"
},
"absolute_paths": true,
"max_image_bytes": 5242880
}
}
}
}
Rules:
pathmust be an absolute path to one existing regular local image. The path is canonicalized; supported formats are PNG, JPEG, GIF, and WebP, with case-insensitive extensions that must match the file signature. Outside-cwd access followscapabilities.tools.view_image.absolute_paths.promptis required and should name the exact visual details to inspect.- Image bytes go only to the explicitly configured vision model; there is no active-chat-model fallback.
capabilities.tools.view_image.max_image_bytesdefaults to 5 MiB and is configurable from 1 byte through 20 MiB. Returned text is capped at 64 KiB.
LSP edit diagnostics are opt-in and workspace-bound. Missing, slow, crashed, stale, or indexing servers skip injection without changing write or hash_edit success. They complement project checks and do not replace cargo check, tests, linters, or repository-specific verification.
Safety boundaries
- Tool calls and effects are represented in the session transcript.
- Relative paths resolve from the active working directory and cannot escape it. Built-ins accepting caller-controlled OS paths have independent, default-allow absolute-path settings; see the authoritative Configuration matrix for keys, aliases, exceptions, and opt-out behavior. LSP edit-diagnostic injection remains workspace-bound because it has no caller path argument.
bash/shellallows shell expansion by default. Setcapabilities.tools.bash.shell_expansion: falseto reject$,~, backticks,{, and}in bash commands during preflight.hash_editandwritereject final symlink mutation targets and enforce size/count limits.hash_editvalidates all sections before mutation when semantic/path checks fail, rejects unanchored or unseen-line hunks, and guardsREMto regular files only. Write replacement is atomic, but committed-but-undurable failures are possible.- Cwd/root checks reduce accidental escapes and common symlink escapes, but they are not a full TOCTOU-safe sandbox against a malicious concurrent local process racing the filesystem.
bash/shellruns through the host shell and is not an OS sandbox.webuses Codex OAuth for active Codex search and environment-onlyEXA_API_KEYfor other search, with no backend/MCP fallback. URL open fetches directly without an API key. URL checks, timeouts, bounded snapshots, and output limits are described above.grepoutput is capped at 64 KiB;weboutput is capped at 48 KiB with explicit truncation metadata.- Mission Control has separate transcript-card and Selected Activity Detail projections;
subagentsshows only safe summaries. Local/session raw results remain unchanged by these display projections. Do not ask tools to read or print secrets unless you accept them in terminal output and session artifacts. - File mutations are coordinated by per-file mutation locks.
Token-triggered streaming reminders
TTSR is disabled by default. When agent.reminders.enabled is true, rules inspect assistant streaming deltas and completed tool-call arguments mid-turn. Regex rules stay dormant until a match; on a match, magi-code aborts the current stream, records a hidden local ttsr_injection JSONL event, injects the configured system reminder, and retries the turn.
Built-in rules cover destructive commands, secret exfiltration, credential routing, cwd widening, and force push patterns when TTSR is enabled. User rules live in agent.reminders.rules settings as { "pattern": "...", "reminder": "..." } objects. TTSR is separate from hooks: hooks run at phase boundaries around tool/assistant events, while TTSR can interrupt provider streaming before a tool executes or assistant text completes.