ClipFlow is a lightning-fast, minimal command-line clipboard history manager written in Odin. It emphasizes speed, simplicity, and zero-bloat design while solving the everyday problem of losing clipboard history.
- Clear, incremental architecture - Can be built module by module
- Well-defined interfaces - Each component has clear inputs/outputs
- Windows-first design - Native Win32 clipboard API integration
- Excellent testing story - Easy to unit test each component
- Performance measurable - Clear metrics to optimize
- Real-world utility - Solves an actual daily problem you can use daily
src/
├── main.odin # Entry point and CLI routing ✅
├── clipboard/
│ ├── system.odin # Windows clipboard API wrapper ✅
│ └── types.odin # Clipboard entry data structures ✅
├── storage/
│ └── history.odin # History persistence and retrieval ✅
├── cli/
│ └── commands.odin # Command parsing, interactive mode, thread-based daemon ✅
└── utils/
├── files.odin # File system utilities ✅
├── time.odin # Timestamp handling ✅
└── hash.odin # Content deduplication ✅
Thread-Based Design:
- Main Thread: Handles interactive command prompt and user input
- Background Thread: Monitors clipboard changes using Windows sequence numbers
- Shared State: Both threads access same clipboard history with proper synchronization
- Clean Lifecycle: Proper thread creation, management, and cleanup
Key Features:
- Double-click to start: No command line required - just double-click the .exe
- Real-time monitoring: Automatic clipboard capture in background
- Interactive prompt:
clipflow>command interface while monitoring continues - Integrated experience: No need for separate service management
- Proper cleanup: Background thread stops when exiting interactive mode
ClipboardEntry :: struct {
id: u64, // Unique identifier
content: string, // The actual clipboard text
timestamp: time.Time, // When it was copied
app_name: string, // Source application (if available)
hash: u64, // Content hash for deduplication
tags: []string, // User-defined tags (future feature)
}
Config :: struct {
max_entries: int, // Maximum history entries (default: 1000)
history_file: string, // Path to history storage
monitor_interval: f64, // Clipboard check interval in seconds
search_limit: int, // Max search results to display
data_format: string, // "json" or "binary"
}Goal: Basic clipboard capture and retrieval
Components to implement:
clipboard/system.odin- Linux X11 clipboard integrationstorage/history.odin- Simple JSON file storagemain.odin- Basic CLI withcapture,list,getcommandscli/commands.odin- Command parsing
Commands:
clipflow capture # Manually save current clipboard
clipflow list # Show recent entries (last 20)
clipflow list --all # Show all entries
clipflow get 5 # Copy entry #5 back to clipboardGoal: Real-time clipboard monitoring with interactive interface
Components implemented:
- Interactive mode with background thread-based daemon
- Automatic clipboard monitoring with sequence number detection
- Thread-based architecture for true background operation
- Clean daemon lifecycle management
New Architecture:
- Interactive Mode: Primary interface combining background monitoring with command prompt
- Thread-based Daemon: Background clipboard monitoring within same process
- Simplified Commands: Streamlined interface focused on interactive experience
Commands:
clipflow interactive # Interactive mode with background daemon (recommended)
clipflow --daemon-worker # Background worker process
clipflow monitor # Foreground monitoring (legacy)Goal: Fast search and optimization
Components to implement:
search/engine.odin- Text search with indexingsearch/fuzzy.odin- Fuzzy matchingutils/hash.odin- Deduplication- Performance profiling
Commands:
clipflow search "API key" # Search clipboard history
clipflow search --fuzzy "api ky" # Fuzzy search
clipflow search --app "firefox" # Filter by source app
clipflow stats # Show performance metricsGoal: Polish and advanced functionality
Components:
- Multiple clipboard format support (images, etc.)
- Encryption for sensitive data
- Export/import functionality
- Integration with system clipboard managers
// clipboard/system.odin interface ✅ **Complete Implementation**
get_clipboard_text :: proc() -> (string, bool) ✅
set_clipboard_text :: proc(text: string) -> bool ✅
get_clipboard_sequence_number :: proc() -> u32 ✅
is_clipboard_changed :: proc(last_sequence: u32) -> bool ✅
get_active_window_name :: proc() -> string ✅
// UTF conversion helpers ✅
utf16_to_utf8 :: proc(utf16_ptr: rawptr, utf16_len: c.int) -> (string, bool) ✅
utf8_to_utf16_global :: proc(text: string) -> (rawptr, bool) ✅Enhanced Implementation Features:
- Sequence Number Detection: Uses
GetClipboardSequenceNumber()for efficient change detection - Unicode Support: Full UTF-16 ↔ UTF-8 conversion with proper memory management
- Window Tracking: Captures source application name for each clipboard entry
- Memory Safety: Proper cleanup of global memory allocations
- Error Handling: Comprehensive error checking for all Windows API calls
Windows API Integration:
- Uses
user32.dllfunctions:OpenClipboard,GetClipboardData,SetClipboardData GetClipboardSequenceNumber()for efficient change detectionGetForegroundWindow()+GetWindowText()for active app tracking- Supports Unicode text (CF_UNICODETEXT) natively
Essential Windows APIs:
// Foreign function declarations for Windows clipboard
foreign import user32 "system:user32.lib"
foreign import kernel32 "system:kernel32.lib"
@(default_calling_convention="stdcall")
foreign user32 {
OpenClipboard :: proc(hwnd: rawptr) -> i32 ---
CloseClipboard :: proc() -> i32 ---
GetClipboardData :: proc(format: u32) -> rawptr ---
SetClipboardData :: proc(format: u32, data: rawptr) -> rawptr ---
GetClipboardSequenceNumber :: proc() -> u32 ---
GetForegroundWindow :: proc() -> rawptr ---
GetWindowTextW :: proc(hwnd: rawptr, text: [^]u16, max_count: i32) -> i32 ---
AddClipboardFormatListener :: proc(hwnd: rawptr) -> i32 ---
}
@(default_calling_convention="stdcall")
foreign kernel32 {
GlobalAlloc :: proc(flags: u32, size: uintptr) -> rawptr ---
GlobalLock :: proc(mem: rawptr) -> rawptr ---
GlobalUnlock :: proc(mem: rawptr) -> i32 ---
GlobalFree :: proc(mem: rawptr) -> rawptr ---
}
// Constants
CF_UNICODETEXT :: 13
GMEM_MOVEABLE :: 0x0002Clipboard Change Detection:
- Use
AddClipboardFormatListener()for efficient notifications - Alternative: Poll
GetClipboardSequenceNumber()every 500ms - Message loop for handling
WM_CLIPBOARDUPDATEmessages
Windows Service Integration:
// Service control functions
foreign import advapi32 "system:advapi32.lib"
@(default_calling_convention="stdcall")
foreign advapi32 {
RegisterServiceCtrlHandlerW :: proc(service_name: [^]u16, handler: rawptr) -> rawptr ---
SetServiceStatus :: proc(handle: rawptr, status: ^SERVICE_STATUS) -> i32 ---
StartServiceCtrlDispatcherW :: proc(table: ^SERVICE_TABLE_ENTRY) -> i32 ---
}JSON Format (Phase 1 - Human readable):
{
"version": "1.0",
"entries": [
{
"id": 1641234567890,
"content": "Hello world",
"timestamp": "2025-01-15T10:30:00Z",
"app_name": "firefox",
"hash": 12345678901234567890
}
]
}Binary Format (Phase 3 - Performance):
- Custom binary format with fixed-size headers
- Memory-mapped file access for large histories
- Built-in compression for large text entries
- Startup time: < 50ms for any command
- Search time: < 100ms for 10,000 entries
- Memory usage: < 10MB for daemon process
- Binary size: < 2MB executable
- Storage efficiency: < 1KB overhead per entry
Default config file: %APPDATA%\ClipFlow\config.json
{
"max_entries": 1000,
"history_file": "%LOCALAPPDATA%\\ClipFlow\\history.json",
"monitor_interval": 0.5,
"search_limit": 50,
"data_format": "json",
"enable_deduplication": true,
"min_entry_length": 3,
"excluded_apps": ["KeePass.exe", "Bitwarden.exe", "1Password.exe"],
"startup_with_windows": true,
"show_notifications": false
}- Each module should have corresponding
*_test.odinfiles - Mock clipboard for testing without system interaction
- Temporary files for storage testing
- End-to-end CLI command testing
- Cross-platform clipboard compatibility
- Performance benchmarking
- Sample clipboard histories of various sizes
- Edge cases (empty strings, very long text, special characters)
- Unicode and emoji handling
# Development build
odin build src -out:clipflow.exe -opt:0 -debug
# Release build
odin build src -out:clipflow.exe -opt:3 -no-bounds-check
# Static linking (for distribution)
odin build src -out:clipflow.exe -opt:3 -no-bounds-check -subsystem:consoleREM install.bat
@echo off
echo Installing ClipFlow...
copy clipflow.exe "%ProgramFiles%\ClipFlow\"
setx PATH "%PATH%;%ProgramFiles%\ClipFlow" /M
clipflow service install
clipflow startup enable
echo ClipFlow installed successfully!- Create MSI installer with WiX Toolset
- Add to Windows Add/Remove Programs
- Desktop shortcut and Start Menu entry
- Automatic service installation
- Start with data structures - Define all types in
clipboard/types.odin - Implement storage layer - Get file I/O working with simple JSON
- Basic clipboard API - Linux X11 integration (use
xclipinitially) - CLI framework - Command parsing and basic commands
- Add monitoring - Background clipboard watching
- Implement search - Text search and filtering
- Performance optimization - Profiling and improvements
- Error handling - Robust error management throughout
- Fail fast and clearly - Provide helpful error messages
- Profile early - Built-in timing for all operations
- Test everything - Each function should be easily testable
- Document as you go - Comments for all public interfaces
- Keep it simple - Resist feature creep, focus on core use case
Challenge: Windows clipboard API complexity Solution: Start with basic text, use Odin's foreign function interface for Win32 APIs
Challenge: Background monitoring without blocking Solution: Use Windows message loops, register for clipboard change notifications
Challenge: Large clipboard histories Solution: Implement lazy loading, pagination for display commands
Challenge: Security (passwords in clipboard) Solution: Content filtering, optional encryption, excluded applications
Challenge: Windows service management Solution: Use Windows Service Control Manager API, handle service lifecycle properly
- Executable size: < 2MB (compare to Electron apps at 100MB+)
- Memory usage: < 10MB daemon (compare to 50MB+ for GUI tools)
- Search speed: < 100ms for 10K entries
- Cold start: < 50ms for any command
- Setup time: < 2 minutes from download to working
- Learning curve: < 5 minutes to master basic usage
- Reliability: 99.9% uptime for background monitoring
- Windows integration: Native Windows service, startup integration
- Performance: Outperform existing Windows clipboard managers like Ditto or ClipX
This enhanced specification provides Claude Code with a clear roadmap, well-defined Windows-specific interfaces, and incremental milestones that make the project highly implementable while showcasing Odin's strengths on Windows.