Tools and modules
What the model can call, when each tool is on, and the modules that add them.
Tools
The model receives the full advertised schema every round (Loop::advertised_tools). Core names live in src/tools/catalog.rs.
Reads return N:hash|text. A stale or ambiguous tag fails before write. read lists a directory or shows an image. search finds text in files and files by name anywhere on disk. pattern is a regex over contents, or a list of alternatives; name matches files whose names hold every word in any order ("q3 report"); glob matches a file pattern, and a glob without wildcards matches names that contain it. Given together, they search the contents of the matching files only. path or paths pick where; the workspace is the default and ~ works. Case is ignored unless case_sensitive is true. word matches whole words, literal turns off regex, newer keeps files modified within a span such as 2d, output picks lines (the default), files, count, or folders (matching files counted per folder), offset pages through long results and answers no entries at offset N past the end, and depth, context, and path given as a list narrow or widen it. A result over 50 KB is cut at a line and says how to narrow it. The older argument names files, count, group, paths, type, exclude, before, after, and multiline still work. Results are newest first, a name search lists symbolic links to files, and a result names the folders and gitignored files it skipped, the folders it could not read, and any path it could not open; no_ignore also searches gitignored files and build folders such as node_modules and target. /proc, /sys, /dev, and the macOS data-volume mirror are never walked. A call that runs past search_secs returns what it found and says so; a path that the disk never answers can still hold one background thread until the operating system returns. Overlapping paths count each file once. A name search (with name or glob) over a path outside the workspace that takes longer than search_index_after_ms starts a background file index of that path in ~/.summonr/cache/names/; later name searches under it answer from the index in well under a second, check every hit on disk, and say how old the index is. An index older than search_index_secs refreshes in the background when it is used, so a file made since the last refresh appears after the next one. Answers from the index skip build folders unless no_ignore, and do not apply .gitignore. Search hits are path:N:col:line; col is the 1-based UTF-16 column of the match, which lsp takes as character. With tags true, hits are path:N:hash|line, and N:hash is the tag that edit takes. edit covers substring replace (old/new), line replace (tag/new), insert (tag/text), delete (op: delete), a batch (edits), and a rename or move (path with to). write creates or overwrites one file, or several (files); over an existing file it returns wrote PATH (N lines, replaced M lines), not the diff. read pages by 50 KB by default; an explicit limit is capped at 1000 lines. run_command takes workdir; its output keeps about 50 KB of head and tail, a single line up to 8 KB, and the full log path is named only when that cut something. Only exact cat FILE, single-file head, and sed -n A,Bp FILE without a workdir are answered by read. Plain search commands without a workdir are answered by search: grep and rg with common flags (-r, -n, -i, -l, -c, -w, -F, -e, --include, -g, -C), find PATH -name|-iname GLOB with -maxdepth, -type f, and -not -path, and mdfind -name WORDS [-onlyin DIR], alone, joined by ;, or piped into head. The result names the search call it ran. Any other form, and ls, wc, and tree, run in the shell. A foreground command waits up to two minutes; past that it keeps running as a background job and returns its id and the call that waits for it, unless timeout_secs was set, which stops it instead. Where a command cannot become a job (a child session, a read-only session, or the jobs module turned off), it is stopped after an hour. Explicit and automatically backgrounded commands keep running after summonr exits, with logs and exit status under .summonr/jobs/. background: true cannot be combined with timeout_secs; use a foreground timeout or stop the returned job. Foreground commands own their descendants: cancellation and completion stop the process group. A background shell waits for its shell jobs before recording completion. A job poll waits until the job exits or the wait limit passes.
| Name | When | Notes |
|---|---|---|
read | always | File, directory, or image |
search | always | Contents (pattern) or files by name (name, glob) under any readable path; ignores case; newer, group, offset, word; content search skips files over 1 MiB |
edit | always | Change or move a file; hashes from read; edits for a batch |
write | always | New or empty files; files for several |
run_command | always | workdir / background / job / kill; full log path |
todo | always | Replaces the Work task list; status pending, active, or done. Update it as tasks start or finish. |
skill | skills catalog exists | Loads one SKILL.md by name |
lsp | lsp on | Diagnostics for a path; definition, references, or new_name at line and character |
web | search on (off by default) | query searches; url fetches as markdown, text, or html |
browser | browser on (off by default) | One Charm action as JSON, or snapshot, read, screenshot, tabs, login, close |
task | task module, interactive session | Child session |
ask | interactive session, not in a child | One to four questions; each has up to four options (label, description) and multiple, or no options for a typed answer |
agents | mail module | List live agent sessions by name |
send | mail module | to (a name, an id, or all) and text: write to a peer's inbox |
inbox | mail module | Read mail that arrived since the last read |
board | mail module | action get, set, or list; key, value |
mcp | an MCP server has over 8 KB of tool schemas | Lists those servers' tool names; query returns matching tools with schemas; tool and arguments call one |
The old names (read_file, list_dir, grep, glob, show_image, write_file, replace_text, replace_lines, insert_after, delete_lines, replace_texts, edit_file, diagnostics, definition, web_search, and web_fetch) still execute and are not advertised. A read-only research child keeps the parent's tool list, so its first request reuses the parent's prompt cache. It can call read, search, skill, and, with search on, web; run_command, edit, and write are refused when called.
Modules
Every optional capability is a module compiled into the binary: search, browser, lsp, jobs, task, skills, mcp, mail, and memory. That list is the built-in module set: curated, switchable, and inside the harness process RSS. search, browser, and mail are off by default so unused tool schemas stay out of the first prefix_hash; mcp is on, and adds schemas only for servers you configure; the mail roster and @ messages work without the mail module. summonr modules lists them with their state; the Modules rows in /settings in the interface switches one and writes [modules] in ~/.summonr/config.toml. After the first prefix_hash in this process, that write is for the next process only. A workspace .summonr/config.toml may turn a module off for that project but cannot turn one on. A new compiled tool is a row on module-api.md in the same change; if a skill or MCP can do the job, it is not a module. summonr runs no third-party code inside the harness; modules read declarative files under .summonr where they need user input.
The search tool is always on and is separate from the search module. It honors .gitignore, skips build directories, binaries, and files over 1 MiB, and lists matching files when only glob is set. With the search module on, web with query reads DuckDuckGo's results page, then Brave's when DuckDuckGo returns nothing, without a key, and url fetches one page. freshness takes day, week, or month. The engine list is data in src/web/engines.toml. Both go through Leyline with a browser identity, so no search API key or self-hosted search service is needed. [search] takes count, allowed_domains, and excluded_domains.
With the browser module on, the browser tool drives the Chrome, Edge, or Brave already installed, through Charm. It takes one action as JSON (navigate, click, fill, press, select, check, and the rest of Charm's actions, with targets as eN refs from a snapshot or CSS), plus snapshot, read, screenshot, tabs, login, and close. It uses a profile of its own at ~/.summonr/browser/profiles/NAME, never your everyday browser, so it holds only the logins you give it; login opens a visible window where you sign in. Cookies are saved after every browser call, so a login survives the next session even when summonr exits abruptly. Every URL it opens passes the same check as web: no private hosts and no plain http. When web with url meets a page that needs JavaScript, it renders the page in this browser. [browser] takes profile (the profile name, default when unset), headed, chrome (the executable), and events (page and runtime). Language modules cover Rust, TypeScript/JavaScript, Python, and Go. They select the server from the file and a project marker, then keep one connection per module in a polyglot checkout. Rust passes initialization options that disable check-on-save, build scripts, proc macros, and cargo --all-targets. Explicit Cargo commands still run through run_command.
A workspace .summonr/config.toml may force a built-in module:
[lsp]module = "rust" Repository config cannot supply executable argv. A trusted ~/.summonr/config.toml may use [lsp] command = ["server", "--stdio"] when a built-in module does not fit. Language servers run as trusted host processes with the inherited environment. They can access files and network resources with your account's permissions. Rename edits returned to summonr still pass through its file policy. Disable the lsp module when you do not trust the server or the project configuration it reads.
Unknown flags exit 1. A red verify gate exits 2. In --goal and --steps, the check decides: when a run stops short, summonr runs the configured check once at exit, and a failed check exits 2 even when the budget ran out. A run that stops short exits 3 when no check is configured, or when the check passed but the goal was not met: a budget breach, a stalled or impossible goal, or an aborted turn. -p runs no check at exit. On Unix, SIGINT exits 130, SIGTERM 143, and SIGHUP 129; on Windows, Ctrl+C exits 130. A signal exit skips the --worktree finish, so the worktree and its branch stay in place. JSON turn receipts keep model text separate from the changed-path list and every configured completion check. verified on a receipt is true only when at least one check ran and every check passed; a turn with no configured check completes with verified: false.
Questions from the model
In an interactive session the model can call ask to put one to four questions to you. The dialog above the composer shows one question at a time: ↑ and ↓ move between options, space toggles an option when several are allowed, and enter picks. Type in the composer to give your own answer instead, or a number to pick that option. One question sends at once; several end on a review where y sends, e edits, and esc cancels. A message you sent into the turn before the dialog opened never answers it; it reaches the model after the dialog closes. The same dialog shows MCP server forms. -p, --steps, --goal, summonr acp, and child sessions have no one to answer, so the model does not get ask there.
Child sessions
The task tool delegates work to fresh child sessions. Only an interactive session offers it: -p, --steps, --goal, and summonr acp runs have no steering channel, so the model does not get task there. A model can emit several task calls in one response. summonr runs them concurrently. Each implement child edits an isolated checkout in <repo>-children/<id> that shares the parent's target/ and node_modules. The parent applies each finished child's edits on its own. Generated files (__pycache__, *.pyc, and the pytest, mypy, and ruff caches) and summonr state under .summonr/ other than check.toml and policy.toml never land. A child never inherits goal or steps mode: an implement child works in plain working mode. A child's first message names only its own checkout. Children started together do not see each other's edits. When two children change the same lines, that child's checkout stays on disk and the others still land. The child shows as a conflict, not a failure: kept <repo>-children/<id>: conflicts with the parent, followed by an rm -rf hint that removes the checkout when you are done. Task card titles use workspace-relative paths, and a card with one child takes that child's title. summonr never deletes a kept checkout. The receipt lists the files that landed. Implement children get the parent's file, shell, and language-server tools; background commands stay with the parent. The parent verifies after they finish. A task call may name a plugin agent with agent; its instructions open the child's first message, and its tools list limits what the child may call. The child's row names that agent. Pass --worktree on the session to isolate the whole run in a git worktree.
A research child reads the parent workspace. It cannot write files or start background commands. It has no shell: it reads and searches. Each child uses the endpoint context window. If the parent has a token or time budget, the children share what remains of it; otherwise a child runs until it finishes or you cancel it. A child gets the parent's system prompt and tool list byte for byte, so its first request reuses the parent's prompt cache; its instructions and working directory arrive in its first message. A child that calls task, web, an MCP tool, or peer mail gets a refusal, and a research child that calls edit or write is told it is read-only. Every child tool call, result, and answer streams into the parent transcript under the child id. A research child that finished before you pressed Esc keeps its result: the model reads it on the next turn instead of an aborted answer.
task with background: true starts the child and returns its id at once. task with child: ID reports its state, elapsed time, and last action while it runs, and its full result once it finishes; kill: true stops it. A turn does not end while a background child runs: summonr waits, then defers the turn the way it does for a background command, until the child finishes or the model kills it. Clear on a background status row dismisses that row for the current view without stopping the child. Its completion report and session log stay available. New children still appear.