Context Switcher
A VSCode/Cursor extension that tracks tab events, Git branch changes, and maintains persistent state per branch.
Features
- Tab Change Tracking: Monitors when you switch between tabs and logs the file information
- File Save Tracking: Logs when files are saved
- Document Open Tracking: Logs when new documents are opened
- Git Branch Tracking: Monitors the current Git branch and logs when it changes
- Workspace Change Tracking: Detects when switching between different projects
- State Persistence: Maintains file activity state per branch in JSON format
- File Activity Tracking: Tracks number of changes and last viewed times for files
- Branch File Search: Quick search through files in current branch with smart ordering
- Favorite Files: Mark files as favorites with visual indicators and priority sorting
- Async Operations: All file operations use async/await for better performance
Development
Prerequisites
- Node.js (version 16 or higher)
- npm or yarn
- Git (for branch tracking functionality)
Setup
Install dependencies:
npm install
Compile the extension:
npm run compile
Debug the Extension:
- Press
F5
in VSCode/Cursor to launch a new Extension Development Host window
- Or use the "Run Extension" configuration from the Debug panel
- The extension will automatically compile before launching
Debugging
The project includes VS Code configuration files for easy debugging:
.vscode/tasks.json
: Defines npm tasks (compile, watch, test, lint)
.vscode/launch.json
: Debug configurations for running the extension
.vscode/settings.json
: Workspace settings for TypeScript and ESLint
Debug Configurations
- Run Extension: Launches the extension in a new Extension Development Host window
- Extension Tests: Runs the extension tests in debug mode
Available Tasks
- npm: compile: Compiles TypeScript to JavaScript
- npm: watch: Watches for changes and recompiles automatically
- npm: test: Runs the test suite
- npm: lint: Runs ESLint on TypeScript files
Testing
- Open the Extension Development Host window
- Open some files and switch between tabs
- Save files
- Switch Git branches (if in a Git repository)
- Check the Developer Console (Help > Toggle Developer Tools) to see the logged events
Available Commands
Context Switcher: Hello World
- Shows a test message to verify the extension is working
Context Switcher: Forget Current File
- Removes the current file from state tracking
Context Switcher: Show Current State
- Displays current branch state information
Context Switcher: Search Files in Current Branch
- Quick search through files in current branch
Context Switcher: Clean Up State (Remove Unwanted Files)
- Removes unwanted files from state tracking
Context Switcher: Toggle Favorite Status
- Mark/unmark the current file as a favorite
Context Switcher: Unfavorite Current File
- Remove favorite status from the current file
Context Switcher: Find in Context
- Open global search with tracked files from current branch
Keyboard Shortcuts
Option+P
(Mac) / Alt+P
(Windows/Linux) - Search files in current branch
Cmd+Shift+8
(Mac) / Ctrl+Shift+8
(Windows/Linux) - Toggle favorite status of current file
Cmd+Option+F
(Mac) / Ctrl+Alt+F
(Windows/Linux) - Find in context (global search with tracked files)
Testing
The project includes comprehensive integration tests using memfs
(in-memory file system) to verify JSON file operations:
Running Tests
npm test
Test Coverage
The tests verify:
- File System Operations: Directory creation, file reading/writing, error handling
- JSON Serialization: State data structure serialization and deserialization
- State Management: Complex state structures and data integrity
- Error Handling: Graceful handling of file system errors
- Async Operations: All StateManager methods use async/await patterns
- State Persistence: Async file operations for state saving and loading
Test Structure
test/simpleStateManager.test.ts
- Core integration tests using memfs
- Tests use in-memory file system to avoid affecting real files
- Verifies all file operations work correctly with the expected JSON structure
- Tests async StateManager operations and state persistence
Async StateManager API
The StateManager now uses async methods for all file operations:
// Branch management
await stateManager.onBranchCreated(branchName: string): Promise<void>
await stateManager.setCurrentBranch(branchName: string): Promise<void>
// File tracking
await stateManager.onFileOpened(filename: string): Promise<void>
await stateManager.onFileSaved(filename: string, numChanges: number): Promise<void>
await stateManager.forgetFile(filename: string): Promise<void>
// Utility methods (sync)
stateManager.getCurrentBranchState(): BranchState | null
stateManager.getAllBranches(): string[]
stateManager.getBranchState(branchName: string): BranchState | null
Event Logging
The extension logs the following events to the console:
[TAB OPENED/CHANGED]
- When switching between tabs
[FILE SAVED]
- When a file is saved
[DOCUMENT OPENED]
- When a new document is opened
[GIT BRANCH DETECTED]
- When a Git branch is first detected
[GIT BRANCH CHANGED]
- When switching between Git branches
[WORKSPACE CHANGED]
- When switching between different projects
[STATE]
- State management events (file opened, saved, forgotten)
[STATE INFO]
- State information and statistics
[SEARCH]
- File search and opening events
Each log entry includes:
- File path (for file events)
- File language/type (for file events)
- Git branch name (for Git events)
- Git repository URL (for Git events)
Git Branch Tracking
The extension automatically detects Git repositories and tracks branch changes using the simple-git
Node.js SDK. It will:
- Detect the current branch when the extension starts
- Monitor for branch changes during file operations
- Periodic Branch Checking: Checks for branch changes every 5 seconds
- Window Focus Detection: Detects branch changes when VS Code window becomes focused
- Log branch transitions with repository information
- Handle cases where no Git repository is present
- Use native Node.js APIs instead of CLI command execution
Branch Change Detection Methods
The extension uses multiple strategies to detect Git branch changes:
Event-Based Detection: Checks for branch changes when:
- Switching between tabs
- Saving files
- Opening new documents
- Changing workspaces
Periodic Detection: Automatically checks for branch changes every 5 seconds using a background timer
Window Focus Detection: Detects branch changes when the VS Code window becomes focused (useful when switching back from terminal or other applications)
This multi-layered approach ensures that branch changes are detected quickly and reliably, even when they happen outside of VS Code (e.g., when switching branches in the terminal).
State Management
The extension maintains persistent state for each branch in a JSON file located at ~/.context-switcher/context-switcher-state.json
. The state includes:
{
"currentBranch": "main",
"branchesWorkedOn": {
"main": {
"lastOpenedAt": "2024-01-01T10:00:00.000Z",
"files": [
{
"filename": "/path/to/file.ts",
"numChanges": 150,
"lastViewedAt": "2024-01-01T10:30:00.000Z",
"isFavorite": true
}
]
}
}
}
State API
onBranchCreated(branchName)
- Adds a new branch to tracking
onFileOpened(filename)
- Tracks when a file is opened
onFileSaved(filename, numChanges)
- Updates file with change count
forgetFile(filename)
- Removes file from tracking
toggleFavorite(filename)
- Toggles favorite status of a file
cleanupUnwantedFiles()
- Removes unwanted files from all branches
File Filtering
The extension automatically filters out unwanted files to keep the state clean and relevant:
Excluded Files/Directories:
- Git-related files (
.git/
directories, files with .git
extension)
- Node.js dependencies (
node_modules/
)
- Build outputs (
out/
, dist/
, build/
)
- Temporary files (
tmp/
, temp/
)
- System files (
.DS_Store
, Thumbs.db
)
- Extension's own state file (
.context-switcher/context-switcher-state.json
)
- Files without extensions (likely directories or special files)
Automatic Cleanup:
- Runs during extension initialization
- Can be triggered manually via the "Clean Up State" command
- Logs filtered files for transparency
State Features
- In-Memory + File Persistence: Current branch state is kept in memory and saved to file
- Cross-Branch Tracking: Maintains separate state for each Git branch
- File Activity Metrics: Tracks number of changes and last viewed times
- Automatic Cleanup: Files can be manually removed from tracking
- Workspace Awareness: State is maintained per workspace
- Async Operations: All file I/O operations use async/await for better performance
- Selective Tracking: Only tracks files opened by the user after changing to a branch, not pre-existing tabs when the extension starts
Selective File Tracking
The extension implements intelligent file tracking that only monitors files opened by the user after changing to a branch:
How It Works
- Extension Startup: When the extension starts, it captures a snapshot of all currently open files but does not track them
- Initial File Capture: The extension records which files were already open when it started
- User Actions Only: Only files opened, saved, or switched to after extension initialization are tracked
- Comprehensive Filtering: All file events (open, save, tab change) filter out initially open files
- Pre-existing File Filtering: Files that were open when the extension started are automatically filtered out
- Branch Switching: When switching branches, the extension starts fresh tracking for the new branch
Benefits
- Clean State: Each branch starts with a clean slate, only tracking user-initiated actions
- Relevant Data: State only contains files the user actually worked on in that branch
- No Noise: Pre-existing tabs from previous sessions don't clutter the state
- Accurate Metrics: File change counts and view times reflect actual user activity
Example Scenario
- User opens VSCode with 5 tabs already open from previous work
- Extension starts and detects current branch is "feature-branch"
- Extension does NOT track the 5 existing tabs
- User opens 2 new files and saves them
- Only the 2 new files are tracked in the state
- User switches to "main" branch
- Extension starts fresh tracking for "main" branch
- Any files opened in "main" are tracked separately
Branch File Search
The extension provides a powerful search feature to quickly find and open files in the current branch:
Search Features
- Smart Ordering: Files are sorted by:
- Number of changes (descending) - most heavily changed files first
- Last viewed time (descending) - most recently viewed files first
- Quick Access: Use
Option+P
(Mac) or Alt+P
(Windows/Linux) to open search
- Rich Information: Each file shows:
- File name and relative path
- Number of changes made
- Last viewed timestamp
- Fuzzy Search: Search by file name, path, or details
- One-Click Opening: Select a file to immediately open it
Search Interface
The search shows a quick pick dialog with:
- Label: File name (with ⭐ icon for favorites)
- Description: Relative path from workspace root
- Detail: Change count, last viewed time, and favorite status
- Placeholder: Current branch name and file count
Favorite Files
The extension allows you to mark files as favorites for quick access and priority in search results:
Features
- Visual Indicators: Favorite files show a ⭐ star icon in the file list
- Priority Sorting: Favorite files appear at the top of search results
- Persistent State: Favorite status is saved per branch and persists across sessions
- Quick Toggle: Use keyboard shortcut or command to toggle favorite status
How to Use
Via Keyboard Shortcut:
- Press
Cmd+Shift+F
(Mac) or Ctrl+Shift+F
(Windows/Linux) while a file is open
- The file will be marked/unmarked as favorite with a confirmation message
Via Command Palette:
- Press
Cmd+Shift+P
(Mac) or Ctrl+Shift+P
(Windows/Linux)
- Type "Toggle Favorite Status" and select the command
In File Search:
- Favorite files appear at the top of the search results with ⭐ icons
- Search results are sorted by: Favorites first → Most changes → Most recent
Favorite File Behavior
- Per-Branch: Each branch maintains its own set of favorite files
- Visual Feedback: Confirmation messages show when files are favorited/unfavorited
- Search Priority: Favorite files always appear first in search results
- State Persistence: Favorite status is saved to
~/.context-switcher/context-switcher-state.json
Dependencies
simple-git
: Node.js Git wrapper for programmatic Git operations
@types/vscode
: VSCode extension API types
typescript
: TypeScript compiler
memfs
: In-memory file system for testing
ts-node
: TypeScript execution for tests
Building for Production
npm run compile
The compiled extension will be in the out/
directory.