AI coding assistants have moved from novelty to necessity. But the hype cycle has settled, and we now have real data on what works and what doesn’t.

The Landscape

ToolBest ForLimitations
GitHub CopilotAutocomplete, boilerplateStruggles with multi-file refactors
CursorFull-featured AI IDEContext window limits on large codebases
Claude CodeTerminal-native agentic codingRequires explicit instruction
OpenCodeInteractive CLI with subagentsNeeds good task decomposition

Where AI Excels

Test Generation

AI-generated tests catch edge cases humans miss. In our codebase, AI-authored tests found 23% more boundary condition bugs than human-written equivalents:

# Human wrote:
def test_divide():
    assert divide(10, 2) == 5

# AI added:
def test_divide_by_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

def test_divide_negative():
    assert divide(-10, 2) == -5
    assert divide(10, -2) == -5

def test_divide_float_precision():
    assert abs(divide(1, 3) - 0.333333) < 0.000001

Documentation and Comments

The best use case isn’t code generation—it’s explanation. Feeding complex functions to an LLM and asking for docstrings produces consistently good results.

Where AI Still Fails

  1. Architecture decisions: AI can implement a pattern you describe but can’t choose the right pattern for your constraints
  2. Security-sensitive code: AI has no concept of threat models and will happily write auth logic with subtle flaws
  3. Framework version awareness: APIs change fast; models are often 6-12 months behind

Our Workflow

The most effective pattern we’ve found:

  • Write specs, not code: Describe what you want, let AI generate the implementation
  • Review, don’t write: Spend your time reviewing AI output, not typing
  • Test everything: AI-generated code gets the same test coverage bar as human code

Bottom line: AI tools amplify good developers. They don’t replace thinking.