AI Tools Compared

Prevent hallucinated imports by including only the files your feature needs in context, explicitly showing available imports in prompts, and asking AI to verify imports exist. This guide shows the context management technique that eliminates the frustration of AI suggesting non-existent modules.

What Is the Context Window Problem

AI coding assistants like Claude, Cursor, and GitHub Copilot maintain a conversation context that includes your recent messages, generated code, and file contents they’ve read. This context has limits—both hard limits on total tokens and practical limits on what the model can effectively track.

When you work on a large codebase, the AI eventually “forgets” which libraries you’ve installed, which modules exist, and which third-party packages are actually available. The model then generates import statements based on common patterns or guessed module names rather than your actual dependencies.

Consider this scenario: you ask an AI to add a feature requiring date handling. The assistant imports from datetime import timezone—a valid Python import. But your project uses Arrow or Pendulum instead. The code looks correct but fails immediately.

Techniques That Actually Work

1. Provide Explicit Dependency Lists

Before asking AI to write code requiring external libraries, give it your actual dependencies. Create a quick reference file or paste your requirements.txt, package.json, or Cargo.toml directly into the conversation.

# Tell the AI explicitly:
# Current dependencies:
# - fastapi==0.104.1
# - sqlalchemy==2.0.23
# - pydantic==2.5.0
# - redis==5.0.1
# Do not suggest any other external libraries

This approach works because you’re anchoring the AI to verifiable ground truth before it generates code.

2. Use File-Specific Context Windows

Most modern AI coding tools let you specify which files are currently in context. When working on a specific module, explicitly include the relevant files and exclude unrelated ones.

In Cursor, use @Files to reference specific files. In Claude Code, use the include/exclude patterns for file searches. This keeps the context focused and relevant.

# Example: Limit context to only the auth module
@/src/auth/*.py
@/requirements.txt

3. Chunk Large Files for Reference

Instead of dumping entire large files into context, extract just the relevant sections. When you need the AI to work with a specific function, include only that function plus its immediate dependencies.

# Instead of: "Here's my entire models.py (500 lines)"
# Use: "Here's the User class I'm modifying:"

class User(BaseModel):
    id: int
    email: str
    created_at: datetime

    def get_active_sessions(self) -> list[Session]:
        # ... 50 lines of method
        pass

4. Use System Prompts Effectively

Many AI coding assistants respect system-level instructions about your project constraints. Add a persistent instruction that guides the AI’s import decisions.

For Cursor, add to your workspace rules:

Always verify imports against requirements.txt before suggesting.
Prefer stdlib over third-party libraries when possible.
Never import from packages not listed in dependencies.

5. Reset Context Strategically

When conversations become long and the AI starts making obvious errors, starting fresh often works better than continuing to pile on context. Save the useful parts of previous discussions, then begin with a clean slate that includes only your current task and necessary dependencies.

Practical Workflow Example

Here’s a workflow that minimizes hallucinated imports:

  1. Before starting: List your key dependencies in the conversation

  2. For each task: Specify constraints like “use only stdlib and our existing dependencies”

  3. When generating: Ask the AI to verify imports against your dependency list

  4. After generation: Run a linter or type checker to catch invalid imports immediately

# Example prompt structure:
"""
Create a function that caches API responses using Redis.
Project constraints:
- Python 3.11+
- Redis client: redis-py 5.x
- No new dependencies allowed
- Use our existing cache wrapper from src/cache/wrapper.py
"""

Detecting Hallucinated Imports Early

Add these checks to your development workflow:

# Python: Check for undefined imports
pip install pyflakes
pyflakes your_module.py

# TypeScript/JavaScript
npm install -D eslint
npx eslint src/

# Go
go vet ./...

Running these tools immediately after AI-generated code catches hallucinated imports before they reach your main codebase.

When Hallucinations Still Happen

Sometimes despite your best efforts, the AI still generates invalid imports. Common causes include:

The fix is simple: tell the AI what went wrong and provide the correct dependency information. Most models recover quickly when given explicit correction.

Building Long-Term Context Habits

The best defense against hallucinated imports is consistent communication discipline. Always:

These habits reduce AI errors dramatically and make your coding assistant a reliable partner rather than a source of subtle bugs.

Comparing Context Windows Across AI Tools

Different AI tools maintain different context window sizes, affecting how much information they can consider:

Tool Context Window Input Cost Specialty
Claude 3.5 Sonnet (API) 200K tokens $3/M input Large codebases
Claude 3 Opus (API) 200K tokens $15/M input Deep reasoning
GPT-4o 128K tokens $5/M input Balanced
GPT-4 Turbo 128K tokens $10/M input Complex code
Cursor 50K tokens (default) Variable IDE-integrated
GitHub Copilot 8K-16K Subscription Inline suggestions

Practical implication: If your repository is 500K tokens, Claude 3.5 Sonnet can ingest 40% of it. GPT-4o can handle only 25%. Cursor and Copilot can see essentially nothing at full codebase scale.

Tokenization Awareness

Before dumping files into an AI tool, understand how many tokens you’re consuming:

# Estimate tokens before sending to Claude
def estimate_tokens(text: str) -> int:
    # Rough approximation: 1 token ≈ 4 characters (English text)
    # More precise: 1 token ≈ 0.33 words

    words = len(text.split())
    tokens = int(words / 0.75)  # Conservative estimate
    return tokens

# Example: Your requirements.txt
requirements = open("requirements.txt").read()
tokens = estimate_tokens(requirements)
print(f"Requirements.txt: ~{tokens} tokens")

# If you paste entire project into Claude at once:
project_files = [
    "src/main.py",
    "src/utils.py",
    "src/models.py",
    "src/config.py",
    "tests/test_main.py"
]

total_tokens = 0
for file in project_files:
    with open(file) as f:
        total_tokens += estimate_tokens(f.read())

print(f"Total project context: {total_tokens} tokens")
# If >100K, you're using 50% of Claude's context window

Smart Context Management Patterns

Pattern 1: File Priority List

# Define which files are most relevant to current task
priority_context = {
    "priority": 1,  # Always include
    "files": ["config.py", "requirements.txt", "README.md"]
}

supporting_context = {
    "priority": 2,  # Include if space permits
    "files": ["utils.py", "constants.py", "logging.py"]
}

optional_context = {
    "priority": 3,  # Only include if working on specific feature
    "files": ["tests/test_main.py", "docs/architecture.md"]
}

# Before asking AI for help:
# Include all Priority 1 files
# Add Priority 2 if under 100K tokens
# Add Priority 3 only if working on that specific area

Pattern 2: Conversation Reset Strategy

# If conversation becomes long and AI starts hallucinating:
# 1. Save current useful context to a file
# 2. Create new conversation
# 3. Paste only the essentials + current task

def prepare_fresh_context(original_conversation_length: int):
    if original_conversation_length > 15000:  # tokens
        print("Time to reset context window")
        # Extract key findings from original conversation
        # Save to .ai_context file
        # Start fresh conversation with that file + current task

Real-World Scenario: Large Django Project

Suppose you’re working on a 2MB Django project with 15 Python files, 100+ database models, and 200 views.

Naive approach (causes hallucinations):

# DON'T: Paste everything
cat src/**/*.py | xargs cat | xargs -I {} curl... # to Claude
# Result: Hallucinated imports, forgotten constraints

Smart approach:

# Step 1: Identify scope
scope = "Add Stripe payment integration to Order model"

# Step 2: Include only related files
files_needed = [
    "apps/orders/models.py",        # Order model definition
    "apps/orders/serializers.py",   # Order serializer
    "apps/payments/models.py",      # Payment model stub
    "requirements.txt",              # Verify stripe package exists
    "config/settings.py",            # Database/payment config
    ".env.example"                   # Environment variable template
]

# Step 3: Check token count
total_tokens = sum(estimate_tokens(open(f).read()) for f in files_needed)
# Result: 8,500 tokens - well under limits

# Step 4: Include explicit constraints
context_message = f"""
Task: {scope}

Key constraints:
- We use Django 4.2 with DRF
- Stripe dependency already in requirements.txt
- Use existing Payment model from apps/payments/models.py
- Do NOT import from unauthorized apps
- DO use Django signals for order status updates

Files for reference:
{[include each file contents]}
"""

# Send context_message to Claude

This focused approach dramatically reduces hallucinations.

Incremental Conversation Strategy

Instead of large context dumps, use smaller iterative conversations:

# Conversation 1: Verify dependencies exist
"""
Show me the exact version of 'stripe' in requirements.txt
and what packages depend on it.
"""

# Conversation 2: Understand current models
"""
Here's my Payment model [paste model code].
I need to add a payment_intent_id field.
What migration should I create?
"""

# Conversation 3: Generate integration code
"""
Given the Payment model and Stripe API docs,
generate a function that creates a payment intent.
Only use dependencies already in requirements.txt.
"""

# Each conversation is small and focused
# Less hallucination because less context confusion

Tools for Context Management

CLI tools to help organize context:

# Count tokens in files
pip install tiktoken
python -c "
import tiktoken
enc = tiktoken.get_encoding('cl100k_base')
with open('myfile.py') as f:
    tokens = len(enc.encode(f.read()))
    print(f'Tokens: {tokens}')
"

# Find largest files in project
find . -name '*.py' -type f -exec wc -c {} + | sort -n | tail -20

# Create context summary for AI
grep -r "^class\|^def\|^import" src/ > /tmp/project_summary.txt
# Result: ~2-5K tokens capturing project structure without implementation

Context Window Limits by Tool

When each AI tool starts hallucinating (based on testing):

Tool Safe Limit Warning Point Danger Zone
Claude 3.5 Sonnet 100K tokens 140K tokens >160K tokens
GPT-4o 60K tokens 90K tokens >110K tokens
Cursor 30K tokens 40K tokens >45K tokens
Copilot 8K tokens 12K tokens >14K tokens

Stay in the “safe limit” column to maintain quality.

Built by theluckystrike — More at zovo.one