Claude Code Issues
Common symptoms:
- Not reading CLAUDE.md
- Ignoring operational workflows
- File access permission errors
- Context window exceeded
This guide helps you diagnose and fix problems with AI coding agents (Claude Code, GitHub Copilot, and Cursor) when used with Cortex TMS. Whether your AI agent is not reading documentation files, generating code that violates patterns, or experiencing context window issues, this page provides systematic solutions.
Claude Code Issues
Common symptoms:
GitHub Copilot Issues
Common symptoms:
Cursor Issues
Common symptoms:
General AI Problems
Common symptoms:
Claude Code generates code that doesn’t follow documented workflows:
Cause 1: CLAUDE.md doesn’t exist or is in wrong location
Cause 2: CLAUDE.md has file permission issues
Cause 3: Claude Code is reading a cached/stale version
Step 1: Check CLAUDE.md exists in project root
ls -la CLAUDE.mdExpected output:
-rw-r--r-- 1 user staff 2048 Jan 15 10:30 CLAUDE.mdIf missing:
# Regenerate with cortex-tmscortex-tms init --force
# Or restore from templatescortex-tms validate --fixStep 2: Verify file encoding
file CLAUDE.mdExpected output:
CLAUDE.md: UTF-8 Unicode textIf wrong encoding:
# Convert to UTF-8iconv -f ISO-8859-1 -t UTF-8 CLAUDE.md -o CLAUDE.md.utf8mv CLAUDE.md.utf8 CLAUDE.mdStep 3: Test with explicit reference
Ask Claude Code:
“Read CLAUDE.md and summarize the operational loop”
Expected: Claude should read and summarize the file.
If Claude can’t read it: File permissions or Claude Code bug.
Check file permissions:
ls -l CLAUDE.mdOutput:
-rw-r--r-- 1 user staff 2048 Jan 15 10:30 CLAUDE.mdPermission breakdown:
rw-: Owner can read/writer--: Group can readr--: Others can readIf permissions are wrong (e.g., -rw-------):
# Make readable by all userschmod 644 CLAUDE.md
# Verifyls -l CLAUDE.md# Output: -rw-r--r-- 1 user staff 2048 Jan 15 10:30 CLAUDE.mdOn shared systems:
# Ensure your user owns the filechown $(whoami) CLAUDE.mdClaude Code may cache file contents. Restart to clear:
Option 1: Exit and restart Claude Code
# Exit Claude Codeexit
# Restartclaude-code .Option 2: Force reload project
In Claude Code, type:
“Reload the project files and re-read CLAUDE.md”
Option 3: Edit CLAUDE.md to trigger refresh
# Add a blank line to CLAUDE.mdecho "" >> CLAUDE.md
# Ask Claude to read it againIf Claude still doesn’t follow CLAUDE.md, be explicit:
Instead of:
“Implement the authentication feature”
Say:
“Read CLAUDE.md to understand the operational loop, then implement authentication following the workflow defined there. Specifically: 1) Create a feature branch, 2) Read NEXT-TASKS.md for requirements, 3) Check docs/core/PATTERNS.md for auth pattern, 4) Implement with TDD, 5) Run validation.”
Or reference specific sections:
“Follow the Git Protocol in CLAUDE.md (Step 0) before making any code changes”
Claude generates code that violates documented conventions:
Cause 1: PATTERNS.md is too large (exceeds Claude’s context)
Cause 2: Patterns are vague (descriptions without examples)
Cause 3: CLAUDE.md doesn’t reference PATTERNS.md
Claude learns better from examples than descriptions.
Before (vague):
## Authentication Pattern
Use RS256 JWT tokens with httpOnly cookies. Tokens expire in 15 minutes.After (concrete example):
## Authentication Pattern
**Canonical Example**: `src/middleware/auth.middleware.ts`
**Always use this exact pattern:**
` ` `typescriptimport { sign, verify } from 'jsonwebtoken';import { readFileSync } from 'fs';
// Load RS256 keysconst privateKey = readFileSync('./keys/private.pem');const publicKey = readFileSync('./keys/public.pem');
// Generate access token (15 min expiry)export function generateAccessToken(userId: string) { return sign( { userId, type: 'access' }, privateKey, { algorithm: 'RS256', expiresIn: '15m' } );}
// Store in httpOnly cookie (NEVER localStorage)export function setAuthCookie(res: Response, token: string) { res.cookie('accessToken', token, { httpOnly: true, // ✅ Prevents XSS secure: true, // ✅ HTTPS only sameSite: 'strict', // ✅ CSRF protection maxAge: 15 * 60 * 1000, // 15 minutes });}
// ❌ NEVER DO THIS// localStorage.setItem('token', token);` ` `
**Key rules:**
- ✅ Use RS256 (asymmetric) for tokens- ✅ Store in httpOnly cookies- ✅ 15-minute expiry for access tokens- ❌ Never use HS256 (symmetric)- ❌ Never use localStorage (XSS vulnerable)Now Claude can copy the exact implementation.
If PATTERNS.md exceeds 500 lines, split by domain:
Before:
docs/core/PATTERNS.md (850 lines - too large)After:
docs/core/PATTERNS.md (200 lines - overview)docs/core/patterns/ ├── authentication.md ├── error-handling.md ├── testing.md ├── database.md └── api-design.mdUpdate CLAUDE.md to reference subdirectories:
## 🛠 Operational Loop
**Step 2: Check Existing Patterns**
- Read `docs/core/PATTERNS.md` for overview- For specific patterns, check: - Authentication: `docs/core/patterns/authentication.md` - Error handling: `docs/core/patterns/error-handling.md` - Testing: `docs/core/patterns/testing.md`In NEXT-TASKS.md, explicitly reference patterns:
Before (vague):
| Status | Task ||--------|------|| 🔵 Todo | Implement authentication |After (explicit):
| Status | Task | Pattern Reference ||--------|------|-------------------|| 🔵 Todo | Implement authentication | Follow `docs/core/PATTERNS.md#authentication` (RS256, httpOnly cookies, 15-min expiry) |Now when Claude reads the task, it knows to check the pattern.
After Claude generates code, ask:
“Does this code follow the authentication pattern from docs/core/PATTERNS.md? Compare your implementation to the canonical example and fix any discrepancies.”
Claude will self-correct if it finds violations.
Claude Code returns errors:
Error: Context window exceeded. Please reduce the amount of context.Or Claude stops mid-response:
I apologize, but I've reached the context limit. Could you please...Claude Code has a context window limit (200k tokens ≈ 150k words). Large codebases or very long files can exceed this limit.
Instead of asking Claude to read all files, use @file to specify exact files:
Instead of:
“Review the entire codebase and implement authentication”
Say:
“@file src/middleware/auth.middleware.ts Implement authentication following the pattern in this file”
This limits context to only the specified file.
Break large tasks into smaller steps:
Instead of:
“Refactor the entire authentication system, add tests, update docs, and deploy”
Say:
Step 1:
“Refactor src/middleware/auth.middleware.ts to use RS256 tokens”
Step 2:
“Add unit tests for the auth middleware”
Step 3:
“Update docs/core/PATTERNS.md with the new auth pattern”
Step 4:
“Run validation and deploy”
If docs exceed context limits, archive or split:
# Check file sizeswc -l NEXT-TASKS.md docs/core/*.md
# Output:# 250 NEXT-TASKS.md (❌ too large)# 850 docs/core/PATTERNS.md (❌ too large)# 420 docs/core/ARCHITECTURE.md (✅ ok)Fix:
# Archive completed taskscortex-tms validate --fix
# Split PATTERNS.mdmkdir docs/core/patterns# Move sections to subdirectoriesCreate executive summaries for large files:
docs/core/PATTERNS-SUMMARY.md:
# Pattern Quick Reference
Full patterns: `docs/core/patterns/*.md`
## Critical Rules
**Authentication**:- RS256 JWT tokens (not HS256)- httpOnly cookies (not localStorage)- 15-min access token expiry- See: `docs/core/patterns/authentication.md`
**Error Handling**:- Use AppError class- Log errors with context- Return user-friendly messages- See: `docs/core/patterns/error-handling.md`
**Testing**:- TDD approach (test first)- 90%+ service coverage- Mock external dependencies- See: `docs/core/patterns/testing.md`Reference the summary in CLAUDE.md:
## 🛠 Operational Loop
**Step 2: Check Existing Patterns**
1. Read `docs/core/PATTERNS-SUMMARY.md` for quick reference2. For detailed implementation, check subdirectoriesCopilot suggestions ignore project conventions:
Cause 1: .github/copilot-instructions.md doesn’t exist
Cause 2: File exceeds 100-line limit (Copilot’s hard limit)
Cause 3: VS Code hasn’t reloaded the file
Step 1: Check file exists
ls -la .github/copilot-instructions.mdIf missing:
# Create directorymkdir -p .github
# Generate with cortex-tmscortex-tms init --force
# Or create manuallycat > .github/copilot-instructions.md <<'EOF'# GitHub Copilot Instructions
See `CLAUDE.md` for full project conventions.
## Critical Rules
- Never commit secrets (API keys, passwords)- Use RS256 JWT tokens (not HS256)- Store tokens in httpOnly cookies (not localStorage)
## Tech Stack
- TypeScript (strict mode)- Express.js- Jest for testing
## Quick Reference
- Patterns: `docs/core/PATTERNS.md`- Tasks: `NEXT-TASKS.md`EOFStep 2: Verify file is under 100 lines
wc -l .github/copilot-instructions.mdExpected:
68 .github/copilot-instructions.mdIf over 100 lines: Copilot will ignore the file.
Copilot has a strict 100-line limit. Trim aggressively:
Before (120 lines - too large):
# GitHub Copilot Instructions
## Authentication Pattern
Always use RS256 JWT tokens with httpOnly cookies.
Example:` ` `typescript// 50 lines of example code` ` `
## Error Handling Pattern
Always use AppError class.
Example:` ` `typescript// 40 lines of example code` ` `After (68 lines - fits limit):
# GitHub Copilot Instructions
See `CLAUDE.md` for full conventions.
## Critical Rules (Security)
**NEVER**:- Store tokens in localStorage → Use httpOnly cookies- Use HS256 for JWT → Use RS256- Commit secrets to Git → Use environment variables
## Tech Stack
- TypeScript (strict), Express.js, Jest
## Patterns
- Auth: `docs/core/patterns/authentication.md` (RS256, 15-min expiry)- Errors: `docs/core/patterns/error-handling.md` (AppError class)- Tests: `docs/core/patterns/testing.md` (TDD, 90%+ coverage)
## Canonical Examples
- Service: `src/services/tasks.service.ts`- Controller: `src/controllers/tasks.controller.ts`- Test: `src/services/tasks.service.test.ts`Key changes:
Copilot caches copilot-instructions.md. Reload window:
Option 1: Command Palette
Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)Option 2: Restart VS Code
# Close VS Code# Reopen projectcode .Option 3: Toggle Copilot
Cmd+Shift+P → "GitHub Copilot: Disable"Cmd+Shift+P → "GitHub Copilot: Enable"Verify Copilot reads the instructions:
Step 1: Open Copilot Chat
Press Cmd+Shift+I (macOS) or Ctrl+Shift+I (Windows/Linux)
Step 2: Ask about instructions
“What are the critical security rules for this project?”
Expected response:
Based on .github/copilot-instructions.md:
- Never store tokens in localStorage (use httpOnly cookies)
- Never use HS256 for JWT (use RS256)
- Never commit secrets to Git (use environment variables)
If Copilot doesn’t mention the file: Instructions aren’t being read.
Copilot suggests code that violates documented security rules:
localStorage.setItem('token', ...) despite instructions forbidding itCause 1: Security rules are buried in the middle of copilot-instructions.md
Cause 2: Rules are stated positively (what TO do) instead of negatively (what NOT to do)
Cause 3: Copilot prioritizes code patterns over documentation
Copilot prioritizes early content. Put critical rules first:
Before:
# GitHub Copilot Instructions
## Tech Stack
TypeScript, Express.js, Jest
## Coding Style
Use camelCase for variables...
## Security Rules
Never commit secrets...After:
# GitHub Copilot Instructions
## Critical Rules (Security)
**NEVER**:- Store tokens in localStorage → Use httpOnly cookies- Use HS256 for JWT → Use RS256- Commit secrets (API keys, passwords) → Use .env
## Tech Stack
TypeScript, Express.js, Jest
## Coding Style
Use camelCase for variables...Show what NOT to do explicitly:
## Authentication (Critical)
✅ **Good**: RS256 JWT in httpOnly cookies` ` `typescriptres.cookie('token', jwt.sign({...}, privateKey, { algorithm: 'RS256' }), { httpOnly: true, secure: true, sameSite: 'strict'});` ` `
❌ **Bad**: HS256 in localStorage` ` `typescript// NEVER DO THISlocalStorage.setItem('token', jwt.sign({...}, secret, { algorithm: 'HS256' }));` ` `Copilot learns from negative examples.
Enforce rules at the linter level:
Install eslint-plugin-no-secrets:
npm install --save-dev eslint-plugin-no-secrets.eslintrc.json:
{ "plugins": ["no-secrets"], "rules": { "no-secrets/no-secrets": "error", "no-restricted-syntax": [ "error", { "selector": "CallExpression[callee.object.name='localStorage'][callee.property.name='setItem']", "message": "Never use localStorage for tokens. Use httpOnly cookies instead." }, { "selector": "Literal[value='HS256']", "message": "Never use HS256 for JWT. Use RS256 (asymmetric) instead." } ] }}Now Copilot suggestions trigger linting errors if they violate rules.
Always review Copilot suggestions before accepting:
Red flags:
localStorage.setItem('token', ...) → Rejectalgorithm: 'HS256' → RejectGood signs:
res.cookie('token', ..., { httpOnly: true }) → Acceptalgorithm: 'RS256' → Acceptprocess.env.API_KEY → AcceptCopilot inline suggestions don’t match project conventions:
Copilot inline suggestions use a smaller context window than chat. They prioritize:
Before coding, open canonical example files:
Step 1: Open reference files
# Open canonical servicecode src/services/tasks.service.ts
# Open canonical controllercode src/controllers/tasks.controller.ts
# Open canonical testcode src/services/tasks.service.test.tsStep 2: Start coding in new file
Copilot now has examples in context and will suggest matching patterns.
Example:
// In src/services/users.service.ts// Type: export class UserService
// Copilot suggests (matching tasks.service.ts pattern):export class UserService { constructor(private db: Database) {}
async getById(id: string): Promise<User> { const user = await this.db.query.users.findFirst({ where: eq(users.id, id) });
if (!user) { throw new AppError('User not found', 404); }
return user; }}Copilot matched the structure from tasks.service.ts.
Guide Copilot with comments:
// Follow the pattern from tasks.service.ts// Use Drizzle query builder (not raw SQL)// Throw AppError for not found (404)export class UserService { // Copilot now suggests code matching the hints}For complex patterns, use Copilot Chat to generate boilerplate:
In Copilot Chat:
“Create a new UserService class following the same pattern as src/services/tasks.service.ts. Include: constructor with db injection, getById method that throws AppError on not found, and createUser method.”
Copilot generates code matching the reference file.
Cursor doesn’t reference custom rules:
Cause 1: .cursorrules file doesn’t exist
Cause 2: .cursorrules is a broken symlink (Windows)
Cause 3: Cursor settings disabled custom rules
Option 1: Copy from CLAUDE.md
cp CLAUDE.md .cursorrulesgit add .cursorrulesOption 2: Create symlink (macOS/Linux)
ln -s CLAUDE.md .cursorrulesgit add .cursorrulesOption 3: Create custom file
cat > .cursorrules <<'EOF'# Cursor Rules
See `CLAUDE.md` for full conventions.
## Tech Stack
- TypeScript (strict mode)- Express.js- PostgreSQL + Drizzle ORM- Jest + Playwright
## Critical Rules
- Never commit secrets- Use RS256 JWT (not HS256)- Store tokens in httpOnly cookies (not localStorage)
## Cursor Workflows
**Multi-File Edits**: Use Cmd+K for single-file, Chat for multi-file
**Pattern Application**: Reference canonical files:- Service: `src/services/tasks.service.ts`- Controller: `src/controllers/tasks.controller.ts`
## Quick Commands
- Test: `npm test`- Lint: `npm run lint`- Dev: `npm run dev`EOFWindows symlinks require Developer Mode or Admin privileges.
Option A: Enable Developer Mode
New-Item -ItemType SymbolicLink -Path .cursorrules -Target CLAUDE.mdOption B: Use Git symlink
# In Git Bash:ln -s CLAUDE.md .cursorrules
# Enable symlinks in Gitgit config core.symlinks true
# Commitgit add .cursorrulesgit commit -m "chore: add .cursorrules symlink"Option C: Copy instead (simpler)
Copy-Item CLAUDE.md .cursorrules⚠️ Remember to update both files when editing.
Step 1: Open Cursor Settings
Cmd+, (macOS) or Ctrl+, (Windows/Linux)
Step 2: Search “cursorrules”
Step 3: Verify settings:
.cursorrulesStep 4: Reload Cursor
Cmd+Shift+P → “Reload Window”
Step 1: Open Cursor Chat
Press Cmd+L (macOS) or Ctrl+L (Windows/Linux)
Step 2: Ask about rules
“What are the coding conventions for this project?”
Expected response:
Based on .cursorrules and CLAUDE.md:
- TypeScript in strict mode
- RS256 JWT tokens (not HS256)
- httpOnly cookies for token storage
- Follow patterns in docs/core/PATTERNS.md
If Cursor doesn’t mention .cursorrules: File isn’t being read.
Cursor Composer applies multi-file changes that violate patterns:
Cursor Composer uses a broad context but may miss specific pattern files if not referenced explicitly.
When using Composer, reference pattern files:
Instead of:
“Refactor all services to use dependency injection”
Say:
“Refactor all services to use dependency injection following the pattern in src/services/tasks.service.ts. Inject database via constructor, use Drizzle query builder, throw AppError for errors.”
This ensures Composer reads the canonical example.
Reference the entire codebase:
“@Codebase Refactor all services to use dependency injection, following the pattern already used in the codebase”
Cursor scans all files and identifies the pattern.
Composer shows diffs before applying. Review each file:
Check for:
Reject changes that violate patterns.
Instead of refactoring all files at once, do one file at a time:
Step 1:
“Refactor src/services/users.service.ts to use dependency injection”
Step 2: Review and accept
Step 3:
“Apply the same refactoring to src/services/projects.service.ts”
Step 4: Review and accept
This gives you control over each change.
All AI agents (Claude Code, Copilot, Cursor) generate code that violates documented patterns:
Cause 1: PATTERNS.md is too abstract (no concrete examples)
Cause 2: Patterns conflict with existing code
Cause 3: Patterns not enforced by linting
Before (abstract):
## Error Handling
Use a custom error class with HTTP status codes.After (concrete):
## Error Handling
**Canonical Example**: `src/errors/AppError.ts`
**Always use this exact pattern:**
` ` `typescript// src/errors/AppError.tsexport class AppError extends Error { constructor( message: string, public statusCode: number = 500, public isOperational: boolean = true ) { super(message); this.name = 'AppError'; Error.captureStackTrace(this, this.constructor); }}
// Usage in services:export class UserService { async getById(id: string): Promise<User> { const user = await this.db.query.users.findFirst({ where: eq(users.id, id) });
if (!user) { // ✅ Throw AppError with 404 status throw new AppError('User not found', 404); }
return user; }}` ` `
**❌ Never do this:**
` ` `typescript// Bad: Generic Error without status codethrow new Error('User not found');
// Bad: Returning null instead of throwingreturn null;` ` `AI agents can now copy the exact implementation.
If AI generates inconsistent code, audit existing codebase:
Step 1: Search for pattern violations
# Find files NOT using AppErrorgrep -r "throw new Error" src/ | grep -v "AppError"
# Find localStorage usagegrep -r "localStorage" src/
# Find HS256 usagegrep -r "HS256" src/Step 2: Fix violations
# Refactor old code to match PATTERNS.md# Update or remove files that don't follow conventionsStep 3: Update PATTERNS.md if needed
If existing code uses a different (better) pattern, update PATTERNS.md to match reality.
Add ESLint rules to enforce patterns:
.eslintrc.json:
{ "rules": { "no-restricted-syntax": [ "error", { "selector": "NewExpression[callee.name='Error']", "message": "Use AppError instead of generic Error class" }, { "selector": "CallExpression[callee.object.name='localStorage']", "message": "Never use localStorage for tokens. Use httpOnly cookies." } ] }}Now AI-generated code that violates patterns fails linting.
AI agents reference old code that no longer exists:
AI agents cache file contents and may not pick up recent changes.
Claude Code:
# Exit and restartexitclaude-code .GitHub Copilot:
Cmd+Shift+P → "Reload Window"Cursor:
Cmd+Shift+P → "Reload Window"Tell AI to re-read specific files:
“Re-read src/services/users.service.ts and then implement the new feature”
This forces AI to fetch the latest content.
Claude Code:
# Clear Claude's cache (if supported)rm -rf ~/.claude-code/cache/Copilot:
Cmd+Shift+P → "GitHub Copilot: Clear Cache"Cursor:
Cmd+Shift+P → "Cursor: Clear Cache"AI agents fail with token limit errors:
Large files, long conversations, or many files in context exceed AI token limits.
# Check file sizeswc -l **/*.md
# Archive large filescortex-tms validate --fixLong chat histories consume tokens. Start fresh:
Claude Code: Exit and restart
Copilot Chat: Clear chat history
Cursor Chat: Start new chat session
Instead of including full files:
“Summarize docs/core/PATTERNS.md in 5 bullet points, then implement authentication using those patterns”
1. Keep Documentation Concise
2. Use Canonical Examples
Show concrete code examples, not abstract descriptions. AI learns by copying.
3. Security Rules First
Put critical security rules at the top of instruction files. AI prioritizes early content.
4. Reference Files Explicitly
In NEXT-TASKS.md, reference specific pattern files. Don’t make AI search.
5. Validate AI Output
Always review AI-generated code. Run tests and linting before committing.
6. Update Docs When AI Fails
When AI violates a pattern, update documentation to be more explicit.
After setting up Cortex TMS, test each AI agent:
Claude Code:
“Read NEXT-TASKS.md and CLAUDE.md, then summarize the current sprint goal and operational workflow”
GitHub Copilot:
Open a new .ts file and type:
// Create a new service class following our patternVerify Copilot suggests code matching your patterns.
Cursor:
In Cursor Chat:
“@Codebase What’s our authentication pattern?”
Verify Cursor references docs/core/PATTERNS.md.
When AI makes mistakes, improve docs:
AI mistake: Uses localStorage for tokens
Fix: Add to copilot-instructions.md:
## Critical Rules
**NEVER store tokens in localStorage** → Use httpOnly cookies
❌ Bad:` ` `typescriptlocalStorage.setItem('token', token);` ` `
✅ Good:` ` `typescriptres.cookie('token', token, { httpOnly: true });` ` `AI alignment is iterative:
After 3-5 iterations, AI will consistently follow your patterns.
Now that you understand AI agent troubleshooting:
cortex-tms validate failures