Part 12: IDE Setup with VS Code

View Source on GitHub

DS-MLOps Dev Tools

Python 3.12+ | Author: Anthony Faustine

Before you begin

This chapter is the entry point to Part 3. No prior VS Code experience is required. If you already have VS Code installed and use it for Python, focus on sections 4 (uv interpreter), 5 (Ruff integration), and 7 (git extensions): these are the settings that differ from a generic Python setup.

Topic Why it matters
Installing VS Code The primary editor for DS/ML work in this book
Essential extensions Python, Ruff, Jupyter, GitLens: the minimum productive setup
Interpreter selection Points VS Code at the uv virtualenv, not the system Python
Format-on-save with Ruff Fixes lint and style issues on every save without running commands
Debugger configuration Step through pipeline code without print statements
Git integration Stage, diff, and review changes without leaving the editor

Callout markers used throughout this chapter are explained on the book cover page.

By the end of Part 12 you will be able to:

# Skill Covered in
1 Install VS Code and understand the layout of the interface Sec. 1
2 Install and configure the essential extensions for DS/MLOps work Sec. 2
3 Configure settings.json for format-on-save with ruff Sec. 3
4 Point VS Code at the uv-managed .venv Python interpreter Sec. 4
5 Run and debug Jupyter notebooks directly inside VS Code Sec. 5
6 Use the Source Control panel and GitLens for git operations without the terminal Sec. 6
7 Use the integrated terminal to run uv and git commands without leaving the editor Sec. 7

1. Installing VS Code

VS Code is a free, open-source editor published by Microsoft. It runs on macOS, Linux, and Windows and has the largest Python extension ecosystem of any editor.

Download the installer for your platform from the official site:

code.visualstudio.com/download

VS Code interface showing the Activity Bar, Editor, Panel, and Status Bar

Source: VS Code User Interface

macOS: open the downloaded .zip, drag Visual Studio Code.app to /Applications, then add the code CLI:

  1. Open VS Code
  2. Press Cmd+Shift+P to open the Command Palette
  3. Type Shell Command: Install 'code' command in PATH and press Enter

Linux (Debian/Ubuntu):

sudo apt install ./<downloaded-file>.deb

Windows: run the installer. The code CLI is added to PATH automatically.

Verify the CLI works:

code --version

Interface overview

The five areas you use most:

Area Shortcut Purpose
Activity Bar (left strip) (none) Switch between Explorer, Search, Source Control, Extensions
Explorer Cmd/Ctrl+Shift+E File tree, open editors
Command Palette Cmd/Ctrl+Shift+P Find and run any VS Code command
Integrated Terminal Ctrl+` Shell inside the editor: run uv, git, pytest
Status Bar (bottom) (none) Active Python interpreter, git branch, errors/warnings count

2. Essential Extensions

The nine extensions below cover every layer of a DS/MLOps project:

flowchart TB
    VSCode["VS Code"]

    subgraph Python["Python Layer"]
        PY["Python\nms-python.python"]
        PYL["Pylance\nms-python.vscode-pylance"]
        RUFF["Ruff\ncharliermarsh.ruff"]
    end

    subgraph Jupyter["Notebook Layer"]
        JUP["Jupyter\nms-toolsai.jupyter"]
        JKEY["Jupyter Keymap\nms-toolsai.jupyter-keymap"]
    end

    subgraph Git["Git Layer"]
        GL["GitLens\neamodio.gitlens"]
        GH["GitHub Pull Requests\ngithub.vscode-pull-request-github"]
    end

    subgraph QoL["Quality of Life"]
        IR["indent-rainbow"]
        YAML["YAML (Red Hat)"]
        TOML["Even Better TOML"]
    end

    VSCode --> Python & Jupyter & Git & QoL

Open the Extensions panel (Cmd/Ctrl+Shift+X) and install each of these. The extension ID is in parentheses; paste it into the search box for an exact match.

Core Python and linting

Extension ID Purpose
Python ms-python.python IntelliSense, debugging, test discovery
Pylance ms-python.vscode-pylance Fast type-aware autocomplete (uses Pyright)
Ruff charliermarsh.ruff Lint and format on save using the ruff binary

The Ruff extension in the VS Code Marketplace

Source: Ruff VS Code Extension

Jupyter notebooks

Extension ID Purpose
Jupyter ms-toolsai.jupyter Run .ipynb notebooks in VS Code
Jupyter Keymap ms-toolsai.jupyter-keymap Classic Jupyter keyboard shortcuts

Git and collaboration

Extension ID Purpose
GitLens eamodio.gitlens Inline blame, commit history, branch comparison
GitHub Pull Requests github.vscode-pull-request-github Review and merge PRs without leaving the editor

Quality of life

Extension ID Purpose
indent-rainbow oderwat.indent-rainbow Colour-coded indentation depth; helps in deeply nested config
YAML redhat.vscode-yaml Schema validation for .pre-commit-config.yaml, _quarto.yml
Even Better TOML tamasfe.even-better-toml Syntax and schema support for pyproject.toml
Pro Tip: Save your extension list as a workspace recommendation

Create .vscode/extensions.json in your project root. When a teammate opens the project, VS Code prompts them to install all recommended extensions automatically:
{
  "recommendations": [
    "ms-python.python",
    "ms-python.vscode-pylance",
    "charliermarsh.ruff",
    "ms-toolsai.jupyter",
    "eamodio.gitlens"
  ]
}

3. Configuring settings.json

VS Code settings live in .vscode/settings.json inside the project (workspace settings) or ~/.config/Code/User/settings.json (user settings). Workspace settings are committed to git and shared with the team.

Create .vscode/settings.json in the grade-predictor project:

{
  "[python]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll.ruff": "explicit",
      "source.organizeImports.ruff": "explicit"
    }
  },
  "[jupyter]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true
  },
  "python.analysis.typeCheckingMode": "basic",
  "python.analysis.diagnosticMode": "workspace",
  "editor.rulers": [100],
  "files.trimTrailingWhitespace": true,
  "files.insertFinalNewline": true
}

What each setting does:

  • editor.defaultFormatter: charliermarsh.ruff: ruff formats on every save, no Black needed
  • source.fixAll.ruff: auto-applies safe lint fixes (--fix) on save
  • source.organizeImports.ruff: sorts imports on save (isort rules)
  • editor.rulers: [100]: vertical guide at column 100 (matches line-length = 100 in pyproject.toml)

Key Concept: Workspace settings override user settings

A developer’s personal settings.json might use Black as the formatter. When they open your project, the workspace .vscode/settings.json overrides that for Python files only. Their other projects are untouched. This is how you enforce a consistent formatter across a team without overwriting anyone’s personal preferences.

Activity 1 - Format on Save

Goal: Create .vscode/settings.json with the configuration above. Open core.py, add an intentionally badly-formatted function, and save the file. Confirm that ruff reformats it automatically on save. The status bar at the bottom should show no ruff errors.

4. Pointing VS Code at the uv .venv Interpreter

After running uv sync, a .venv/ directory exists in the project root. VS Code needs to know about it to provide autocomplete and run code correctly.

Option A: Auto-detect (VS Code usually picks this up automatically):

  1. Open the project folder (code . from the terminal)
  2. Look at the bottom-right of the Status Bar, which shows the active Python interpreter
  3. Click it, then select the interpreter at ./.venv/bin/python

Option B: Set it explicitly in settings.json:

{
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"
}

The Python interpreter picker in VS Code showing available environments

Source: VS Code Python Environments

Once the interpreter is set, the IntelliSense for all packages installed by uv sync becomes available. Hovering over a pandas function shows its signature; Cmd+Click jumps to the source.

Common Mistake: Using the system Python or a conda env instead of .venv

If the Status Bar shows Python 3.x.x 64-bit without a path, VS Code is using the system Python. Packages installed by uv sync will not be visible, autocomplete will be incomplete, and notebooks will fail to import project dependencies. Always confirm the interpreter path ends with .venv/bin/python.

5. Jupyter Notebooks in VS Code

With the Jupyter and Python extensions installed, VS Code opens .ipynb files as interactive notebooks. The experience is close to JupyterLab with some advantages: IntelliSense works inside cells, you can set breakpoints, and the Variable Inspector shows live DataFrame previews.

A Jupyter notebook running in VS Code with code cells and output

Source: VS Code Jupyter Notebooks

Key shortcuts for notebooks in VS Code:

Action Shortcut
Run cell and move to next Shift+Enter
Run cell, stay Ctrl+Enter
Insert cell above / below A / B (in command mode)
Toggle cell type (code/markdown) M / Y
Restart kernel Cmd/Ctrl+Shift+P → “Restart Kernel”
Open Variable Inspector Cmd/Ctrl+Shift+P → “Jupyter: Variables”

Select the kernel: when you first open a notebook, VS Code asks which kernel to use. Choose the .venv Python interpreter. This ensures every import in the notebook finds the packages installed by uv sync.

Activity 2 - Run a Notebook in VS Code

Goal: Open tutorials/01-python-basics/08-pandas-core.ipynb in VS Code. Select the .venv kernel. Run the first three cells with Shift+Enter. Open the Variable Inspector and confirm the DataFrame is visible. Change one cell to produce a different output and save.

6. Git and GitLens in VS Code

VS Code has a built-in Source Control panel (Cmd/Ctrl+Shift+G). It shows every modified file as a coloured indicator in the Explorer and in the Source Control panel, where you can stage, commit, and push without touching the terminal.

The VS Code Source Control panel showing the file change list and staging area

Source: VS Code Source Control

GitLens features

GitLens enhances the built-in git support. The three features used most in DS work:

Inline blame: hover over any line to see who wrote it and when. Useful when debugging a pipeline step someone else wrote.

File History: right-click a file → “Open File History” to see every commit that touched it as a timeline.

Branch comparison: in the GitLens sidebar, compare two branches to see exactly which files and lines differ, useful before opening a PR.

GitLens inline blame showing commit author and message on hover

Source: GitLens documentation

GitHub Pull Requests extension

With the GitHub Pull Requests extension, you can:

  • See open PRs in a sidebar panel
  • Leave inline review comments directly in the diff view
  • Check out a PR branch with one click
  • Merge a PR without leaving VS Code

Pro Tip: Use the editor’s diff view to review your changes before committing

Click any modified file in the Source Control panel to open a side-by-side diff. This is the best way to catch accidental changes (a stray debug print, a hardcoded path, a dropped import) before they enter git history.

7. Integrated Terminal

The integrated terminal (Ctrl+`) opens a shell inside VS Code with the current project directory already set. Split it into multiple panes with the split icon to run a test suite in one pane and a Quarto preview in another.

# Run in the integrated terminal exactly as you would in a standalone shell
uv run ruff check .
uv run pytest tests/ -v
uv run quarto preview

VS Code activates the .venv environment automatically in the integrated terminal when it detects a workspace interpreter. You can confirm this by running:

which python
# /path/to/grade-predictor/.venv/bin/python
Activity 3 - Full Workflow in VS Code

Goal: Without leaving VS Code, complete this sequence:
  1. Open the integrated terminal. Run uv run ruff check src/ and fix any findings.
  2. Open the Source Control panel. Stage the changed files and write a conventional commit message.
  3. Use the GitLens File History on core.py to view its commit history.
  4. Push the commit using the Source Control panel’s sync button.

Capstone - A Configured Development Environment

Set up your grade-predictor project so the full Dev Tools stack runs seamlessly inside VS Code.

Capstone - Zero-friction Setup

  1. Install all extensions listed in Section 2
  2. Create .vscode/settings.json with format-on-save and the ruff formatter
  3. Create .vscode/extensions.json with the five core extension recommendations
  4. Confirm VS Code is using .venv/bin/python as the interpreter
  5. Open a notebook, select the .venv kernel, and run it top to bottom without errors
  6. Make a small change, stage it in the Source Control panel, and commit with a conventional commit message
Resource Why it matters
VS Code Python tutorial Official walkthrough: install, run, debug
VS Code Jupyter docs Kernel selection, Variable Inspector, cell magic
Ruff VS Code extension Configuration options beyond format-on-save
GitLens docs Full feature reference for blame, history, and compare
VS Code keybindings Printable cheat sheet for all platforms
Concept Key rule
Interpreter Always use .venv/bin/python from uv sync. Check the Status Bar before running anything.
Format on save Set charliermarsh.ruff as the default Python formatter. Ruff replaces Black and isort.
Workspace settings .vscode/settings.json is committed; it enforces the formatter for the whole team.
.vscode/extensions.json Committed; VS Code prompts teammates to install the recommended extensions.
Kernel selection A notebook’s kernel must match the project’s .venv or imports will fail silently.
Source Control panel Stage, commit, push without the terminal. Use the diff view to review before committing.

Next: Part 13: Project Setup with uv builds the grade-predictor project that the rest of Part 3 operates on.