When a developer types a function signature or a comment describing intent, an attached model can return a suggestion—often a complete implementation, sometimes just a nudge. This is AI pair programming. It matters when you’re working in a familiar language and want to avoid boilerilerplate, when you’re exploring an unfamiliar API and need examples without leaving the editor, or when you’re performing repetitive refactors across many files. It does not matter when you need deterministic output, when correctness guarantees are required, or when your environment cannot transmit code to external services. The following guide is organized by what you’re trying to accomplish, with concrete commands, configuration patterns, and the sharp edges you’ll encounter.

Generating code suggestions

Most IDEs bind a single key to accept a suggestion and another to dismiss it. In VS Code with the GitHub Copilot extension, press Tab to accept the current suggestion and Cmd+E (macOS) or Ctrl+E (Linux/Windows) to cycle to the next one. In the Neovim plugin, the default is <C-x><C-o> for completion and <C-g> to dismiss. Tabnine uses Tab by default as well, but can be configured to require an explicit Cmd+Shift+Enter acceptance.

Suggestions are generated from the current file contents plus any explicitly referenced context. To reference a specific function or class, place your cursor on it and use the @ syntax in your prompt. For example, typing /doc @myClass will ask the model to generate documentation for myClass using its actual source. If you want to limit the context to the current function only, many extensions offer a “function-only” mode that strips imports and out-of-scope definitions before sending the prompt.

# Cursor on the function below; press Tab to accept suggestion.

def calculate_discount(price, customer_type):
    """Apply tiered discount based on customer type."""
    # AI suggests:
    if customer_type == "premium":
        return price * 0.15
    elif customer_type == "student":
        return price * 0.10
    else:
        return price * 0.05

The model does not “see” your screen. It receives a text snapshot: the file being edited, the language mode, and any @ references you’ve included. What it returns is a probabilistic completion, not a compiled artifact. If the suggestion looks wrong, you can reject it and the extension will typically remember the rejection to bias future suggestions away from that pattern.

Managing context and prompts

Effective pair programming depends on what the model knows about your codebase. Most tools let you attach files or symbols explicitly. In Copilot, the @workspace reference sends a summary of your project structure; you can also drag individual files into the chat pane. Continue.dev, an open-source alternative, uses a continue.conf.yaml file in the project root to define persistent context. A minimal config looks like this:

# continue.conf.yaml
models:
  - provider: openai
    model: gpt-4o-mini
context:
  files:
    - "*.py"
    - "README.md"
  ignore:
    - "*.db"
    - ".git/"

When the config exists, Continue will automatically include matching files in every prompt. The ignore list prevents sensitive or binary files from being transmitted. If you omit the config, the tool defaults to the open files in your editor plus the language’s standard library documentation.

Prompt format matters. A common pattern is to start with a clear intent line, followed by constraints, followed by examples:

Implement a function that validates email addresses. 
Constraints: no external libraries, return True/False, handle international TLDs.
Example: "[email protected]" → True, "invalid" → False

This structure consistently produces more predictable output across different models.

Debugging and error resolution

AI pair programming can interpret error messages and suggest fixes, but the quality varies. When a Python traceback includes a NameError, the model often identifies the missing import or incorrect variable scope. When a JavaScript error reads Cannot read properties of undefined, the model may suggest a null check or optional chaining operator. In practice, the model’s suggestions should be verified against the actual runtime behavior.

Consider this real interaction pattern:

  1. Copy the full error message.
  2. Paste it into the AI chat, prefixed with Error: .
  3. Add a brief description of what you’re trying to achieve.
  4. Review the suggested fix, run the test, and iterate.

A typical failure mode is the model hallucinating a function that doesn’t exist in your version of a library. If you’re on requests==2.31.0 and the model suggests response.json(indent=2), that method doesn’t exist—json() returns a dict, it doesn’t accept formatting arguments. The sharp edge here is confidence: the model’s phrasing can sound authoritative while being semantically wrong. Always run the suggested change in a throwaway script before applying it to production code.

Another common issue: the model suggests a fix that works in a different language version. A for...of loop suggestion in a for...in codebase, or a type-hinted function in an untyped project. These mismatches are easiest to catch when you read the suggestion aloud—if it doesn’t match your codebase’s conventions, it’s likely a mismatch, not a bug in the model.

Customizing behavior

Every tool offers some way to influence what the model pays attention to. In Copilot, you can adjust the “aggressiveness” of suggestions via the IDE settings—higher aggression means more suggestions, lower means fewer but more conservative ones. Tabnine offers a “completion score” threshold; set it too low and you’ll get noise, set it too high and you’ll rarely see suggestions.

Many extensions let you override the system prompt. In Continue.dev, the systemPrompt field in continue.conf.yaml lets you write a few sentences that apply to every request. A practical example:

systemPrompt: |
  You are a senior engineer working in a Python codebase.
  Follow PEP 8, use type hints where appropriate,
  and never suggest deprecated APIs from the standard library.

When a system prompt is set, it’s prepended to every user prompt, shaping the model’s posture without requiring you to repeat constraints each time. If you switch projects, remember to update or remove the system prompt—carrying a generic “senior engineer” prompt into a Rust or Go project can produce style mismatches.

Some tools also let you set a “temperature” or creativity parameter. Lower values (e.g., 0.2) produce more deterministic, repetitive output—useful for boilerplate. Higher values (e.g., 0.8) increase variety at the cost of consistency. Not all products expose this; Copilot’s UI does not provide a slider, but the underlying model temperature is fixed at a conservative value. Tabnine and Continue.dev both expose a temperature setting in their advanced preferences.

Sharp edges

Hallucinated APIs and outdated knowledge

Models are trained on a snapshot of public code and documentation. If your project uses a recently released library version, the model may suggest functions or patterns that existed in an earlier version but were removed or renamed. This is especially acute in fast-moving ecosystems like JavaScript frameworks or Rust crates. Always verify the suggestion against your actual Cargo.toml or package.json.

Privacy and code transmission

Sending code to an external service means your file contents—including proprietary logic, API keys embedded in comments, or unreleased designs—leave your machine. Most commercial extensions offer an “on-premises” or “self-hosted” mode, but the free or default configurations typically transmit code. If your organization has data-handling policies, verify which mode your team is using before enabling pair programming on sensitive repositories.

Token limits and context truncation

Every request has a token budget. If you attach too many files or a very large codebase, the model will silently truncate the beginning or end of the context, often without telling you. The result is a suggestion that references a function or variable that doesn’t exist in the snippet the model actually saw. A practical workaround is to attach only the files directly relevant to the task, or to use the @ reference for specific symbols rather than broadcasting entire directories.

Mode confusion: “complete” vs. “chat”

Many extensions offer two modes: a completion mode that suggests the next few lines as you type, and a chat mode that accepts free-form prompts. A common point of confusion is expecting chat-style clarification (e.g., “what does this function do?”) inside the completion mode. The completion mode does not support dialogue; it only emits a single suggestion based on the current cursor position. If you need a conversation, switch to the chat pane or open the extension’s web interface.

Language-specific limitations

Pair programming works best in languages with rich public documentation and many examples in the training data—Python, JavaScript, TypeScript, Go, and Java are well-supported. In less-common languages or domain-specific dialects, the model’s suggestions may be sparse or generic. If you’re working in, say, R, PL/SQL, or a specialized embedded language, treat the suggestions as starting points, not finished work.

Test generation pitfalls

Asking the model to “write tests for this function” often produces syntactically valid but semantically hollow test suites. The model may import testing frameworks that aren’t installed, assert on states that can never be reached, or omit edge cases that you know exist from reading the function body. A reliable pattern is to write one or two manual tests yourself, then ask the model to extend them. That way you control the test shape and the model fills in the repetitive assertions.

When to turn it off

There are moments when AI pair programming adds noise rather than signal. During a high-stakes production incident, you need deterministic, auditable output—suggestions that can be reviewed line-by-line without probabilistic uncertainty. When reviewing a security-sensitive change, you should not rely on the model to identify injection vulnerabilities; human review with static analysis tools is required. And when onboarding to a new codebase where every file is unfamiliar, the model’s suggestions may reference patterns you haven’t internalized yet, leading you down blind alleys. In those cases, disable the extension, read the code directly, and re-enable pair programming once you have a mental model of the architecture.

This page was rewritten on 11 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.