Introduction to Claude Code: Agents, Commands, and Skills

Ever wanted to tell an AI "go build this thing" and have it actually do the work instead of just talking about it? Welcome to Claude Code, Anthropic's CLI tool that transforms Claude from a chatbot into an autonomous coding agent.
I know, original. But here's the thing: Claude Code is fundamentally different from just running prompts through the API. It's a framework for orchestrating multi-step engineering tasks, spawning specialized agents, running bash commands, and managing state across long-running sessions. This is where AI stops being a productivity tool and becomes a legitimate teammate.
Let me walk you through what makes it work, how to set it up, and most importantly, how to think about agents, commands, and skills so you don't get lost in the terminology.
Table of Contents
- What Even Is Claude Code?
- Installation and First Run
- Project Structure
- Preferences
- The Agentic Coding Paradigm
- CLAUDE.md: Your Project's Operating System
- Project Structure
- Code Quality Standards
- When Uncertain
- Available Agents
- Slash Commands: Your Interface to Claude
- Skills vs Commands vs Agents: Know the Difference
- Skills: Auto-Invoked Patterns
- Example
- Commands: Explicit Entry Points
- Agents: Autonomous Workers
- Decision Framework
- Built-In Tools: What Claude Can Actually Do
- Read Tool
- Write Tool
- Edit Tool
- Bash Tool
- Glob Tool
- Grep Tool
- A Typical Workflow: Building Something Real
- Practical Example: Creating Your First Skill
- Implementation
- Understanding Context Windows and Efficiency
- Hooks: The Hidden Automation Layer
- Troubleshooting: Common Gotchas
- Setting Up a Real Project
- Structure
- Standards
- Advanced Patterns: Where Power Users Go
- Cost Management: Picking the Right Model
- What You've Actually Learned
What Even Is Claude Code?
Claude Code is a command-line interface that lets you invoke Claude with filesystem access, bash execution, git integration, and persistent state management. It's not a GUI. It's not a web app. It's a CLI that gives Claude the tools to actually engineer things.
When you install Claude Code, you're basically saying: "Claude, here's a project. Read it. Understand it. Run commands. Make changes. Think about what you're doing and tell me why." It's the difference between asking a question and deputizing someone to actually solve a problem.
The core idea: you give Claude a project with a .claude/ directory that contains configuration, agents, and reusable skills. Claude reads that configuration and adapts its behavior to match your workflow. It's not writing code for its own entertainment. It's following your architectural preferences, respecting your project structure, and building things the way you want them built.
Installation and First Run
Getting started is straightforward. You'll need Node.js installed (version 16+), then:
npm install -g @anthropic-ai/claude-codeAfter installation, initialize Claude Code in your project:
cd your-project
claude-code initThis creates the .claude/ directory structure with templates for agents, commands, and skills. The initial setup is minimal, just enough to get you started.
Next, you'll authenticate:
claude-code authThis opens your browser, authenticates through your Anthropic account, and stores your credentials securely. You can verify it worked by running:
claude-code --versionNow here's the critical part: create or edit the CLAUDE.md file in your project root. This is the personality file. It tells Claude how your project is organized, what it should care about, and how to behave. Think of it as your project's constitution.
# CLAUDE.md - My Project Configuration
You are working on a React/TypeScript application.
## Project Structure
```
/
├── src/ # Source code
│ ├── components/ # React components
│ ├── hooks/ # Custom hooks
│ ├── utils/ # Utilities
│ └── types/ # TypeScript types
├── tests/ # Test files
├── docs/ # Documentation
└── package.json # Dependencies
```
## Preferences
- Use TypeScript strict mode
- Follow functional component patterns
- Write tests for all utilities
- Prefer composition over inheritanceThat's it. Claude now understands your structure and your preferences. You've set the stage.
The Agentic Coding Paradigm
Here's where Claude Code gets interesting. Traditional AI tools work synchronously: you ask, it answers, you ask again. Claude Code works agentic: you describe a goal, it breaks it down into tasks, spawns agents to solve pieces in parallel, combines results, and verifies the output.
Think about building a feature. The old way: you'd write the spec, paste it into Claude, get code back, test it, ask for fixes, repeat. Inefficient.
The new way: Claude reads your project structure, understands your architecture from CLAUDE.md, spawns a frontend agent to build the UI, a backend agent to build the API, a test agent to write tests, and a documentation agent to write docs. They run in parallel with shared context. Then Claude validates everything works together.
That's the agentic paradigm. Multiple specialized workers, coordinated execution, shared state.
The key insight: agents in Claude Code are workers with isolated context and assigned tasks. Commands are entry points you trigger. Skills are reusable patterns. Understanding the distinction between these three changes how you structure everything.
CLAUDE.md: Your Project's Operating System
CLAUDE.md is where you configure Claude's behavior for your project. It's not optional. It's foundational. This file tells Claude:
- How your project is organized
- What architectural patterns you follow
- What you care about (performance, accessibility, testing)
- How to handle conflicts (your preferences override defaults)
- What agents and commands are available
Here's a realistic example:
# CLAUDE.md - Engineering System
You are an AI engineer working on a SaaS platform.
## Project Structure
The application follows a standard full-stack architecture:
```
/
├── .claude/ # Claude Code configuration
│ ├── agents/ # Specialized workers
│ ├── commands/ # Entry point slash commands
│ ├── skills/ # Reusable patterns
│ └── hooks/ # Lifecycle hooks
├── frontend/ # React + TypeScript
│ ├── components/
│ ├── hooks/
│ ├── pages/
│ └── __tests__/
├── backend/ # Node.js + Express
│ ├── routes/
│ ├── controllers/
│ ├── models/
│ ├── middleware/
│ └── __tests__/
├── database/ # Database migrations
├── docs/ # Documentation
└── package.json
```
## Code Quality Standards
- TypeScript: strict mode always
- Testing: 80%+ coverage minimum
- Linting: ESLint + Prettier (no deviations)
- Commits: Conventional commits format
- Reviews: No direct pushes to main
## When Uncertain
1. Ask the user for clarification
2. Propose multiple approaches
3. Document assumptions
4. Verify before committing
## Available Agents
Use `/dispatch [agent] [task]` to invoke:
- `frontend-builder`: React component development
- `api-developer`: Backend API endpoints
- `test-engineer`: Test suite creation
- `docs-writer`: Documentation generationNotice this isn't a specification. It's guidance. Claude uses it to make decisions about how to solve problems. When Claude encounters a directory, it checks CLAUDE.md to understand what that directory is for. When it needs to choose between two approaches, it refers to your standards.
This is how you make Claude follow your conventions without micromanaging every decision.
Slash Commands: Your Interface to Claude
Slash commands are how you interact with Claude Code. They're triggered with / and invoke custom logic defined in the .claude/commands/ directory.
Some built-in commands are always available:
| Command | Purpose |
|---|---|
/help | Show available commands |
/model | Switch between Opus, Sonnet, Haiku |
/compact | Reduce context size (for long sessions) |
/clear | Clear conversation history |
Custom commands live in .claude/commands/ as markdown files. Here's the anatomy:
# my-command
Description of what this command does.
$ARGUMENTS:
- arg1: Description of first argument
- arg2: Description of second argument (optional)
---
When invoked with `/my-command foo bar`:
1. Parse the arguments
2. Understand the context
3. Accomplish the goal
4. Report resultsWhen you run /my-command foo bar, Claude reads this file, understands the goal, and executes the task. It's declarative: you describe what should happen, Claude figures out the implementation.
Real example:
# build-feature
Build a complete feature from specification.
$ARGUMENTS:
- feature_name: Name of the feature (e.g., "user-authentication")
- description: What this feature does
---
When invoked with `/build-feature user-auth "Handle login/logout"`:
1. Create feature branch
2. Create directory structure under src/features/user-auth
3. Generate component skeleton
4. Generate tests
5. Add to feature exports
6. Commit with message "feat: Add user-auth feature"This is powerful. You're not writing imperative code; you're declaring intent. Claude handles the implementation details.
Skills vs Commands vs Agents: Know the Difference
Here's where people get confused. All three are in .claude/ but they work differently. Let me break it down with a decision framework.
Skills: Auto-Invoked Patterns
Skills are reusable solutions to common problems. They're markdown files in .claude/skills/ that describe how to handle a specific type of task.
When to use: When you want Claude to automatically apply a pattern without explicit invocation.
Example skill file (.claude/skills/typescript-validation.md):
# TypeScript Validation
When validating form inputs or API parameters:
1. Define a Zod schema for the structure
2. Create a validation function using `z.parse()`
3. Wrap form submissions with error handling
4. Return validation errors to the user
## Example
```typescript
import { z } from 'zod';
const userSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export const validateUser = (data: unknown) => {
try {
return userSchema.parse(data);
} catch (error) {
return null;
}
};
```
When Claude encounters a validation problem, it automatically considers this skill. You've codified your approach so it's consistent everywhere.Commands: Explicit Entry Points
Commands are user-triggered workflows. When you type /something, you're invoking a command. They live in .claude/commands/ and define a complete task.
When to use: When you need to trigger a multi-step workflow explicitly.
Commands are synchronous from your perspective (you type, Claude executes, you get results) but internally they can spawn agents and orchestrate complex work.
Agents: Autonomous Workers
Agents are autonomous workers with isolated context, assigned a specific task, and spawned by commands or other agents. They appear in .claude/agents/ as markdown files describing their role and capabilities.
When to use: When you need parallel execution, specialization, or breaking work into independent tasks.
Example agent (.claude/agents/test-engineer.md):
# test-engineer
Role: Write comprehensive tests for new features.
When spawned with task "test the login feature":
1. Read the login component code
2. Identify all code paths and edge cases
3. Write unit tests for each path
4. Write integration tests for the full flow
5. Verify coverage is >80%
6. Report test results
Tools available:
- Read files
- Run test runner (npm test)
- Verify assertions passWhen you invoke a command that needs tests, the command can spawn the test-engineer agent. That agent works independently, in parallel with other agents, and reports results back.
Decision Framework
flowchart TD
Q1{"Handle this problem<br/>automatically?"}
Q2{"Trigger a workflow<br/>explicitly?"}
Q3{"Parallel execution of<br/>specialized tasks?"}
Q4{"Orchestrate commands<br/>& agents together?"}
A1["Create a SKILL"]
A2["Create a COMMAND"]
A3["Create an AGENT"]
A4["Create a COMMAND<br/>that spawns AGENTS"]
Q1 -->|YES| A1
Q1 -->|NO| Q2
Q2 -->|YES| A2
Q2 -->|NO| Q3
Q3 -->|YES| A3
Q3 -->|NO| Q4
Q4 -->|YES| A4
style Q1 fill:#3b82f6,stroke:#0f172a,stroke-width:2px,color:#0f172a
style Q2 fill:#ec4899,stroke:#0f172a,stroke-width:2px,color:#0f172a
style Q3 fill:#f59e0b,stroke:#0f172a,stroke-width:2px,color:#0f172a
style Q4 fill:#8b5cf6,stroke:#0f172a,stroke-width:2px,color:#0f172a
style A1 fill:#22c55e,stroke:#0f172a,stroke-width:2px,color:#0f172a
style A2 fill:#22c55e,stroke:#0f172a,stroke-width:2px,color:#0f172a
style A3 fill:#22c55e,stroke:#0f172a,stroke-width:2px,color:#0f172a
style A4 fill:#22c55e,stroke:#0f172a,stroke-width:2px,color:#0f172aBuilt-In Tools: What Claude Can Actually Do
Inside Claude Code, you have access to tools that let you interact with the filesystem, run commands, and gather information. These are the building blocks.
Read Tool
Read files from the filesystem:
Read /path/to/file.tsClaude can read entire files or specific line ranges, and it understands different file types (code, markdown, JSON, YAML, etc.). It's how Claude gets context about your project.
Write Tool
Create or overwrite files:
Write /path/to/file.tsYou pass the file path and content. Claude creates the file or replaces it entirely. Use Edit for modifications.
Edit Tool
Make targeted changes to existing files:
Edit /path/to/file.tsYou specify the old text and new text. Claude finds the exact location and makes the change. Much safer than rewriting entire files.
Bash Tool
Run arbitrary bash commands:
Bash: npm testThis executes the command and captures output. Claude can run tests, build projects, start services, or any shell script.
Glob Tool
Find files matching patterns:
Glob: src/**/*.test.tsReturns all TypeScript test files under src. Useful for understanding project structure.
Grep Tool
Search file contents:
Grep: "export function" --type tsSearches for patterns across files. Claude uses this to understand existing code before making changes.
A Typical Workflow: Building Something Real
Let's walk through a realistic example. You want Claude to add authentication to your app. Here's how it plays out:
Step 1: Set the stage
You type:
/build-feature user-auth "Implement JWT-based authentication"Claude reads this command from .claude/commands/build-feature.md. It understands the goal.
Step 2: Understand the project
Claude reads CLAUDE.md, understands your architecture. It globs the project to see what already exists. It reads relevant files to understand your patterns.
Step 3: Decompose the work
Claude realizes this needs multiple specialized agents:
- Backend API agent: Create auth endpoints
- Frontend agent: Create login/logout UI
- Test agent: Write auth tests
- Docs agent: Document the flow
It spawns all four in parallel.
Step 4: Execution
Each agent works independently:
- Backend agent reads your express setup, creates
/api/auth/loginand/api/auth/logoutendpoints - Frontend agent creates a LoginForm component and adds routing
- Test agent writes integration tests
- Docs agent updates your README
Step 5: Validation
Claude combines results, runs tests, verifies everything compiles. If tests fail, it fixes them.
Step 6: Commit
Claude creates a commit with the changes:
git add .
git commit -m "feat: Add JWT authentication"Step 7: Report back
You get a summary: "I've added authentication with 145 lines of backend code, 89 lines of frontend code, and 52 lines of tests. All tests pass. Ready to review."
That's it. You've gone from idea to complete, tested feature in one interaction. That's the power of agentic coding.
Practical Example: Creating Your First Skill
Let me show you how to create an actual skill. Say your team always creates API endpoints with error handling, logging, and validation. Instead of having Claude reinvent this every time, you encode it as a skill.
Create .claude/skills/api-endpoint-pattern.md:
# API Endpoint Pattern
When creating a new REST API endpoint:
1. Create a route handler function with proper typing
2. Include input validation using Zod or similar
3. Wrap the handler in error middleware
4. Add request/response logging
5. Include JSDoc comments explaining parameters and return type
6. Write unit tests covering happy path and error cases
## Implementation
```typescript
import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
const router = Router();
// Schema
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1),
});
type CreateUserRequest = z.infer<typeof createUserSchema>;
/**
* POST /users - Create a new user
* @param email - User email address
* @param name - User full name
*/
router.post('/users', async (req: Request, res: Response, next: NextFunction) => {
try {
const data = createUserSchema.parse(req.body);
// Implementation here
res.status(201).json({ id: 1, ...data });
} catch (error) {
next(error);
}
});
export default router;
```
When Claude encounters "create an endpoint for X", it automatically applies this pattern. Consistency without micromanagement.Now whenever you ask Claude to build an API endpoint, it knows your standard approach. It's like giving Claude your style guide, but executable.
Understanding Context Windows and Efficiency
Here's a hidden layer that matters: Claude Code manages context very carefully. Each session has a context window, the amount of text Claude can hold in memory at once. Going over the limit means Claude forgets earlier parts of the conversation.
Smart projects structure their .claude/ files to be lean. Don't write a 10,000 word CLAUDE.md file. Write a concise 2,000 word file that points to other documentation. Break large projects into smaller contexts.
You can check your context usage:
/compact # Compress conversation history
/clear # Clear old messages to free up spacePro move: Use /compact after major milestones. Claude summarizes everything that's happened, stores it, and clears the verbose history. You maintain context continuity without losing track.
Hooks: The Hidden Automation Layer
There's one more piece: hooks. These are automation scripts that trigger at key moments in Claude Code's workflow. They're stored in .claude/hooks/ and let you automate routine tasks.
Example: automatically run tests whenever Claude makes changes:
# hooks/post-write.sh
#!/bin/bash
# Runs after Claude writes files
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Claude should fix this."
exit 1
fiHooks enforce standards without requiring Claude to explicitly remember. Your project stays healthy automatically.
Troubleshooting: Common Gotchas
Gotcha 1: Vague CLAUDE.md
If your configuration is generic, Claude will be generic. "Use best practices" isn't actionable. "Use functional React components with TypeScript, prefer custom hooks over render props, test all utils" is actionable. Be specific.
Gotcha 2: Forgetting to Commit
Claude doesn't automatically commit changes. You need to explicitly ask for commits in your commands:
# my-command
When done, commit all changes with appropriate commit message.Without this, changes stay uncommitted and you can lose work between sessions.
Gotcha 3: Context Overflow
Long-running sessions accumulate context. After about 50 interactions, consider using /compact to clean up. Claude will summarize and continue, but you'll start fresh with a leaner history.
Gotcha 4: Model Switching Costs
Switching from Sonnet to Opus mid-stream costs more. Plan model selection upfront in your .claude/config.yaml and stick with it unless you have a specific reason to switch.
Gotcha 5: Assuming Claude Remembers Everything
Claude doesn't have memory between separate invocations of Claude Code. If you close Claude and reopen it tomorrow, Claude starts fresh (though it can read all the files you wrote). Always document important decisions in markdown files, not just in conversation history.
Setting Up a Real Project
Walk through a realistic setup for a Node.js project:
Step 1: Initialize
cd my-project
claude-code initStep 2: Create CLAUDE.md
# my-project Configuration
You are building a REST API with Node.js, Express, and TypeScript.
## Structure
- src/ - Source code
- tests/ - Test files
- dist/ - Compiled output
## Standards
- TypeScript strict mode
- ESLint enforces style
- 80%+ test coverage required
- Conventional commitsStep 3: Create agents in .claude/agents/
# api-developer
Role: Build REST API endpoints
When asked to create an endpoint:
1. Create route file in src/routes/
2. Add schema validation
3. Create corresponding test file
4. Verify tests pass
5. Report what was createdStep 4: Create commands in .claude/commands/
# api-endpoint
Create a complete REST endpoint.
$ARGUMENTS:
- method: HTTP method (GET, POST, etc.)
- path: URL path (e.g., /users)
- description: What this endpoint does
When invoked, spawn the api-developer agent with this task.Step 5: Start using it
/api-endpoint POST /users "Create a new user"That's a complete project setup. Claude now has context, agents, commands, and patterns. You can start asking it to build features.
Advanced Patterns: Where Power Users Go
Once you understand the basics, there are advanced patterns that unlock real power.
Pattern 1: Skill Composition
Create skills that build on other skills. If you have a validation skill and an error-handling skill, create a validation-with-errors skill that combines both.
Pattern 2: Multi-Agent Orchestration
Create commands that spawn 3-5 agents in parallel, each working on a piece of the puzzle, then merge results. This is where you get exponential speedup.
Pattern 3: Conditional Agents
Use the decision framework from earlier. Create an agent that reads the codebase, decides what needs to be done, and spawns other agents based on findings. Meta-automation.
Pattern 4: Context Inheritance
Agents spawned from a command inherit context from the parent. Use this to pass project state, configuration, or decisions down to child agents without repeating information.
Pattern 5: Failure Recovery
Structure your commands to catch failures and retry with a different approach. If the first method fails, try an alternative. This resilience matters for long-running tasks.
Cost Management: Picking the Right Model
Claude Code supports three models, and choosing right matters for your wallet:
| Model | Speed | Quality | Cost | Use Case |
|---|---|---|---|---|
| Opus | Slowest | Highest | $$$ | Complex reasoning, architecture decisions |
| Sonnet | Medium | Good | $$ | Most coding tasks, default choice |
| Haiku | Fastest | Lower | $ | Simple tasks, parsing, batch operations |
You can switch models mid-session:
/model sonnet # Use Claude Sonnet 4 (default)
/model opus # Use Claude Opus for complex work
/model haiku # Use Haiku for quick tasksPro tip: Use Haiku for spawned agents doing straightforward work (read files, run tests, apply formatting). Use Opus for the main agent orchestrating the overall task. Use Sonnet for everything else. You'll save money and get faster results.
You can also set a default in your .claude/config.yaml:
default_model: sonnet
model_selection:
architecture_decisions: opus
test_generation: haiku
documentation: haiku
feature_building: sonnetClaude respects these preferences. More control, consistent costs.
What You've Actually Learned
Claude Code is not magic. It's structured automation built on a few core pieces:
- Configuration (
CLAUDE.md): How to tell Claude about your project - Agents: Specialized workers that solve pieces of problems
- Commands: User-triggered workflows that orchestrate agents
- Skills: Reusable patterns that guide implementation
- Tools: Filesystem and bash access so Claude can actually do work
You combine these pieces to build a system where Claude isn't just answering questions. It's building features, running tests, writing docs, and managing your project.
The gotcha that experienced users know: Claude Code is only as good as your configuration. If your CLAUDE.md is vague, Claude will be vague. If your agent descriptions are clear and specific, Claude will execute with precision. Invest in your configuration. That investment is where the real leverage lies.
Think of it this way: setting up Claude Code well is like building a framework or library for your project. Initial investment of time and thought, but then everything built on top of it becomes faster, more consistent, and more maintainable.
The engineers who figure this out early will ship features faster than those still pasting specs into ChatGPT. That's the competitive advantage Claude Code offers.