Claude Code in VS Code: The Extension, Not the CLI

No. The extension bundles a private copy of the CLI for its own chat panel, but typing claude in a terminal requires the separate standalone install. Run that once and every CLI command works in any terminal, including claude mcp add and claude --resume, which you will need for the panel's CLI-only gaps.
Two tools are visible to it. getDiagnostics is read-only and returns the errors and warnings from the Problems panel. executeCode runs Python in the active Jupyter notebook's kernel and is not read-only. The server hosts about a dozen tools; the rest are internal RPC filtered out before the tool list reaches Claude.
No. On every call the code is inserted as a new cell at the end of the active notebook, VS Code scrolls it into view, and a native Quick Pick asks you to Execute or Cancel. That confirmation is separate from PreToolUse hooks: an allowlist entry lets Claude propose running a cell, and the Quick Pick is what lets it actually run.
Four things. The CLI has all commands and skills while the extension has a subset, full MCP server configuration while the extension can only manage existing servers, the bang shell shortcut, and tab completion. Since both share conversation history, you can resume a panel conversation in the terminal when you need one of them.
Click the selection indicator in the prompt box footer to toggle it — the eye-slash icon means the selection is hidden from Claude. For a file that should never be shared this way, add a Read deny rule for its path, which blocks both the selected text and the open-file notice.

Key Takeaway
The Claude Code VS Code extension is a graphical client with its own bundled copy of the CLI. Installing it does not put the claude command on your shell PATH — that needs a separate standalone install. The extension and CLI share conversation history, so a session started in one can be resumed in the other.
I installed the extension, used it happily for a week, then opened the integrated terminal to run one CLI-only command and got command not found. The extension had been running Claude Code the whole time, from a private copy it keeps for its own panel. Sharing that binary with my shell was never part of the deal, and nothing had told me otherwise.
That is a small thing that explains a larger one: the extension is a client, not a wrapper. It has features the terminal does not, lacks features the terminal has, and shares the conversation history so you can move between them. This post covers what it genuinely does better, how to reference things into a prompt, the local MCP server and the one non-read-only tool it exposes, the feature gap, and the security note about configuration files that execute themselves.
The extension bundles a private copy of the CLI for its chat panel. Typing the command in a terminal needs the standalone install, and running that once makes every command on the documentation site work in any terminal — including the ones you will need for MCP configuration, which is only partially available in the panel.
The two share conversation history, which is the part worth exploiting. A conversation started in the panel can be continued in the terminal by resuming it, which opens a picker to search for and select it. That makes the feature gap much less painful than it sounds: when you hit something the panel cannot do, you move that one conversation rather than starting again.
With auto-edit permissions on, Claude Code can modify VS Code configuration files that VS Code may execute automatically. The mitigations are specific rather than general: enable Restricted Mode for untrusted workspaces, prefer Manual mode over auto or edit-automatically, and review changes before accepting. Note that on Pro, Max and Team plans, Auto is the extension's built-in starting permission mode — so this is the default state, not an opt-in.
Four things are meaningfully better here than in a terminal, and one of them changed how I use plan mode:
The referencing is the other place the graphical client wins, because it can see what your editor is doing. The terminal-output mention is the one I use most and the one people are most surprised exists.
# @-mentions fuzzy match, so partial names work.
Explain the logic in @auth # matches auth.js, AuthService.ts
What is in @src/components/ # trailing slash for a folder
# Terminal output, by the terminal's title — no copy-pasting
# a stack trace ever again.
Why did this fail? @terminal:dev-server
# Large PDFs: ask for pages rather than the whole file.
Read pages 1-10 of @spec.pdf
Read @spec.pdf from page 3 onward
# Option+K / Alt+K inserts a reference to the current file AND
# selection, as @app.ts#5-10.
#
# The footer shows how many lines are selected, and clicking the
# indicator TOGGLES whether Claude can see them — the eye-slash
# icon means the selection is hidden.
#
# Shift-drag files into the box to add them as attachments.The selection indicator in the footer is a toggle, not just a readout. Clicking it controls whether Claude can see your highlighted text, and the eye-slash icon means the selection is hidden. That is the fix for the awkward moment when you have a block of something sensitive selected and want to ask an unrelated question without closing the file first.
Like the JetBrains plugin, the extension runs a local MCP server the CLI connects to. It is hidden from the MCP list because there is nothing to configure, which means the people who need to know it exists — anyone allowlisting MCP tools in a hook — are the least likely to find it by accident.
# The extension runs a local MCP server named "ide". It hosts
# about a dozen tools; exactly TWO are visible to the model.
mcp__ide__getDiagnostics read-only. The errors and warnings in
the Problems panel, optionally scoped
to one file.
mcp__ide__executeCode NOT read-only. Runs Python in the
active Jupyter notebook's kernel.
# The rest are internal RPC the CLI uses to drive its own UI —
# opening diffs, reading selections, saving files — and are
# filtered out before the tool list reaches Claude.
# Transport: 127.0.0.1 on a random port in 10000-65535, not
# configurable. Unencrypted ws://. A fresh token per activation
# at ~/.claude/ide/<port>.lock with 0600 permissions inside a
# 0700 directory, presented as
# X-Claude-Code-Ide-AuthorizationThis is the one non-read-only tool the model can see in VS Code, and the way it is fenced is worth studying as a design pattern rather than just a feature. The permission system can let Claude propose running code; a human in VS Code is what lets it actually run.
# The Jupyter tool cannot run anything silently. On every call:
#
# 1. the code is inserted as a new cell at the END of the
# active notebook
# 2. VS Code scrolls it into view
# 3. a native Quick Pick asks Execute or Cancel
#
# Cancel — or Esc — returns an error to Claude and nothing runs.
#
# It refuses outright when:
# - there is no active notebook
# - the Jupyter extension is not installed
# - the kernel is not Python
#
# The Quick Pick is SEPARATE from PreToolUse hooks. An allowlist
# entry for the tool lets Claude PROPOSE running a cell; the
# Quick Pick is what lets it actually run. Two independent gates,
# and the second one is a human every single time.That two-gate design is the answer to a question people ask about agentic tools generally: how do you allow a capability without allowing it unattended. The allowlist grants the proposal, the native picker grants the execution, and the two live in different systems so neither can be configured into granting both. Worth copying if you are building anything similar.
The gap is small but specific, and knowing it saves you looking for something that is not there.
Where the two differ:
| Feature | CLI | VS Code extension |
|---|---|---|
| Commands and skills | All of them | A subset — type slash to see what is available |
| MCP server configuration | Full | Partial — add servers via the CLI, manage existing ones in the panel |
| The bang shell shortcut | Yes | No |
| Tab completion | Yes | No |
Checkpoints work in the extension and are more discoverable there than in the terminal: hover any message and you get three distinct options, which is a genuinely better model than a single rewind. You can fork the conversation from that point while keeping all code changes, rewind the code while keeping the whole conversation, or do both at once. Those are three different intentions and they deserve three different buttons.
The extension also registers a URI handler, which is the underrated bit of plumbing here. Opening that URL from a shell alias, a bookmarklet or any script starts a new Claude Code tab — launching VS Code first if it is not running, or using the focused window if it is. That is how you wire Claude Code into tooling that has nothing to do with VS Code.
Use the panel for the work where seeing things matters — reviewing a plan you can annotate, scanning a diff, keeping four conversations in tabs — and drop to the terminal for the handful of things only it can do. The single setup step worth doing on day one is the standalone CLI install, because without it the terminal escape hatch is not there when you need it, and the error you get says nothing about why.
Sources & further reading