A Beginner’s Guide to Setting Up Claude Code for High Performance Agentic Programming
This article walks through the actual configuration, permissions, hooks, and command habits that separate a fresh install from a setup that holds up under real, sustained agentic work.
--> A Beginner’s Guide to Setting Up Claude Code for High Performance Agentic Programming - KDnuggets
-->
Join Newsletter
Introduction
Most people's Claude Code setup never gets past day one. They run the installer, log in, type a prompt, get something useful back, and never touch a config file again. Weeks later, sessions start losing track of earlier decisions, the same permission prompt shows up fifty times a day, and every long task ends the same way: a wall of context warnings and a conversation that has to be abandoned and restarted from scratch.
None of that is a limitation of the model. It's a limitation of the setup. Claude Code ships with sensible defaults, but sensible defaults and high performance are different bars, and the gap between them is almost entirely made up of a handful of files most beginners never open. This guide closes that gap. It walks through the actual configuration, permissions, hooks, and command habits that separate a fresh install from a setup that holds up under real, sustained agentic work, verified against Anthropic's current documentation rather than assumed from an older version of the tool.
Installing Claude Code the Right Way
Claude Code installs as a standalone command-line interface (CLI), and the current recommended path is the native installer rather than npm, though npm still works as a fallback:
macOS, Linux, or WSL
curl -fsSL https://claude.ai/install.sh | bash
Windows PowerShell
irm https://claude.ai/install.ps1 | iex
Or, via npm, if you'd rather manage it with your existing Node toolchain
npm install -g @anthropic-ai/claude-code
Once installed, cd into an actual project directory before running claude for the first time. This matters more than it sounds like it should: Claude Code scopes its project memory and settings to the directory you launch it from, so starting it from your home folder or your desktop means it never picks up the right context for anything you're working on.
cd your-project-directory claude
The first run walks you through authentication — either OAuth login with a Claude subscription (Pro, Max, or Team) or an application programming interface (API) key tied to a Console account. Beyond the terminal, Claude Code is also available through a VS Code extension, a JetBrains plugin, a desktop app, and a web-based version at claude.ai for sessions you want to pick up from a browser rather than a terminal. All of them read from the same underlying settings and project files, so nothing you set up in the terminal is wasted if you later switch to an integrated development environment (IDE) panel.
With that done, the install itself is the easy part. What actually determines whether Claude Code performs well from here is the set of three files most tutorials skip past.
The Three Files That Actually Run the Show
Claude Code reads configuration from two places: your project's .claude/ directory (and a CLAUDE.md at the project root), and a global ~/.claude/ directory that applies across every project on your machine. Understanding what lives where is the single biggest lever on whether the tool performs well or drifts, according to Anthropic's own documentation on the .claude directory structure.
CLAUDE.md is project memory — instructions Claude reads at the start of every session in that repository: architecture notes, build and test commands, code style rules, and anything else that would otherwise need re-explaining every single time. Run /init in a fresh project, and Claude Code will scan the codebase and generate a starting CLAUDE.md for you, which you then refine with /memory. Keep it lean. Anthropic's guidance is to treat it as a living reference under roughly 2,500 tokens, and to push anything long or path-specific into .claude/rules/*.md files instead, which can be scoped to load only when Claude touches matching files.
settings.json, living at .claude/settings.json for project-level config or ~/.claude/settings.json for personal defaults, is where permissions, hooks, environment variables, and model defaults actually live. This is the file most beginners never open, and it's directly responsible for two of the most common complaints about the tool: constant permission interruptions and Claude reaching for a more expensive model than a task actually needs.
Auto memory is the newer, quieter layer: Claude can write and read its own working notes across a session without you managing a file directly, toggled with the autoMemoryEnabled setting or the CLAUDE_CODE_DISABLE_AUTO_MEMORY environment variable if you'd rather keep memory fully manual and auditable through CLAUDE.md alone.
The practical rule that ties these together, echoed across Anthropic's documentation and independent breakdowns of the config system alike, is this: stable rules belong in CLAUDE.md, because instructions buried only in conversation history get lost the moment a long session triggers automatic compaction. If a rule needs to survive past today's session, write it down.
Setting Up Permissions and Hooks Before Needed
Claude Code runs in one of three permission modes, cycled with Shift+Tab:
Default, which asks before every potentially risky tool call.
Auto-Accept Edits, which lets file edits through without prompting while still gating other tools.
Plan Mode, which is read-only — no edits, no shell commands — until you approve a plan. Plan Mode is worth defaulting to for your first sessions in an unfamiliar codebase, since it forces Claude to propose before it acts.
Beyond the interactive modes, settings.json lets you write actual permission rules, so you're not manually approving the same safe command fifty times a session:
{ "permissions": { "allow": [ "Bash(npm test:*)", "Bash(npm run lint:*)", "Read(**)" ], "ask": [ "Bash(git push:*)" ], "deny": [ "Bash(rm -rf /*)", "Bash(sudo:*)", "Read(.env)" ] } }
What this does: anything matching allow runs without a prompt, anything matching deny is blocked outright regardless of what else matches, and anything left unlisted falls back to asking you directly. That deny-first ordering matters: a deny rule always wins even if a broader allow rule would otherwise cover it, which is what makes it safe to grant fairly broad read and test-running access without also opening the door to destructive commands.
Hooks go a step further than permission rules, since a rule can only allow or block a call, while a hook can actually run something in response to one. A PostToolUse hook that auto-formats every file Claude edits is one of the most commonly recommended starting points:
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "npx prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\"" } ] } ] } }
What this does: every time Claude writes or edits a file, this hook fires afterward and runs Prettier against exactly the file that changed, using the path Claude Code passes in through the $CLAUDE_TOOL_INPUT_FILE_PATH environment variable. You stop manually reformatting after every edit, and your style rules apply consistently whether Claude wrote the file or you did.
A PreToolUse hook can go further and actually block a dangerous command before it runs, which is a stronger guarantee than a permission rule alone since it can inspect the exact command text rather than just matching a pattern:
#!/usr/bin/env python3
.claude/hooks/block-dangerous-bash.py
import json, re, sys
DANGEROUS_PATTERNS = [ r'\brm\s+.*-[a-z]*r[a-z]*f', r'sudo\s+rm', r'chmod\s+777', r'git\s+push\s+--force.*main', ]
input_data = json.load(sys.stdin) if input_data.get('tool_name') == 'Bash': command = input_data.get('tool_input', {}).get('command', '') for pattern in DANGEROUS_PATTERNS: if re.search(pattern, command, re.IGNORECASE): print("BLOCKED: matches a dangerous command pattern", file=sys.stderr) sys.exit(2) sys.exit(0)
What this does: Claude Code pipes the tool call's details to this script as JSON on stdin before the command runs. If the bash tool is about to execute something matching a recursive force-delete, a sudo rm, a world-writable chmod, or a forced push to main, the script prints a reason and exits with code 2, which Claude Code's hook system treats as a hard block — stopping the command before it ever runs. Register it in settings.json under PreToolUse with a Bash matcher, and this becomes a permanent safety net rather than something you have to remember to check for manually.
The Commands Worth Learning First
Claude Code ships with more than sixty built-in commands as of this writing, and trying to memorize all of them on day one is a waste of time. The table below covers the ones that actually change how a session performs, organized by what they're for, pulled directly from Claude Code's official command reference.
Command Category What It Does
/init Setup Scans your codebase and generates a starting CLAUDE.md
/memory Setup Opens CLAUDE.md for editing directly
/clear Context Starts a fresh conversation while keeping project memory
/compact [focus] Context Summarizes conversation history to free up context; accepts instructions on what to preserve
/context Context Shows current context window usage
/plan Planning Toggles Plan Mode; Claude proposes before it acts, nothing executes until you approve
/diff Review Opens an interactive diff of every change made this session
/code-review [--fix] Review Checks the current diff for correctness bugs; --fix applies the findings
/security-review Review Checks the current diff specifically for security vulnerabilities
/review Review Gives a read-only review of a GitHub pull request
/resume [session] Navigation Resumes a previous conversation by name or ID
/branch [name] (alias /fork) Navigation Forks the current conversation into a new session
/rewind Navigation Rolls code and/or conversation back to an earlier checkpoint
/model Cost & Performance Switches the active model mid-session without losing context
/effort Cost & Performance Sets reasoning depth (low through max) to match task complexity
/cost Cost & Performance Shows token usage and spend for API-key users
/agents Delegation Manages subagents — view, create, or invoke specialized agents
/permissions Configuration Manages permission rules interactively
/hooks Configuration Manages hooks interactively
/doctor Diagnostics Checks your install for configuration problems
A useful habit for a beginner: build fluency with /compact, /plan, and /diff first, since those three alone solve the majority of early frustration — sessions that degrade from context bloat, edits that go further than intended, and not knowing exactly what changed. Everything else in the table earns its place once those three are muscle memory.
Building Your Own /truth Command
Here's a fair note before this section: /truth isn't a command that ships with Claude Code. It doesn't appear in the official command reference, and it's not something I could confirm across any current documentation or community guide while researching this article. What's genuinely useful, though — and likely what prompted the idea — is a command that makes Claude check its own recent claims against the actual codebase before you trust them and move on. That's a real gap worth closing, and it's a perfect example of Claude Code's custom command system, so here's how to build it yourself.
Custom commands are defined as skills — a folder with a SKILL.md file. Create one at .claude/skills/truth/SKILL.md:
--- description: Verify Claude's most recent claims and edits against the actual codebase allowed-tools: Read, Grep, Glob, Bash(git diff:*) ---
Re-examine everything you just told me in this conversation against what actually exists in the codebase right now. Specifically:
- For every file you claim to have
[truncated for AI cost control]