What it does on each task
The same agent runs in the terminal, VS Code, JetBrains, a desktop app, and on the web. It needs a paid plan or an API key. Permissions, hooks, and a short project file are how the cheque stays small. Ask for a plan before a multi-file edit.
Starter
print("cd your-repo")
print("claude")
print("Explain how a short code is created. Do not edit files.")
Example
“Do not edit files” is a real first prompt on a codebase you do not know. You get a map before a diff.
You describe an outcome. Claude Code reads files, searches, runs commands, and edits, one tool call at a time. It asks before actions you have not allowed. The same agent runs in the terminal, VS Code, JetBrains, a desktop app, and on the web. It needs a paid Claude plan or an Anthropic API key.
cd your-repo claude # trust the folder when asked, then: # "Explain how a short code is created and resolved. Do not edit files."
Trusting a folder lets the agent read it. It is not a blank cheque to push, delete, or curl data out. Permissions, hooks, and a tight CLAUDE.md are how you keep the cheque small.
Start with an explanation, not an edit
On a repo you did not write, “analyse this project” replaces a one-hour knowledge transfer. Correct a wrong plan in one paragraph instead of reverting six files. Review prompts should say “flag missing tests,” not “improve this,” or you get a noisy rewrite.
Starter
prompts = [
"Explain how a short code is created and resolved. Do not edit files.",
"Where would a 4-character code collide with a 6-character code?",
"Add a failing test for that, then fix it, then show the diff.",
]
print(prompts[0])
Example
A stack trace pasted in should name the file to open first. You still confirm before anyone edits.
The highest-value first prompt on a codebase you do not know is “analyse this project”. On a small LangChain bootcamp repo that means: which notebooks exist, what they teach, what is uncommitted. You get a knowledge transfer without booking a teammate.
Prompts that stay useful
- “Where is the bug if a short code of length 4 sometimes collides? Only read.”
- “Add a failing test for that collision, then fix it, then show me the diff.”
- “Review this change the way a teammate would. Do not rewrite style.”
Ask for a plan before a multi-file edit. If the plan touches the wrong module, you correct one paragraph instead of reverting six files.
CLAUDE.md is project memory
Keep it short and true. A 400-line style guide gets ignored in the middle. User-level memory is for preferences across repos. Project rules stay in the repo. If the file lies, the agent will follow the lie confidently.
Starter
# CLAUDE.md Short codes are 6 characters, [a-z0-9]. Run tests with: python -m pytest Do not add dependencies. Never commit .env. Prefer a failing test before a fix.
Example
“Use pytest, not unittest” in that file saves the argument on every session, including a review bot in CI.
Instructions you retype every session belong in CLAUDE.md at the repo root. Claude reads it when a session starts.
# CLAUDE.md This repo is a tiny URL shortener: three Python files, no framework. - Short codes are 6 characters, [a-z0-9]. - Run tests with: python -m pytest - Do not add dependencies. - Never commit .env or print secrets. - Prefer a failing test before a fix.
Keep it short and true. A 400-line style guide gets ignored in the middle. A user-level memory is for preferences across repos (“use pytest”). Project rules stay in the repo so the next person, and CI, see the same file.
Slash commands, skills, hooks, subagents
Hooks beat reminders. “Please do not read .env” is a request. A deny rule is a control. Use requests for taste and rules for secrets. MCP servers attach external tools (issues, browsers, internal APIs) without teaching the agent a one-off shell pipeline. A subagent is for a wide search that would flood the main conversation.
Starter
deny = ["git push", "cat .env", "rm -rf"]
allow = ["python -m pytest", "git diff", "git status"]
print("deny", deny)
print("allow", allow)
Example
“Run the tests and summarise failures” becomes a slash command. Blocking `cat .env` becomes a deny rule, not a sentence in the prompt.
| Piece | What it is | Use it for |
|---|---|---|
| Slash command | A saved prompt you invoke with /name | The paragraph you retype: “write a pytest for the function I mention” |
| Skill | A procedure, often a folder with a SKILL.md | A multi-step job that should happen the same way every time, such as “add an API endpoint” |
| Hook | Your script at a fixed point (before a tool, after an edit) | A rule that is code. A prompt can be talked out of a hook. A hook that rejects rm -rf cannot. |
| Subagent | A side task with its own context | A wide search that would flood the main conversation |
| MCP server | External tools over the Model Context Protocol | Issue trackers, browsers, internal APIs |
# A hook idea: block edits outside the repo, and block reading .env # Settings also support allow and deny lists for shell commands. # Deny: git push, curl | sh, cat .env # Allow: python -m pytest, git diff, git status
Practice on a link shortener
A link shortener with one bug (codes shorter than 6) is enough. Ask for the explanation, then a test that fails on "ab", then the fix. Run pytest yourself. Unattended mode comes after the tests exist, not before.
Starter
ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"
def looks_like_code(text: str) -> bool:
return len(text) == 6 and all(ch in ALPHABET for ch in text)
print(looks_like_code("ab")) # False, too short
print(looks_like_code("ab12cd")) # True
Example
The bug is an alias: a 2-character string matching a 6-character code. The test is assert not looks_like_code('ab'). The fix is the length check.
A good teaching repo is three files: create a short code, resolve it, and a bug that only appears sometimes (a collision, an off-by-one, a missing character in the alphabet). You can hold the whole program in your head, so you can tell when the agent is wrong.
# shortener.py (the bug: codes can be shorter than 6, so "ab" aliases "ab12cd")
import secrets
ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"
def create_code(length: int = 6) -> str:
return "".join(secrets.choice(ALPHABET) for _ in range(length))
def looks_like_code(text: str) -> bool:
return all(ch in ALPHABET for ch in text) # forgot: len(text) == 6
A solid session: ask for an explanation, ask for a test that fails on "ab", then ask for the fix, then run pytest yourself. Unattended mode (“fix the bug and stop”) is something you turn on after the tests exist, not before.
Day-to-day uses beyond the tutorial repo
- Onboarding: “map the request path from the HTTP handler to the database”.
- Migrations: “list every caller of
create_codebefore we change its signature”. - Incident: paste a stack trace and ask which file to open first. You still confirm before editing.
Headless mode and review in CI
A review bot should share the repo’s CLAUDE.md. Compare this with an open agent harness: both can plan, edit, spawn subagents, and speak MCP. This one is wired to Claude. An open harness can point at other models. Procedures you write as files travel further than a habit that only lives in one chat.
Starter
job = "Flag missing tests and anything that looks like a secret. Do not rewrite style." print(job)
Example
“Flag a missing test for looks_like_code” is a good CI comment. “Clean up the whole file” is how you get a drive-by rewrite.
The same agent can run without an interactive terminal: a script, or a GitHub Action that comments on a pull request. That reviewer is useful when it has the same CLAUDE.md and a narrow job (“flag missing tests and secrets”). It is noisy when the prompt is “improve this PR”.
Compare this with Deep Agents: both plan, edit files, spawn subagents, and speak MCP. Claude Code is Anthropic’s product around Claude. Deep Agents is the open harness you can point at other models. Skills you write as markdown travel further than a habit that only lives in one chat.
Practice
- Write a 8-line
CLAUDE.mdfor a repo you actually work in. - Add one deny rule you wish a past agent had obeyed.
- Turn “run the tests and summarise failures” into a slash command.
- Fix
looks_like_codeonly after a test fails on a 2-character string.