Snippets

Purpose and Scope

Snippets are reusable code templates that help users enter repeated structures such as loops, conditionals, file headers, or framework boilerplate without retyping them. In VS Code, user snippets are reader-facing editor features: they can appear in IntelliSense, can be selected through the Insert Snippet command, and can be inserted through tab completion when editor.tabCompletion is enabled. The official snippet syntax follows TextMate snippets with VS Code-specific limitations, so authors should think in terms of prefixes, bodies, variables, placeholders, and choices rather than arbitrary script execution.

This page connects that user model to the repository paths that shape snippet-adjacent behavior in the workbench. The strongest source evidence here is the code-action integration for snippets, where snippets become refactor-style actions such as surround-with and start-with-snippet. The page also covers AI-facing code snippets, which are not the same as user-defined snippet templates: they are contextual code excerpts collected for completions and chat editing. Keeping those terms separate matters because user snippets insert authored templates, while Copilot code snippets provide surrounding evidence for generated answers.

Sources: src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts, src/vs/editor/contrib/codeAction/common/types.ts, extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/contextProviders/codeSnippets.ts, extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/components/codeSnippets.tsx

Relevant Source Files

  • src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts - Registers snippet-backed code actions for surrounding a non-empty selection and starting an empty file from a file-template snippet.
  • src/vs/editor/contrib/codeAction/common/types.ts - Defines CodeActionKind, including Refactor, Source, and the SurroundWith kind used by snippet code actions.
  • extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/contextProviders/codeSnippets.ts - Filters resolved Copilot context items of type CodeSnippet, validates their document URIs, records inclusion or exclusion expectations, and adds relative paths.
  • extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/components/codeSnippets.tsx - Renders validated Copilot code snippets into prompt chunks, groups snippets by URI, filters empty snippets, and orders groups by importance.
  • src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts - Defines the service contract for mapping chat-produced code blocks to text or notebook edits.
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts - Provides the editor integration surface for chat edits, diff decorations, view zones, accessibility signals, and modified-file editor behavior around AI-generated changes.

Core User Model

A user-defined snippet starts as a JSON entry scoped either to a language or globally. The documentation workflow is intentionally lightweight: run the snippets configuration command, choose a language or a global snippets file, edit the JSON with comments, and then use the result through IntelliSense, the snippet picker, or tab completion. Extension authors can share the same format by placing a snippets file in an extension folder and contributing it through the contributes.snippets manifest entry with a language identifier and path. Marketplace snippet extensions are therefore packaging around the same underlying editing primitive.

The workbench code-action integration shows how snippets also participate in contextual editor commands rather than only completion lists. SurroundWithSnippetCodeActionProvider refuses to return actions for an empty selection, asks the snippet service for surroundable snippets at the current model and position, and then returns up to four concrete snippet actions before falling back to a More command. This keeps the lightbulb menu small while still exposing the full command when more choices exist. Each concrete action is labeled with the snippet name and applies a workspace edit generated from the selected range and snippet.

Sources: src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts

File-template snippets use the opposite condition. FileTemplateCodeActionProvider only offers actions when the text model is empty, then requests snippets with fileTemplateSnippets: true and includeNoPrefixSnippets: true. That means a file template is treated as a starter action for a blank buffer, not as a surround action for selected text. Like surround-with snippets, it limits visible actions to four and then uses an overflow command, here wired to ApplyFileSnippetAction.Id. The source-level behavior explains why some snippets appear as quick editor actions only in very specific document states.

Sources: src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts

Code Actions and Snippet Kinds

Snippet actions are categorized through the editor code-action kind hierarchy. The shared CodeActionKind object defines broad families such as quickfix, refactor, notebook, and source, then derives more specific kinds. SurroundWith is defined as refactor.surround, which lets the editor treat surround-with snippets as a refactoring-style operation instead of a source action or quick fix. The filtering helpers use hierarchical containment and intersection checks, so a caller asking for refactors can include suitable snippet actions while source actions remain hidden unless explicitly requested.

This classification matters for extension authors and workbench contributors because snippet behavior is surfaced through the same action infrastructure as code fixes, refactors, organize-imports, and fix-all commands. If a snippet-backed action is filtered out, it may not be because the snippet file is wrong; it may be because the request asked for a different action kind or excluded a parent kind. The code also includes auto-apply modes such as ifSingle, first, and never, which are shared action semantics rather than snippet-specific settings.

Sources: src/vs/editor/contrib/codeAction/common/types.ts, src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts

Snippet Syntax, Built-ins, and Grammars

The official snippet authoring model is based on TextMate snippet syntax, with VS Code not supporting interpolated shell code or \u escapes in that syntax. Built-in snippets are available for several languages, and installed extensions can add more. The repository paths for this page do not enumerate each bundled language snippet file, but the product model is clear: snippets are language-aware templates, and extension manifests can contribute them. When documenting or testing a snippet contribution, treat the snippet JSON as the data contract and the workbench providers as consumers that decide where that data is surfaced.

Syntax highlighting is related but distinct. A grammar contribution tokenizes source text so themes can color it; a snippet contribution inserts templated text into a document. The official syntax highlighting guide describes TextMate grammars and semantic token providers as the two layers behind coloring, while the snippet guide describes contributes.snippets as the sharing point for snippet bundles. In practice, a language extension may contribute both grammars and snippets, but a broken grammar does not imply a broken snippet insertion path, and a snippet extension can exist without owning tokenization.

AI Code Snippets and Prompt Context

The Copilot completion code uses the phrase code snippets for a different runtime object: small excerpts of existing code that become prompt context. getCodeSnippetsFromContextItems filters resolved context items down to type CodeSnippet, expands the primary URI plus any additional URIs, validates every referenced document through the completions text-document manager, and records provider expectations as either included or content excluded. Only snippets whose referenced documents all validate are returned. That validation boundary prevents stale, invalid, or excluded content from silently entering the completion prompt.

Sources: extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/contextProviders/codeSnippets.ts

The prompt component then prepares those contextual snippets for the model. CodeSnippets listens for completion request data, exits when there are no snippets or no document, attaches relative paths, groups snippets with the same URI together, filters out empty snippet values, and computes group importance from the maximum importance value in each group. It sorts by importance and reverses the output so the most important group is emitted last, then renders natural-language prompt text such as comparing a snippet or multiple snippets from a URI. This is prompt assembly, not user snippet insertion.

Sources: extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/components/codeSnippets.tsx, extensions/copilot/src/extension/completions-core/vscode-node/lib/src/prompt/contextProviders/codeSnippets.ts

Chat Editing and Generated Code Blocks

Chat editing introduces a third related concept: generated code blocks that must be mapped back into workspace edits. ICodeMapperRequest carries code blocks with code, resource URI, optional markdown-before-block text, chat request metadata, session resource, model name, and location. A mapper provider implements mapCode, writing text edits or notebook cell edits through ICodeMapperResponse. CodeMapperService keeps registered providers and delegates to the first provider, returning early if cancellation is requested. This service contract is useful when AI output must become concrete file or notebook changes.

Sources: src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts

The editor integration for chat editing sits on top of normal editor and diff infrastructure. The imported types show that the integration works with code editors, overlay widgets, view zones, diff rendering, line range mappings, model decorations, minimap and overview ruler colors, editor selection reveal behavior, accessibility signals, and modified-file entry state. That surface is broader than snippets, but it is relevant because snippet-like generated code still needs review, decoration, accessibility, and acceptance flows when it arrives from chat. User snippets insert known templates; chat edits present generated changes that require richer review UI.

Sources: src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts, src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts

Practical Authoring and Verification Flow

When authoring snippets, start with the built-in user-snippet workflow before packaging anything. Create or edit a language-specific or global snippet file, verify that the prefix appears in IntelliSense, test Insert Snippet from the Command Palette, and decide whether tab completion is appropriate for the audience. If the snippet is intended to wrap selected text, verify it with a non-empty selection and the surround-with action path. If it is intended to create an entire file, verify it from an empty model so the file-template action can appear.

For extension packaging, copy the tested snippet JSON into the extension folder, declare it under contributes.snippets, and tag the extension category as Snippets when it is primarily a snippet bundle. If the extension also contributes language support, keep snippets and grammars conceptually separate in reviews: snippets prove insertion behavior, while grammars prove tokenization and theming. For AI or chat-related investigations, inspect whether the term snippet refers to an authored snippet template, a Copilot context excerpt, or a generated chat code block before tracing the wrong subsystem.

Compact Reference

AreaConcrete source-level contractUser-visible effect
Surround with snippetSurroundWithSnippetCodeActionProvider.provideCodeActions(model, range) returns no actions for an empty range and uses getSurroundableSnippets for non-empty selections.Selected code can be wrapped by eligible snippets from the lightbulb or command path.
File template snippetFileTemplateCodeActionProvider.provideCodeActions(model) returns actions only when model.getValueLength() === 0.Empty files can be started from template snippets.
Action kindCodeActionKind.SurroundWith = Refactor.append('surround').Snippet surround actions participate in refactor-style code-action filtering.
Copilot context snippetgetCodeSnippetsFromContextItems(...) filters CodeSnippet items and validates all referenced URIs.Only valid contextual code excerpts enter completion prompts.
Prompt renderingCodeSnippets groups snippets by URI, filters empty values, orders by importance, and renders prompt chunks.The model sees grouped code evidence with relative paths where available.
Chat code mappingICodeMapperProvider.mapCode(request, response, token) emits text edits or notebook edits.Chat-generated code blocks can become reviewed workspace changes.