Skip to content

Troubleshooting and Best Practices: Tips 96-100

Claude Code just rewrote a 20-line service into a factory, a registry, and three interfaces — and you accepted it before you read it. Or it’s halfway down the wrong path and you hit Ctrl+C, which kills the whole session instead of the task. The difference between a frustrating session and a fast one is not the model; it’s having a recovery routine: commit before you delegate, interrupt cleanly, and revert without ceremony.

  • A real permissions allow/ask/deny policy you can paste into .claude/settings.json
  • The commit-before-you-delegate habit that makes a bad result a one-line undo
  • The correct way to interrupt (Escape, not Ctrl+C) and when to use each
  • Copy-paste prompts to de-overengineer a solution and to self-review your diff
  • A “When This Breaks” recovery checklist for the failure modes you will actually hit

Balance security with productivity through thoughtful permission management:

Claude Code permissions live in a permissions object in .claude/settings.json with allow, ask, and deny arrays. Entries are tool rules (Read, Bash(git diff *)), not bare command words, and Bash specifiers use space-globs — never colons.

{
"permissions": {
"allow": [
"Read",
"Bash(git status)",
"Bash(git diff *)",
"Bash(ls *)",
"Bash(grep *)"
],
"ask": [
"Edit",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(npm install *)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Read(./.env)"
]
}
}

Security Best Practices

  • Never auto-allow destructive commands
  • Be cautious with commands that include sensitive files
  • Review commands that access environment variables
  • Use MCP servers for sensitive operations
  • Maintain different policies for different environments

A concrete reason to keep git add in ask rather than allow: a blanket git add . can sweep in .env files with secrets, node_modules, build artifacts, or local notes. Prefer specific paths (git add src/) or interactive staging (git add -p), and let the ask rule force a deliberate confirmation each time.

Working with AI requires a different approach to version control. The traditional habit is: make changes, debug extensively, commit when perfect. With Claude Code, invert it — commit the current state first, let Claude attempt the change, and if the result is worse than what you had, revert and re-prompt rather than debugging the AI’s output line by line.

The mechanical loop looks like this in the terminal:

Terminal window
git add . && git commit -m "Checkpoint before Claude refactoring"
# In the REPL: "Refactor this module to use dependency injection"
# If the result is overly complex:
git reset --hard HEAD
# In the REPL: /clear, then re-prompt with tighter constraints

Reverting is usually faster than debugging an AI mistake, produces a cleaner final implementation, and saves you from anchoring on a bad first attempt. Treat commits as checkpoints in a video game: save often so retrying a different strategy costs you one line, not an afternoon.

Tip 98: Handle Complex Solutions Carefully

Section titled “Tip 98: Handle Complex Solutions Carefully”

Claude sometimes overengineers solutions. Watch for these patterns:

// Claude's overly complex solution
class UserServiceFactory {
private static instance: UserServiceFactory;
private serviceCache: Map<string, IUserService>;
static getInstance(): UserServiceFactory {
if (!this.instance) {
this.instance = new UserServiceFactory();
}
return this.instance;
}
createService(type: string): IUserService {
// 50 more lines of factory logic
}
}
// What you actually needed
class UserService {
constructor(private db: Database) {}
async getUser(id: string) {
return this.db.users.findOne(id);
}
}

Common overengineering patterns to watch for: unnecessary abstraction layers, premature optimization, over-generalization, deep inheritance hierarchies, and design patterns applied where a function would do.

How to prevent:

# Add to CLAUDE.md
## Simplicity Principles
- PREFER simple solutions over complex ones
- AVOID premature abstraction
- USE design patterns only when clearly beneficial
- START with the simplest working solution
- REFACTOR to add complexity only when needed

Tip 99: Use Escape Key for Proper Interruption

Section titled “Tip 99: Use Escape Key for Proper Interruption”

Master the art of stopping Claude effectively. The key distinction:

  • Wrong: Ctrl+C — this exits Claude Code entirely and you lose the session.
  • Right: Escape — this stops the current operation but keeps the conversation, so you can immediately add context and continue.

Reach for Escape the moment you notice any of these:

  • Claude is heading in the wrong direction
  • You realize you need to provide more context
  • You want to add an additional instruction
  • The operation is taking longer than the task warrants
  • You spot an error in your own request

The recovery is just Escape, then keep typing. For example: Claude starts implementing, you press Escape, and you type Wait, I forgot to mention we need to maintain backward compatibility with the v1 API — Claude picks up the new constraint without restarting.

Variations worth internalizing: early Escape (stop as soon as the approach looks wrong), let it finish (sometimes it’s faster to see where it lands), Escape + /clear for a complete direction change, and Escape + refine to add constraints mid-execution.

Working effectively with Claude Code is a skill, and the adjustment is real. Most developers move through a recognizable arc:

  1. Week 1-2: Adjustment Period

    • Feels awkward and slow
    • Tendency to over-verify everything
    • Unsure what’s safe to delegate
  2. Week 3-4: Finding Rhythm

    • You develop trust in specific areas
    • You learn Claude’s strengths and failure modes
    • You start batching related tasks
  3. Month 2 and beyond: Flow

    • A natural delegate-verify-revert rhythm develops
    • Previously tedious tasks become routine
    • You measure your own usage with /cost instead of guessing at “X times faster”

Rather than chasing a productivity multiplier, track something you can verify: how often you accept Claude’s first attempt unedited, and how often you revert. Both improve as your prompting tightens.

## Daily Workflow Best Practices
### Morning Routine
1. Clear previous context: `/clear`
2. Review yesterday's work
3. Plan today's tasks
4. Queue up morning work
5. Review and commit completed tasks
### During Development
- Commit before each Claude task
- Clear between unrelated work
- Use specific, detailed requests
- Verify output before proceeding
- Update CLAUDE.md with learnings
### End of Day
- Review all changes
- Update documentation
- Check `/cost` for optimization
- Plan tomorrow's work
- Commit and push

Two prompts cover most of your day-to-day QA: a self-review of what you just changed, and a test-writing pass that goes beyond the happy path.

Sustainable Practices

  1. Continuous Learning

    • Regular retrospectives
    • Share discoveries with team
    • Update workflows based on experience
  2. Cost Management

    • Daily usage reviews
    • Model selection optimization
    • Context management discipline
  3. Quality Focus

    • Never compromise on verification
    • Maintain high testing standards
    • Regular security audits
  4. Team Alignment

    • Shared standards and practices
    • Regular knowledge sharing
    • Coordinated improvements

When a session goes sideways, you want a recovery routine, not a debugging spiral. Work through these in order.

  1. Claude went down the wrong path and is still running. Press Escape (not Ctrl+C, which kills the session). Add the missing constraint in plain language and let it continue from there.

  2. The result is worse than what you had. Don’t debug the AI’s output. Run git reset --hard HEAD to return to your checkpoint, then /clear and re-prompt with a tighter spec. This is why you commit before delegating.

  3. Claude over-engineered the solution. Use the de-overengineering prompt from Tip 98 to collapse the abstraction in place, or reset and re-prompt asking for “the simplest thing that passes the tests.”

  4. Context is polluted and answers are drifting. Run /clear to drop the conversation history before starting unrelated work. A stale context is the most common cause of off-target responses.

  5. Costs are climbing faster than expected. Check /cost in the REPL, then route routine work to Sonnet 4.6 and reserve Opus 4.8 for genuinely hard tasks. Long, unbroken sessions are usually the culprit — /clear between tasks also trims token spend.

  6. A permission rule isn’t taking effect. Remember rules evaluate deny, then ask, then allow, and Bash specifiers are space-globs (Bash(npm run *)), not colons. A bare command word in the old autoAllow/blocked shape is a no-op — migrate to the permissions object from Tip 96.

You’ve reached the end of the 100 tips. The throughline: speed without verification is worthless, and a tight delegate-verify-revert loop beats trusting any single output. To go deeper: