This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
VolumeKeeper is a Windows desktop application that manages per-application volume settings. It monitors volume changes in the Windows Volume Mixer, saves them, and automatically restores volume levels when applications launch.
- Surgical Precision: Only make changes explicitly requested by the user
- Minimal Changes: Make the smallest number of human-understandable changes possible
- No "Boyscout" Changes: Avoid fixing unrelated issues unless explicitly requested
- Honesty Over Pleasing: Be honest about limitations rather than attempting to please
- Document Don't Fix: Note related issues but don't fix them without user request
- Respect Existing Patterns: Follow established code patterns even if not optimal
Follow these collaborative principles:
- Reflect independently before proposing solutions
- Consider implications within Windows/WinUI 3 constraints
- Identify potential issues with audio APIs and permissions
- Document reasoning and assumptions
- Explicitly state your position and reasoning
- Address concerns before proceeding
- Base decisions on technical merit
- Document compromises and rationale
- Focus solely on the specific task requested
- Be explicit about what will and won't be changed
- Separate suggestions from current work
- Respect existing WinUI 3/MVVM patterns
- Use latest C# features (nullable reference types, file-scoped namespaces)
- Follow .NET naming conventions (PascalCase for public members, camelCase for private)
- Use
async/awaitfor all IO operations and UI updates - Prefer LINQ over loops where readable
- Use dependency injection for testability
- Implement
INotifyPropertyChangedfor data binding - Use
ConfigureAwait(false)for non-UI async calls - Avoid using
this.prefix unless necessary for disambiguation - Prefer guard clauses over nested if statements for early returns
Follow Uncle Bob's clean code principles for maintainable, readable code:
- Single Responsibility: Each method should do one thing well
- Small Methods: Keep methods small (ideally < 20 lines)
- Descriptive Names: Use intention-revealing names that explain what the method does
- Method Arguments: Prefer fewer arguments (0-3 ideal, avoid >4)
- No Side Effects: Methods should not have hidden side effects
- Extract Helper Methods: Break down complex logic into well-named helper methods
- Extract Configuration: Use classes to group related settings
- Eliminate Duplication: Don't repeat yourself (DRY principle)
- Meaningful Comments: Write code that explains itself; use comments sparingly for "why" not "what"
- Consistent Formatting: Follow consistent indentation and spacing
- Error Handling: Use proper exception handling, especially for Windows API calls
- Small Classes: Classes should have a single reason to change
- Cohesion: Class methods should work together toward a common purpose
- Encapsulation: Hide implementation details, expose only what's necessary
- Composition over Inheritance: Prefer composition when possible
- MVVM Pattern: Separate View, ViewModel, and Model concerns
- Classes: Use nouns (e.g.,
VolumeManager,ApplicationSettings) - Methods: Use verbs (e.g.,
SaveVolumeSettings,DetectApplicationLaunch) - Properties: Use descriptive names (e.g.,
CurrentVolumenotVol) - Events: Use EventHandler suffix (e.g.,
VolumeChangedEventHandler) - Constants: Use PascalCase (e.g.,
DefaultVolume)
- AVOID unnecessary comments: Code should be self-explanatory through good naming and structure
- Extract methods instead: If code needs explanation, extract it to a well-named method
- ONLY comment for unusual/unexpected behavior: Add comments when code does something non-obvious
- Example: Windows API quirks or workarounds
- Example: Audio session management complexities
- XML Documentation: Use for public APIs only
- Remove obsolete comments: Keep comments accurate and current
- Extract Method: When logic becomes complex, extract into helper methods
- Extract Class: When a class has too many responsibilities
- Extract Interface: For testability and loose coupling
- Replace Magic Numbers: Use named constants for hardcoded values
- Understand the Request: What exactly is being asked? Is it clear and specific?
- Assess Impact: What modules/files will be affected? Are there dependencies?
- Consider Alternatives: Are there simpler approaches? What are the trade-offs?
- Plan Minimally: What's the smallest change that addresses the request?
- Identify Risks: What could break? What threading issues exist?
- Is this change compatible with the target .NET version?
- Are we following best practices and MVVM patterns?
- Is error handling adequate for Windows API calls?
- Does this maintain responsiveness (no blocking UI thread)?
# Build the project
dotnet build
# Run the application
dotnet run --project VolumeKeeper
# Build in Release mode
dotnet build -c Release
# Publish for release
dotnet publish -c Release
# Run tests (when implemented)
dotnet test- .NET 9.0 SDK
- Windows OS (net9.0-windows target)
- Visual Studio 2022 or VS Code with C# extensions
The project follows a WinUI 3 application structure with MVVM implementation:
- App.xaml/App.xaml.cs: WinUI 3 application entry point with system tray integration
- MainWindow.xaml/MainWindow.xaml.cs: Main UI window with NavigationView for Home and Logs tabs
- HomePage.xaml/HomePage.xaml.cs: Volume management tab with application list and controls
- LogsPage.xaml/LogsPage.xaml.cs: Activity feed tab showing real-time logs
-
Audio Management Layer
- Windows Core Audio API wrapper (using NAudio)
- Volume monitoring service
- Application detection service
- Volume restoration service
-
Data Layer
- Settings persistence (JSON)
- Application volume profiles
- Configuration management
-
UI Layer
- System tray integration
- Main window with tabs (Home, Logs)
- MVVM ViewModels for data binding
- Real-time logging display
-
Services
- Background monitoring service
- Application launch detection
- Volume change detection and persistence
- Logging service with timestamps
- MVVM Pattern: Separate UI from business logic
- Async Operations: Keep UI responsive
- Service Pattern: Encapsulate audio and persistence logic
- Observer Pattern: For volume change notifications
- Repository Pattern: For settings persistence
- Target .NET 9.0 with WinUI 3 for UI
- Use async/await for all potentially blocking operations
- Implement core functionality in order: detect → store → restore
- Focus on minimal, clean implementation
- Handle audio system access errors gracefully
- Provide real-time logging for user visibility
- Ensure proper disposal of audio resources
- Handle Windows session changes (lock/unlock, sleep/wake)
CRITICAL: Always log exceptions instead of swallowing them silently. Every catch block must:
- Log the exception using the appropriate Logger method (
Error,Warn,Info,Debug) - Include context about what operation failed
- Use a named logger for automatic source inference
The Logger class supports named loggers that automatically infer the source from the calling location:
Recommended approach (automatic source inference):
private readonly Logger _logger = new ConsoleLogger().Named();
try
{
// Some operation
}
catch (Exception ex)
{
_logger.Error("Failed to perform operation X", ex);
// Source is automatically inferred from the calling class
}Alternative approach (explicit source):
try
{
// Some operation
}
catch (Exception ex)
{
App.Logger.Error("Failed to perform operation X", ex, "ComponentName");
}Debug(message, exception?, source?)- Detailed diagnostic informationInfo(message, exception?, source?)- General informational messagesWarn(message, exception?, source?)- Warning messages for potential issuesError(message, exception?, source?)- Error messages for failures
Never use empty catch blocks or silent exception handling. The logging service provides visibility to users about what's happening in the application.
The main feature of VolumeKeeper is to persist and restore application volume levels automatically:
- Monitor volume changes for all applications in real-time
- Capture volume modifications from both:
- VolumeKeeper's own UI controls
- Windows Volume Mixer changes
- Save volume levels immediately when changed
- Use JSON file for storing volume settings
- Structure:
{ "executable.exe": volumePercentage } - Example:
{ "firefox.exe": 75, "chrome.exe": 50, "spotify.exe": 30 } - Store as percentage values (0-100) for user clarity
- Match applications by full executable path
- Case-insensitive matching (e.g., "C:\Firefox\firefox.exe" = "c:\firefox\FIREFOX.EXE")
- Different installations of the same executable can have different pinned volumes
- Ignore all other attributes:
- Icon
- File hash
- Command line arguments
- Window title
- Detect when applications launch
- Check if saved volume exists for the executable path
- Automatically apply the saved volume level
- Log all restoration activities
- Use NAudio for Windows Core Audio API access
- Thread-safe JSON file operations
- Background services for monitoring
- Real-time logging of all activities
VolumeKeeper is a fully functional Windows application with the following implemented features:
- ✅ Volume Persistence Architecture: Implemented using
VolumeSettingsManagerwith JSON storage - ✅ Background Monitoring Services:
AudioSessionManagerandAudioSessionServiceprovide real-time monitoring - ✅ Volume Storage and Restoration: Automatic volume restoration on application launch
- ✅ User Interface: Complete WinUI 3 interface with Home and Logs tabs
- ✅ System Tray Integration: Fully functional system tray with quick access menu
- ✅ Multi-Device Support: Tracks audio sessions across all active audio devices
- ✅ Real-time Logging: Comprehensive activity logging with timestamps
- Support for multiple audio session controls per process
- Dynamic audio device change detection and handling
- Improved resource management and disposal patterns
- Enhanced device switching support
The application follows the planned architecture with all core components implemented:
- Audio Management Layer: Complete (AudioSessionManager, AudioSessionService)
- Data Layer: Complete (VolumeSettingsManager, WindowSettingsManager)
- UI Layer: Complete (MainWindow, HomePage, LogsPage, system tray)
- Services: Complete (monitoring, detection, persistence, logging)