Skip to main content

File-to-Database Mapping

MonoTerm follows a clear write/read separation pattern.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                    WRITE/READ ARCHITECTURE                           β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   WRITE LAYER (Rust)                   READ LAYER (TypeScript)       β•‘
β•‘   ==================                   ======================        β•‘
β•‘                                                                      β•‘
β•‘   Rust PTY Log        ────writes───▢   Frontend Polling              β•‘
β•‘        β”‚                               (control-tabs-worked)         β•‘
β•‘        β–Ό                                                             β•‘
β•‘   atomic-term.db                                                     β•‘
β•‘                                                                      β•‘
β•‘   Rust Session        ────writes───▢   Frontend Recovery             β•‘
β•‘        β”‚                               (main app startup)            β•‘
β•‘        β–Ό                                                             β•‘
β•‘   session.db                                                         β•‘
β•‘                                                                      β•‘
β•‘   Rust OnIt           ────writes───▢   Frontend Display              β•‘
β•‘        β”‚                               (project init, sidebar)       β•‘
β•‘        β–Ό                                                             β•‘
β•‘   onit.db                                                            β•‘
β•‘                                                                      β•‘
β•‘   Watcher Daemon      ────writes───▢   Frontend Polling              β•‘
β•‘        β”‚              (direct)         (watcher tab)                 β•‘
β•‘        β–Ό                                                             β•‘
β•‘   niia-watcher.db                                                    β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Rust Modules (Writers)

The backend modules that write to databases.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                     RUST WRITE MODULES                               β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   MODULE              DATABASE            WHAT IT WRITES             β•‘
β•‘   ══════              ════════            ══════════════             β•‘
β•‘                                                                      β•‘
β•‘   PTY Log             atomic-term.db      Parsed terminal activity   β•‘
β•‘   (VTE Parser)                            File operations detected   β•‘
β•‘                                           from command output        β•‘
β•‘                                                                      β•‘
β•‘   Session DB          session.db          Terminal heartbeats        β•‘
β•‘                                           Session state              β•‘
β•‘                                           Tab information            β•‘
β•‘                                                                      β•‘
β•‘   OnIt                onit.db             Project information        β•‘
β•‘                                           Activity logs              β•‘
β•‘                                           Folder associations        β•‘
β•‘                                                                      β•‘
β•‘   Auto-fix            atomic-term.db      Path corrections           β•‘
β•‘   (Cross-DB)          (updates)           Resolves truncated paths   β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

TypeScript Modules (Readers)

The frontend modules that read from databases.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                    TYPESCRIPT READ MODULES                           β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   MODULE                  DATABASE            WHAT IT READS          β•‘
β•‘   ══════                  ════════            ═════════════          β•‘
β•‘                                                                      β•‘
β•‘   Worked Files            atomic-term.db      Recently worked files  β•‘
β•‘   Polling                                     for sidebar display    β•‘
β•‘                                                                      β•‘
β•‘   Project Init            onit.db             Project list           β•‘
β•‘                                               Folder mappings        β•‘
β•‘                                                                      β•‘
β•‘   Watcher Tab             niia-watcher.db     File change events     β•‘
β•‘                                               Watch path status      β•‘
β•‘                                                                      β•‘
β•‘   Terminals Tab           session.db          Active sessions        β•‘
β•‘                                               Recovery candidates    β•‘
β•‘                                                                      β•‘
β•‘   Diff Viewer             work-wiki-diff.db   Git diff history       β•‘
β•‘                                               File versions          β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Terminal Activity Flow

From PTY output to worked files display.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                 TERMINAL ACTIVITY FLOW                               β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   STEP 1: PTY OUTPUT                                                 β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  PTY Daemon ──▢ Rust Backend ──▢ VTE Parser (Alacritty)       β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   STEP 2: SAVE + EMIT                                                β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  VTE Parser detects file operation                            β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ INSERT INTO parsed_activities                         β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Auto-fix resolves truncated paths                            β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ UPDATE path column                                    β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Emit event to frontend                                       β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   STEP 3: FRONTEND READ                                              β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  Tauri invoke("get_worked_files")                             β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ SELECT FROM parsed_activities                         β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Display in "Worked Files" sidebar                            β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Session Recovery Flow

How sessions are recovered after app restart.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                  SESSION RECOVERY FLOW                               β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   STEP 1: SESSION CREATE                                             β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  New terminal tab opened                                      β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  INSERT INTO terminal_heartbeats                              β”‚  β•‘
β•‘   β”‚  (terminal_id, instance_id, is_alive=1)                       β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   STEP 2: HEARTBEAT (every 10 seconds)                               β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  Frontend sends heartbeat                                     β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  UPDATE terminal_heartbeats                                   β”‚  β•‘
β•‘   β”‚  SET last_heartbeat = NOW()                                   β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   STEP 3: APP RESTART                                                β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  Cleanup stale terminals (no heartbeat for 30s)               β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Find recoverable sessions (PTY socket still exists)          β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Reconnect to PTY daemon                                      β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Restore terminal display                                     β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

File Watcher Flow

From file system event to UI display.
╔═════════════════════════════════════════════════════════════════════╗
β•‘                   FILE WATCHER FLOW                                  β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   STEP 1: DAEMON WRITE (Direct - No IPC)                             β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  OS detects file change                                       β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ Rust notify crate                                     β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  File Watcher Daemon                                          β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ Direct rusqlite (no IPC overhead)                     β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  INSERT INTO file_events                                      β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   STEP 2: UI POLLING (every 3 seconds)                               β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚  Frontend polls for changes                                   β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β”‚ Tauri invoke("query_file_events")                     β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  SELECT FROM file_events                                      β”‚  β•‘
β•‘   β”‚  WHERE timestamp > last_check                                 β”‚  β•‘
β•‘   β”‚       β”‚                                                       β”‚  β•‘
β•‘   β”‚       β–Ό                                                       β”‚  β•‘
β•‘   β”‚  Update watcher tab UI                                        β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Design Principles Applied

╔═════════════════════════════════════════════════════════════════════╗
β•‘                     DESIGN PRINCIPLES                                β•‘
╠═════════════════════════════════════════════════════════════════════╣
β•‘                                                                      β•‘
β•‘   SIMPLICITY (SMPC)                                                  β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚ [x] Direct rusqlite writes (no ORM overhead)                  β”‚  β•‘
β•‘   β”‚ [x] Each Rust module handles ONE database                     β”‚  β•‘
β•‘   β”‚ [x] Frontend uses simple invoke() for reads                   β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•‘   ORDER FROM CHAOS (OFAC)                                            β•‘
β•‘   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β•‘
β•‘   β”‚ [x] Heartbeat + cleanup pattern for recovery                  β”‚  β•‘
β•‘   β”‚ [x] Emit for immediate updates, polling for history           β”‚  β•‘
β•‘   β”‚ [x] Daemon survives crash, writes continue                    β”‚  β•‘
β•‘   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β•‘
β•‘                                                                      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Module Reference Table

LayerModuleDatabaseDirection
RustPTY Logatomic-term.dbWrite
RustSession DBsession.dbWrite/Read
RustOnItonit.dbWrite/Read
RustAuto-fixatomic-term + niia-watcherCross-DB
DaemonFile Watcherniia-watcher.dbWrite
TypeScriptWorked Pollingatomic-term.dbRead
TypeScriptWatcher Tabniia-watcher.dbRead
TypeScriptTerminals Tabsession.dbRead