Issue 09 | Precise Prompt Scoping (Scope Boundary Control)
🎯 Learning Objectives
By the end of this issue, you will master:
- Why Claude sometimes "oversteps" and modifies unrelated code
- How to constrain modification scope using file paths and directory limitations
- Advanced usage of Subagent scope isolation
- Precise control with
--allowedTools/--disallowedTools
📖 Core Concepts Explained
9.1 Problem: Why does Claude "overstep"?
When you say "fix this bug", Claude might:
- ✅ Modify the target file ← Expected behavior
- ❌ "Optimize" other unrelated files along the way ← Overstepping
- ❌ Refactor modules you didn't mention ← Overconfidence
This is because Claude defaults to having read/write access to the entire project. Without explicit boundary instructions, it might "mean well but do harm".
9.2 Three-Layer Scoping Control Method
┌─ Layer 1: Prompt Level ─────────────────────────┐
│ "Only modify src/auth/login.ts, do not touch other files" │
│ → Simplest, suitable for one-time instructions │
├─ Layer 2: Settings Level ──────────────────────── │
│ .claude/settings.json → permissions.deny │
│ → Persistent protection, suitable for team sharing │
├─ Layer 3: CLI Level ───────────────────────────── │
│ --allowedTools "Read" "Edit(src/auth/**)" │
│ → Limited at startup, suitable for scripting │
└──────────────────────────────────────────────────┘
💻 Simulating Claude TUI Interaction
Scenario 1: Unscoped — Claude Oversteps
> Fix the password validation bug during user login
╭─ Claude ─────────────────────────────────────────────╮
│ │
│ 🔍 Tool: Grep ("password" across src/**) │
│ 🔍 Tool: Read (src/auth/login.ts) │
│ 🔍 Tool: Read (src/auth/register.ts) │
│ 🔍 Tool: Read (src/utils/validation.ts) │
│ │
│ Bug found! Missing await during password comparison. │
│ │
│ ⚙️ Tool: Edit → src/auth/login.ts │
│ ╭─ DIFF ─────────────────────────────────────╮ │
│ │ - if (bcrypt.compare(password, user.hash)) │ │
│ │ + if (await bcrypt.compare(password, │ │
│ │ + user.hash)) │ │
│ ╰─────────────────────────────────────────────╯ │
│ ✅ This is the correct fix! │
│ │
│ ⚙️ Tool: Edit → src/utils/validation.ts │
│ ╭─ DIFF ─────────────────────────────────────╮ │
│ │ - // TODO: add password strength check │ │
│ │ + export function checkPasswordStrength( │ │
│ │ + password: string): PasswordStrength { │ │
│ │ + // ... 40 lines of new code ... │ │
│ │ + } │ │
│ ╰─────────────────────────────────────────────╯ │
│ ⚠️ This modification is outside your requested scope!│
│ │
│ ⚙️ Tool: Edit → src/auth/register.ts │
│ ╭─ DIFF ─────────────────────────────────────╮ │
│ │ + import { checkPasswordStrength } │ │
│ │ + from '../utils/validation'; │ │
│ │ + // Check password strength during registration │
│ │ + if (checkPasswordStrength(pw) │ │
│ │ + === 'weak') { ... } │ │
│ ╰─────────────────────────────────────────────╯ │
│ ⚠️ Another file modified! │
│ │
╰──────────────────────────────────────────────────────╯
Scenario 2: Precisely Scoped — Only Target File Modified
> Fix the password validation bug in src/auth/login.ts.
Only modify this one file, do not touch any other files.
╭─ Claude ─────────────────────────────────────────────╮
│ │
│ 🔍 Tool: Read (src/auth/login.ts) │
│ │
│ Problem found: bcrypt.compare on line 34 is missing await. │
│ │
│ ⚙️ Tool: Edit → src/auth/login.ts │
│ ╭─ DIFF ─────────────────────────────────────╮ │
│ │ - if (bcrypt.compare(password, user.hash)) │ │
│ │ + if (await bcrypt.compare(password, │ │
│ │ + user.hash)) │ │
│ ╰─────────────────────────────────────────────╯ │
│ │
│ ✅ Fix complete. Only src/auth/login.ts was modified.│
│ │
│ 💡 I also noticed a TODO in validation.ts │
│ regarding password strength checking. Would you like me to start a new │
│ session to handle it? │
│ │
╰──────────────────────────────────────────────────────╯
💻 Code Demo: CLI Level Precise Control
# Only allow reading and editing the src/auth/ directory
claude --allowedTools "Read" "Glob" "Grep" "Edit(src/auth/**)"
# Forbid executing any bash commands (pure edit mode)
claude --disallowedTools "Bash"
# Limit tools + limit turns (secure execution in CI/CD)
claude -p \
--allowedTools "Read" "Glob" "Grep" \
--max-turns 5 \
"Review the security of the src/payment/ directory"
# Only allow executing specific bash commands
claude --allowedTools \
"Read" "Glob" "Grep" \
"Bash(npm test *)" \
"Bash(npm run lint)"
Settings File Level Protection
// .claude/settings.json — Project level
{
"permissions": {
"deny": [
"Write(.env*)",
"Edit(.env*)",
"Write(prisma/migrations/**)",
"Edit(prisma/migrations/**)",
"Bash(rm -rf *)",
"Bash(DROP *)",
"Bash(sudo *)"
]
}
}
💡 Prompt Scoping Quick Reference
❌ Vague Instructions (Prone to Overstepping):
"Fix login bug"
"Optimize performance"
"Add error handling"
✅ Precise Instructions (Clear Scope):
"Fix missing await for bcrypt.compare on line 34 in src/auth/login.ts"
"Only optimize database query performance in src/api/search.ts, do not modify other files"
"Add try-catch to the createOrder function in src/routes/payment.ts"
🔧 Involved CLI Flags
| Flag | Purpose | Example |
|---|---|---|
--allowedTools |
Whitelist to limit available tools | "Read" "Edit(src/**)" |
--disallowedTools |
Blacklist to disable tools | "Bash" "Write" |
--max-turns |
Limit maximum execution turns | --max-turns 3 |
--add-dir |
Add additional directory access | --add-dir ../shared |
📝 Key Takeaways from this Issue
- Claude defaults to read/write access for the entire project, requiring active scope limitation
- Prompt Level: Directly state "only modify X file" in the instruction
- Settings Level: Use
permissions.denyto protect sensitive files - CLI Level: Use
--allowedToolsfor whitelist restrictions - Core of a good Prompt: Specific filename + Specific action + Clear boundaries