| name | vscode-package-json-and-contributes |
| description | Guidance for updating VS Code extension package.json fields and contributes entries while keeping activation events, menus, and localization aligned. |
Skill: package.json Contribution Points
Overview
package.json is the single source of truth for everything VS Code knows about an extension
before it activates. It is statically parsed by VS Code at startup. Every user-visible
feature (commands, settings, menus, languages, grammars, snippets, etc.) must be declared here.
Key Top-Level Fields
{
"name": "my-extension",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.2.3",
"publisher": "myPublisher",
"engines": { "vscode": "^1.100.0" },
"main": "./dist/extension.js",
"activationEvents": [...],
"contributes": { ... }
}
activationEvents
| Event | When to use |
|---|
onLanguage:<id> | Extension serves a specific language |
onCommand:<id> | Command invoked from Command Palette or menu |
onStartupFinished | Delay until after all eager extensions load |
workspaceContains:<glob> | Workspace contains specific files |
* | Avoid — eager activation harms startup time |
Tip: As of VS Code 1.74, most onCommand: events are inferred automatically.
You still need onLanguage: and workspaceContains: explicitly.
contributes.commands
"commands": [
{
"command": "ext.myCommand",
"title": "%command.myCommand.title%",
"category": "%command.myCommand.category%",
"icon": "$(symbol-method)",
"enablement": "editorLangId == fxml"
}
]
- Every
command value must be registered in TypeScript via vscode.commands.registerCommand.
- Use
%key% placeholders for all user-visible strings.
category groups the command in the Command Palette under Category: Title.
contributes.menus
"menus": {
"editor/context": [
{
"command": "ext.myCommand",
"when": "resourceLangId == fxml",
"group": "navigation"
}
],
"explorer/context": [...],
"editor/title": [...],
"commandPalette": [
{ "command": "ext.internalCommand", "when": "false" }
]
}
group controls ordering: navigation, 1_modification, 9_cutcopypaste, z_commands.
contributes.configuration
"configuration": {
"title": "%config.title%",
"properties": {
"ext.myFeature.enabled": {
"type": "boolean",
"default": true,
"description": "%config.myFeature.enabled.description%",
"scope": "resource"
}
}
}
- Use
"scope": "resource" for workspace-folder-level settings (most common).
- Use
"scope": "machine" for paths to external executables (e.g., Scene Builder path).
- Add
"markdownDescription" for rich hover documentation with links and code.
contributes.languages
"languages": [
{
"id": "fxml",
"aliases": ["FXML", "fxml"],
"extensions": [".fxml"],
"configuration": "./language-configuration.json",
"icon": { "light": "./images/fxml-light.svg", "dark": "./images/fxml-dark.svg" }
}
]
language-configuration.json defines brackets, comments, auto-closing pairs, and indentation rules.
contributes.grammars
"grammars": [
{
"language": "fxml",
"scopeName": "source.fxml",
"path": "./syntaxes/fxml.tmLanguage.json"
}
]
scopeName must match the scopeName field inside the .tmLanguage.json file.
- Injected grammars use
"injectTo": ["source.java"] to augment another language.
contributes.snippets
"snippets": [
{ "language": "fxml", "path": "./snippets/fxml.json" }
]
contributes.keybindings
"keybindings": [
{
"command": "ext.myCommand",
"key": "ctrl+shift+o",
"mac": "cmd+shift+o",
"when": "editorLangId == fxml"
}
]
contributes.configurationDefaults
Override default settings for a language or globally:
"configurationDefaults": {
"[fxml]": {
"editor.semanticHighlighting.enabled": false,
"editor.formatOnSave": true
}
}
Checklist for package.json Changes
References