Tool Selection

The right tool returns exactly what you need. The wrong tool dumps thousands of tokens of noise. Choose tools like a surgeon, not a bulldozer.

Intermediate 10 min read

Dedicated Tools vs Bash

In Claude Code, the agent has access to both dedicated tools (Grep, Glob, Read, Edit, Write) and a general Bash shell. Bash can technically do everything the dedicated tools can, but at a significant token cost:

TaskBash commandBash tokensDedicated toolTool tokens
Find login functiongrep -rn "function login" .~2,000 (all matches)Grep tool~200 (matches only)
List PHP filesfind . -name "*.php" | head -50~800Glob tool~150
Read one functioncat auth.php~4,000 (full file)Read with range~300 (lines 45-80)
Search for a symbolgrep -r "getUserById"~500Grep tool~80

Grep - Find Before You Read

Grep is the most powerful token-saving tool in agentic coding. Use it to locate the exact file and line before committing to reading a file. The pattern: grep first, read targeted.

Grep strategies
# Find a function definition:
Grep: pattern="function getUserById", glob="*.php"
Result: app/models/UserModel.php:67  (tells you exactly where to read)

# Find all usages of a method:
Grep: pattern="->getUserById\(", type="php"
Result: 4 files with line numbers (read only what you need)

# Find a bug-related string:
Grep: pattern="session_regenerate_id", glob="*.php"
Result: auth/AuthController.php:89  (one file, one line)

# Find a CSS class:
Grep: pattern="\.hero-title", glob="*.css"
Result: assets/css/main.css:234  (targeted)

# Pattern: never read a file without grep-ing first
# Exception: files named in CLAUDE.md as the obvious place to look

Glob - List by Pattern

Glob finds files by name pattern and returns only paths, not content. Use it to discover file names before deciding what to read.

Glob vs find
# Anti-pattern (Bash - returns too much):
$ find . -name "*.php" -path "*/controllers/*"
# Returns absolute paths for 40 controller files + metadata = ~500 tokens

# Better (Glob tool):
Glob: pattern="app/controllers/*.php"
# Returns just filenames sorted by modification time = ~100 tokens

# Most useful Glob patterns:
"src/**/*.ts"          - all TypeScript files recursively
"app/models/*.php"     - all model files
"tests/**/*Test.php"   - all test files
"*.{js,ts}"            - JS and TS at root
"config/*.php"         - all config files

Read with Line Ranges

Once you know where a function is (from Grep), read only that range. The Read tool accepts offset (start line) and limit (number of lines).

Targeted reads
# Full file read (anti-pattern for large files):
Read: file_path="app/models/UserModel.php"
-> 400 lines, ~3,500 tokens

# Targeted read after grep tells you login() is at line 67:
Read: file_path="app/models/UserModel.php", offset=60, limit=30
-> 30 lines (the function + context), ~280 tokens
-> 12.5x cheaper

# In Claude Code you can say:
"Read app/models/UserModel.php lines 60-90"
# The agent will use Read with the correct offset and limit

# Strategy: grep -> get line number -> read offset=(line-5) limit=40

When to Use Bash

Bash is the right choice for these operations - not for file exploration:

  • Run tests - composer test 2>&1 | tail -30 (pipe to trim output)
  • Git operations - git status, git diff HEAD --stat
  • Build / compile - npm run build 2>&1 | tail -20
  • Install packages - composer require vendor/package
  • Run migrations - php artisan migrate
  • Check process status - php -v, mysql --version
Always pipe Bash output to tail or grep

Long Bash outputs are tool results that go straight into context. npm install can produce 2,000+ lines. npm install 2>&1 | tail -5 gives you just the result. composer test 2>&1 | tail -30 gives you just the test summary. Build this habit for all verbose commands.

Tool Cost Comparison

OperationRecommended toolTypical tokensAvoid
Find a function/classGrep50-300Bash grep, cat full file
List files by typeGlob50-200Bash find, ls -R
Read a known functionRead (offset+limit)100-500Read (full file)
Edit a fileEdit (old_string/new_string)~50Write (full rewrite)
Run testsBash + tail100-500Bash without pipe
Check git changesBash git diff --stat50-200git diff (full patch)
Search all usagesGrep (files_with_matches mode)30-100Bash grep -rn
Add to your CLAUDE.md
## Tool preferences (follow these strictly)
- Use Grep tool, never `grep` or `rg` Bash commands
- Use Glob tool, never `find` or `ls -R`
- Read files with offset+limit when the target section is known
- Pipe all Bash output to `| tail -30` or `| head -20` to limit tokens
- Use Edit (old/new string) for changes, not Write (full rewrite)
- Run `composer test 2>&1 | tail -30` not `composer test` alone

Frequently Asked Questions

Running cat /path/to/large-file.php via Bash on a 500-line file. You get the entire file in the tool result. Compare to Grep, which returns only matching lines and their context. For a file with one relevant function, Grep uses 50-200 tokens where Bash cat uses 4,000-6,000.

No - Bash is essential for running tests, checking git status, running build commands, and executing shell pipelines. Avoid it for file-reading operations (cat, head, tail, find, grep) where dedicated tools are far more efficient. Bash for execution, dedicated tools for exploration.

Yes. Add a tools preference section to your CLAUDE.md: "Use Grep not grep/cat. Use Glob not find. Read files with line ranges when the relevant section is known. Run Bash only for test execution and build commands." Agents follow these guidelines when they are explicit and in the system prompt.

Test output can be verbose. Pipe long output to a summary: composer test 2>&1 | tail -20 gives you just the summary lines instead of every passing test. For 200-test suites, this reduces tool result tokens from 5,000+ to under 500.