vscode-changelists
Organize your Git changes into named groups — just like JetBrains Rider.
Features
- Create, rename, and delete changelists
- Drag & drop files between changelists
- Bulk stage/unstage per changelist
- Move files via quick pick (
Ctrl+Shift+P → "Move to Changelist")
- Workspace-level persistence (survives restarts)
Usage
- Open the Source Control panel (
Ctrl+Shift+G / Cmd+Shift+G)
- Find the Changelists section in the activity bar
- Right-click to create a new changelist
- Drag files between groups, or right-click → Move to Changelist
Requirements
- VSCode 1.109.0+
- Git extension (built-in) must be enabled
Commands
| Command |
Description |
| Create Changelist |
Creates a new named group |
| Rename Changelist |
Rename an existing group |
| Delete Changelist |
Remove group; files return to Default |
| Move to Changelist |
Quick pick to reassign a file |
| Move to Default Changelist |
Move file directly to the Default group |
| Stage Changelist |
Bulk stage all files in a group |
| Unstage Changelist |
Bulk unstage all files in a group |
Architecture Overview
If you're new to VSCode extension development, here's how the pieces fit together.
Extension Lifecycle
Every extension has an activate() function (src/extension.ts) that VSCode calls on load. The package.json declares when to activate — this extension uses onStartupFinished, meaning it loads after VSCode is ready.
package.json is the Manifest
This is the most important file. It declares everything the extension contributes to VSCode:
contributes.commands — Command IDs (e.g. vscode-changelists.createChangelist) that appear in the Command Palette
contributes.views — Tree views in panels (ours lives in the SCM panel)
contributes.menus — Maps commands to context menus, title bars, and inline buttons. Uses when clauses to control visibility
activationEvents — Tells VSCode when to load the extension
Core APIs Used
| API |
Purpose |
vscode.commands.registerCommand |
Binds functions to command IDs |
vscode.window.createTreeView |
Creates the changelist tree widget with drag-and-drop |
TreeDataProvider |
Interface defining tree content via getChildren() and getTreeItem() |
vscode.scm.createSourceControl |
Creates an entry in the Source Control panel with resource groups |
context.workspaceState |
Key-value store persisted per-workspace (survives restarts) |
vscode.extensions.getExtension('vscode.git') |
Accesses the built-in Git extension API |
FileDecorationProvider |
Adds git status badges (M, A, D) to files in tree views |
How the Pieces Connect
package.json declares: "I have command X, view Y, menu item Z"
↓
activate() wires them: registerCommand(X, handler)
createTreeView(Y, treeProvider)
↓
User interacts: clicks tree item → command fires → model updates
↓
View refreshes: model fires event → tree provider calls refresh()
→ VSCode re-calls getChildren() → UI updates
Data Flow
- VSCode Git extension fires a repo state change →
GitService emits onDirtyFilesChanged
extension.ts calls model.assignUntracked(dirtyUris) to auto-assign new files to the Default changelist
ChangelistModel updates state, persists, and fires onDidChange
ChangelistTreeProvider and ChangelistProvider listen and refresh their views
Key Concepts
- Disposables — Everything you create (commands, views, providers) returns a
Disposable. Push them to context.subscriptions so they clean up when the extension deactivates.
when clauses — JSON expressions in package.json that control when menu items are visible, referencing values like viewItem and view.
contextValue — Set on tree items to control which context menu actions appear (e.g. changelist-default-staged).
- Events — VSCode uses
vscode.EventEmitter<T> for change notifications (e.g. onDidChangeTreeData tells VSCode to re-render the tree).
For the full file-by-file breakdown, see CLAUDE.md.
Development
npm install # Install dependencies
npm run compile # Compile TypeScript
npm run watch # Watch mode for development
npm run lint # Run ESLint
npm run test # Run tests
Press F5 in VSCode to launch the Extension Development Host.
Known Limitations
- Changelists are UI-only — they have no effect on git state
- The Default changelist cannot be deleted