Comprehensive guide for developers working on Smart Commit.
- Prerequisites
- Setup
- Project Structure
- Architecture
- Development Workflow
- Debugging
- Adding Features
- Testing
- Packaging and Publishing
- Troubleshooting Development
| Software | Minimum Version | Recommended | Download |
|---|---|---|---|
| Node.js | 20.0.0 | 20.x LTS | nodejs.org |
| npm | 9.0.0 | Latest | Bundled with Node.js |
| Git | 2.0.0 | 2.40+ | git-scm.com |
| VS Code | 1.103.0 | Latest | code.visualstudio.com |
| TypeScript | 5.x | 5.x | npm install -g typescript |
node --version # v20.x.x
npm --version # 9.x.x
git --version # 2.x.x
code --version # 1.103.0+
tsc --version # 5.x.xgit clone https://github.com/maxinne-dev/vscode-smart-commit.git
cd vscode-smart-commitnpm installThis installs:
- Runtime:
simple-git,uuid - Dev: TypeScript, ESLint,
@typespackages, VSCE
npm run compileOutput is written to out/ directory.
code .vscode-smart-commit/
├── .vscode/ # VS Code configuration
│ ├── launch.json # Debug configurations
│ ├── settings.json # Editor settings
│ └── tasks.json # Build tasks
├── docs/ # Documentation
│ ├── CHANGELOG.md
│ ├── FEATURES.md
│ ├── USER_GUIDE.md
│ └── ...
├── src/ # TypeScript source code
│ ├── extension.ts # Entry point
│ ├── commands/ # Command handlers
│ │ └── index.ts
│ ├── services/ # Core business logic
│ │ ├── changeListManager.ts
│ │ ├── gitService.ts
│ │ ├── commitGuardService.ts
│ │ └── configService.ts
│ ├── providers/ # VS Code providers
│ │ ├── treeDataProvider.ts
│ │ └── dragDropController.ts
│ ├── types/ # TypeScript interfaces
│ │ ├── changeList.ts
│ │ ├── git.d.ts
│ │ └── index.ts
│ └── utils/ # Utility functions
│ ├── constants.ts
│ ├── helpers.ts
│ └── logger.ts
├── out/ # Compiled JavaScript (gitignored)
├── node_modules/ # Dependencies (gitignored)
├── package.json # Extension manifest
├── tsconfig.json # TypeScript configuration
├── .eslintrc.json # ESLint rules
├── .gitignore # Git ignore patterns
├── LICENSE # MIT License
└── README.md # Main documentation
Extension manifest defining:
- Metadata (name, version, publisher)
- Activation events
- Contributed commands, views, configuration
- Dependencies
- Scripts
Entry point with two exports:
activate(context): Called when extension activatesdeactivate(): Called when extension deactivates
TypeScript compiler configuration:
- Target: ES2020
- Module: CommonJS
- Output directory:
out/ - Source maps enabled
┌─────────────────────────────────────────────┐
│ VS Code Extension Host │
├─────────────────────────────────────────────┤
│ extension.ts (Entry Point) │
├─────────────────────────────────────────────┤
│ Commands │
│ - createList, deleteList, renameList │
│ - moveToList, stageList, setActiveList │
├─────────────────────────────────────────────┤
│ Services (Business Logic) │
│ ┌────────────────────────────────────────┐ │
│ │ ChangeListManager │ │
│ │ - State management │ │
│ │ - CRUD operations │ │
│ │ - Active list enforcement │ │
│ └────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ GitService │ │
│ │ - Git extension integration │ │
│ │ - Repository monitoring │ │
│ │ - File status tracking │ │
│ └────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ CommitGuardService │ │
│ │ - Staged file validation │ │
│ │ - Mixed list detection │ │
│ └────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ ConfigService │ │
│ │ - Settings management │ │
│ │ - Configuration change handling │ │
│ └────────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ Providers (UI Integration) │
│ ┌────────────────────────────────────────┐ │
│ │ TreeDataProvider │ │
│ │ - Tree view data source │ │
│ │ - List/Tree mode switching │ │
│ │ - Node generation │ │
│ └────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ TreeDragAndDropController │ │
│ │ - Drag-and-drop handling │ │
│ │ - Data transfer logic │ │
│ └────────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ Types & Utils │
│ - Type definitions │
│ - Constants │
│ - Logging │
│ - Helpers │
└─────────────────────────────────────────────┘
│ │
│ │
v v
┌──────────────────┐ ┌──────────────────┐
│ VS Code APIs │ │ Git Extension │
│ - workspace │ │ - Repository │
│ - window │ │ - Status │
│ - commands │ │ - Operations │
└──────────────────┘ └──────────────────┘
Role: Core state management and business logic
Responsibilities:
- Maintain in-memory list of change lists
- Enforce active list singleton pattern
- Persist state to workspace storage
- Emit change events for UI updates
- Handle CRUD operations (create, rename, delete)
- Manage file assignments
Key Methods:
createList(name): Create new change listdeleteList(id): Remove list and reassign filessetActiveList(id): Set singleton active listmoveFile(filePath, targetListId): Reassign filegetListForFile(filePath): Query file's listsaveState(): Persist to storage
Events:
onDidChangeState: Fired on list or file changesonDidChangeActiveList: Fired on active list change
Role: Integration with VS Code's Git extension
Responsibilities:
- Detect and access Git repositories
- Monitor Git state changes (modifications, staging, commits)
- Map Git file statuses to change lists
- Emit events for Git operations
Key Methods:
initialize(): Find and connect to Git extensiongetRepository(): Access current repositorygetChanges(): Get modified files with statusstageFiles(files): Stage files via Git APIonDidChange: Event for Git state changesonDidStageFiles: Event for staging operationsonDidCommit: Event for successful commits
Integration:
- Uses
vscode.gitextension API - Subscribes to Git repository events
- Debounces rapid changes (150ms)
Role: Validate staged files before commit
Responsibilities:
- Validate staged files belong to same change list
- Show warning dialog for mixed lists
- Provide unstage/commit/cancel options
- Intercept commit command (optional)
Key Methods:
validateStagedFiles(): Check for mixed listsshowGuardDialog(validation): Present options to userunstageExtraFiles(files): Remove non-primary files from staging
Flow:
- User triggers commit
- Service validates staged files
- If mixed lists detected, show dialog
- User chooses action (unstage/commit/cancel)
- Proceed or abort based on choice
Role: Data source for tree view
Responsibilities:
- Implement
vscode.TreeDataProvider<TreeNode> - Generate tree structure from change lists
- Switch between list and tree modes
- Handle expansions and refresh
Key Methods:
getChildren(element?): Return child nodesgetTreeItem(element): CreateTreeItemrepresentationrefresh(): Trigger UI updatereveal(file): Scroll to and select file
Node Types:
ChangeListNode: Change list headersDirectoryNode: Folders (tree mode only)FileNode: Individual files
1. User modifies file.ts
↓
2. Git extension detects change
↓
3. GitService receives onDidChange event
↓
4. GitService queries ChangeListManager for file's list
↓
5. If unassigned, ChangeListManager assigns to active list
↓
6. ChangeListManager fires onDidChangeState
↓
7. TreeDataProvider receives event
↓
8. TreeDataProvider calls refresh()
↓
9. Tree view updates UI
1. User stages files from change list "Feature A"
↓
2. User presses Ctrl+Enter
↓
3. CommitGuardService intercepts
↓
4. Service validates staged files
↓
5. Detects file from "Bug B" also staged
↓
6. Shows warning dialog
↓
7. User selects "Unstage Extra Files"
↓
8. Service unstages "Bug B" file
↓
9. Commit proceeds with only "Feature A" files
↓
10. GitService detects commit
↓
11. ChangeListManager removes committed files
↓
12. TreeDataProvider refreshes UI
Keep TypeScript compiler running:
npm run watch- Automatically recompiles on save
- Shows compilation errors in terminal
- Faster iteration
Method 1: F5 Keyboard Shortcut
- Open project in VS Code
- Press
F5 - Extension Development Host launches
- Test your changes
Method 2: Debug View
- View → Run (
Ctrl+Shift+D) - Select "Run Extension" from dropdown
- Click green play button
After making changes:
In Extension Development Host:
- Press
Ctrl+R(Windows/Linux) /Cmd+R(macOS) - Or: Developer → Reload Window
No need to restart; reload picks up recompiled code.
Typical Workflow:
-
Edit Code
- Modify TypeScript files in
src/ - Watch mode auto-compiles
- Modify TypeScript files in
-
Reload Extension
- Ctrl+R in Development Host
-
Test Changes
- Interact with extension
- Check Output → Smart Commit for logs
- Verify behavior
-
Iterate
- Repeat until satisfied
Setting Breakpoints:
- Open TypeScript file in
src/ - Click line number gutter (red dot appears)
- F5 to start debugging
- Interact with extension to hit breakpoint
Debugging Controls:
- Continue (F5): Resume execution
- Step Over (F10): Execute line, skip function calls
- Step Into (F11): Enter function calls
- Step Out (Shift+F11): Exit current function
- Restart (Ctrl+Shift+F5): Restart debug session
- Stop (Shift+F5): End debugging
Evaluate Expressions:
- Hit a breakpoint
- Open Debug Console (View → Debug Console)
- Type expressions to evaluate:
activeList.name manager.getAllLists().length JSON.stringify(state, null, 2)
Use Structured Logging:
import { logger } from './utils/logger';
logger.debug('Detailed info', { listId, fileName });
logger.info('Operation completed', { result });
logger.warn('Unexpected condition', { value });
logger.error('Operation failed', error);
logger.event('Git', 'Commit detected', { fileCount });View Logs:
- Output panel:
Ctrl+Shift+U/Cmd+Shift+U - Select "Smart Commit" from dropdown
Access:
- Help → Toggle Developer Tools
- Or:
Ctrl+Shift+I/Cmd+Option+I
Useful Tabs:
- Console: JavaScript errors and warnings
- Network: HTTP requests (if any)
- Application: Storage, cache (workspace state)
1. Update package.json
Add command contribution:
{
"command": "smartCommit.duplicateList",
"title": "Duplicate Change List",
"category": "Smart Commit",
"icon": "$(copy)"
}Add to context menu:
{
"command": "smartCommit.duplicateList",
"when": "view == smartCommit.changeLists && viewItem =~ /^changeList/",
"group": "3_edit@3"
}2. Define Types (if needed)
In src/types/changeList.ts:
// Existing interface is sufficient for this feature3. Add Service Method
In src/services/changeListManager.ts:
public duplicateList(listId: string): ChangeList | undefined {
const source = this.lists.find(l => l.id === listId);
if (!source) {
logger.warn('Cannot duplicate non-existent list', { listId });
return undefined;
}
const newList = this.createList(`${source.name} (Copy)`);
if (!newList) return undefined;
// Copy file assignments
const sourceFiles = this.getFilesForList(listId);
sourceFiles.forEach(file => {
this.fileMapping.set(file.resourceUri.fsPath, newList.id);
});
this.saveState();
this._onDidChangeState.fire();
logger.info('List duplicated', { sourceId: listId, newId: newList.id });
return newList;
}4. Register Command
In src/commands/index.ts:
export function registerCommands(
manager: ChangeListManager,
treeView: vscode.TreeView<AnyTreeNode>,
config: ConfigService
): vscode.Disposable {
const disposables: vscode.Disposable[] = [];
// ... existing commands ...
disposables.push(
vscode.commands.registerCommand(
COMMANDS.DUPLICATE_LIST,
async (node?: ChangeListNode) => {
if (!node) {
logger.warn('Duplicate list called without node');
return;
}
const duplicated = manager.duplicateList(node.list.id);
if (duplicated) {
vscode.window.showInformationMessage(
`Duplicated "${node.list.name}" as "${duplicated.name}"`
);
} else {
vscode.window.showErrorMessage('Failed to duplicate change list');
}
}
)
);
return vscode.Disposable.from(...disposables);
}5. Add Constant
In src/utils/constants.ts:
export const COMMANDS = {
// ... existing commands ...
DUPLICATE_LIST: 'smartCommit.duplicateList',
} as const;6. Test
- Compile:
npm run compile - Press F5 to launch
- Create a change list with files
- Right-click list → Duplicate Change List
- Verify new list appears with same files
7. Document
Update:
docs/FEATURES.md: Add "Duplicate List" sectiondocs/USER_GUIDE.md: Add workflow exampledocs/CHANGELOG.md: Add to[Unreleased]sectionREADME.md: Add to commands table
Manual Test Checklist:
- Feature works as expected
- No console errors
- Edge cases handled (empty lists, many files, etc.)
- UI updates correctly
- State persists across reloads
- Logs are informative
- Documentation updated
Automated Tests (Future):
When test infrastructure is added:
- Write unit tests for service methods
- Write integration tests for commands
- Add regression tests for bug fixes
Test Scenarios:
-
Basic Operations
- Create, rename, delete lists
- Move files between lists
- Set active list
- Stage and commit
-
Edge Cases
- Empty lists
- Many files (100+)
- Large files
- Rapid changes
- External Git operations
-
Error Handling
- Invalid list names
- Deleting active list
- Moving files from deleted lists
Not yet implemented. Planned:
Unit Tests:
npm run test:unitIntegration Tests:
npm run test:integrationE2E Tests:
npm run test:e2eCreate VSIX:
npm run packageOutput: smart-commit-0.0.1.vsix
code --install-extension smart-commit-0.0.1.vsixPrerequisites:
- Publisher account on Visual Studio Marketplace
- Personal Access Token (PAT) with
Marketplace (publish)scope
Publish:
vsce publishOr manually:
- Package:
npm run package - Upload VSIX to marketplace web UI
Update Version:
# Patch: 0.0.1 → 0.0.2
npm version patch
# Minor: 0.0.1 → 0.1.0
npm version minor
# Major: 0.0.1 → 1.0.0
npm version majorIssue: Extension Development Host doesn't show extension.
Solutions:
- Check compilation errors:
npm run compile - Check activation events in
package.json - View Output → Smart Commit for errors
- Restart Development Host
Issue: Debugger doesn't stop at breakpoints.
Solutions:
- Ensure source maps are enabled (
"sourceMap": trueintsconfig.json) - Recompile:
npm run compile - Restart debug session (Ctrl+Shift+F5)
- Check breakpoint is in executed code path
Issue: Code changes don't appear in Development Host.
Solutions:
- Check watch mode is running:
npm run watch - Verify compilation succeeded (no errors in watch terminal)
- Reload Extension Development Host: Ctrl+R / Cmd+R
- Check correct files are being edited (not
out/, onlysrc/)
Issue: Extension behaves oddly, state seems corrupted.
Solutions:
- Clear workspace state: Delete
.vscode-testfolder - Reinstall dependencies:
rm -rf node_modules && npm install - Clean build:
rm -rf out && npm run compile
- Read Architecture Docs: OVERVIEW.md, BLUEPRINT.md
- Review Code: Browse
src/to understand implementation - Contribute: See CONTRIBUTING.md for guidelines
- Ask Questions: GitHub Discussions
Happy developing! ✓