This is the single project-instructions file for Cursor, Claude Code (claude.ai/code), and similar tools. Read it before making changes. Do not add Co-authored-by:, Signed-off-by:, or IDE/agent attribution to commit messages (see Coding Principles).
Build a polished macOS (Apple Silicon) stats app (Rust + Tauri) that reads CPU/process metrics and presents them in a clean "macOS glass" UI. Favor correctness, safety, and maintainability over hacks.
mac-stats is a lightweight system monitor for macOS (Rust + Tauri). It shows real-time CPU, GPU, RAM, and disk usage in the menu bar with low overhead (on the order of ~0.5% idle, under 1% with the CPU window open). It includes real-time metrics, temperature (SMC), CPU frequency (IOReport), a process list, themes, idle optimizations, and Ollama chat with code execution, FETCH_URL (server-side fetch, no CORS), and BROWSER_SCREENSHOT (CDP: PNG under ~/.mac-stats/screenshots/, attachable in Discord when requested). MCP setup: docs/010_mcp_agent.md; Ori Mnemos memory vault: docs/038_ori_mnemos_mcp.md.
# Development (hot reload where applicable)
./run dev
# or
cd src-tauri && cargo run
# Release build
./run
# or
cd src-tauri && cargo build --release
# CPU window (testing)
./target/release/mac_stats --cpu
# Verbosity: default is -vv. Use -vvv for maximum, -v for minimal.
./target/release/mac_stats
./target/release/mac_stats -vvv
# Detailed frequency / IOReport logging
./target/release/mac_stats --frequencyDiscord, the scheduler, website monitors, background compaction, and Ollama-sidecar behaviour only exist while the mac_stats process is alive. The repo does not ship a LaunchAgent or login-item installer—if nothing starts the app after exit or reboot, you get zero background automation until someone launches it again.
- User quit — ⌘Q, or “Quit” from the menu bar app menu.
- Reboot, logout, or forced log out — the process does not survive; it must be started again at login unless you configure that (see below).
- Deploy / agent workflow — Instructions often use
pkill -f mac_statsbefore a new build. If the follow-up start (./run,cargo run --release, oropen -a mac-stats) fails or is skipped, the app stays down. This is a common source of “it was fine yesterday.” - Crash or SIGKILL — Panic,
kill -9, or the OS terminating the app; no automatic restart unlessKeepAlive(below) or a watchdog is configured. - Sleep / disk unmount — Unusual for menu-bar apps, but running from a network or external volume that unmounts will kill the binary path; prefer
/Applicationsor a stable local path for always-on installs.
- After any intentional kill — In the same session or script, start mac-stats again and confirm:
pgrep -fl mac_statsreturns a PID, and~/.mac-stats/debug.logshows a fresh startup block within the last minute. - After reboot — Either enable a LaunchAgent or add mac-stats to System Settings → General → Login Items (for an
/Applications/mac-stats.appinstall). - Before assuming “Discord/scheduler is broken” — Verify the process is running first; most “it stopped working” reports are an absent process, not a logic bug.
Use a user LaunchAgent so macOS starts the app at login and restarts it if it exits (including crash). Adjust paths to match your install.
Installed app (DMG / /Applications): confirm the executable name with
ls "/Applications/mac-stats.app/Contents/MacOS/"
(often mac-stats).
Create ~/Library/LaunchAgents/com.raro42.mac-stats.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.raro42.mac-stats</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/mac-stats.app/Contents/MacOS/mac-stats</string>
<string>-vv</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>10</integer>
</dict>
</plist>Load and start once:
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.raro42.mac-stats.plist 2>/dev/null || true
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.raro42.mac-stats.plist
launchctl kickstart -k gui/$(id -u)/com.raro42.mac-statsTo unload (stop auto-restart): launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.raro42.mac-stats.plist
Dev tree (release binary): point ProgramArguments at
$HOME/projects/mac-stats/src-tauri/target/release/mac_stats
(and the same -vv or flags you use). Prefer a stable path; rebuilding replaces the binary but keeps the same path.
If you cannot use LaunchAgent, a cron or separate launchd job can run every few minutes:
pgrep -f mac_stats >/dev/null || open -a mac-stats(Use open -a only for an installed .app; for dev, replace the right-hand side with cd "$HOME/projects/mac-stats" && ./run.) This reduces silent downtime but is coarser than KeepAlive.
- Treat “restart mac-stats” as kill + start + verify PID + check log tail, not kill alone.
- After macOS updates or reboot, do not assume the app relaunched unless LaunchAgent or Login Items are configured.
- Rust (core logic + FFI)
- Tauri (UI shell)
- Web UI (HTML/CSS/JS or framework as used in repo)
- macOS-specific metrics via:
- User-mode: libproc / sysctl (safe keys only), NSProcessInfo thermal state
- Root-mode (optional): powermetrics parsing OR IOReport (private) behind a helper
- Keep modules small and cohesive.
- When coding, create logs and read them afterwards.
- Execute the app yourself, read the logs, understand if changes are working from the logs - iterate until you are confident the change is good to be test by a human.
- ALWAYS check for build errors before starting the app: Run
cargo checkinsrc-tauri/directory and fix any compilation errors before attempting to start the app. - Commits: Do not add
Co-authored-by:,Signed-off-by:, or any Cursor/agent/IDE attribution to commit messages. Do not advertise the agent or tool in commits or in the repo. To enforce this locally, run./scripts/install-git-hooks.shonce (installs a prepare-commit-msg hook that strips such lines). - After changes that affect runtime behavior (Redmine, tasks, agent prompts, scheduler, Discord, Ollama tools): restart mac-stats automatically — always run a start after any
pkill(see Keep mac-stats running). Example:pkill -f mac_stats; cd src-tauri && cargo run --release. Default verbosity is -vv so logs are visible. Then verify the process (pgrep -fl mac_stats) and test (relevant task, feature, or~/.mac-stats/debug.log). Skipping the start after kill is a common cause of prolonged downtime. - Never install software on the host. Always ask before installing.
- If you need to install software, use containers.
- No "god files": split into
metrics/,ffi/,ui/,config/,logging/. - Prefer safe Rust. Minimize
unsafeand isolate it inffi/with strict audits. - Every
unsafeblock must have a comment explaining invariants and safety assumptions.
- Do not claim that
sysctl hw.cpufrequencyexists on Apple Silicon — it doesn't. - CPU frequency + many sensors require root and are unstable across macOS versions.
- Prefer Apple-supported indicators:
- CPU usage (host stats/libproc)
- Thermal state (
NSProcessInfo.thermalState) - Thermal pressure (where available)
- If implementing frequency/temperature:
- Use
powermetrics --format jsonwhen running as root OR - Use IOReport (private) only behind a root helper and treat output as unstable.
- Use
- Never allow Obj-C/C++ exceptions to cross into Rust.
- If calling Obj-C/C++: use a shim that catches exceptions and returns error codes.
- No panicking across FFI boundaries. All extern functions must be
noexceptstyle. - Always validate CoreFoundation types with
CFGetTypeID()before casting. - Always check for null pointers from CF APIs.
- Follow CF ownership rules (Create/Copy = you release; Get = do not release).
- Avoid
transmutefor IOReport payloads; validate sizes and useread_unalignedif needed.
- UI must run unprivileged.
- Root-only functionality must be isolated:
- separate binary/daemon, launched via launchd or explicit sudo in dev mode
- communicate over a Unix domain socket or localhost with auth token
- Make root metrics optional; app must work gracefully without them.
- When doing "frontend" changes, you can pkill running instance and restart the app.
- Use
tracingfor structured logs. - Provide
--verbose/--jsonflags for CLI diagnostics. - Always execute the code after changes and read the logs.
- When debugging crashes:
- include an LLDB recipe in
docs/debugging.md - include env flags:
MallocScribble,MallocGuardEdges - document how to breakpoint
objc_exception_throw,__cxa_throw,abort
- include an LLDB recipe in
- Use macOS-like glass design:
- backdrop blur + subtle borders + soft shadows
- consistent spacing, typography, and units
- Always display units (°C, GHz, W, %).
- Prefer ring gauges (SVG) over heavy pie charts.
- Animate value changes subtly (200–350ms), never flashy.
- Keep responses and code changes minimal and targeted.
- When asked to refactor, propose a file/module plan first, then implement.
- Add or update tests for parsing and metrics extraction where possible.
- Hard-coded absolute paths (especially root-only locations).
- Global mutable state unless justified; prefer explicit state passing.
- Copying private Apple keys/constants without isolating them and documenting risk.
- Over-promising sensor availability on Apple Silicon.
- Use
rustfmtandclippyclean builds. - Prefer
anyhow+thiserrorfor error handling. - Use
serdefor structured data exchanged with UI.
- When asked to update MD files or agents inside
.mac-stats, or to sync repo defaults into~/.mac-stats: merge default content into existing files; do not overwrite. - Add missing sections, new agents, or new bullets; preserve the user’s existing content. See
docs/024_mac_stats_merge_defaults.md.
- Ask for the exact macOS version and target (Dev vs notarized distribution).
- Default to the safest, Apple-supported approach.
Use the provided measurement script to track performance metrics:
# Measure with CPU window open (30 seconds)
./scripts/measure_performance.sh 30 1 window
# Measure idle (menu bar only, 60 seconds)
./scripts/measure_performance.sh 60 1 idle
# Custom: 120 seconds, 2-second intervals
./scripts/measure_performance.sh 120 2 idleScript Features:
- Measures CPU usage (%), Memory (%), RSS/VSZ (MB), thread count
- Outputs live measurements + statistics
- Saves results as text report + CSV for analysis
- Reusable for before/after comparison
- Located in
scripts/directory (keep root clean)
Output Files:
performance_window_YYYYMMDD_HHMMSS.txt- Detailed reportperformance_window_YYYYMMDD_HHMMSS.csv- Data for spreadsheets
-
Baseline Measurement (before any changes):
./scripts/measure_performance.sh 30 1 window # With window ./scripts/measure_performance.sh 30 1 idle # Without window
-
Implement Optimizations:
- See
docs/001_task_optimize_backend.md(backend) - See
docs/002_task_optimize_frontend.md(frontend) - See
docs/003_task_optimize_advanced_idle.md(advanced)
- See
-
Measure After Each Phase:
# After Phase 1: ./scripts/measure_performance.sh 30 1 window # After Phase 2: ./scripts/measure_performance.sh 30 1 window # Compare: Phase 1 vs Phase 2 vs baseline
-
Track Cumulative Improvement:
- Save results with phase names
- Compare CSV files in spreadsheet
- Document CPU reduction percentage
mac-stats/
├── scripts/ ← All development/measurement scripts
│ ├── build-dmg.sh
│ ├── measure_performance.sh ← Performance measurement
│ ├── take-screenshot.sh
│ └── trace_backend.sh
├── docs/ ← Documentation and analysis
│ ├── 000_task_optimize_summary.md
│ ├── 001_task_optimize_backend.md
│ ├── 002_task_optimize_frontend.md
│ └── 003_task_optimize_advanced_idle.md
├── src-tauri/ ← Source code
│ ├── src/ ← Rust backend
│ ├── dist/ ← Frontend assets
│ └── Cargo.toml
└── README.md ← Keep root clean, no scripts here!
Rule: All .sh, .py, and utility scripts go in scripts/ directory, not root.
The codebase follows a clear separation between Rust backend (Tauri) and JavaScript frontend, with modular organization for maintainability.
mac-stats/
├── src/ ← Frontend source (JavaScript/HTML/CSS)
│ ├── dashboard.html ← Main dashboard UI
│ ├── dashboard.js ← Dashboard logic (delegates to modules)
│ ├── dashboard.css ← Dashboard styles
│ ├── ollama.js ← Ollama AI chat integration (unified module)
│ ├── tauri-logger.js ← Console logging bridge to Rust
│ ├── main.js ← Main entry point
│ ├── index.html ← App entry HTML
│ └── assets/ ← Icons and images
├── src-tauri/ ← Rust backend (Tauri application)
│ ├── src/
│ │ ├── main.rs ← Entry point, CLI argument parsing
│ │ ├── lib.rs ← Main app logic, Tauri setup, background threads
│ │ ├── state.rs ← Application state management
│ │ │
│ │ ├── commands/ ← Tauri commands (exposed to frontend)
│ │ │ ├── mod.rs ← Command module exports
│ │ │ ├── ollama.rs ← Ollama orchestrator (planning, execution, tool dispatch coordinator)
│ │ │ ├── ollama_config.rs ← Ollama configuration, startup, env resolution
│ │ │ ├── ollama_chat.rs ← Chat transport (send messages, streaming, dedup)
│ │ │ ├── ollama_frontend_chat.rs ← Frontend chat Tauri commands (chat with execution, continue)
│ │ │ ├── ollama_models.rs ← Ollama model management (list, pull, delete, embed, load/unload)
│ │ │ ├── ollama_logging.rs ← Ollama JS execution logging bridge
│ │ │ ├── ollama_memory.rs ← Memory/soul loading for Ollama sessions
│ │ │ ├── tool_loop.rs ← Tool execution loop (parse, dispatch, dedup, budget)
│ │ │ ├── tool_parsing.rs ← Tool invocation parsing from model responses
│ │ │ ├── loop_guard.rs ← Cross-tool cycle and repetition detection
│ │ │ ├── pre_routing.rs ← Deterministic pre-routing (screenshot, RUN_CMD, REDMINE)
│ │ │ ├── agent_descriptions.rs ← Agent/tool description building for prompts
│ │ │ ├── agent_session.rs ← Agent session runner (sub-agent Ollama calls)
│ │ │ ├── browser.rs ← fetch_page, SSRF validation for Ollama web tasks
│ │ │ ├── browser_helpers.rs ← Browser task detection, retry prompts, navigation checks
│ │ │ ├── browser_tool_dispatch.rs ← Browser tool handlers (screenshot, navigate, click, etc.)
│ │ │ ├── network_tool_dispatch.rs ← FETCH_URL, BRAVE_SEARCH, DISCORD_API, REDMINE_API handlers
│ │ │ ├── delegation_tool_dispatch.rs ← AGENT, SKILL, RUN_JS, RUN_CMD, PYTHON_SCRIPT handlers
│ │ │ ├── misc_tool_dispatch.rs ← OLLAMA_API, MCP, CURSOR_AGENT, MASTODON_POST, MEMORY_APPEND
│ │ │ ├── task_tool_handlers.rs ← TASK_* and SCHEDULE tool handlers
│ │ │ ├── verification.rs ← Verification pipeline (OllamaReply, success criteria, retry)
│ │ │ ├── content_reduction.rs ← Content truncation, skill/JS execution helpers
│ │ │ ├── compaction.rs ← Periodic session compaction
│ │ │ ├── session_history.rs ← Session history preparation (cap, compaction, annotations)
│ │ │ ├── prompt_assembly.rs ← Execution system prompt assembly
│ │ │ ├── reply_helpers.rs ← Reply routing, final-reply extraction, Mastodon helpers
│ │ │ ├── redmine_helpers.rs ← Redmine request parsing, time entries, ticket extraction
│ │ │ ├── perplexity_helpers.rs ← PERPLEXITY_SEARCH handler, result formatting
│ │ │ ├── schedule_helpers.rs ← Schedule parsing (cron/at)
│ │ │ ├── monitors.rs ← Monitor management (add, remove, check)
│ │ │ ├── alerts.rs ← Alert management
│ │ │ ├── security.rs ← Keychain/credential management
│ │ │ ├── logging.rs ← Generic JS console logging bridge
│ │ │ ├── plugins.rs ← Plugin system commands
│ │ │ ├── brave.rs ← Brave Search API commands
│ │ │ ├── run_cmd.rs ← RUN_CMD allowlisted command execution
│ │ │ ├── python_agent.rs ← PYTHON_SCRIPT execution
│ │ │ ├── cursor_agent.rs ← Cursor-agent proxy commands
│ │ │ ├── judge.rs ← Judge hook for completion quality
│ │ │ ├── perplexity.rs ← Perplexity Search API commands
│ │ │ ├── agents.rs ← Agent listing/prompt Tauri commands
│ │ │ ├── discord.rs ← Discord-related Tauri commands
│ │ │ ├── scheduler.rs ← Scheduler Tauri commands
│ │ │ ├── skills.rs ← Skill listing
│ │ │ └── window.rs ← CPU window toggle command
│ │ │
│ │ ├── metrics/ ← System metrics collection
│ │ │ └── mod.rs ← CPU, RAM, GPU, disk, temperature, frequency
│ │ │
│ │ ├── ollama/ ← Ollama API client
│ │ │ └── mod.rs ← HTTP client, chat API, model listing
│ │ │
│ │ ├── monitors/ ← Monitoring implementations
│ │ │ ├── mod.rs ← Monitor trait and registry
│ │ │ ├── website.rs ← HTTP/HTTPS website monitoring
│ │ │ └── social.rs ← Social media monitoring (Mastodon, etc.)
│ │ │
│ │ ├── alerts/ ← Alert system
│ │ │ ├── mod.rs ← Alert rules and engine
│ │ │ ├── rules.rs ← Alert rule definitions
│ │ │ └── channels.rs ← Alert delivery channels (Telegram, Slack, etc.)
│ │ │
│ │ ├── plugins/ ← Plugin system
│ │ │ └── mod.rs ← Script-based plugin execution
│ │ │
│ │ ├── security/ ← Security utilities
│ │ │ └── mod.rs ← macOS Keychain integration
│ │ │
│ │ ├── config/ ← Configuration management
│ │ │ └── mod.rs ← Paths, build info, app config, screenshots_dir()
│ │ │
│ │ ├── browser_agent/ ← CDP browser (screenshots)
│ │ │ └── mod.rs ← connect_cdp, navigate, take_screenshot (PNG to ~/.mac-stats/screenshots/)
│ │ │
│ │ ├── ffi/ ← Foreign Function Interface
│ │ │ ├── mod.rs ← FFI module exports
│ │ │ ├── ioreport.rs ← IOReport API wrappers (CPU frequency)
│ │ │ └── objc.rs ← Objective-C wrappers (thermal state)
│ │ │
│ │ ├── ui/ ← UI components
│ │ │ ├── mod.rs ← UI module exports
│ │ │ └── status_bar.rs ← Menu bar status item
│ │ │
│ │ └── logging/ ← Logging infrastructure
│ │ ├── mod.rs ← Tracing setup and configuration
│ │ └── legacy.rs ← Legacy logging (if any)
│ │
│ ├── dist/ ← Frontend assets (copied from src/)
│ │ ├── cpu.js ← CPU window logic (UI-specific, delegates to ollama.js)
│ │ ├── ollama.js ← Synced from src/ollama.js
│ │ ├── tauri-logger.js ← Synced from src/tauri-logger.js
│ │ └── themes/ ← UI themes
│ │ └── apple/
│ │ ├── cpu.html ← CPU window HTML template
│ │ └── cpu.css ← CPU window styles
│ │
│ └── Cargo.toml ← Rust dependencies
│
├── scripts/ ← Development and utility scripts
│ ├── sync-dist.sh ← Sync frontend files to dist/
│ ├── measure_performance.sh ← Performance measurement tool
│ └── ...
└── docs/ ← Documentation
└── ...
src/ollama.js - Ollama AI Chat Integration (Single Source of Truth)
- Purpose: Unified module for all Ollama-related functionality
- Features:
- Connection management (auto-configuration, connection checking)
- Chat message handling with conversation history
- Code execution flow (ping-pong with Ollama)
- Model management
- Exposed via
window.Ollamaglobal object
- Conversation History: Maintains in-memory conversation history (last 20 messages) for context-aware responses
- Code Execution: Handles
ROLE=code-assistantresponses, executes JavaScript, sends results back to Ollama - Location: Primary source in
src/ollama.js, synced tosrc-tauri/dist/ollama.js
src/dashboard.js
- Main dashboard logic
- Delegates Ollama functionality to
ollama.jsmodule - UI event handling
src/tauri-logger.js
- Intercepts
console.log/warn/errorcalls - Forwards logs to Rust via
log_from_jsTauri command - Provides source file detection from stack traces
src-tauri/dist/cpu.js
- CPU window-specific UI logic
- Delegates Ollama functionality to
window.Ollama.* - Monitor history, collapsible sections, icon status management
src-tauri/src/commands/ollama.rs - Ollama Tauri Commands
ollama_chat_with_execution: Unified chat command that:- Gets system metrics for context
- Sends question to Ollama with conversation history
- Handles FETCH_URL tool: if the model replies with
FETCH_URL: <url>, the app fetches the page and sends the content back to Ollama (no CORS; server-side fetch) - Handles BROWSER_SCREENSHOT: opens URL via CDP (browser_agent), saves PNG to ~/.mac-stats/screenshots/, returns path; from Discord the screenshot is attached to the channel
- URL parsing for FETCH_URL and BROWSER_SCREENSHOT: first token only, trailing punctuation (
.,,,;,:) stripped so model text like "...usecases. The..." does not produce a trailing dot on the URL - Detects JavaScript code in responses (
ROLE=code-assistantor pattern matching) - Extracts code (handles
console.log()wrappers) - Returns structured response indicating if code execution is needed
answer_with_ollama_and_fetch: Used by Discord and scheduler; returns OllamaReply{ text, attachment_paths }so callers can attach screenshot paths (e.g. Discord sends the PNG).ollama_chat_continue_with_result: Follow-up command for code execution flow:- Takes JavaScript execution result
- Sends follow-up message to Ollama with full conversation history
- Handles ping-pong (recursive code execution up to 5 iterations)
- Returns final answer or next code block
check_ollama_connection: Connection status checkinglist_ollama_models: Model listingconfigure_ollama: Endpoint/model configuration
src-tauri/src/ollama/mod.rs - Ollama API Client
- HTTP client for Ollama API
- Chat request/response handling
- Model listing
- Connection checking
- API key management (Keychain integration)
src-tauri/src/commands/monitors.rs - Monitor Management
- Add/remove monitors
- Check monitor status
- Monitor persistence (disk storage)
- Monitor stats caching (last check, last status)
src-tauri/src/monitors/ - Monitor Implementations
website.rs: HTTP/HTTPS website monitoring (response time, status codes, SSL)social.rs: Social media monitoring (Mastodon mentions, etc.)mod.rs: Monitor trait definition and registry
src-tauri/src/alerts/ - Alert System
- Rule-based alerting (SiteDown, BatteryLow, TemperatureHigh, etc.)
- Alert channels (Telegram, Slack, Mastodon, Signal)
- Cooldown mechanism to prevent spam
src-tauri/src/metrics/mod.rs - System Metrics
- CPU usage, temperature, frequency
- RAM, disk, GPU usage
- Battery status
- Process list
- Optimized with caching to minimize CPU overhead
src-tauri/src/ffi/ - Foreign Function Interface
ioreport.rs: IOReport API wrappers for CPU frequency (Apple Silicon)objc.rs: Objective-C wrappers for thermal state- All
unsafecode isolated here with safety comments
src-tauri/src/security/mod.rs - Security
- macOS Keychain integration
- Credential storage/retrieval
- API key management
src-tauri/src/lib.rs - Main Application Logic
- Tauri application setup
- Background threads for metrics collection
- Menu bar updates
- Window management
- Resource lifecycle management (IOReport, SMC)
- User sends message →
src/ollama.js::sendChatMessage() - Add to history →
addToHistory('user', message) - Invoke Rust →
ollama_chat_with_executioncommand - Rust command (
commands/ollama.rs):- Gets system metrics
- Builds messages array with conversation history
- Calls Ollama API via
ollama/mod.rs - Detects code in response
- Returns structured response
- JavaScript execution →
executeJavaScriptCode()inollama.js - Follow-up →
ollama_chat_continue_with_resultwith execution result - Final answer → Displayed in UI, added to history
- Frontend →
check_monitor(monitor_id)Tauri command - Rust →
commands/monitors.rs::check_monitor() - Monitor lookup →
monitors/mod.rsregistry - Execute check →
monitors/website.rsormonitors/social.rs - Update stats → In-memory cache (last_check, last_status)
- Return result → Frontend updates UI
- Frontend files in
src/are synced tosrc-tauri/dist/viascripts/sync-dist.sh - Single source of truth:
src/ollama.jsis the primary file, synced todist/ollama.js - Always sync after changes: Run sync script or manually copy when modifying frontend files
- Tauri serves from:
src-tauri/dist/directory
- Module Delegation: Frontend modules delegate to specialized modules (e.g.,
dashboard.js→ollama.js) - Single Source of Truth: One primary file per feature, synced to distribution locations
- Conversation History: Maintained in JavaScript, passed to Rust for API calls
- Structured Responses: Rust commands return structured data (needs_code_execution, final_answer, etc.)
- Error Handling: Comprehensive error handling with logging at each layer
- State Management: In-memory state in Rust (monitors, alerts), localStorage in JavaScript (Ollama config)
Frontend Feature:
- Add to
src/directory - Update
scripts/sync-dist.shif needed - Include in HTML templates (
dashboard.html,cpu.html)
Backend Feature:
- Create module in
src-tauri/src/ - Add Tauri command in
src-tauri/src/commands/ - Register command in
src-tauri/src/lib.rs→tauri::generate_handler! - Update
src-tauri/src/commands/mod.rsexports
Ollama Integration:
- All Ollama code lives in
src/ollama.js(frontend) andsrc-tauri/src/commands/ollama.rs+src-tauri/src/ollama/mod.rs(backend) - Conversation history managed in JavaScript, passed to Rust
- Code execution handled in JavaScript, results sent back to Rust for follow-up
High-level behavior that complements the directory tree above:
- main.rs: CLI entry (verbosity,
--cpu,--frequency). - lib.rs: Tauri setup, background metrics and menu bar; IOReport subscriptions and SMC. Expensive metrics (temperature, frequency) are emphasized when the CPU window is visible to limit idle cost. Careful CoreFoundation retain/release.
- metrics/mod.rs: Cached
SystemMetrics,CpuDetails, process list (~30s cache), etc. - state.rs: Shared state (
Mutex/OnceLock): sysinfo, disks, status item, app handle, caches, IOReport handles. - ui/status_bar.rs: Menu bar item;
build_status_text;create_cpu_windowon demand. Click handler applies pending menu bar updates (workaround for unreliable Tauri main-thread callbacks). - ffi/: IOReport (frequency), Objective-C bridge; aligns with FFI Safety Rules.
- logging:
tracingwithdebug1!/debug2!/debug3!by verbosity; logs under~/.mac-stats/debug.log.
- Lazy CPU window creation (not at startup).
- Selective reads: temperature about every 20s when the window is visible; frequency about every 30s via IOReport; SMC/IOReport subscriptions cleared when the window closes.
- SMC: M3 temperature keys cached after first discovery; prefer direct key reads over scanning all keys.
- Menu bar: background thread prepares text; user click drains updates to the UI.
- Process list cached ~30s.
- IOReport lifecycle: Subscribe when the CPU window opens (expensive); reuse for frequency reads; tear down on close (similar in spirit to exelban/stats, with correct CF retain/release).
- M3/M4 temperature: Try the standard path (M1/M2); fall back to M3-specific keys (e.g. Tf04, Tf09, Tf0A); cache the first working key.
- Memory / threads: Respect CF ownership; globals and thread-local patterns match Tauri and main-thread UI constraints; SMC may use thread-local where
Sendis an issue.
- Features grew iteratively; some code is pragmatic rather than textbook Rust.
- Automated tests: No large formal suite; still add parsing/unit tests where practical (see Output & Formatting).
- Tauri: Prefer the documented menu-bar click workaround over assuming all main-thread hooks behave the same everywhere.
./target/release/mac_stats # default -vv
./target/release/mac_stats -vvv
./target/release/mac_stats -v
./target/release/mac_stats --frequency
./target/release/mac_stats --cpu
tail -f ~/.mac-stats/debug.logWhen debugging: CPU window visibility drives expensive reads; temperature may read 0 if SMC is unavailable or no M3 key was found; frequency needs an active IOReport subscription (window visible); menu bar text may update on click, not continuously.
Single source of truth: src-tauri/Cargo.toml version only. Rust exposes get_app_version() via env!("CARGO_PKG_VERSION") / Config; the frontend loads it at runtime (e.g. CPU UI). HTML templates may contain placeholder version strings replaced by JavaScript—avoid hardcoding the version in many places.
- OpenClaw:
../openclaw(from repo root: multi-channel AI gateway; compaction, memory, session reset; seedocs/035_memory_and_topic_handling.md). - Hermes:
../hermes-agent(from repo root: skills/workspace with SKILL.md files; not a chat gateway — the Hermes repo on disk is named hermes-agent, nothermes).