Skip to content

Read-only mode

Set readOnly: true and the tool surface shrinks to the four non-mutating tools. The mutating tools and bash are not registered at all — a model literally cannot call them.

What it exposes

ts
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:

ts
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:

ts
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

Released under the MIT License.