Mastering Claude Code CLI: The Complete Guide for DevOps Engineers
If you have been using Claude in a browser tab to help with code, you are leaving most of its capability on the table. Claude Code CLI brings the full power of Claude directly into your terminal — it reads your actual codebase, runs real commands, edits files, commits code, and integrates with every tool in your DevOps stack. This guide covers everything from installation to advanced patterns that most engineers never discover.
What Is Claude Code?
Claude Code is an agentic coding assistant that lives in your terminal. Unlike a chat interface where you paste code snippets, Claude Code:
- Reads your entire codebase — it understands the real structure of your project
- Runs actual commands —
git,docker,kubectl,terraform,npm, whatever you need - Edits files directly — makes changes across multiple files in a single operation
- Integrates with your IDE — VS Code and JetBrains show diffs in their native viewers
- Connects to external tools — databases, GitHub, AWS, Slack, and more via MCP
For DevOps engineers specifically, this means you can say “review our Terraform configs for security issues, fix what you find, and open a PR” — and it will actually do it.
Installation
macOS / Linux:
curl -fsSL https://claude.ai/install.sh | bash
Homebrew:
brew install --cask claude-code
Windows (PowerShell):
irm https://claude.ai/install.ps1 | iex
After installing, run claude in any project directory to start a session. Run claude --help to see all options.
Quick start:
cd my-project
claude # interactive session
claude -p "explain this project structure" # one-off query
claude --continue # resume last session
CLAUDE.md — Your Project’s Permanent Memory
Every time you start a Claude Code session, it reads CLAUDE.md files automatically. Think of it as a briefing document — you write it once and never have to re-explain your project setup.
Where to put them
| File | Scope | Shared via Git? |
|---|---|---|
~/.claude/CLAUDE.md | All your projects | No — personal preferences |
./CLAUDE.md | This project | Yes — team-wide conventions |
./.claude/CLAUDE.md | This project (alt) | Yes |
./CLAUDE.local.md | This project | No — gitignored overrides |
What to put in a project CLAUDE.md
The golden rule: include what Claude cannot infer from reading the code. Commands, gotchas, team conventions, and architecture decisions that are not obvious from the files.
# My Infrastructure Platform
## Build and Test
- Build: `npm run build`
- Tests: `npm test` — run single tests with `npm test -- --grep "auth"`
- Lint: `npm run lint`
- Type check: `npm run typecheck`
## Architecture
- API handlers in `src/api/handlers/`
- Terraform configs in `infra/`
- Each service has its own `Dockerfile.prod`
## Code Style
- ES modules only (import/export) — no CommonJS
- 2-space indentation
- camelCase for variables, PascalCase for types
## Git Workflow
- Feature branches: `feature/description`
- Always create a PR — never push directly to main
## Common Commands
- Deploy staging: `npm run deploy:staging`
- Deploy prod: `npm run deploy:prod`
- View production logs: `npm run logs:prod`
- Run migrations: `npm run db:migrate`
## Secrets
- Never hardcode credentials — all secrets in AWS Secrets Manager
- Use `.env.example` for documentation, never `.env` itself
## Known Gotchas
- The auth service requires `NODE_ENV=production` to initialise properly
- Database migrations run automatically on deploy — no manual step needed
- Some integration tests require a local Redis instance on port 6379
Path-scoped rules
For large projects, create .claude/rules/ with topic-specific files that only load when Claude is working in the relevant area:
.claude/
├── CLAUDE.md ← always loaded
└── rules/
├── api.md ← loads when editing src/api/**
├── security.md ← loads when editing any auth-related file
└── infra.md ← loads when editing infra/**
Example .claude/rules/security.md:
---
paths:
- "src/api/**/*.ts"
- "infra/**/*.tf"
---
# Security Rules
- Always validate and sanitise user input at API boundaries
- Use parameterised queries — never string interpolation in SQL
- Never log secrets, tokens, or PII — scrub before logging
- Return generic error messages externally — no stack traces
- Require authentication on all non-public endpoints
Keep CLAUDE.md under 200 lines. Longer files reduce adherence — Claude loses track of rules buried at line 350.
Saving Tokens — How to Keep Costs Low
Context is the most important resource to manage. Every message you send includes your entire conversation history, all the files Claude has read, and every command output. It adds up fast.
Check your usage
/cost # estimated session cost
/usage # detailed token breakdown
/context # see what is consuming context space
Clear between tasks
The single most effective thing you can do:
/clear
When you finish a task and start something unrelated, clear the context. Stale conversation history about your auth bug wastes tokens on every message when you switch to asking about your CI pipeline.
Compact your context
/compact focus on infrastructure changes
/compact summarises the conversation history but lets you tell it what to preserve. Use it when a session gets long but you are not ready to clear completely.
Add a compact instruction to your CLAUDE.md:
## Compact instructions
When compacting, always preserve:
- Code changes made so far
- Test results and error messages
- Architecture decisions reached
Choose the right model for the task
/model claude-sonnet-4-6 # default — best balance of cost and capability
/model claude-opus-4-6 # for complex architectural decisions
/model claude-haiku-4-5 # for simple repetitive tasks
Sonnet handles 95% of DevOps tasks well. Save Opus for genuinely complex problems.
Control extended thinking
Extended thinking is powerful but expensive. Turn it down for simple tasks:
/effort low # disable extended thinking
/effort high # enable for complex problems
/effort xhigh # max thinking tokens
Use subagents for investigation
When you need Claude to explore a large codebase to answer a question, spawn a subagent instead of doing it in your main session:
Use a subagent to investigate why our authentication service is slow
Subagents run in their own context and report back a summary — keeping your main conversation clean.
MCP — Connecting Claude to Everything
MCP (Model Context Protocol) is what lets Claude Code talk to external systems — databases, GitHub, AWS, Slack, your custom APIs. Once configured, Claude can query them directly without you having to copy-paste data.
Adding MCP servers
# Add a GitHub MCP server
claude mcp add --transport http github https://api.github.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
# Add a local Postgres server
claude mcp add --transport stdio postgres \
"mcp-postgres --connection-string postgresql://user:pass@localhost/db"
Or configure directly in .claude/settings.json:
{
"mcp": {
"servers": {
"github": {
"transport": "http",
"url": "https://api.github.com/mcp/",
"headers": {
"Authorization": "Bearer YOUR_GITHUB_PAT"
}
},
"postgres": {
"transport": "stdio",
"command": "mcp-postgres",
"args": ["--connection-string", "postgresql://user:pass@localhost/db"]
}
}
}
}
Useful MCP servers for DevOps
| Server | What it enables |
|---|---|
| GitHub | Search PRs, read comments, create issues, review code diffs |
| Postgres / MySQL | Query databases directly, analyse schemas, debug data issues |
| AWS | List resources, check CloudWatch logs, manage S3 |
| Web Fetch | Pull in documentation, error pages, API references |
| Filesystem | Read files outside your project root |
| Slack | Post notifications, read channel history |
| Memory | Persist information across sessions |
| Docker | Inspect containers, images, network config |
Check what is loaded
/mcp # list configured servers and their context cost
Disable servers you are not using — each one adds to your context overhead.
Hooks — Automating the Boring Parts
Hooks are shell commands that run automatically at specific points in Claude’s lifecycle. Unlike CLAUDE.md instructions (which are advisory), hooks are deterministic — they always run.
Hook events
| Event | When it fires |
|---|---|
SessionStart | At the beginning of every session |
PreToolUse | Before Claude runs any tool |
PostToolUse | After a tool succeeds |
PermissionRequest | When Claude needs your approval |
SessionEnd | When the session closes |
Configuration
Hooks go in .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/format-on-save.sh"
}
]
}
]
}
}
Practical hook examples
Auto-format files after Claude edits them:
#!/bin/bash
# ~/.claude/hooks/format-on-save.sh
input=$(cat)
files=$(echo "$input" | jq -r '.tool_output.files_edited[]' 2>/dev/null)
for file in $files; do
case "$file" in
*.ts|*.js) npx prettier --write "$file" 2>/dev/null ;;
*.py) black "$file" 2>/dev/null ;;
*.go) gofmt -w "$file" 2>/dev/null ;;
*.tf) terraform fmt "$file" 2>/dev/null ;;
esac
done
exit 0
Block destructive commands:
#!/bin/bash
# ~/.claude/hooks/block-destructive.sh
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
BLOCKED="rm -rf|kubectl delete|terraform destroy|DROP TABLE|truncate"
if echo "$cmd" | grep -qE "$BLOCKED"; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook. Review and run manually."
}
}'
else
exit 0
fi
Load environment variables at session start:
{
"env": {
"NODE_ENV": "development",
"DEBUG": "app:*",
"POSTGRES_HOST": "localhost",
"AWS_REGION": "us-east-1"
}
}
Or use a SessionStart hook to load from a .envrc:
#!/bin/bash
# ~/.claude/hooks/load-env.sh
[ -f .envrc ] && source .envrc
exit 0
Permissions — Fewer Prompts, More Flow
By default, Claude asks for permission before running commands or editing files. Here is how to reduce that friction without giving up safety.
Permission modes
Press Shift+Tab to cycle through modes:
| Mode | Behaviour |
|---|---|
| Default | Ask before every tool use |
| Accept Edits | Auto-approve file edits, ask for shell commands |
| Plan | Show plan first, then ask before executing |
| Auto | Smart classifier — only asks for genuinely risky commands |
Or set a default in .claude/settings.json:
{
"permissions": {
"defaultMode": "acceptEdits"
}
}
Allowlist common operations
Stop being asked about things you always approve:
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(docker build *)",
"Bash(docker ps)",
"Bash(kubectl get *)",
"Bash(terraform plan *)",
"Bash(terraform init)",
"Bash(terraform fmt *)",
"Edit",
"WebFetch(domain:github.com)",
"WebFetch(domain:docs.aws.amazon.com)"
],
"deny": [
"Bash(terraform apply)",
"Bash(terraform destroy *)",
"Bash(kubectl delete *)",
"Bash(rm -rf *)",
"Read(.env)"
]
}
}
Separate team and personal settings
Put shared permissions in .claude/settings.json (committed to git) and personal overrides in .claude/settings.local.json (gitignored):
// .claude/settings.local.json (your personal overrides)
{
"permissions": {
"allow": [
"Bash(brew *)",
"Bash(nvim *)"
]
}
}
Essential Slash Commands
| Command | What it does |
|---|---|
/clear | Reset conversation history — do this between tasks |
/compact [focus] | Summarise history, optionally preserving specific areas |
/cost | Show estimated session cost |
/usage | Detailed token usage breakdown |
/context | Show what is taking up context space |
/model [name] | Switch Claude model mid-session |
/effort [low|high|xhigh] | Control extended thinking |
/init | Generate a starter CLAUDE.md for the current project |
/mcp | Manage and check MCP servers |
/memory | View and edit CLAUDE.md and auto memory |
/hooks | View configured hooks |
/rename [name] | Name the current session for easy resumption |
/resume [name] | Resume a named session |
/rewind | Restore to a previous message (double-tap Esc also works) |
/btw [question] | Ask a quick side question that never enters history |
/review | Run a code review subagent |
/doctor | Diagnose installation issues |
IDE Integration
VS Code
Install the Claude Code extension from the marketplace, or:
code --install-extension anthropic.claude-code
Useful keyboard shortcuts:
| Action | Shortcut |
|---|---|
| Focus Claude input | Cmd+Esc |
| Insert file reference | Option+K |
| New conversation | Cmd+N |
| Open in new tab | Cmd+Shift+Esc |
When Claude proposes file changes, VS Code shows them in its native diff viewer — you can approve, reject, or edit each change individually before accepting.
JetBrains (IntelliJ, PyCharm, GoLand, WebStorm)
Install Claude Code from Settings → Plugins → Marketplace.
Connect your terminal session to the IDE:
claude
/ide
This links the terminal session to your open IDE so diffs appear there instead of in the terminal.
DevOps-Specific Workflows
Terraform
# Review configs for issues
claude "review infra/main.tf for security issues and best practices"
# Plan changes safely
claude "run terraform plan and explain what would change"
# Generate module documentation
claude "generate README documentation for our terraform modules"
Restrict permissions so Claude can plan but never apply:
{
"permissions": {
"allow": ["Bash(terraform plan *)", "Bash(terraform init)", "Bash(terraform fmt *)"],
"deny": ["Bash(terraform apply)", "Bash(terraform destroy *)"]
}
}
Kubernetes
# Review manifests
claude "review all manifests in k8s/ for security and best practices"
# Generate a Helm chart
claude "create a Helm chart for our Node.js API service"
# Debug a failing deployment
cat deployment-error.log | claude -p "what is causing this failure and how do I fix it?"
CI/CD with GitHub Actions
name: Claude Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: AI Code Review
run: |
claude -p "Review the changes in this PR for bugs, security issues, and best practices. Be specific." \
--output-format json > review.json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
Pipe data directly
# Debug log output
cat app.log | claude -p "what errors are here and what is causing them?"
# Review recent git history
git log -20 --oneline | claude -p "summarise what changed recently"
# Analyse docker logs
docker logs myapp --tail 100 | claude -p "what is wrong with this service?"
Tips Most Engineers Miss
1. Ask side questions without polluting context:
/btw what Node version does this project need?
The answer appears in an overlay and is never saved to history.
2. Pipe directly from the shell:
cat errors.log | claude -p "what is causing this?"
3. Use ! for quick shell commands inside a session:
> ! git log --oneline -5
> ! docker ps
4. Name your sessions:
claude -n "oauth-implementation"
# Later
claude --resume oauth-implementation
5. Use worktrees for parallel work:
# Two independent sessions, two branches
claude -w feature-auth # terminal 1
claude -w bugfix-api # terminal 2
6. Set a cost limit:
claude -p "audit entire infrastructure" --max-budget-usd 2.00
7. Use --add-dir in monorepos:
claude --add-dir ../shared-lib ../api-service -p "refactor the shared auth code"
8. Double-tap Escape to rewind without typing /rewind.
9. Generate your CLAUDE.md automatically:
/init
Claude reads your project and generates a starter CLAUDE.md. Edit it from there.
10. Check what the auto-memory system saved:
/memory
Claude saves learnings across sessions automatically. This shows what it remembers about you and your project.
Putting It All Together: A Recommended Setup
Here is a practical starting point for a DevOps project:
.claude/settings.json (commit to git):
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(npm run *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(terraform plan *)",
"Bash(terraform init)",
"Bash(terraform fmt *)",
"Bash(docker build *)",
"Bash(docker ps)",
"Bash(kubectl get *)"
],
"deny": [
"Bash(terraform destroy *)",
"Bash(terraform apply)",
"Bash(kubectl delete *)",
"Bash(rm -rf *)",
"Read(.env)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [{ "type": "command", "command": ".claude/hooks/format.sh" }]
}
]
}
}
CLAUDE.md (commit to git):
# Project Name
## Build and Test
- Build: `npm run build`
- Test: `npm test`
- Lint: `npm run lint`
## Deployment
- Staging: `npm run deploy:staging`
- Production requires manual approval — create a PR
## Architecture
- API: `src/api/` — Express + TypeScript
- Infra: `infra/` — Terraform on AWS
- K8s manifests: `k8s/`
## Rules
- No secrets in code — use AWS Secrets Manager
- All infra changes via Terraform — no manual console changes
- Every feature needs a PR and passing tests
Run /init to let Claude generate a starter version based on your actual project, then edit it.
Claude Code is at its best when it has context about your project, constraints on what it can touch, and clear instructions about your conventions. Invest 30 minutes in your CLAUDE.md and settings once, and every session after that starts with a Claude that already understands your project.
The full documentation is at docs.anthropic.com/claude-code.
