Advanced Claude Code Techniques
You already use Claude Code daily, but you suspect you are leaving capability on the table. The model seems to “think harder” on some prompts than others and you are not sure why. You have heard MCP servers can give Claude direct database and GitHub access, but the config snippets you copied off a blog post silently failed to load. And you keep running one task at a time when you have four independent things to ship.
This guide covers the techniques that separate a casual Claude Code user from someone who drives it like a power tool: controlling reasoning depth, connecting external tools through MCP, writing your own MCP tool, automating reviews in CI, and running genuinely isolated parallel sessions.
What You’ll Walk Away With
Section titled “What You’ll Walk Away With”- A correct mental model of extended thinking and how to actually control its depth (effort levels, not magic keywords)
- A working
.mcp.jsonthat loads on the first try, plus the current way to add the GitHub MCP server - A minimal, real custom MCP server using the official SDK — copy-paste runnable
- A GitHub Actions workflow that runs Claude on every PR, triggered by
@claudementions - A worktree-based pattern for true parallel work with zero cross-contamination
Controlling Extended Thinking
Section titled “Controlling Extended Thinking”Extended thinking is enabled by default. It is not a mode you switch on with a keyword — and this is the single most common misconception. Phrases like “think”, “think hard”, and “ultrathink” are interpreted as ordinary prompt text. They do not allocate a thinking-token budget. If you have been sprinkling “ultrathink” into prompts expecting a 128k-token reasoning pass, it was doing nothing special.
How depth is actually controlled depends on the model:
- On Opus 4.6 and newer (including Opus 4.8 and Fable 5), thinking uses adaptive reasoning. The model dynamically allocates reasoning based on an effort level:
low,medium, orhigh(default). Fable 5 additionally supportsxhighandmaxfor maximum reasoning depth. Set the level in/model, or with theCLAUDE_CODE_EFFORT_LEVELenvironment variable. - On other models, thinking uses a fixed budget of up to 31,999 tokens drawn from the output budget. Cap it with the
MAX_THINKING_TOKENSenvironment variable. (This variable is ignored on Opus 4.6+ unless you set it to0, which disables thinking entirely on any model.)
So the lever is the effort level or the token cap — not the wording of your prompt.
# Inside the REPL, raise reasoning depth for a hard task/model
# Then select Opus with "high" effort, or set it for the session:export CLAUDE_CODE_EFFORT_LEVEL=highclaude# Limit the fixed thinking budget (max 31,999) on non-adaptive modelsexport MAX_THINKING_TOKENS=10000claude
# Disable thinking entirely on any modelexport MAX_THINKING_TOKENS=0What you do control with your prompt is the structure of the reasoning. Asking Claude to work through a problem in explicit stages reliably produces better results than a one-line request, regardless of effort level.
Connecting MCP Servers
Section titled “Connecting MCP Servers”Model Context Protocol (MCP) servers give Claude direct, structured access to external systems — GitHub, a database, a browser — instead of you copy-pasting context. The setup that bites people is the config file format and pointing at archived reference packages.
The GitHub MCP server is now a remote HTTP server, not a global npm install. Add it with one command:
claude mcp add --transport http github https://api.githubcopilot.com/mcp/For local stdio servers (a database, a browser), you configure them in .mcp.json at your project root. The top-level key is mcpServers — not servers. With the wrong key the file is silently ignored.
{ "mcpServers": { "postgres": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"] }, "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest"] } }}A few things worth knowing that the snippets you find online usually get wrong:
- Stdio MCP servers run through
npx(oruvxfor Python-only servers). There is nonpm install -gstep —npxfetches and runs them on demand. @modelcontextprotocol/server-postgresis a legacy reference server. It still resolves on npm, but treat it as a starting point; many teams move to a maintained vendor server.- For browser automation use
@playwright/mcp, not the archivedserver-puppeteer.
Once a server is loaded, you stop describing context and start asking for outcomes:
# With the GitHub MCP serverOpen an issue for the login 500s, tag it "bug" and "auth", and link thethree most recent commits that touched src/auth/.
# With the Postgres MCP serverShow me the schema for the users table, then find accounts with no loginin the last 30 days.Building a Custom MCP Server
Section titled “Building a Custom MCP Server”When no off-the-shelf server fits — you want Claude to trigger your deploy script, hit an internal API, or run a proprietary tool — write a small one. Use the official SDK, @modelcontextprotocol/sdk. The API is McpServer with registerTool, connected over a transport.
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import { z } from 'zod';
const server = new McpServer({ name: 'project-tools', version: '1.0.0' });
server.registerTool( 'deploy-staging', { description: 'Deploy the given branch to the staging environment', inputSchema: { branch: z.string() }, }, async ({ branch }) => { // Call your real deploy pipeline here. const url = `https://staging.example.com/${branch}`; return { content: [{ type: 'text', text: `Deployed ${branch} -> ${url}` }] }; });
await server.connect(new StdioServerTransport());Register it in .mcp.json like any other stdio server, then ask Claude to deploy a branch by name. Custom servers shine for deployment automation, internal API access, and any workflow that touches tools only your team has.
Automating PR Reviews in CI
Section titled “Automating PR Reviews in CI”You can have Claude review every pull request automatically. This runs through GitHub Actions and the anthropics/claude-code-action, not a YAML config file at .github/claude-code-review.yml (that path does not exist).
-
Install the GitHub app
Run this inside the Claude Code REPL. It walks you through installing the app and adding the required secrets:
/install-github-app -
Add the workflow file
Copy the example workflow into
.github/workflows/claude.yml. A minimal automated review looks like this:.github/workflows/claude.yml name: Claude Reviewon:pull_request:types: [opened, synchronize]jobs:review:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v5- uses: anthropics/claude-code-action@v1with:anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}prompt: |Review this PR. Report only real issues, grouped by:security, correctness, missing error handling.Be concise. Skip style nits.The instruction goes in the
promptinput. (direct_promptis the deprecated v0.x name — useprompton@v1.) -
Trigger it on demand from a comment
With the action installed, mention
@claudein any PR or issue comment and it responds:@claude review this PR for security issues@claude suggest improvements to the error handling in src/api/
The pattern that works well in practice: let the Action post an automated first pass on every PR, and reserve @claude mentions for targeted follow-ups (“explain this resolution”, “check the migration for backwards compatibility”). Claude catches mechanical issues so human reviewers can focus on design and intent.
Running Truly Parallel Work
Section titled “Running Truly Parallel Work”When you have several independent tasks — a feature, an urgent hotfix, a migration — you want each one isolated so they cannot step on each other. The primitive for that is git worktrees, one per task. A common mistake is reaching for --add-dir: that flag adds extra directories to a single session for context, it does not create isolated parallel instances.
Give each task its own worktree, then run a separate Claude session in each:
# One worktree (and branch) per taskgit worktree add ../app-feature -b feature/notificationsgit worktree add ../app-hotfix -b hotfix/auth-timeout
# Terminal 1cd ../app-feature && claude# Terminal 2cd ../app-hotfix && claudeEach session has its own context and sees only the files in its worktree, so there is zero cross-contamination. When a task is done, remove its worktree with git worktree remove ../app-feature. For the full worktree workflow, see Version Control.
If you only need a fresh branch off the same starting point (not full file isolation), claude --resume <id> --fork-session gives each terminal a clean session without a second working directory.
Optimizing Your Own Workflow
Section titled “Optimizing Your Own Workflow”Claude Code can help tighten how you use Claude Code. The highest-leverage move is curating your CLAUDE.md so the model stops repeating context you give it manually.
For navigation-heavy editing, enable Vim keybindings with the /vim command (or set it permanently via /config). It gives you hjkl motion, text objects, and . to repeat the last change in the input editor.
When This Breaks
Section titled “When This Breaks”Reasoning stays shallow no matter what you type — On Opus 4.6+, depth is set by effort level, not prompt wording. Run /model and select high effort. “Think harder” in the prompt does nothing.
MAX_THINKING_TOKENS seems ignored — It is ignored on Opus 4.6+ (adaptive reasoning controls depth there). Use the effort level instead. The only exception is MAX_THINKING_TOKENS=0, which disables thinking on any model.
MCP server does not load — Check the top-level key in .mcp.json is mcpServers, not servers. Verify the server appears with claude mcp list, and run claude --debug "mcp" to see startup errors. For stdio servers, confirm the npx/uvx command runs on its own in a terminal.
GitHub Action does not respond to @claude — Confirm the app is installed (/install-github-app), the ANTHROPIC_API_KEY secret exists, and the workflow lives at .github/workflows/claude.yml. If you copied an older example, replace the direct_prompt input with prompt.
Parallel sessions interfere — You are probably sharing a directory. Give each task its own worktree; --add-dir does not isolate sessions, it only adds context paths to one session.
What’s Next
Section titled “What’s Next”With these techniques in hand, learn how to scale them across a team. Continue to Team Collaboration for collaborative AI-assisted development patterns.