Chat-Based Coding: Asking the Right Questions
Chat-Based Coding: Asking the Right Questions
While code completion works through implicit signals (comments, variable names, cursor position), chat-based coding is explicit and conversational. You describe what you want, the AI generates it, and you iterate until it’s right.
Chat-based coding excels at problems that are too complex for completion alone: implementing algorithms, refactoring large sections, explaining errors, and building features that span multiple files.
Chat vs. Completion: When to Use Each
Before diving into technique, understand when to use chat:
| Scenario | Use Completion | Use Chat |
|---|---|---|
| Writing boilerplate (variable initialization) | ✓ | |
| Implementing a known algorithm | ✓ | |
| Adding one function to existing pattern | ✓ | |
| Debugging an error | ✓ | |
| Refactoring across files | ✓ | |
| Writing test cases | ✓ | |
| Explaining how code works | ✓ | |
| One-line fixes | ✓ | |
| Architecture decisions | ✓ | |
| Naming variables | ✓ |
The difference: completion works best when the AI can infer intent from context. Chat works best when you explicitly explain intent.
The Chat Interface Basics
Different tools present chat differently:
Copilot Chat (GitHub Copilot X):
- Opens in VS Code sidebar
- Can reference open files with
#file - Can reference symbols with
# - Shows suggestions in your editor
Cursor Chat:
- Opens with
Cmd+K - Full codebase understanding
- Can make edits directly from chat
- Shows diffs for proposed changes
Claude Code (Web):
- Chat interface at claude.ai
- Can upload files/folders
- Shows code in formatted blocks
- Makes edits in a separate view
Cody (Sourcegraph):
- VS Code sidebar
- References your actual codebase
- Can search and cite specific functions
- Good for asking about existing code
Despite interface differences, the technique is similar: ask clearly and provide context.
Providing Effective Context
The biggest mistake beginners make is asking vague questions without context.
Bad vs. Good Chat Requests
Bad Request:
User: "How do I validate emails?"
AI: Generic answer about regex, no knowledge of your code
Result: Boilerplate code you'll need to adapt
Good Request:
User: "I'm building a user registration system in FastAPI.
I have a User model with email field. I need to validate
email addresses with custom rules:
- Must be company domain
- Must not be a +alias (no+alias@company.com invalid)
Where in my code should this go?"
AI: Understands your tech stack and constraints
Result: Specific solution integrated with your existing code
Context Layers
Provide context in this order:
Layer 1: Your Goal
"I need to implement pagination for API results"
Layer 2: Your Tech Stack
"...using Django REST Framework and PostgreSQL"
Layer 3: Your Constraints
"...where results must be sorted by creation date
and we're returning 50 items per page"
Layer 4: Your Code Context
"Here's my current serializer... [paste code]"
Layer 5: What You’ve Tried
"I tried using DRF's PageNumberPagination but it's not respecting
the sort order I set in the queryset"
Each layer makes the response more tailored.
Effective Chat Patterns
Pattern 1: The Specification Chat
Use chat to work through specifications before coding:
You: "I need to build an image upload feature. The requirements are:
- Users upload JPG/PNG, max 5MB
- Resize to three sizes: thumbnail, medium, large
- Store on S3 with signed URLs
- Track upload metadata in database
What's the best architecture?"
AI: [Explains approach, potential issues, suggestions]
You: "Good, but what about validating file types? Could someone
upload an executable with .jpg extension?"
AI: [Explains validation strategies]
This conversation clarifies requirements before you write code, saving rework.
Pattern 2: The Explanation Chat
Use chat to understand unfamiliar code:
You: "I'm looking at this middleware, what does it do?"
[paste code]
AI: [Explains purpose, how it works, integration points]
You: "How would I extend it to add logging?"
AI: [Specific code for your use case]
Explaining code is often faster than reading it yourself.
Pattern 3: The Error Debugging Chat
When you hit an error, chat is more effective than completion:
You: "I'm getting this error:
[paste full stack trace]
I'm trying to authenticate users with JWT.
Here's my auth middleware:
[paste code]
What's wrong?"
AI: [Identifies issue, explains why, provides fix]
Stack traces alone are often ambiguous. Code context clarifies the issue.
Pattern 4: The Refactoring Chat
For large changes, chat is essential:
You: "I have this large function that does too much.
[paste code]
Can you help me break this into smaller functions?"
AI: [Suggests decomposition]
You: "That's good, but how do I handle the error case
that spans multiple extracted functions?"
AI: [Refines the approach]
This iterative refinement is chat’s strength.
Pattern 5: The Learning Chat
Use chat to deepen understanding:
You: "Explain how middleware works in Express.js"
AI: [Comprehensive explanation]
You: "So if I have three middleware functions, are they
always called in order?"
AI: [Clarifies with examples]
You: "What if one throws an error?"
AI: [Explains error handling flow]
You’re building mental models, not just getting code.
Inline Chat: The Middle Ground
Many tools (Cursor, Copilot, VS Code) offer “inline chat” — chat that appears right in your editor at your cursor.
When inline chat is useful:
- You’re sitting in one file and need quick context
- You want to reference selected code directly
- You need a fast question-answer without context switching
When to avoid inline chat:
- The problem spans multiple files
- You need to see diffs or edits clearly
- You’re doing exploratory/learning work
Using Inline Chat Effectively
In Cursor (Cmd+I) or VS Code:
-
Select the relevant code before opening inline chat
-
Ask a specific question about that selection:
Selected: function processUserData(user) { ... } Ask: "What would this function do if user is null? How should I handle that case?" -
Review the suggestion carefully before accepting
Inline chat is fast but easy to misuse. Only use when the scope is small and clear.
File References: Giving Context
Different tools provide ways to reference other files:
Copilot (with #file syntax):
"My API endpoint returns a user object.
#user.ts defines the interface.
#api.ts has the endpoint handler.
How do I validate the returned data matches the interface?"
Cursor (with @ symbol):
"@database.ts shows my connection setup.
How would I add a migration for a new table?"
Claude Code (with file upload):
[Upload your entire project folder]
"Walk me through the authentication flow in this codebase"
Using file references makes the AI aware of your actual structure, not generic assumptions.
The Iteration Loop
Chat coding is iterative. Rarely does the first response be exactly right.
The Iteration Process
Step 1: Initial Request
"I need a function that sorts an array of objects by date"
AI: [Provides a generic sort function]
Step 2: Refine
"This looks good, but the dates are in 'dateString' format
(2024-03-15), not Date objects. Does this still work?"
AI: [Adjusts for string dates]
Step 3: Adapt
"I also need to handle invalid dates gracefully, moving them
to the end. Can you update it?"
AI: [Adds error handling]
Step 4: Integrate
"Here's my existing code that uses this. Can you show me how
to integrate your function?"
AI: [Shows integration with your codebase]
Each iteration gets closer to exactly what you need.
When to Share Code in Chat
What to Paste
Always paste:
- Code you’re trying to modify
- Error messages and stack traces
- Function signatures that the AI needs to work with
- Config files relevant to the problem
Never paste:
- Secrets, API keys, credentials
- Entire files when only a snippet is relevant
- Code unrelated to the problem (keep context focused)
- Binary files or large media
How Much Context to Paste
Too little:
"How do I connect to a database?"
[Too vague, generic answer]
Just right:
"I'm using Python with SQLAlchemy.
I have models defined here [relevant part],
and I'm trying to query users like this [code snippet].
What's the issue?"
Too much:
[Pastes entire 10,000-line codebase]
"Help me understand this"
[Can't effectively analyze]
Paste enough context for the AI to understand your specific situation, but not so much that it’s overwhelming.
Managing Chat Conversations
Chat interfaces keep conversation history. Use this effectively:
Conversation Continuity:
- The AI remembers previous messages in the conversation
- It understands context from earlier exchanges
- You can ask “Refine that” or “Show me another approach”
When to Start New Conversations:
- Switching to a completely different task
- You’ve gone 20+ exchanges deep
- The conversation got off track
- You want to reset context
Bookmarking Solutions:
- Copy good solutions to a file or notes
- Chat history might be deleted or hard to find later
- You might need the exact code again
Chat for Different Languages
The AI can code in any language. Specify clearly:
"I need a function in Go that:
[clear requirements]"
AI: [Provides Go solution]
If the AI generates code in the wrong language:
"Sorry, I need this in Python, not JavaScript"
AI: [Immediately translates]
Language doesn’t matter, but being clear matters.
Real-World Chat Example
Here’s a complete chat session showing good technique:
You: "I'm building an analytics dashboard. I need to fetch
daily active user counts for the last 30 days from my
database. I'm using Node.js with Postgres and Sequelize.
What's the best query?"
AI: [Explains approach, provides Sequelize code]
You: "Good. How do I make sure this handles timezone
differences correctly? Users in different timezones
should all count as the same 'day'."
AI: [Adjusts query with timezone handling]
You: "Perfect. One more thing - can I cache this for
5 minutes since it's expensive to recalculate?"
AI: [Shows caching pattern with Redis or in-memory cache]
You: [Pastes response handling code]
"Where should I add the cache lookup?"
AI: [Shows exact integration point]
You: "Exactly what I needed. How would I test this?"
AI: [Provides test cases]
This conversation solved a real problem from initial approach through testing, with refinement at each step.
Exercises
-
Specification Chat: Pick a feature you’re building or want to build. Use chat to work through the full specification before writing code. Document:
- Initial idea
- Questions you asked for clarification
- Final decisions made
- How this compares to diving straight into coding
-
Error Debugging: Next time you hit a confusing error, use chat:
- Paste the full stack trace
- Paste relevant code
- Ask what’s wrong Compare this to debugging alone. Was chat faster? More accurate?
-
Refactoring Session: Find a function or file you think could be cleaner. Use chat to:
- Get refactoring suggestions
- Iterate on proposed solutions
- Generate updated code Accept or reject each suggestion with reasoning.
-
Learning Deep Dive: Pick a technology or pattern you don’t fully understand. Use iterative chat to:
- Get an explanation
- Ask clarifying questions
- Request examples
- Explore edge cases Document what you learned.
-
Codebase Walkthrough: Share code from a project with chat. Ask:
- “What does this component do?”
- “How would I extend it for [new requirement]?”
- “What are potential issues here?” Verify the AI’s answers match your intent.