46+ built-in agent tools, part 1: files, search, git, and the web
More tools don't make a better agent. Rysh's rule: a tool earns a slot only when it beats bash. Here's the working half of the toolbox.
Here's an unpopular opinion from a company whose homepage says "40+ built-in tools": tool count is a vanity metric.
Every agent platform brags about tool count. But an agent with a hundred overlapping tools is worse than one with a sharp toolbox — every redundant tool is another way to pick the wrong one, another chunk of context window spent on schemas, another decision the model can fumble.
So rysh's toolset is governed by one ruthless rule:
A tool earns a slot only when it offers something
bashcannot.
The agent already has a shell. If bash can do the job cleanly, the job belongs to bash, with guidance in the system prompt. A dedicated tool has to justify itself with at least one of: structured output a program can parse, preview/approval safety, secret redaction, cross-pane coordination, or a genuinely distinct modality. Across the whole platform that discipline still adds up to 46+ tools — this post tours the single-agent half: files, search, git, code intel, environment, testing, and the web. (Part 2 covers the coordination and memory tools — the ones no single-agent CLI has.)
Files: where safety pays the rent
file_read— read a file, with sane limits so one giant file doesn't flood the context window.edit— targeted change: one exact old/new string pair, or an atomic batch of edits to a file. Old text must match exactly and uniquely — no fuzzy matching its way into the wrong block.file_write— create or replace a whole file.
Why not sed and cat > file via bash? Because writes deserve ceremony. edit and file_write are preview-first: the change is rendered as a coloured diff in your pane and waits for your approval before disk changes. You can't build that guarantee on ad-hoc shell writes — which is exactly why file mutation gets tools and file plumbing doesn't.
Search: structured, fast, boring
glob— find files by pattern.grep— find content by regex, results structured for an agent to iterate.
These earn slots by being the highest-frequency calls an agent makes. Investigating a bug is 80% search; giving those calls predictable, parseable output makes every downstream step cheaper.
Git: reads are free, commits are ceremony
Here's the consolidation rule in action. Rysh has exactly one dedicated git tool: git_commit — and it's approval-gated by default, because writing history is a decision with your name on it.
Everything else — git status, git diff --color=always, git log, git show — is just bash, and runs prompt-free under the allowlist. There is no git_status tool, no git_diff tool. They'd be wrappers around things the shell already does perfectly. Slots denied.
Code intelligence: one tool, one job
symbol_search— find where a symbol is declared, not just where its name appears.
Grep tells you a string occurs in 40 places; symbol_search tells you which one is the declaration. That's a real modality difference — grep can't know the difference between a definition and a call site. One tool, no overlap. (Directory trees? ls, tree, find — bash.)
Environment: the redaction tool
env_read— read environment variables, with values redacted for variables whose names mark them as secrets.
This one's the clearest example of the earning-a-slot rule. printenv isn't on the shell allowlist, so it asks you first — and once you say yes, its output goes to the model. env_read puts a guard on that path: a variable such as AWS_SECRET_ACCESS_KEY, or anything with SECRET, TOKEN or PASSWORD in its name, comes back as <redacted>, so the agent learns the variable exists without seeing the value. The match is by name, so a key stored under a name like ANTHROPIC_API_KEY is not caught. (Process and port inspection, meanwhile: ps, lsof — bash.)
Testing: structured results beat scrollback
test_run— run Go tests and get a structured summary: pass/fail/skip counts and a PASS/FAIL status, on top of the raw output.
The consumer of test output is often not you — it's the agent's next step. A count up front means the agent knows "2 failed" before it reads a line of output, instead of regex-parsing 400 lines of scrollback to find out. Lint and builds, by contrast, stay in bash (go vet, go build, golangci-lint): their output is already terse enough.
The web: a different modality entirely
web_search— search the live web.web_fetch— fetch and read a page.
Bash genuinely can't do this well (curl gives you HTML soup and no search). Fresh docs, changelogs, error messages from three weeks ago — this is how an agent escapes its training cutoff.
The takeaway
Look at the pattern across every family: plumbing goes to bash, and tools exist where they buy safety, structure, or reach. Approval-gated writes. Redacted env reads. Parseable tests. Live web. The rest rides the shell, governed by the same allowlist: routine reads run free, and anything not on the list asks you first.
All of it runs on Claude, with your own API key, on your own machine — and every tool call is visible in the pane as it happens.
A sharp toolbox, not a big one. Part 2 is where it gets unusual: tools that let agents inspect each other's panes, message each other, and share memory across a workspace.
Opinionated about agent tooling? So are we — come argue with the founders directly as a design partner: rysh.ai/design-partner.
More in this series: 46+ built-in agent tools, part 2: cross-pane coordination and shared memory · The bash allowlist: safe-by-default shell execution for agents