Lesson 4 of 4 · AI for Engineers

Setting Up Your AI-Augmented Workflow

reading25 min

When Jake joined Stripe in 2019, his onboarding checklist had 47 items: install these tools, configure these linters, set up these git hooks, learn these conventions. By day three, his environment was tuned and he could focus on code.

Fast-forward to 2026. The onboarding checklist at any AI-forward engineering org now includes a 48th item: configure your AI-assisted development environment. And just like the other 47 items, doing this right upfront pays dividends every single day afterward.

This lesson walks you through setting up a complete AI-augmented engineering workflow -- from IDE configuration to model selection to context management to the project configuration files that make AI tools actually understand your codebase.


Step 1: IDE and Extension Setup

Your IDE is the cockpit of your AI-augmented workflow. Here's how to configure the three most common setups:

Concept Card

Option A: Cursor (Recommended Starting Point)

Cursor is a VS Code fork with built-in AI capabilities. If you're currently using VS Code, migration is seamless -- your extensions, keybindings, and settings transfer directly.

Bash
# Install Cursor
# Download from cursor.sh or:
brew install --cask cursor   # macOS

# Your VS Code settings automatically import on first launch
# Verify by checking: Cmd+Shift+P → "Cursor Settings"

Essential Cursor Configuration:

JSON
// settings.json -- Cursor-specific settings
{
  // AI-specific
  "cursor.ai.model": "claude-sonnet-4-20250514",
  "cursor.ai.enableTab": true,
  "cursor.ai.tabSuggestionDelay": 200,

  // Codebase indexing -- CRITICAL for context quality
  "cursor.ai.indexOnStartup": true,
  "cursor.ai.indexIgnorePatterns": [
    "node_modules/**",
    "dist/**",
    "build/**",
    ".next/**",
    "*.min.js",
    "*.lock",
    "coverage/**"
  ],

  // General quality-of-life
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "typescript.preferences.importModuleSpecifier": "non-relative"
}

Option B: VS Code + GitHub Copilot

If you prefer staying with VS Code, GitHub Copilot provides excellent inline completions:

Bash
# Install Copilot extensions
code --install-extension GitHub.copilot
code --install-extension GitHub.copilot-chat

# Recommended companion extensions for AI-augmented workflow:
code --install-extension ms-vscode.vscode-typescript-next
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension eamodio.gitlens

VS Code Copilot Settings:

JSON
{
  "github.copilot.enable": {
    "*": true,
    "markdown": true,
    "yaml": true
  },
  "github.copilot.advanced": {
    "length": 500,
    "temperature": "",
    "inlineSuggestCount": 3
  },
  // Keybinding tip: Alt+] and Alt+[ cycle through suggestions
  // Tab accepts, Escape dismisses
}

Option C: Terminal-First with Claude Code

For engineers who live in the terminal (Vim/Neovim users, tmux enthusiasts, or anyone who prefers keyboard-driven workflows):

Bash
# Install Claude Code
npm install -g @anthropic-ai/claude-code

# Verify installation
claude --version

# First run -- authenticates and sets up
claude

# Recommended: Create a shell alias for quick access
echo 'alias cc="claude"' >> ~/.zshrc

# For Vim/Neovim users, add Copilot for inline completions:
# In your init.lua or .vimrc:
# Plug 'github/copilot.vim'

Claude Code Configuration:

Bash
# Set your preferred model
claude config set model claude-sonnet-4-20250514

# Set permission mode (how much autonomy Claude Code gets)
# "ask" = asks before every file write and command
# "auto" = auto-approves safe operations
claude config set permissions auto

# Set your preferred editor for when Claude Code needs you to review
claude config set editor vim
The Hybrid Approach

Many productive engineers use a hybrid setup: Cursor or VS Code with Copilot for daily coding, plus Claude Code in a terminal pane for complex tasks, codebase exploration, and operations that benefit from shell access. You don't have to pick one.


Step 2: Project Configuration Files

The single highest-leverage action you can take with AI coding tools is creating proper project configuration files. These files are read by the AI at the start of every interaction and dramatically improve output quality.

Warning

Do not let Setting Up Your AI-Augmented Workflow become a hidden assumption. If teammates cannot see the rule, config, or verification path, Claude will behave inconsistently across sessions.

CLAUDE.md -- For Claude Code

This file lives in your project root and is automatically loaded by Claude Code:

markdown
# CLAUDE.md

## Project Overview
E-commerce platform backend. Node.js/TypeScript monorepo with Express API,
PostgreSQL via Prisma, Redis for caching and queues, deployed on AWS ECS.

## Architecture

### Service Boundaries
- `packages/api/` -- REST API (Express + TypeScript)
- `packages/worker/` -- Background job processor (Bull + Redis)
- `packages/shared/` -- Shared types, utilities, validators
- `packages/db/` -- Prisma schema and migrations

### Key Dependencies
- Express 4.18 (NOT v5 -- we're waiting for stable release)
- Prisma 5.x with PostgreSQL 15
- Bull 4.x for job queues
- Zod 3.x for runtime validation
- Vitest for testing

## Commands
```bash
npm run dev           # Start all services
npm run test          # Run all tests
npm run test:unit     # Unit tests only
npm run test:int      # Integration tests (needs Docker)
npm run lint          # ESLint + Prettier check
npm run db:migrate    # Run pending migrations
npm run db:generate   # Regenerate Prisma client
npm run db:seed       # Seed development data

Code Conventions

TypeScript

  • Strict mode enabled, no any types
  • Use type for data shapes, interface for contracts
  • All function parameters must be typed (no inference on params)
  • Prefer readonly for function parameters that shouldn't be mutated

Error Handling

  • Business errors: custom error classes extending AppError
  • Never throw in utility functions -- return Result<T, E>
  • API routes catch errors in middleware, not per-route

Database

  • All queries go through repository classes, never raw Prisma in routes
  • Migrations must be backward-compatible (no breaking column drops)
  • Use transactions for multi-table writes

Testing

  • Unit tests: colocated as *.test.ts
  • Integration tests: tests/integration/
  • Minimum 80% branch coverage on new code
  • Test naming: should [expected behavior] when [condition]

API Design

  • RESTful with consistent response envelope: { data: T, meta?: { page, total } }
  • Pagination: cursor-based, not offset-based
  • Rate limiting: 100 req/min for authenticated, 20 for anonymous
  • All inputs validated with Zod schemas

Common Patterns

New API Endpoint Checklist

  1. Define Zod schema in packages/shared/src/schemas/
  2. Create/update repository method in packages/db/src/repositories/
  3. Add route handler in packages/api/src/routes/
  4. Add integration test in tests/integration/
  5. Update OpenAPI spec if public-facing

New Background Job Checklist

  1. Define job type in packages/shared/src/jobs/
  2. Add processor in packages/worker/src/processors/
  3. Add producer function in packages/api/src/jobs/
  4. Add retry configuration in packages/worker/src/config/

### .cursorrules -- For Cursor

```markdown
# .cursorrules

You are an expert TypeScript/Node.js developer working on an e-commerce
platform backend. Follow these conventions strictly:

## Response Format
- When modifying existing code, show only the changed sections with
  enough context to locate the change
- When creating new files, show the complete file
- Always include necessary imports
- Add JSDoc comments for exported functions

## Code Style
- Use `const` by default, `let` only when reassignment is necessary
- Prefer early returns over nested conditionals
- Maximum function length: 30 lines (extract helpers)
- Use descriptive variable names -- no single-letter names except
  loop indices and lambda parameters

## TypeScript Specifics
- Use strict null checks -- always handle null/undefined explicitly
- Prefer discriminated unions over optional fields for state
- Use `as const` for literal types
- Generic type parameters: T for main type, K for keys, V for values

## When Writing Tests
- Use Vitest (not Jest -- similar API but different imports)
- Structure: describe → it → arrange/act/assert
- Use factories for test data, never raw object literals
- Mock external services, never databases in unit tests

## When Writing Database Code
- Use Prisma's typed queries -- never raw SQL unless for performance
- Always use transactions for multi-table mutations
- Include `select` clauses to avoid over-fetching
- Handle unique constraint violations explicitly

## What NOT to Do
- Never use `any` type -- use `unknown` and narrow
- Never use `console.log` -- use the structured logger
- Never commit `.env` files or secrets
- Never use synchronous file I/O in request handlers

.github/copilot-instructions.md -- For GitHub Copilot

markdown
# Copilot Instructions

This is a TypeScript monorepo for an e-commerce platform.

## Key Conventions
- All API responses use the envelope format: { data, meta? }
- Use Zod for validation, Prisma for database access
- Errors are custom classes extending AppError
- Tests use Vitest with the describe/it pattern

## Libraries
- Express 4.18 (NOT v5)
- Prisma 5.x
- Zod 3.x
- Vitest (NOT Jest)
- Bull 4.x for queues

## Patterns to Follow
- Repository pattern for data access
- Result<T,E> for error handling in utilities
- Cursor-based pagination
- Structured logging with pino
Keep Configuration Files Updated

These files are only useful if they accurately reflect your current codebase. Add updating .cursorrules or CLAUDE.md to your "new feature" checklist. When you change a convention, update the config file the same day. Stale configuration files actively mislead the AI.


Step 3: Model Selection Strategy

Not all models are equal for all tasks. Understanding model characteristics helps you route tasks to the right model.

Model Comparison for Code Tasks

ModelBest ForLatencyCostContext
Claude Sonnet 4Everyday coding, fast iterationLowMedium200K
Claude Opus 4Complex architecture, deep reasoningHighHigh200K
GPT-4oMulti-modal, broad knowledgeLowMedium128K
GPT-o3Mathematical/algorithmic reasoningHighHigh200K
Gemini 2.5 ProMassive context, long codebasesMediumMedium1M
Llama 3.3 70BLocal/private, good general codingMediumFree (self-hosted)128K
DeepSeek V3Cost-effective, strong at codeLowLow128K

Map Your Setting Up Your AI-Augmented Workflow Layers

  1. Open your global, project, and local Claude configuration files.
  2. Write down which rule for this lesson belongs in each layer and why.
  3. Start a fresh Claude Code session and confirm the effective behavior matches your intent.

Routing Strategy

Python
# Mental model for choosing a model:

def choose_model(task: dict) -> str:
    if task["requires_large_context"]:
        # Reading 50+ files, understanding full codebase
        return "gemini-2.5-pro"  # 1M context

    if task["requires_deep_reasoning"]:
        # Architecture decisions, complex debugging,
        # multi-step planning
        return "claude-opus-4"  # or "o3"

    if task["requires_privacy"]:
        # Proprietary code that can't leave your network
        return "llama-3.3-70b"  # self-hosted

    if task["is_routine"]:
        # CRUD, tests, boilerplate, quick edits
        return "claude-sonnet-4"  # fast + good enough

    # Default: start with Sonnet, escalate to Opus if needed
    return "claude-sonnet-4"

In Cursor, you can switch models per-request:

Cursor Chat: Click the model selector dropdown
  → claude-sonnet-4-20250514 for most tasks
  → claude-opus-4-20250514 for complex reasoning
  → gpt-4o for when you want a different perspective

Step 4: Context Management Workflow

How you feed context to AI tools determines the quality of output. Here's a systematic approach.

Quick Check

What is the main benefit of using Setting Up Your AI-Augmented Workflow well in Claude Code?

The Context Hierarchy

Level 1: Automatic Context (tool handles this)
  ├── Current file
  ├── Cursor position
  ├── Open tabs
  └── Codebase index (Cursor, Claude Code)

Level 2: Project Context (you configure once)
  ├── CLAUDE.md / .cursorrules
  ├── README.md
  └── Configuration files

Level 3: Task Context (you provide per-request)
  ├── Relevant files (@file references in Cursor)
  ├── Error messages and stack traces
  ├── Requirements or specs
  └── Examples of desired output

Level 4: Conversation Context (accumulates during session)
  ├── Previous messages
  ├── Previous code generations
  └── Your corrections and refinements

Effective Context Provision in Cursor

# Use @ references to include specific context:

@api/routes/users.ts @db/repositories/userRepo.ts
Add a "deactivate user" endpoint that:
1. Sets user.active = false
2. Revokes all active sessions
3. Cancels pending orders
4. Sends notification email via the job queue

Effective Context Provision in Claude Code

Bash
# Claude Code can explore your codebase, but you can guide it:

$ claude

> Read the files in src/auth/ and src/middleware/ to understand
> our current authentication flow. Then add support for API key
> authentication alongside the existing JWT flow. API keys should
> be stored hashed in the database and support scoping (read-only,
> read-write, admin).

The Context Budget

Think of your context window as a resource budget:

200K token context window (Claude)
─────────────────────────────────
System prompt + CLAUDE.md:        ~2,000 tokens
Task description:                 ~500 tokens
Relevant code files:              ~10,000-30,000 tokens
Conversation history:             ~5,000-20,000 tokens
─────────────────────────────────
Available for model reasoning:    ~150,000-182,000 tokens

Rule of thumb: Keep your explicit context under 30K tokens
for best results. The model needs "thinking room."
Less Is More

A common mistake is dumping your entire codebase into context. This is counterproductive -- the model's attention is diluted across irrelevant code, and the important context gets lost. A focused 5,000-token context of exactly the right files produces better results than a 50,000-token dump of everything.


Step 5: Git Integration

Your AI workflow should integrate cleanly with your git workflow.

Branch Strategy for AI-Assisted Work

Bash
# Always create a feature branch for AI-assisted work
git checkout -b feat/add-rate-limiting

# Make AI-assisted changes
# Review ALL changes carefully (git diff)
git diff

# Stage selectively -- don't blindly git add -A
git add -p   # Interactive staging lets you review each hunk

# Write descriptive commit messages (AI can help here too)
git commit -m "feat(api): add sliding window rate limiting

- Redis-backed sliding window counter per API key
- 100 req/min limit with configurable override per key
- X-RateLimit headers in all responses
- Graceful degradation on Redis failure (fail-open with logging)

Co-authored-by: Claude <noreply@anthropic.com>"

Pre-Commit Hooks for AI-Generated Code

Add extra safety nets for AI-generated code:

Bash
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# Type check -- catches hallucinated APIs
npx tsc --noEmit

# Lint -- catches style violations
npx eslint --max-warnings 0 .

# Test -- catches logic errors
npm run test:unit

# Security check
npx audit-ci --moderate
JSON
// package.json
{
  "lint-staged": {
    "*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.test.{ts,tsx}": [
      "vitest related --run"
    ]
  }
}

Step 6: Building Your Daily Workflow

Here's what an optimized AI-augmented engineering day looks like:

Morning: Planning and Architecture

1. Review PRs with AI assistance
   → Claude Code: "Review the diff in PR #234 for security issues,
      performance problems, and style violations"

2. Plan the day's implementation
   → Cursor Agent: "I need to implement feature X.
      What files need to change and in what order?"

Midday: Implementation

3. Write code with inline completions
   → Copilot/Cursor Tab handles boilerplate as you type

4. Complex implementations with agent mode
   → Cursor Agent or Claude Code for multi-file changes

5. Test generation
   → "Generate tests for the UserService.deactivate method
      covering: success, user not found, already deactivated,
      database error, partial failure in session revocation"

Afternoon: Review and Refinement

6. Self-review with AI
   → "Review my changes today. Focus on: error handling
      completeness, test coverage gaps, performance implications"

7. Documentation updates
   → "Update the API documentation to include the new
      rate-limiting headers and deactivation endpoint"

8. Commit and PR preparation
   → "Write a PR description summarizing the changes,
      motivation, and testing approach"

Set Up Your AI-Augmented Workflow

  1. Choose your IDE setup -- Install Cursor or configure VS Code with Copilot
  2. Create project configuration -- Write a CLAUDE.md and/or .cursorrules for your main project. Include: project overview, commands, code conventions, common patterns, and things to avoid.
  3. Configure model routing -- Set your default model for everyday tasks, and note which model to use for complex reasoning tasks
  4. Set up git safety nets -- Add pre-commit hooks for type checking and linting
  5. Run a test task -- Pick a medium-complexity task from your backlog and complete it using your new AI-augmented workflow. Time yourself and note friction points.

Target: Complete this setup in under 2 hours. The configuration files should be at least 50 lines each with specific, actionable conventions -- not generic advice.

Common Setup Pitfalls

1. Over-Trusting the Defaults

Most AI tools ship with generic settings optimized for demos. The defaults are rarely optimal for production engineering work:

Default: Accept all suggestions automatically
Better:  Review each suggestion, use Tab selectively

Default: Use the fastest model for everything
Better:  Route complex tasks to stronger models

Default: Include all files in context
Better:  Configure ignore patterns for generated files, node_modules, builds

2. Ignoring the Feedback Loop

Your AI workflow should have a feedback mechanism:

Week 1: Track tasks where AI helped vs. where you had to fix AI output
Week 2: Update .cursorrules/CLAUDE.md based on common corrections
Week 3: Refine your prompting patterns based on what worked
Week 4: Share learnings with your team and update shared configuration

3. Working Against Your Natural Flow

If you're a keyboard-driven developer, don't force yourself into a mouse-heavy AI workflow. If you think in types first, let AI generate implementations from your type definitions. Match the tool to your cognitive style, not the other way around.

Key Takeaways

  • IDE setup is a one-time investment that affects every subsequent interaction -- spend the time to get it right
  • Project configuration files (CLAUDE.md, .cursorrules) are the highest-leverage action for AI tool effectiveness
  • Model selection should be task-driven: fast models for routine work, powerful models for complex reasoning
  • Context management follows the "less is more" principle -- focused context beats comprehensive context
  • Git integration with pre-commit hooks provides a safety net for AI-generated code
  • Build a daily workflow rhythm: planning with AI in the morning, implementation with inline tools midday, review and documentation in the afternoon
  • Update your configuration files regularly -- stale conventions actively mislead AI tools
  • The best workflow matches your cognitive style and existing habits, augmented rather than replaced