Covers what Claude Code is, how it works, and how to use it well. From the basics to multi-agent orchestration.
Most developers hear “Claude Code” and picture a smarter Copilot, something that completes code faster, with fewer mistakes. That assumption is wrong, and it matters.
Claude Code is not an autocomplete tool. Autocomplete tools are prediction engines - you type, they predict what comes next, always reacting to what you've already written. Claude Code operates at a different level.
Instead of completing the next line of code, you give it a task, and it figures out what needs to happen to complete that task.
For example, imagine you ask:
Claude Code doesn't start typing immediately in your editor. Instead it:
All of this happens in one go; without you pointing it to each file, without you watching it type line by line.
This is what people mean when they call Claude Code an “agent.” It doesn't complete your sentences. It takes on tasks. The difference is not speed or quality; it's the level at which it operates. Autocomplete works at the line level. Claude Code works at the task level.
The shift from autocomplete to agent requires a different way of working. Most developers who start using Claude Code treat it like a supercharged Copilot and get supercharged-Copilot results. The real value is elsewhere.
Stop giving Claude Code lines to write. Give it goals to reach.
|
Weak prompt |
Strong prompt |
|---|---|
|
"Write a function that checks if a JWT is expired." |
"Add token expiry validation to the auth middleware. Tokens expire after 24 hours. Return a 401 with the message 'Token expired' if invalid." |
|
"Fix this bug." |
"Fix the race condition in UserService.updateProfile; it fails when two requests hit concurrently. Follow the locking pattern in OrderService." |
The strong prompt gives Claude Code a clear goal, the relevant constraints, and the expected behavior. With that, it makes good decisions on its own. Without it, it guesses.
The feedback loop is also longer than autocomplete. You give a task and wait. The output is a complete diff, not a streaming suggestion. That pause is uncomfortable at first. Let it run. Fighting the pause by sending follow-ups early just fragments the task.
Claude doesn't need complete sentences. It needs clear intent. Beyond prompting well yourself, there's a growing ecosystem of open-source tools that reshape how Claude Code behaves by default - trimming verbosity, resisting over-engineering, or hardening its judgment before it writes a line. A few popular tools are:
None of these replace a good prompt, they're defaults that hold even when your prompt isn't perfect. Worth trying one or two if Claude's output is consistently more verbose or more elaborate than the task calls for.
In long sessions, responses start to drift. Claude forgets earlier decisions, suggests things already ruled out, and the quality dips. This is a context window problem. Older parts of the conversation get compressed as it grows.
The fix is counterintuitive: start a new session. Carry forward only what matters, like the current code state, the remaining goal, and the key constraints, and leave the rest behind. Treat each session as a discrete unit of work, not an ongoing conversation. Once the unit is done, or you feel the quality dipping, close it out and start clean rather than pushing through.
Claude Code has no memory between sessions. Every conversation starts completely blank. Without a fix, you'd explain your project from scratch every single time.
Claude Code solves this with two mechanisms: CLAUDE.md for project-level context and auto memory for session learnings.
CLAUDE.md is a special file Claude Code reads at the start of every session. It's a standing brief: a document that tells Claude what it's working on, how the codebase is structured, what conventions to follow, and what to avoid.
A solid CLAUDE.md covers:
How to create it: Either write it manually (best if you know the project well) or run /init to have Claude scan your project and generate a scaffold. The /init output is roughly 30% useful. It identifies the framework and directory structure, but can't know about team conventions, what's in progress, or decisions that live in your head. You fill in the rest.
|
Type |
Path |
Scope |
|---|---|---|
|
Project root |
./CLAUDE.md |
Whole project, committed to repo, shared with team |
|
Inside .claude |
./.claude/CLAUDE.md |
Same scope, cleaner root |
|
Local personal |
./CLAUDE.local.md |
Your tweaks, gitignored, never shared |
|
Global |
~/.claude/CLAUDE.md |
Applies to every project on your machine |
|
Subdirectory |
./some/folder/CLAUDE.md |
Scoped to that part of the codebase |
Beyond CLAUDE.md, Claude Code saves things it learns during sessions to a persistent memory directory at ~/.claude/projects/<project>/memory/. In the next session, those learnings are already there, you don't have to re-explain that your app stores prices in paise, or that UserService is deprecated.
You can also add to memory yourself. Run /memory during a session to view, add, or remove entries. Keep the memory index trimmed, only the first 200 lines load automatically, and a short, accurate memory beats a long, cluttered one.
Everything lives inside .claude/ Claude Code's local configuration directory. It holds CLAUDE.md, skills, custom slash commands, sub-agent definitions, spec documents, and permission settings. At the project level, commit this folder to git. It's team infrastructure, not personal config, the same way you'd commit .github/ or .vscode/.
Here's a trap that catches almost everyone.
You open a session and type: "Build me a user authentication system." Ten minutes later, you have a full implementation - login, registration, password reset, sessions. It's impressive. It runs.
Then you look closer. It used a session library you didn't want. The password rules don't match your security policy. There's no rate limiting on failed attempts. The error messages are generic strings instead of the structured format your frontend expects.
The code works, but it's not the right code. And now you're in a loop of corrections and patches.
This is vibe coding - interacting with Claude in a fast, conversational, exploratory way without planning upfront. The problem is that every decision Claude can't find in your prompt, it makes on its own; silently, invisibly, in ways that only become visible when you look closely at the output.
Spec-Driven Development (SDD) is the opposite approach. Before Claude writes a single line of code, you write a specification document that answers all the questions Claude would otherwise have to guess.
The spec is the single source of truth. Every decision - frameworks, data shapes, error formats, edge cases, acceptance criteria is made by you in writing before development starts.
A good spec covers:
The workflow:
Every phase has a checkpoint. Problems surface early, when they're cheap to fix.
|
Dimension |
Vibe Coding |
Spec-Driven Development |
|---|---|---|
|
Starting point |
A rough idea |
A written specification |
|
Who decides requirements |
Claude infers them |
You define them upfront |
|
Control |
Low - Claude leads |
High - you lead |
|
Speed to first result |
Very fast |
Slower upfront, faster overall |
|
Code quality |
Unpredictable |
Consistent and traceable |
|
Works well for |
Prototypes, side projects |
Production systems, teams |
|
Failure mode |
Code you don't understand |
Over-specified, rigid specs |
|
Debugging approach |
Ask Claude to fix it |
Check against spec for drift |
Neither is always right. For quick experiments, vibe coding is fine. For production systems, teams, or anything that will be maintained, write the spec first.
Where to save specs: Keep them in .claude/specs/ inside your project. They're versioned in git alongside the code, accessible to Claude in future sessions, and readable by new team members.
Even with a spec in hand, Claude can still go in an unexpected direction on complex tasks. Plan Mode is the fix.
Before Claude writes any code, type /plan and Claude will lay out its approach: which files it will touch, what changes it will make, what decisions it's making, and why. You review the plan before anything is written.
If the approach is wrong, you say so now, before Claude builds in the wrong direction, and before you have to read a large diff to figure out what happened. Think of it like reviewing a PR before the code exists rather than after.
What to look for when reviewing a plan:
Plan Mode pairs naturally with SDD: the spec defines what should be built, the plan defines how Claude will build it. Review both before work starts.
Most AI coding tools live in a box. They read your code, generate suggestions, and hand control back to you. The actual execution: running the tests, building the project, calling commands stays on your side.
Claude Code has access to your terminal. It can run commands, read the output, and act on what it sees. All as part of completing a task.
This is the single biggest differentiator from every browser-based AI coding assistant on the market.
Here's the difference this makes for debugging. With a tool that can only read code, you describe an error, it guesses a fix, you run it, it might fail, you relay the error back, and repeat.
Claude Code can run your tests directly. When a test fails, it reads the failure output, understands what went wrong, edits the code, and runs the test again. It keeps doing this until the tests pass without you relaying error messages or manually re-running anything.
The same applies to builds, linters, and type checkers. Give Claude a failing test suite and a goal, and it works through failures methodically.
When Claude edits code, it doesn't rewrite entire files. It reads the relevant sections, makes targeted changes, and leaves everything else untouched. You see the difference. You accept or reject. That's the loop.
For large, complex tasks, Claude breaks the work into steps and shows you progress as it goes. You can follow along, interrupt if something looks wrong, and steer as needed.
Giving an AI terminal access is not a neutral decision. Claude can run commands that delete files, make API calls, push commits, or modify databases. Claude Code has a permission system to keep this safe.
Three levels for any action:
Configured in .claude/settings.json, committed to git, and shared with the team. The defaults are conservative. Loosen them gradually, not all at once.
Claude Code ships with dozens of built-in slash commands, but a small set covers almost everything you'll reach for day to day.
|
Command |
What it does |
|---|---|
|
/init |
Scans your project and generates a CLAUDE.md scaffold |
|
/plan |
Claude lays out its approach before writing any code |
|
/review (or /code-review) |
Claude reviews current changes or a specific file for bugs, security issues, and quality issues |
|
/commit |
Claude writes an intent-focused commit message and commits |
|
/pr |
Claude drafts a pull request: summary, what changed, test plan |
|
/memory |
View, add, or remove entries from Claude's auto memory |
|
/clear |
Resets the conversation to an empty context when Claude starts mixing up earlier files or decisions |
|
/compact |
Compresses earlier conversation history into a summary to free up context space on long sessions |
|
/permissions |
Reviews or edits what Claude is allowed to do without asking |
|
/mcp |
Connects and manages MCP servers for the current session |
|
/model |
Switches the underlying model for the session |
|
/cost |
Shows token usage and cost for the current session |
/commit and /pr are worth calling out specifically. Claude understands what the changes mean, not just what they are. A commit message from Claude explains the intent and what problem the change solves, rather than listing which files were touched.
Out-of-the-box Claude Code is good. Configured Claude Code is a different product.
You can create your own slash commands, stored in .claude/commands/ as Markdown files, committed to your repo, available to the whole team.
A custom command defines exactly what Claude should do when invoked. For example, if your team always builds API endpoints the same way (route file, controller, service, tests, type definitions), you write a /new-endpoint command that scaffolds all of it in one shot. No prompting. No pattern explanation. No variation.
The rule: Every time you write the same long prompt more than twice, that prompt belongs in a custom command.
Skills are a more powerful version of custom commands. Where commands are saved prompts, skills are reusable agent behaviors; multi-step workflows with full access to tools, files, and the terminal.
A code-review skill might read every changed file in the current branch, check them against your team's style guidelines, run linter and tests, and produce a structured review report. A release-notes skill might read the git log since the last tag, group commits by type, and write a formatted changelog.
Use commands for simple, repeatable prompts. Use skills for fully automated workflows.
MCP (Model Context Protocol) is an open protocol that lets Claude connect to external systems – databases, APIs, internal tools, web services - as if they were just another tool available in the session.
Before MCP, everything Claude could interact with was on your machine: files, terminal, git history. With MCP, Claude can reach into your actual systems:
MCP servers can be public (a growing ecosystem exists) or internal - your team builds one that exposes exactly the data Claude needs.
Everything about how Claude Code behaves for your project lives in .claude/settings.json: which commands auto-run, which require approval, which are blocked, what environment variables are available, which MCP servers are connected.
Because this file is committed to git, the entire team shares the same configuration. No "Claude does different things on my machine" problem. When a new developer joins and clones the repo, Claude Code is already configured exactly the way the team decided it should work.
Everything covered so far involves one Claude instance, one session, and one task at a time. Claude Code goes further: you can run multiple Claude agents simultaneously, each working on a different piece of the problem, coordinated by an orchestrating agent.
When Claude Code spawns a sub-agent, it starts a fresh Claude instance with its own context window, its own tools, and a specific task. That instance runs independently. No shared memory with the parent session or other agents. Each sub-agent burns tokens independently.
Sub-agents are the right tool when work can be genuinely split into independent streams. For sequential tasks (where step B depends on step A), sub-agents add cost without adding speed. For parallel work streams, the time savings are real and significant.
The most common multi-agent pattern is the orchestrator pattern: one agent, the orchestrator, breaks a large task into pieces, delegates each piece to a sub-agent, and assembles the results.
For example, take a feature that touches five areas: database migration, API endpoint, service layer, frontend components, and tests. A single-agent approach handles these sequentially. With orchestration, the orchestrator spawns five sub-agents that all run in parallel. What would take two hours sequentially takes fifteen minutes.
The orchestrator also monitors. If a sub-agent gets stuck or produces something that conflicts with another agent's output, the orchestrator intervenes.
Just as you can define custom commands, you can define custom sub-agent types for recurring roles:
Custom sub-agents are defined in .claude/ and committed to the repo. Everyone gets the same specialized agents when they clone the project.
The key to a useful agent is tight scope. "Helps with backend stuff" isn't useful. "Reviews Python code against our style guide, checks for N+1 queries, and verifies error handling follows our conventions" is.
Multiple agents editing files in the same directory would overwrite each other's changes. Claude Code solves this with Git worktrees, isolated copies of your repository, each pointing to a different branch, where one agent can work without touching what any other agent is doing.
When the orchestrator spawns sub-agents for parallel work, each gets its own worktree. Agent-A works on the API changes. Agent-B works on the frontend changes. Neither can interfere with the other. The orchestrator merges results when both finish.
Multi-agent orchestration is powerful and early. The failure modes are real:
The teams that use orchestration successfully have already done the foundational work: good CLAUDE.md files, tight specs, clear custom agent definitions. Orchestration amplifies your foundation. If the foundation is shaky, it amplifies the problems.
The framing of "developer plus AI assistant" is already feeling dated. What's emerging looks more like a developer leading a small team of specialized agents: directing work, reviewing results, making judgment calls, and letting agents handle execution.
This doesn't reduce the developer's role. It raises the bar on it. Judgment, taste, and domain knowledge become more important, not less, because you're now responsible for the output of a system that can produce a lot of code very fast.