Surface Monitor for Windsurf IDE — a performance monitoring and diagnostics tool for Windsurf (Stable, Next, and Insiders).
- Installation
- Quick Start
- Why Use Surfmon?
- Commands
- What It Monitors
- Target Selection
- Exit Codes
- Common Issues
- Development
pip install surfmonOr with uv:
uv tool install surfmonOr run directly without installing:
uvx surfmon check -t stable # Using uvx
pipx run surfmon check -t stable # Using pipxFor development:
git clone https://github.com/detailobsessed/surfmon.git
cd surfmon
uv sync# One-shot health check (--target is required)
surfmon check -t stable
# Verbose output with all process details
surfmon check -t stable -v
# Target Windsurf Insiders
surfmon check -t insiders- 🔍 Debug Performance Issues — Identify memory leaks, CPU spikes, and resource bottlenecks
- 📊 Monitor Over Time — Track resource usage trends with watch sessions and historical analysis
- 🧹 Clean Up Resources — Remove orphaned processes
- 🔧 Troubleshoot Crashes — Detect extension host crashes, language server issues, and PTY leaks
- 📈 Visualize Trends — Generate matplotlib plots showing resource usage over time
The main command. Shows system resources, Windsurf memory/CPU, active workspaces, top processes, and language servers in consistent fixed-width tables.
surfmon check -t stable # Basic check
surfmon check -t stable -v # Verbose (all processes)
surfmon check -t stable --json # Output JSON to stdout (for agent/pipe consumption)Continuously monitors Windsurf with a live-updating terminal dashboard. Saves periodic JSON snapshots for historical analysis.
surfmon watch -t stable # Default: 5s interval, save every 5min
surfmon watch -t next -i 10 -s 600 # Check every 10s, save every 10min
surfmon watch -t insiders -i 10 -n 720 # 720 checks = 2 hours
surfmon watch -t stable -o ~/reports # Custom output directoryAnalyzes JSON reports from watch sessions (or any directory containing JSON reports) to detect memory leaks, process growth, and performance degradation. Optionally generates a 9-panel matplotlib visualization.
surfmon analyze reports/watch/20260204-134518/
surfmon analyze reports/watch/20260204-134518/ --plot
surfmon analyze reports/watch/20260204-134518/ --plot --output analysis.pngTerminal Output:
Generated Matplotlib Visualization:
Detects and kills orphaned chrome_crashpad_handler processes left behind after Windsurf exits. Windsurf must be closed for this command to work.
surfmon cleanup -t stable # Interactive (asks for confirmation)
surfmon cleanup -t next --force # No confirmationCaptures a detailed PTY ownership snapshot for diagnosing Windsurf's PTY leak. Shows per-PID breakdown, FD-level detail (active vs idle), Windsurf version, and uptime.
surfmon pty-snapshot -t next # Display snapshot
surfmon pty-snapshot -t next --json # Output JSON to stdout (for agent/pipe consumption)System — Total/available memory, memory %, swap, CPU cores
Windsurf Processes — Process count, total memory & CPU, top 10 by memory, thread counts
Language Servers — Detects and tracks basedpyright, JDT.LS, Codeium language servers, YAML/JSON servers
MCP Servers — Lists enabled MCP servers from Codeium config
Workspaces — Active workspace paths and load times
PTY Usage — Windsurf PTY allocation vs system limits, per-PID breakdown, FD-level active/idle classification, raw lsof capture for forensic analysis
Issues — Orphaned crash handlers, extension host crashes, update service timeouts, telemetry failures, logs directory in extensions folder
Surfmon requires you to specify which Windsurf installation to monitor. Use --target (-t) with one of stable, next, or insiders:
surfmon check -t stable # Windsurf Stable
surfmon check -t next # Windsurf Next
surfmon check -t insiders # Windsurf InsidersAlternatively, set SURFMON_TARGET in your environment to avoid passing -t every time:
export SURFMON_TARGET=insiders
surfmon checkThe --target flag is required for check, watch, and cleanup. Commands that operate on saved data (analyze) do not require it.
0— No issues detected1— Issues detected (see output)130— Interrupted (Ctrl+C)
| Issue | Cause | Fix |
|---|---|---|
| Orphaned crash handlers | Crash reporters not cleaned up on exit | surfmon cleanup -t stable --force |
logs directory error |
Marimo extension creates logs in wrong place | Move ~/.windsurf/extensions/logs |
| Update service timeouts | DNS or firewall blocking update checks | Check DNS/firewall settings |
| High memory usage | Too many language servers or extensions | Disable unused extensions |
src/surfmon/
__init__.py # Version
cli.py # Typer CLI — check, watch, cleanup, analyze
config.py # Target detection, paths, environment config
monitor.py # Core data collection — processes, language servers, MCP, PTYs
output.py # Rich terminal display and Markdown export
tests/
conftest.py # Shared fixtures
test_bugfixes.py # Regression tests
test_cli.py # CLI command tests
test_config.py # Configuration and target detection tests
test_monitor.py # Core monitoring logic tests
test_output.py # Display and formatting tests
poe test # Run tests
poe test-cov # Run with coverage
poe lint # Ruff check
poe typecheck # ty check- psutil — Cross-platform process and system monitoring
- typer — CLI framework
- rich — Terminal output with tables and colors
- python-decouple — Environment configuration
- matplotlib — Visualization for
analyzeplots
- Python 3.14+
- macOS (tested), Linux (untested), Windows (untested) though it should work
- Windsurf IDE installed
Screenshots in this README were created using:
- Static images (termshot) - Captures terminal output as PNG
- Animated GIF (vhs) - Records terminal sessions as GIF
To recreate the watch GIF:
brew install vhs gifsicle
# Create tape file
cat > watch-demo.tape << 'EOF'
Output docs/screenshots/watch.gif
Set FontSize 13
Set Width 900
Set Height 400
Set Theme "Catppuccin Mocha"
Set BorderRadius 10
Set WindowBar Colorful
Set WindowBarSize 30
Type "uvx surfmon watch --interval 2 --max 15"
Enter
Sleep 32s
EOF
# Generate and optimize
vhs watch-demo.tape
gifsicle -O3 --colors 256 docs/screenshots/watch.gif -o docs/screenshots/watch.gif



