Read-only mode
Set
readOnly: trueand the tool surface shrinks to the four non-mutating tools. The mutating tools andbashare not registered at all — a model literally cannot call them.
What it exposes
import { createAgentTools } from "@clarvis/agent-tools";
const tools = createAgentTools({ workspaceRoot: process.cwd(), readOnly: true });
console.log(tools.listTools().map((t) => t.name));
// [ 'read_file', 'list_dir', 'glob', 'grep' ]In read-only mode only read_file, list_dir, glob, and grep are exposed. write_file, edit_file, multi_edit, apply_patch, and bash are dropped from the surface.
How a blocked call behaves
Because the mutating tools are never registered, listTools() doesn't advertise them and callTool treats them as unknown — a call comes back as an error result with code not_found, not a permission error:
const res = await tools.callTool("write_file", { path: "x", content: "y" });
res.isError; // true
JSON.parse(res.text).error; // "not_found"This is deliberate: the read-only surface is defined by what is registered, so there is a single source of truth for both advertising and dispatch. There is no separate allow-list to keep in sync.
When to use it
- Retrieval / RAG over a repo — let a model read, glob, and grep to answer questions without any ability to change files or run commands.
- Code review and analysis — inspect a diff or a codebase where mutation would be out of scope.
- Untrusted or exploratory runs — a strong default when you're not ready to grant write or shell access. Note it is not a security boundary on its own; see below.
Combine with confinement
Read-only removes the write and shell tools; workspace confinement (on by default) keeps the read tools inside the workspace root. Together they give a model that can only read files within one directory:
const tools = createAgentTools({
workspaceRoot: "/srv/project",
readOnly: true,
confineToWorkspace: true, // the default; shown for emphasis
});Even so, treat these as defense-in-depth, not isolation — run the process in an OS-level sandbox. See Deploy securely.
argv & environment
If you drive config from argv/env via buildConfig, the same switch is --read-only or READ_ONLY=1 (accepts 1/true/yes/on). See Configuration.
See also
- Configuration —
readOnlyand every other option - The core API —
selectSurface(readOnly)decides the surface - Workspace confinement — the path guard that read tools still honor