This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
NoteMode is a lightweight desktop text editor built with C# (.NET 10.0) and Avalonia UI framework using MVVM architecture.
# Build (from src/ directory)
cd src
dotnet build
# Run the application
dotnet run --project NoteMode
# Release build
dotnet build -c ReleaseSolution file: src/NoteMode.sln
MVVM Pattern with manual dependency injection:
- Models/ - Data structures for state serialization (
AppState,TabState) - Services/ - Business logic:
StateService(JSON persistence),CacheService(tab content caching),SyntaxService(language detection and highlighting) - ViewModels/ - Presentation logic with
INotifyPropertyChangedbindings andRelayCommandfor commands - Views/ - Avalonia XAML (
.axaml) UI definitions
Data Flow:
User Input → MainWindow Events → MainWindowViewModel Commands
→ Services → TabViewModel State → EditorView UI
State Persistence:
- App state:
~/.notemode/state.json(window size, font size, active tab, tabs list) - Tab content cache:
~/.notemode/cache/{TabId}.cache(auto-saved every 500ms)
- Avalonia 11.3.x - Cross-platform UI framework
- Avalonia.AvaloniaEdit 11.4.0 - Text editor component
- ReactiveUI.Avalonia - Reactive extensions for MVVM
Program.cs- Avalonia app builder setupApp.axaml.cs- Service creation, ViewModel initialization, shutdown handlingMainWindow.axaml.cs- UI events, file dialogs, drag-and-drop
Each tab (TabViewModel) has:
- Dirty state tracking: Compares current content vs. original, shows "●" indicator when modified
- Auto-caching: Content saved to disk 500ms after changes (debounced)
- Syntax highlighting: Applied based on file extension via
SyntaxService(30+ languages supported)
Smart tab selection: When closing a tab, selects next tab to the right, or previous if rightmost.
Uses Dracula color scheme defined in Themes/Dracula.axaml:
- Background:
#282a36, Title bar:#21222c, Foreground:#f8f8f2 - Syntax colors set in
SyntaxService.cs(comments gray, strings yellow, keywords pink, etc.)
- All UI icons (except the app icon) use Lucide SVG paths from https://github.com/lucide-icons/lucide/tree/main/icons
- Icons are stroke-based: use
Stroke,StrokeThickness="1.5",StrokeLineCap="Round",StrokeJoin="Round"— neverFillfor icons. (Avalonia usesStrokeJoin, notStrokeLineJoin.) - Lucide SVGs use a 24×24 viewBox. Multi-element SVGs (multiple
<path>,<circle>,<rect>,<ellipse>) must be combined into a singleDatastring:- Concatenate multiple
<path d="..."/>with spaces:"M3 12h18 M12 3v18" - Convert
<circle cx="12" cy="12" r="10"/>→M2 12a10 10 0 1 0 20 0a10 10 0 1 0-20 0 - Convert
<ellipse cx="12" cy="5" rx="9" ry="3"/>→M3 5a9 3 0 1 0 18 0a9 3 0 1 0-18 0 - Convert
<rect x="3" y="3" width="18" height="18" rx="2"/>→M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z
- Concatenate multiple
- When adding new icons, find the matching Lucide icon at the URL above, fetch its SVG, and convert using the rules above.
Defined in MainWindow.axaml:
Ctrl+NNew tab,Ctrl+OOpen,Ctrl+SSave,Ctrl+Shift+SSave AsCtrl+Shift+ASave All,Ctrl+WClose tab,Ctrl+Shift+WToggle whitespaceCtrl+ScrollFont size (6-72pt, handled inEditorView.axaml.cs)