Once you understand the architecture, you need design principles to guide implementation (or evaluation, if you're choosing tools).
Here are five principles that distinguish in-situ AI from chat-first AI:
Principle 1: AI Moves to the Code
Not: Code moves to the AI.
In practice:
- Invoke AI from within the editor, terminal, or test runner
- Never require opening a separate application
- Context comes to the model, not the other way around
Bad example: "Copy this function into ChatGPT and ask why it's slow."
Good example: Select the function, press Cmd+Shift+K, type "why slow?"
Principle 2: Infer Before Asking
Don't ask the developer to provide what the tool can see.
Inferrable context:
- Current language and framework
- File structure and relationships
- Recent errors or test failures
- Git history and diffs
- Environment configuration
Should still ask the developer:
- Intent ("make this faster" vs "make this safer")
- Constraints ("don't break the API")
- Preferences ("use pattern X, not Y")
Example:
Bad prompt requirement:
"I'm working in Python 3.11 with Django 4.2 on a PostgreSQL database.
Here's my model: [paste]. Here's my view: [paste].
Here's the error: [paste].
Why doesn't this work?"
Good prompt requirement:
"why doesn't this work?"
(Tool already knows language, framework, database, has the model file, view file, and error.)
Principle 3: Minimize Mode Switches
Every time you force a switch from building → explaining → building, you pay a tax.
Strategies to minimize:
Inline invocation
- Keyboard shortcut, not menu dive
- Available anywhere: editor, terminal, test output
Structured responses
- Show diffs, not paragraphs of explanation
- If explanation is needed, keep it brief and above the diff
Immediate application
- One click/keystroke to apply
- No copy-paste required
Transient UI
- Panel appears, you use it, it disappears
- Doesn't become "a place you go"
Principle 4: Respect the Cognitive Stack
Remember the four layers from Chapter 2? Good tools maintain them.
Problem Context
- Tool can reference the ticket/issue if linked
- Can surface related documentation
- Preserves the "why are we doing this" even when deep in implementation
Code Context
- Aware of module boundaries
- Understands project-specific patterns
- Can reference other parts of the codebase
Runtime Context
- Integrates with test runners
- Watches logs and errors
- Can connect to debuggers
Social Context
- This one's hard to automate, but:
- Can surface code review comments
- Can highlight recent changes and authors
- Can note deprecated patterns in docs
The more layers the tool understands, the less you have to manually explain.
Principle 5: Make Context Gathering Visible (Optional)
Some developers want to see what context the AI is using. Others don't care.
Good compromise:
- Show a subtle indicator: "using 3 files, last error, current diff"
- Allow expanding to see exactly what was sent
- Allow manually adding/removing context
Why this matters:
- Builds trust ("I can see what it knows")
- Helps debug bad suggestions ("Oh, it didn't see the config file")
- Teaches the developer what context is useful
Evaluating Tools Against These Principles
When assessing an AI coding tool (whether you're building or buying), score it:
| Principle | Score (1-5) | Evidence |
|---|---|---|
| AI moves to the code | ___ | Can I invoke without leaving editor? |
| Infers before asking | ___ | What context does it auto-gather? |
| Minimizes mode switches | ___ | How many alt-tabs per interaction? |
| Respects cognitive stack | ___ | How many layers does it understand? |
| Context visibility | ___ | Can I see what it's using? |
Total: ___ / 25
- 20-25: Excellent in-situ tool
- 15-19: Good tool with some friction
- 10-14: Mediocre, significant context tax
- 5-9: Chat-first tool with minimal context awareness
- 0-4: Actively harmful to flow