@brain-core

Tools

The four fs_* tools brain-core contributes: read, list, search, and write across the URI-native filesystem.

brain-core's tools/ folder holds the four fs_* tools that cover the whole filesystem surface. Each declares its feature gate on its own schema (x-neuralis.requires.features), and the matching HTTP routes carry the same gates independently — the agent path and the direct-HTTP path are both checked, deny-by-default. See package-system tools for the schema-first tool contract.

ToolFeatureWhat it does
fs_readdrive.readBatch read (up to 10 files) by URI or UUID. Each entry can be a bare reference or {uri, line_start, line_end} carrying its own line window, so one call can take two hundred lines of one file and all of another; a batch-level window applies to the entries that do not bring their own. Output is line-numbered under a lines X-Y / total header, and when the snippet cap trims a whole-file read it states the total size and the next window to ask for. Images, video, audio, and PDFs are emitted as media content blocks for capable models; each block's source URI is reported so the chat stream can re-read it on conversation reload (a rendered PDF is kept inline, since re-reading it would re-render).
fs_listdrive.readBounded recursive tree that merges the vector index with live connector entries; omitting uri returns a full root view plus a source registry line. sources_only answers with the registry alone — which sources exist and how they are, without walking any of them — and limit accepts any size down to one entry.
fs_searchdrive.searchThree modes: semantic (meaning-based over the index), filter (metadata plus query keyword over indexed content — term-frequency ranked — and glob filename match), grep (literal fixed-string search over live connector content; glob narrows the scanned files, path_glob takes a real path glob, and case_sensitive plus context control the match and how many surrounding lines come back). Every mode reports truncated and total_seen, so a result set cut at its limit is never mistaken for the whole answer. Enforces the per-URI read policy on every result in all three modes. When the embedding provider is unavailable in a way waiting cannot fix — a missing embedding key, a credential-use limit, the embedding daily dollar cap, an active model that no longer resolves, or an exhausted account balance — semantic degrades to the full-text search and returns results with a warning rather than failing the call.
fs_writedrive.writeThe write verb. Each key is an operation: create, overwrite, edit, insert, lines, fields, move, copy, mkdir, revert, delete.

Connector-first reads

fs_read and fs_list are connector-first: live data comes from the connector even when the index is cold, and presence is reconciled by a targeted index lookup. Semantic and filter search require a warm index; grep bypasses the index entirely (ripgrep / git grep over connector content). fs_search enforces the per-URI read policy on every result across all three modes — a read:false subtree is silently absent — so grep is the uri-policy-gated counterpart to shell grep: a caller with drive.search plus read on a path can grep it without any execute / shell access. The full read/list/search behavior is detailed on Sources and connectors and Memory and sync.

When a source is a git checkout, fs_list also tags each dirty file with its git working-tree status — a bracketed letter ([M] modified, [A] added, [D] deleted, [R] renamed, [?] untracked) shown alongside the sync-presence glyph as a separate, orthogonal signal (a file can be both indexed and modified). The git status is scoped to the folder being listed — never a whole-repo scan — then time-boxed and cached, so it preserves the same "pay only for what you view" performance on million-file sources; it is fail-soft (any problem simply omits the badge). The Files widget renders the same status as a colour-coded badge in the tree. A source whose own root is a checkout is badged directly; a source that merely contains checkouts is badged per nested repository, each queried under the same folder scope. Badges refresh on the next listing, and the widget's Git Control view adds the live change-set, hunk staging, commit, branch and side-by-side diff surfaces on top of them — see Files UI.

fs_write — one tool, one key per operation

fs_write is the write verb, and the key names the operation rather than an action string beside a dozen conditional fields:

  • Content: edit (a list of exact-text replacements), insert (add lines at a line number), lines (replace a line range), overwrite (replace the whole file), create (make a new one), fields (category, status, pinned, tags, metadata).
  • Structure: move, copy, mkdir, revert, delete.

The content keys compose in one call — applied create/overwrite, then edit, insert, lines and fields — and land as a single write with a single undo point. If any one of them cannot be applied, none of them is: the file is left exactly as it was and the answer says which key failed and why. Each structural key stands on its own; a call that mixes two of them is refused with the operation to send first named in the message.

create never overwrites. When the name is taken the file lands beside it as name-2.ext and the answer reports the URI actually used, so overwrite is the only way to replace content — and it says so in its own name.

Asking is per key. A tool can declare which of its top-level keys need a confirmation, and fs_write declares delete: under the balanced permission mode an edit or a move runs without interrupting, and a delete asks first. Under auto nothing asks — that mode exists so an unattended run can finish, and a prompt it cannot answer would simply stop it. A delete is a revertible tombstone wherever a revert baseline can be taken. On a folder URI a delete removes the tree; over the external MCP surface, where there is nobody to confirm, a recursive folder delete that would leave files with no undo point is refused and the answer says to delete them one at a time instead.

A write to a path the source excludes from indexing is saved and revertible but stays out of search, and the answer reports that rather than implying the file is searchable.

fs_write — the verbs

Every key on fs_write is a verb, and its presence is the intent:

  • Content: create (never overwrites — an occupied name lands beside it and the answer says where), overwrite (full replace), edit[] (find/replace, one or many), insert (line-wise), lines (a line range), fields (frontmatter / metadata only). These COMPOSE: several in one call become one write with one undo point, applied in a fixed order.
  • Structure: move, copy, mkdir, delete, revert. Each stands alone.
  • Undo: revert — every write snapshots a baseline on the file node, so revert is one-level undo without any external service.

An empty folder has no file node to review, so mkdir always lands committed (and is not supported on brain://, where folders are implicit); an agent's copy lands pending_review like any other agent write, and its destination may be in another source.

The delete key opens an approval interaction in chat — the file is only removed after the user approves. The tool DECLARES that posture on the key itself, so an edit in the same permission mode stays quiet. Under the auto mode nothing asks: that mode exists so an unattended run can finish, and a prompt it cannot answer would simply stop it. A delete is a revertible tombstone wherever a revert baseline can be taken.

Coordinate and scope

Every file lives at the four-tuple coordinate (uri, connector, os_uri?, container_dir?). Source visibility is evaluated per scope and per-path access is governed by URI policies; the brain:// memory source is additionally isolated per agent. See the brain-core overview security section for the full scope rules.

On this page