Chapter 5: Files, Tools, and the Terminal
In Chapter 0 you learned what a terminal is, what a command is, and how to move between folders. In Chapter 1 you met Claude Code and let it answer a few simple questions. This chapter explains the bridge between the two: how Claude Code actually uses the terminal you just learned to use.
Everything useful that Claude Code does — reading a file, fixing a bug, looking up a guideline on the web — happens through a small set of built-in tools. The word “tool” here has a specific meaning. It does not mean “feature.” It means a named action Claude is allowed to take on your computer. Read is a tool. Edit is a tool. Bash is a tool. Eight of them do almost all the daily work, and once you know what each one does, the rest of this book makes sense.
🧠 Remember. A tool is just a verb Claude is allowed to use. You don’t run the tools yourself. You describe what you want, and Claude picks the tool. Your job is to describe the goal clearly enough that the right verb is the obvious one.
The eight tools, with a clinical analogy each
Below are the eight tools you will see most. Read each line once. You will see these names scroll past in the terminal as you work, and you should be able to recognize each.
- Read — opens a file and pulls its contents into Claude’s view. Like pulling a chart out of the rack and laying it open on the desk.
- Write — creates a brand-new file (or, if you allow it, overwrites an existing one). Like starting a new admission note on a blank sheet.
- Edit — changes specific words inside an existing file without touching the rest. Like editing one line of a discharge summary instead of rewriting the whole document.
- Bash — runs a command in the terminal exactly like you would. Like asking the EMR to “run this report” — it executes and prints the answer.
- Glob — finds files whose names match a pattern. Like searching the chart rack for “every chart whose folder name ends in
-2025.” - Grep — finds text inside files. Like asking, “show me every chart that mentions methotrexate.”
- WebSearch — does a Google-style search and returns links. Like asking a librarian to find references on a topic.
- WebFetch — opens one specific webpage and reads it. Like pulling down one article from the journal stack.
Those eight verbs are the daily workhorses. Claude has a few more specialized tools — Task, for instance, launches the subagents you will meet in Chapter 13 — but you will see these eight far more than all the rest combined.
💡 Tip. When you watch Claude work, you’ll see lines flash by like “Read… Edit… Bash…” with file names next to them. That is Claude announcing which tool it just used. Read those lines. They tell you what Claude actually did, not just what it said it did.
How Claude picks which tool
There is a logic to it. Once you see the logic, you stop being surprised by Claude’s choices.
| What you ask | What Claude reaches for |
|---|---|
| “What does this file do?” | Read the file. |
“Find every place we use the function optimus_encode.” |
Grep the repo for optimus_encode. |
| “List all the SQL files in the extraction folder.” | Glob for *.sql. |
| “Run the test suite.” | Bash to run pytest. |
| “Add a new column to this table.” | Read the file, then Edit the relevant line. |
| “Create a new notebook for the chemo checker.” | Write a new file. |
| “What does the KDIGO 2024 guideline say about Stage 3 timing?” | WebSearch, then WebFetch on the best result. |
Notice the pattern. When you name the file, Claude reads it. When you don’t, Claude has to search. The more specific your prompt, the cheaper and faster the answer.
💡 Tip. If Claude reaches for Grep when you wanted it to just open one file, the fix is in your prompt, not in Claude. Name the file and the search disappears.
The @ shortcut: telling Claude which file you mean
This is the single most useful keystroke in Part 2 of the book.
When you type @ inside a Claude Code prompt, a small file picker appears. Start typing a file name. It narrows down. Pick one. The file’s path is dropped into your prompt with a marker that tells Claude, “read this first, before doing anything else.”
Here is what it looks like on screen. You type:
Take a look at @
A small menu opens listing files in your current folder. You start typing aki and the menu narrows to notebooks/aki_extraction.py. You press Enter. Your prompt now reads:
Take a look at @notebooks/aki_extraction.py and tell me
why the baseline creatinine is null for about 12% of patients
in the last run.
You press Enter. Claude reads that one file directly. No searching, no guessing.
Without the @, Claude would have to look around. It might glob, then grep for “baseline creatinine,” then read three files that mention the words but aren’t what you meant, then finally land on the right one. That work is not free — every file Claude reads uses up its short-term memory (the context window, covered in detail in Chapter 6). The @ skips all of that.
You can @ more than one file in the same prompt:
Compare the staging logic in @notebooks/aki_v3.py and
@notebooks/aki_v4.py and tell me what changed.
🧠 Remember. Every file you can name, you should name.
@is how. The clearer the address, the cheaper the work.
The ! shortcut: running a command and showing Claude the result
The second shortcut is ! (the exclamation mark). If you start a line with !, the rest of the line is run as a terminal command, exactly as if you had typed it yourself — and the output is fed back into Claude.
Example. You want Claude to comment on your recent git history. Without !, you’d have to run git log yourself, copy the output, paste it in. With !, you do this:
!git log --oneline -20
What changed in the extraction code in the last two weeks?
The first line runs immediately. The terminal shows you the last 20 commits. Claude sees the same output. Your follow-up question is then answered against that history.
Another example, from a real KHCC session:
!python -c "import polars as pl; print(pl.read_parquet('data/cohort.parquet').schema)"
Now write the extraction prompt assuming those columns.
The first line prints the column layout of a data file. Claude sees the columns. The second line asks for code that fits them.
🔧 Technical Stuff. A
!command runs directly in your shell — Claude does not interpret it or ask permission for it — and the output is added to the conversation, where your next prompt can refer to it. You could get the same effect by running the command yourself and pasting the output. The shortcut saves the round trip.
Pasting screenshots: show, don’t describe
Claude Code can see images. If you take a screenshot — of an error message in your editor, a Databricks notebook cell with a red traceback, a chart with the wrong axis — you can paste it directly into the prompt with Ctrl+V. (Some Mac terminals take Cmd+V instead — if one doesn’t work, try the other.)
This is almost always faster than typing out what the screen says. The image becomes part of Claude’s view, exactly the same as if you’d shown it to a colleague over your shoulder.
💡 Tip. For visual problems (a Plotly chart with the wrong colors, a gtsummary table that exploded), screenshot and paste. For text problems (a Python traceback you already have selected), copy the text. Images use more of Claude’s memory than plain text, so don’t use them for things text can handle.
Should you run a command, or should Claude run it?
A question new users ask: “If Claude can run any terminal command, should I ever run commands myself?”
Yes, sometimes. Here is the split.
Run it yourself when:
- It’s a one-liner you have typed a thousand times (
git status,ls,pwd). - It is something destructive (
rm -rf some-folder) — you want your finger on the trigger, not Claude’s. - You want the output for yourself, not for Claude. There is no point paying for Claude to ingest output you only wanted to glance at.
Let Claude run it when:
- The output should inform Claude’s next step (“run the tests, then fix whatever fails”).
- You want a record of the command in the transcript so future-you can see what happened.
- It is part of a multi-step task and you don’t want to babysit each step.
⚠️ Warning. Do not let Claude run a command whose effect you do not understand. If Claude proposes
rm -rf node_modules, you should know that deletes a folder permanently. Read what Claude proposes before approving. Permissions (which we set up in Chapter 4) are a backstop, not a substitute for attention.
A KHCC walkthrough: one notebook, one bug
You are working on the AKI Notification Pipeline. That is the AI Office pipeline (described in Chapter 0.5) that scans every adult inpatient’s serum creatinine every morning, applies the KDIGO criteria, and emails the nephrology team about new acute kidney injury events. The code lives in a repository called aidi-extractions, which holds roughly eighty other notebooks too.
You have a bug. The baseline creatinine column is coming back empty for about 12% of patients in the last run.
The slow way. You write:
Find the AKI extraction code and fix the bug where baseline
creatinine is sometimes null.
Claude does not know which of the eighty notebooks is the AKI one. It globs the folder. It greps for “baseline creatinine.” It reads four files that mention the phrase. Eventually it lands on the right one. By the time it starts thinking about the bug, it has used a lot of memory finding the file you already knew.
The fast way. You write:
@notebooks/aki_extraction.py — the baseline_creatinine
column is null for about 12% of patients in the last run.
Read the function that computes it, and tell me why before
proposing any fix.
Claude reads exactly one file. It locates the relevant function. It begins reasoning about the failure. The whole exchange uses a fraction of the memory of the slow version.
The savings compound. Over a workday of twenty prompts, the @ habit can save you an hour and a meaningful amount of money.
🧠 Remember. Every unnecessary file Claude reads is one more thing competing for its attention. The cleaner the input, the sharper the answer.
When Glob and Grep are the right answer
The @ shortcut works when you know which file matters. When you don’t, Glob and Grep are exactly what you want.
Grep the aidi-extractions repo for any call to
azure_openai_client. I want to know which pipelines still use
the old wrapper.
That is a Grep job. Claude will return every match with line numbers, and you can read through them.
Glob every R Markdown file under analyses/ that was modified
in the last 30 days.
That is a Glob job, with a bit of Bash for the date filter. Don’t fight the right tool.
🔧 Technical Stuff. Grep here is powered by a faster, modern version of grep called ripgrep. It is regex-aware (supports patterns like
azure_.*_client), respects your.gitignorefile (so it skips build folders), and is much faster than the oldgrepyou may remember.
WebFetch and WebSearch: use them sparingly
These two tools reach out to the internet. They are good for:
- Looking up a library’s current behavior (“does pandas 2.2 still have
read_clipboard?”). - Pulling down a clinical guideline you do not have locally (a CAP protocol page, a KDIGO update).
- Checking whether an error message has a known fix.
They are bad for:
- Replacing documentation you should have saved into your repo once and re-used.
- Random fact-checking that does not change your code.
- “Just browse around the internet a bit.” Claude will fill its memory with pages that didn’t help.
⚠️ Warning. Never use WebFetch on a page that might contain credentials, internal URLs, or patient information. The page contents land in Claude’s transcript and possibly your logs. Treat WebFetch like any other external request: it leaves a record.
The whole idea, in one sentence
Claude has a small set of hands. Your prompts decide which hand reaches.
@ says use the Read hand on this specific file. ! says use the Bash hand on this specific command, and show me what came back. A vague prompt says figure out which hand to use, and good luck. Specificity is steering.
Try This
- Open Claude Code in a folder that has at least a few files. Type
@and watch the file picker appear. Pick a file. Ask, “summarize this file in three sentences.” Notice that the very first thing Claude does is Read — no searching first. - Type
!git log --oneline -10followed by “what’s the theme of the last ten commits?” Confirm that Claude can answer without you pasting anything. - Take a screenshot of any error message — from your editor, a Databricks cell, anywhere. Paste it into Claude Code and ask, “what’s wrong here?” Notice how much faster this is than typing out the error.
- Ask Claude to “find every place we use the old Fernet wrapper” (or substitute any function name from a project you know). Watch which tool it picks. Then ask the same thing but say, “grep for
legacy_fernet.” Compare the speed.
Watch Out
- Don’t let Claude grep for something you could have named with
@. Naming the file is always cheaper than searching for it. - Don’t paste a screenshot when plain text would do. Images cost Claude more memory than text. Use them for things that are genuinely visual.
- Don’t let Claude run destructive commands without reading them. Read the proposed command. If it starts with
rm,git reset --hard, or--force, slow down. - Don’t WebFetch sensitive pages. Whatever Claude pulls down enters the transcript. Treat it as if you forwarded the page to an external address.
- Don’t fight the tool choice. If Claude keeps picking Grep when you wanted Read, the prompt is the bug — fix the prompt, not the agent.