Claude Code: Intermediate & Advanced Techniques
AI coding assistants have evolved from simple autocompletion tools into sophisticated development partners. Claude Code represents the next step in this evolution, offering a framework for what can be described as "autonomous programming." It's a tool designed to integrate deeply into your workflow, do jobs what AI coding previously cannot do:
- Code Understanding & Q&A: Acts as a project expert, explaining how large codebases work, making it invaluable for onboarding new team members.
- Large-Scale Refactoring: Excels at modifying massive files (e.g., 18,000+ lines) where other AIs fail, thanks to its ability to understand global code relationships.
- Debugging: Provides step-by-step reasoning to find the root cause of bugs, unlike tools that just offer a fix without context.
- Complex Feature Generation: Follows an "explore → plan → implement" workflow. It can be prompted to first analyze the problem and create a detailed plan before writing a single line of code.
- Test-Driven Development (TDD): Can be instructed to write failing tests first, then generate the minimal code required to make them pass, significantly accelerating the TDD cycle.
Let's dive into the techniques that will help you harness this power effectively.
1. Foundational Setup: The Core of Your Workflow
A robust setup is the bedrock of an efficient workflow. Investing time here pays dividends in every subsequent interaction with Claude Code.
- Project Memory with CLAUDE.md: At the heart of any project is a concise
CLAUDE.mdfile in the root directory. This file acts as the project's short-term memory, containing key architectural principles, coding standards, and testing procedures. To keep this file lean and focused, use imports like@docs/testing.mdto reference more detailed documentation. You can quickly add new rules by starting a message with#or edit the memory directly with the/memorycommand. - Monorepo Awareness: Modern development often involves monorepos. To grant Claude access to multiple packages for cross-directory analysis and refactoring, use the
--add-dirflag or defineadditionalDirectoriesin your.claude/settings.jsonfile. This is crucial for tasks that span multiple parts of your codebase. - Keyboard & Terminal Ergonomics: Speed is essential. Master key shortcuts to streamline your interactions. Use
Esc Escto quickly edit your previous message. EnableShift+Enterfor newlines by running/terminal-setuponce. For Vim enthusiasts, the/vimcommand enables familiar Vim-style motions for a more comfortable editing experience.
2. Streamlining Your Day-to-Day Workflow
With a solid foundation, you can introduce practices that reduce friction and boost your daily productivity.
Using the Right Mode
The CLI offers several permission modes to suit different tasks and risk appetites:
default: The safest starting point. It prompts you for confirmation before performing potentially risky actions, offering a good balance of safety and speed.acceptEdits: A "live coding" mode that automatically accepts file edits without a prompt. It's ideal for rapid iteration and when you're closely supervising the process.plan: A "safe" mode designed for tasks like code reviews. Claude can analyze and discuss the code but cannot modify any files.bypassPermissions: Skips all permission prompts entirely. Use this mode with extreme caution and only in sandboxed environments where accidental changes have no consequence.
You can set a default mode in .claude/settings.json or specify one for a session with the --permission-mode flag.
Slash Commands & Customization
Repetitive tasks are perfect candidates for automation. Turn your most common prompts into reusable tools by creating custom slash commands. Simply store them as Markdown files with YAML frontmatter in the .claude/commands/ directory.
- Use
allowed-toolsin the frontmatter to restrict what a command can do, adding a layer of safety. - The
!prefix lets you run shell commands (e.g.,!git status -sb) and inject their output directly into your prompt's context. - Use
$ARGUMENTSto pass parameters to your commands, making them flexible and more powerful.
Resuming and Parallelizing Work
claude --continue: Instantly jumps you back into your most recent session.claude --resume: Presents a list of past sessions, letting you pick up exactly where you left off.- Git worktrees: For large-scale refactors, use
git worktreeto create isolated branches. This allows you to run separate Claude sessions in parallel, each with its own context, preventing confusion and collisions.
Output Styles for Collaboration
/output-style explanatory: Enriches responses with an "Insights" section, making it perfect for mentoring junior developers or explaining complex changes in a pull request./output-style learning: Structures responses withTODO(human)placeholders, actively inviting you to collaborate and fill in the gaps.
3. Incorporating Quality & Safety
True autonomy requires guardrails. Integrate quality checks and safety nets directly into your workflow to build with confidence.
Hooks for Guardrails
Hooks are shell commands that automatically run at specific lifecycle events, offering a deterministic way to enforce standards. Configure them in .claude/settings.json.
PreToolUse: Run checks before a tool is used. For example, you can block edits to sensitive files or require a corresponding test file to exist before allowing a write operation.PostToolUse: Automate cleanup tasks after a tool is used. This is perfect for running formatters likeprettierorgofmt, as well as linters and quick tests after every edit.Notification: Send a desktop alert when Claude requires your input, so you can switch tasks without losing your place.
For example, let Mac notify you once the job is done - code ~/.claude/settings.json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "say \"job's done!\""
}
]
}
]
}
}
Permissions and Security
Define explicit allow, ask, and deny rules in your settings to manage tool access without constant prompting.
- Allow: Safe, routine operations like
Bash(npm run test:*). - Ask: Potentially risky actions you want to approve manually, such as
Bash(git push:*). - Deny: Critical security rules to prevent catastrophes, such as
Read(./.env)orRead(./secrets/**).