Skip to content

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.

  • A correct mental model of extended thinking and how to actually control its depth (effort levels, not magic keywords)
  • A working .mcp.json that 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 @claude mentions
  • A worktree-based pattern for true parallel work with zero cross-contamination

Extended thinking is enabled by default. The durable control is the effort level, but Claude Code also recognizes one special one-turn hint: include ultrathink anywhere in a prompt to request deeper reasoning for that turn. It adds an in-context instruction and does not change the effort level sent to the API. Phrases such as “think”, “think hard”, and “think more” remain ordinary prompt text.

How depth is actually controlled depends on the model:

  • Fable 5, Sonnet 5, and Opus 4.7 or newer always use adaptive reasoning. They support low, medium, high, xhigh, and max; high is the default except on Opus 4.7, where it is xhigh. Set the level with /effort, the slider in /model, --effort, or CLAUDE_CODE_EFFORT_LEVEL.
  • Opus 4.6 and Sonnet 4.6 also expose effort levels, but can revert to the old fixed budget by setting CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1. Only then does a positive MAX_THINKING_TOKENS value cap the fixed budget.
  • Disabling differs on Fable. On the first-party Anthropic API, MAX_THINKING_TOKENS=0 disables thinking on supported models except Fable 5. Fable’s adaptive thinking is always on; the session toggle and zero-token setting do not disable it.

So the lever is the effort level or the token cap — not the wording of your prompt.

Terminal window
# Inside the REPL, raise reasoning depth for a hard task
/model
# Or set the session effort before launch:
export CLAUDE_CODE_EFFORT_LEVEL=high
claude

What 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.

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:

Terminal window
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 (or uvx for Python-only servers). There is no npm install -g step — npx fetches and runs them on demand.
  • @modelcontextprotocol/server-postgres is 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 archived server-puppeteer.

Once a server is loaded, you stop describing context and start asking for outcomes:

# With the GitHub MCP server
Open an issue for the login 500s, tag it "bug" and "auth", and link the
three most recent commits that touched src/auth/.
# With the Postgres MCP server
Show me the schema for the users table, then find accounts with no login
in the last 30 days.

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.

deploy-mcp-server.ts
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.

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).

  1. 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
  2. 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 Review
    on:
    pull_request:
    types: [opened, synchronize]
    jobs:
    review:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v5
    - uses: anthropics/claude-code-action@v1
    with:
    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 prompt input. (direct_prompt is the deprecated v0.x name — use prompt on @v1.)

  3. Trigger it on demand from a comment

    With the action installed, mention @claude in 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.

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.

The short path is to let Claude create the worktree for you — --worktree (or -w) with a name per task, one terminal each:

Terminal window
# Terminal 1
claude --worktree feature-notifications
# Terminal 2
claude --worktree hotfix-auth-timeout

Each worktree lands under .claude/worktrees/<name>/ on a new branch worktree-<name>, and on exit Claude offers to remove it — automatically when it is clean and the session was unnamed, with a prompt when there is work in it. Add .claude/worktrees/ to .gitignore, and a .worktreeinclude at the repo root (.gitignore syntax) to copy .env and friends into each fresh checkout.

Two gotchas. An interactive --worktree needs workspace trust, so run plain claude in the repo once first. And claude -p --worktree skips both the trust check and the exit prompt, so nothing cleans up — remove those with git worktree remove.

Reach for git directly when you need a specific existing branch, or the worktree somewhere other than .claude/worktrees/:

Terminal window
git worktree add ../app-hotfix hotfix/auth-timeout
cd ../app-hotfix && claude

Either way each session sees only the files in its worktree, so there is zero cross-contamination. For the full worktree workflow, see Version Control; for driving several of these at once from one terminal, see tmux for agent fleets.

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.

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, open /config and set Editor mode to Vim. It gives you hjkl motion, text objects, and . to repeat the last change in the input editor; the former /vim command was removed.

Reasoning stays shallow no matter what you type — Run /effort or use the /model slider and select high or xhigh. Use ultrathink only as a one-turn hint; it does not change the API effort level.

MAX_THINKING_TOKENS seems ignored — Positive values apply only in fixed-budget mode on Opus/Sonnet 4.6. Use effort on adaptive models. A value of 0 disables thinking on the first-party Anthropic API except on Fable 5, where thinking cannot be turned off.

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.

With these techniques in hand, learn how to scale them across a team. Continue to Team Collaboration for collaborative AI-assisted development patterns.