Dashboard/Phase 3: Customization
🔧 Troubleshoot10 min20 XP

Lesson 24: Troubleshoot — Permission Errors & Config Conflicts

Day 24 of 50 · ~10 min reading · Phase 3: Customization


Introduction

You've set up your project with CLAUDE.md, permissions, commands, rules, and skills. Everything's working beautifully... until something goes wrong.

Claude suddenly can't do something you expected. Or it's ignoring your rules. Or you get an error about permissions.

This lesson teaches you how to diagnose and fix three common configuration problems.


Scenario 1: Permission Mode Blocks a Needed Action

What Happened

You're in the middle of a complex refactoring. Claude says:

"I'd like to run npm test to verify my changes, but this action requires your approval. Approve?"

You've set permissions to "ask every time," and now Claude is asking about something you do 50 times a day. It's slowing you down.

What It Looks Like

[In Claude Code conversation]

Claude: I've refactored the function. Let me run tests to verify.
        > Approve running: bash command "npm test"?
User: [clicks approve, again]
Claude: Tests passed. Now let me refactor the next function.
        > Approve running: bash command "npm test"?
User: [frustrated, clicks approve again]

Or the opposite problem:

[In Claude Code conversation]

Claude: I'll push these changes to main.
[Push happens without asking]
User: No! I didn't approve that!

Diagnose

The problem is your permission settings don't match your workflow.

Check .claude/settings.json:

cat .claude/settings.json

If you see:

{
  "permissions": {
    "mode": "ask_every_time"
  }
}

And you keep approving the same actions, your permissions are too strict.

If you see a permissive mode but Claude did something risky without asking, your permissions are too loose.

Fix

Tighten or loosen permissions strategically.

If certain actions (like npm test) are safe and you do them constantly, allowlist them:

{
  "permissions": {
    "mode": "plan",
    "bypassTools": {
      "allowed": ["bash:npm test", "bash:npm run lint", "bash:git status"]
    }
  }
}

If you're nervous about a specific dangerous action, blocklist it:

{
  "permissions": {
    "mode": "plan",
    "bypassTools": {
      "blocked": ["bash:git push origin main", "bash:rm -rf"]
    }
  }
}

Then test it: Run a task and verify Claude behaves as expected.

Lesson Learned

Permissions are a tradeoff between safety and speed. Find the sweet spot for your workflow. If you're waiting for approvals constantly, loosen permissions. If you're nervous Claude will break something, tighten them. You can always adjust later.

The goal isn't to be maximally safe or maximally fast — it's to be safe enough while staying productive.


Scenario 2: CLAUDE.md Is Too Long and Claude Ignores Parts

What Happened

You spent time documenting everything in CLAUDE.md. You included:

  • Project history
  • Detailed architecture diagrams
  • Every edge case and exception
  • Philosophy on code quality
  • Team conventions
  • Build system deep dive

It's comprehensive and helpful. But now Claude is ignoring some of it. Claude asks about things you documented or follows patterns differently than you specified.

What It Looks Like

Your CLAUDE.md says:
"Always use async/await, never use .then()"

Claude creates a new function using .then() anyway:
```typescript
db.query().then(result => { ... })

You ask: "Why didn't you use async/await?" Claude: "I don't have that pattern in my context."


Or:

Your CLAUDE.md says: "Tests go in /tests directory"

Claude creates tests in tests instead. You ask why. Claude: "I didn't see that documented."


### Diagnose

**The problem is your CLAUDE.md is too long.**

Check the file:
```bash
wc -l CLAUDE.md

If it's over 200-300 lines, context window pressure is eating into Claude's ability to apply your conventions. Claude has limited space, and a massive CLAUDE.md takes up space that could be used for the actual task.

Also check: Is the information you need buried deep?

If the convention Claude missed is on line 180 in a 400-line file, Claude might not have seen it before running out of context.

Fix

Cut CLAUDE.md down to essentials.

Keep:

  • Quick project overview (2-3 lines)
  • How to test (2-3 lines)
  • How to build (2-3 lines)
  • Critical conventions (5-10 lines)
  • Key patterns (5-10 lines)

Move to rules or separate docs:

  • Architecture deep dives → create rules for /src, /api, etc.
  • Edge cases and exceptions → .claude/memory/
  • Philosophy and history → separate README.md for humans
  • Detailed patterns → .claude/skills/

Example: before (too long)

# Our Project

## History
Founded in 2020, blah blah blah...
[10 lines]

## Philosophy
We believe in clean code and strong types...
[15 lines]

## Style Guide (Comprehensive)
[50 lines covering every possible scenario]

## Testing Strategy (Detailed)
[40 lines with rationale and examples]

## Deployment Process
[30 lines with links and references]

Example: after (lean)

# Project: Task Manager

## Tech
Node.js + React + TypeScript

## Test
`npm test` — tests in `/tests`, Jest framework

## Build
`npm run build` → `/dist`

## Style
- async/await, no .then()
- camelCase functions, PascalCase components
- Absolute imports with @/alias

## Key rules
- TypeScript required (no any)
- Every feature needs tests
- Validate all inputs

Then create .claude/rules/src.rules.md for detailed conventions in that directory.

Lesson Learned

Brevity is a feature. A tight CLAUDE.md costs less context and forces you to identify what actually matters. Details belong in rules, memory, or regular documentation. Claude reads CLAUDE.md before the conversation starts — make it count, not make it comprehensive.


Scenario 3: Conflicting Rules Cause Unexpected Behavior

What Happened

You have rules in multiple places:

  • CLAUDE.md says: "Use async/await"
  • .claude/rules/src.rules.md says: "Use async/await"
  • .claude/memory/patterns.md mentions: "Avoid async/await for simple operations"

Now Claude is confused about what to do. Different parts of your configuration are giving different signals.

Or perhaps:

  • CLAUDE.md says: "Tests go in /tests"
  • .claude/rules/src.rules.md says: "Tests go in __tests__ alongside source"

Now when Claude creates a test in /src, is it following global rules or local rules?

What It Looks Like

In a conversation:
Claude: I need to get user data. Should I use async/await?
User: Yes, like I said in CLAUDE.md
Claude: But memory says to avoid it for simple cases...
[Claude writes something inconsistent]

Or Claude creates tests in one place in some parts of the code and another place in other parts.

Diagnose

The problem is your configuration has contradictions.

Check for conflicts:

  1. CLAUDE.md vs. rules: If CLAUDE.md and .claude/rules/ say different things, which wins? (Answer: rules are path-specific and override global, but it's confusing.)

  2. Rules vs. memory: If a rule says "always use TypeScript" but memory says "JavaScript is fine for scripts," Claude might be uncertain.

  3. Multiple memory files: If you have multiple .claude/memory/ files saying different things, Claude has to reconcile them.

  4. Old vs. new: If you have outdated documentation, Claude might follow old patterns.

Fix

Enforce one source of truth per category.

Global conventions → CLAUDE.md only

  • Tech stack
  • How to test
  • How to build
  • Key style rules (2-3 most important)

Local conventions → Rules only

  • Directory-specific patterns
  • Different style for different areas (API might be different from frontend)

Lessons learned → Memory only

  • "We tried this pattern and it didn't work"
  • "This error means X"
  • Debugging hints

Specific tasks → Skills only

  • "To add a component, do this"
  • "To deploy, follow these steps"

Then delete or consolidate:

# If CLAUDE.md and rules say the same thing, delete from rules
# If memory contradicts current practice, update it or delete it
# If a skill contradicts rules, delete the contradiction from the skill

Example: before (conflicting)

CLAUDE.md: "Tests in /tests with Jest"
Rules: "Tests alongside source in __tests__"
Memory: "Jest for unit tests, Mocha for integration"
Skill: "Create tests in __tests__"

Example: after (coherent)

CLAUDE.md: "Tests use Jest in /tests directory"
Rules: (empty — no need to repeat global)
Memory: "We tried Mocha and switched to Jest in 2024"
Skill: "Create test in /tests following Jest patterns"

Lesson Learned

Your configuration should be consistent. Don't make Claude guess which rule applies. One level should be primary:

  • CLAUDE.md for global
  • Rules for local overrides
  • Memory for lessons, not current policy
  • Skills for tasks, not conventions

If you notice contradiction, clean it up. Claude will work better, and so will you (you'll understand your own project better).


Prevention Checklist

Before deploying a configuration, ask:

  • Is CLAUDE.md under 200 lines?
  • Does CLAUDE.md have any contradictions with rules?
  • Do rules contradict each other or CLAUDE.md?
  • Is memory documenting lessons, not current policy?
  • Are skills teaching tasks, not conventions?
  • Can I explain my permission settings in one sentence?
  • Have I tested the configuration in a real task?

Key Takeaway

Configuration problems usually come from three things: permissions don't match your workflow, documentation is too large or scattered, or conflicting information confuses Claude. The fixes are simple: align permissions, tighten documentation, and establish one source of truth for each category. When in doubt, less is more — lean documentation beats comprehensive documentation.


What's Next?

You've now mastered Phase 3: customization. You know how to teach Claude about your project, set boundaries, create workflows, and avoid configuration pitfalls.

Phase 4 introduces a new dimension: What happens when Claude reaches outside your project? How do you let Claude connect to APIs, databases, external tools, and services?

The answer is MCP — the Model Context Protocol. It's how Claude's context extends beyond your filesystem.


← Back to Curriculum