How I use Claude Code

I was skeptical for a while. AI coding tools always felt like slightly smarter autocomplete — useful for boilerplate, annoying when they hallucinate an API that doesn't exist. Claude Code is different enough that it took me some time to adjust how I work with it.

It's not a suggestion engine. It reads your files, runs commands, edits code, commits — and it does all of this in a loop until the task is done. Once that clicked, I stopped fighting it and started actually delegating.

Getting started

npm install -g @anthropic-ai/claude-code
claude

That drops you into a session. The other mode I use constantly is -p for one-shots:

claude -p "what does this codebase do"
git diff HEAD~1 | claude -p "write a PR description for this"

-p prints to stdout and exits, which makes it composable with other tools. I use it in small shell scripts more than I expected to.

CLAUDE.md is the most important thing

Every project I work on has a CLAUDE.md at the root. Claude reads it at the start of every session — it's how you give it persistent context without re-explaining things every time.

Mine usually has: what the project is, how to run it, which commands it can run freely, and things I explicitly don't want it to do. That last one matters. "Never touch .env files" and "don't auto-push" have saved me more than once.

Run /init in a new project and Claude will generate a starter one by exploring the repo. It's a decent base to edit from.

There's also ~/.claude/CLAUDE.md for global preferences. I keep things there like which package manager to use, how I want commits worded, and formatting preferences that apply everywhere.

Permissions

By default it asks before doing anything consequential. You can approve per-action or just start a session with --dangerously-skip-permissions to skip all prompts. I do that on fresh branches when I want it to move fast, but never on anything I care about losing.

The permission prompt always shows the exact command it's about to run. I actually read it. Approving blindly is how you end up with dropped tables.

The slash commands I actually use

  • /compact — when the session has been going for a while, this summarizes the history and frees up context. I use it between distinct subtasks.
  • /clear — wipes the conversation but keeps file context. Good for starting a new unrelated task without opening a new terminal.
  • /init — generates a CLAUDE.md for the current project.
  • /commit — lets Claude write the commit message. It usually does a better job than I would since it has the full context of what changed and why.

You can also create custom commands in .claude/commands/ as markdown files. I have one for my code review checklist — just type /review and it runs through everything I'd otherwise forget.

@-referencing files

Prefix any path with @ and the file gets injected directly into your message:

@src/lib/auth.ts why does the token refresh fail silently here?

It'll find files on its own too, but @ is faster when you already know where the relevant code lives.

Context window and long sessions

It fills up. The fix is just /compact before switching to a new task. For very large things — like a full dependency migration — I'll split it across sessions and start the next one with a quick summary of where I left off.

--continue resumes the last session if you closed the terminal. --resume lets you pick from a list if you have multiple going.

Plan mode

Before I let it touch anything major I switch to plan mode — Shift+Tab twice. It describes exactly what it's going to do without doing it. I push back on anything that looks off, then let it run.

Skipping this on a refactor once cost me 20 minutes of undoing changes across files I hadn't mentioned. I use it every time now.

What I actually delegate to it

A few things that work really well in practice:

Whole-file rewrites with a clear goal. "Migrate this Express handler to use the new auth middleware, keep error handling consistent with the rest of the codebase." It reads the surrounding code first, so it doesn't just do a mechanical swap.

Git archaeology. "Which commit broke this and why" — it runs git log, git blame, git show, pieces it together. Faster than doing it yourself.

Writing tests for existing code. Give it a file and tell it which test framework you're using. The tests it writes actually reflect the logic, not just the function signature.

Boilerplate that follows your existing patterns. New routes, new components, new migrations. It reads a few existing examples first and matches the style.

What I don't delegate

Anything with external side effects I haven't explicitly set up for — sending emails, hitting external APIs in production, deploying. I'll let it write the code, but I run it myself.

I also keep it off anything secrets-adjacent. It's in the CLAUDE.md.


It took me a couple of weeks to find a workflow that felt natural. The short version: keep CLAUDE.md updated, use plan mode before anything big, and give it goals instead of steps. The less you micromanage it, the better it works.