---
title: "Tools"
---

# Tools

The tools the CLI's agent works through, how editing, shell commands and the interpreter tool behave, and how language servers and the local code index help it.

The agent acts only through tools, and every tool call passes the [permission engine](https://neuralinverse.com/docs/cli/permissions/) first. `/tools` lists what is available in a session. The effect column below is what the permission engine and the modes reason about.

## Built-in tools

| Tool | What it does | Effect |
|---|---|---|
| `read_file` | Read a file (text, images, notebooks) with line numbers; `paths` reads up to 10 files in one call | read |
| `list_dir` | Directory tree | read |
| `find_files` | Find files by glob pattern, respecting `.gitignore` | read |
| `search_text` | Regular-expression search across files (ripgrep when available) | read |
| `code_intel` | Definitions, references, hover, symbols and diagnostics from language servers | read |
| `code_search` | Ranked search over the workspace code index | read |
| `write_file` | Create or replace a file | write |
| `edit_file` | Replace an exact piece of text in a file | write |
| `multi_edit` | Several replacements in one file, all or nothing | write |
| `apply_patch` | Add, change, rename and delete several files with one patch, all or nothing | write |
| `notebook_edit` | Replace, insert or delete a Jupyter notebook cell | write |
| `run_shell` | Run a shell command, optionally in the background; sandboxed when the sandbox is on | execute |
| `shell_output`, `shell_kill` | Read from or stop a background command | read, execute |
| `repl` | Persistent Python or Node.js interpreter sessions | execute |
| `web_fetch` | Fetch a URL as readable text; private addresses are blocked | network |
| `web_search` | Web search through Brave, Tavily or SearXNG, when configured | network |
| `update_plan` | Keep a visible checklist of the task's steps | none |
| `delegate` | Hand a self-contained job to a helper agent, optionally in the background | none |
| `task_status`, `task_result`, `task_stop` | Follow and control background helpers | none |
| `ask_user` | Ask you a multiple-choice question | none |
| `propose_plan` | In read-only mode, submit a plan for approval and switch modes | none |
| `worktree` | Create, list, switch to and remove git worktrees | execute |
| `wait` | Pause, for example while a deployment runs | none |
| `load_skill` | Load a skill's full instructions | read |
| `mcp_resources`, `mcp_read_resource` | Browse and read MCP server resources | read |
| `find_tools` | Load MCP tools on demand when many are installed | none |
| `mcp_<server>_<tool>` | Tools from your [MCP servers](https://neuralinverse.com/docs/cli/mcp/) | as declared |

Other tools appear in some situations:

- `team` starts a [team run](https://neuralinverse.com/docs/cli/autonomy/) for large, separable tasks (`"team": { "enabled": false }` turns it off).
- `work_declare`, `work_check_overlap`, `work_update` and `work_ack_overlap` appear while you are signed in to Govern. See [Organisation context](https://neuralinverse.com/docs/cli/organisation-context/#the-agents-team-work-tools).
- The `fw_*` and `hdl_*` tools appear when a [developer environment](https://neuralinverse.com/docs/cli/environments/) is active.

## Editing

**Tools per model family** (`tools.profile`, default `auto`). OpenAI-family models (`gpt-*`, o-series, `codex`) are offered `apply_patch` instead of `edit_file` and `multi_edit`; Anthropic, Gemini and other models keep the exact-replacement tools. `edit`, `patch` and `both` force a choice.

The patch format:

```text
*** Begin Patch
*** Update File: src/app.ts
@@ function main() {
   const a = 1;
-  const b = 2;
+  const b = 3;
*** Add File: src/new.ts
+export const created = true;
*** Delete File: src/old.ts
*** Update File: src/name.ts
*** Move to: src/renamed.ts
@@
-old line
+new line
*** End Patch
```

Every section is computed before anything is written, so a failing hunk changes nothing. A hunk whose context differs from the file only in whitespace is applied when it matches exactly one place, and the result says so. A hunk that does not match is reported with its number, its line in the patch, the lines it expected and the closest region of the file.

**Edit fallback** (`tools.fuzzyEdits`, default on). When `edit_file` or `multi_edit` cannot find the exact text, they retry with indentation-relative matching and then whitespace-normalised matching. A fallback is applied only when it matches exactly one place, and the result names the strategy and the lines, followed by the diff. When nothing matches, the error lists the three closest regions.

**Batched reads** (`tools.batchedReads`, default on). `read_file` takes up to 10 `paths` and returns each under a `==> path <==` header.

Every agent edit is also checked by the [checks gate](https://neuralinverse.com/docs/cli/checks/) before it is written.

## Shell commands

Commands are parsed into a full syntax tree before the permission check, so pipelines, `&&` chains, substitutions, here-documents, redirections and wrappers such as `sudo`, `env`, `timeout`, `xargs`, `sh -c` and `find -exec` are each checked on their own. Commands that cannot be analysed statically, such as `eval "$cmd"`, always ask when deny rules exist.

| Setting | Default | Meaning |
|---|---|---|
| `bash.defaultTimeoutMs` | 120000 | Timeout of a command |
| `bash.maxTimeoutMs` | 600000 | Longest timeout the agent may ask for |
| `bash.maxOutputChars` | 30000 | Output kept; longer output is cut on line boundaries, keeping the head and tail |
| `bash.shell` | | Shell to use |
| `env` | | Extra environment variables for commands the agent runs |

Commands the agent starts do not inherit secret-named environment variables; see [Permissions and modes](https://neuralinverse.com/docs/cli/permissions/#secrets-in-the-tool-environment-and-output).

## The repl tool

`repl` keeps an interpreter running for the conversation, so variables, imports and loaded data carry over between calls. It is offered when `python3` (Windows: `python`) or `node` is on `PATH`. `"tools": { "repl": false }` turns it off.

| Action | Input | Effect |
|---|---|---|
| `run` (default) | `language`, `code`, optional `timeout_ms` (default 60000, max 600000) | Runs the code; a final expression's value is printed; exceptions are reported and the session survives them |
| `reset` | `language` | Restarts that interpreter |
| `list` | | Running interpreters with their process id and cell count |

Standard input is not available. On a timeout or interruption the cell is interrupted and the state kept; an interpreter that does not respond within a couple of seconds is restarted and its state lost. Interpreters start in the project root with the same environment and sandbox as `run_shell`. For rules, the subject is `repl:<language> <first line of code>`, for example `"allow": ["repl(repl:python *)"]`. Calls are never treated as read-only.

## Web tools

`web_fetch` fetches a URL as readable text and blocks private addresses. `webFetch.allowedDomains`, `webFetch.deniedDomains` and `webFetch.maxBytes` limit it, as do rules such as `web_fetch(domain:docs.rs)`.

`web_search` is available only when a backend is configured: `BRAVE_SEARCH_API_KEY`, `TAVILY_API_KEY` or `SEARXNG_URL`.

## Helper agents and worktrees

`delegate` hands a self-contained job to a helper agent with its own conversation, which keeps the main context small. Helpers can run in the background (`agents.maxBackground`, default 4). Named profiles give helpers a brief, a restricted tool set or another model; see [Instructions, commands and skills](https://neuralinverse.com/docs/cli/extending/#sub-agents). `worktree` creates checkouts under `worktree.directory` (default `.neuralinverse/worktrees`).

## Verification after edits

After a turn in which the agent changed files, the CLI can run the project's own fast checks (type check, lint, related tests) and hand failures back to the model, for a bounded number of rounds.

| Key | Meaning |
|---|---|
| `verify.enabled` | Turn it off with `false` |
| `verify.mode` | `off`, `suggest` or `auto`. Default: `auto` in `auto-edit` and `full-auto`, `suggest` in `ask`, `off` otherwise |
| `verify.checks` | Your own checks: `{ "kind": "typecheck" \| "lint" \| "test" \| "build", "command", "cwd" }`; these always run |
| `verify.timeoutMs` | Default 300000 |
| `verify.maxRounds` | Default 3 |

## Language servers

`code_intel` and the diagnostics shown after edits use language servers already installed on your machine; nothing is installed for you. Supported: TypeScript and JavaScript (`tsc --lsp` from TypeScript 7+, `typescript-language-server`, `vtsls`), Python (`pyright`, `basedpyright`, `pylsp`, `jedi-language-server`), Go (`gopls`), Rust (`rust-analyzer`), Java (`jdtls`), C and C++ (`clangd`), C# (`csharp-ls`), Ruby (`ruby-lsp`, `solargraph`), PHP (`intelephense`, `phpactor`), Swift (`sourcekit-lsp`), Lua, YAML, JSON and Bash. After an edit, new errors and warnings in that file are shown to the agent.

```jsonc
{ "lsp": { "disabled": ["pyright"], "servers": { "zls": { "command": "zls", "extensions": [".zig"] } } } }
```

## Code index and repository map

On first use the CLI builds a local index of the workspace in `~/.neuralinverse/projects/<workspace>/index/`, never inside the repository: symbols per file for many languages, imports, and a keyword index over identifiers, paths and text. It honours `.gitignore` and skips vendored, build and cache folders, generated or minified files, binaries and files over 1 MB. A file watcher (or a rescan every 60 seconds) keeps it current. `/index` shows its status; `/index rebuild` scans again.

A short repository map (about 1500 tokens: the most imported and most recently changed files with their top-level declarations) is added to the system prompt.

```jsonc
{ "index": { "enabled": true, "maxFiles": 50000, "repoMapTokens": 1500 } }
```

**Semantic search is off by default, and the index is purely local.** Setting `index.embeddings` turns on vector search and **sends chunks of your indexed source code and your search queries to that provider's embeddings endpoint.** Use a provider you trust with your code; a local Ollama model keeps everything on your machine:

```jsonc
{ "index": { "embeddings": { "provider": "ollama", "model": "nomic-embed-text" } } }
```

Supported: OpenAI-compatible `/embeddings` (OpenAI, Azure OpenAI, vLLM, LM Studio), Ollama `/api/embed`, Gemini `batchEmbedContents`, and Bedrock Titan and Cohere embedding models.

## How the agent loop is tuned

| Setting | Default | Effect |
|---|---|---|
| `harness.loopDetection` | on | Watches for the same call with the same result three times, five failing tool results in a row, or `harness.stallTurns` (default 8) turns without progress. First a note asks the model to change approach; the second time the turn ends with the reason `stalled` |
| `harness.autoContinue` | on | An answer cut off by the output limit is continued automatically, up to `harness.maxAutoContinues` (default 2) times |
| `prompt.version` | `v1` | `v2` adds workflow guidance and notes per model family. Opt-in until eval results show it helps |
| `tools.deferThreshold` | 40 | Above this many tools, MCP tools load on demand through `find_tools` |

Each default is meant to be changed only after measurement with the [evals](https://neuralinverse.com/docs/cli/evals/).
