Surfmon
Surface Monitor for Windsurf IDE — a performance monitoring and diagnostics tool for Windsurf (Stable, Next, and Insiders).
Table of Contents
- Installation
- Quick Start
- Why Use Surfmon?
- Commands
- What It Monitors
- Target Selection
- Exit Codes
- Common Issues
- Development
Installation
pip install surfmon
Or with uv:
uv tool install surfmon
Or run directly without installing:
uvx surfmon check -t stable # Using uvx
pipx run surfmon check -t stable # Using pipx
For development:
git clone https://github.com/detailobsessed/surfmon.git
cd surfmon
uv sync
Quick Start
# 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
Why Use Surfmon?
- 🔍 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
Commands
check — Quick Performance Snapshot
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)
watch — Live Monitoring Dashboard
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 directory
analyze — Historical Trend Analysis
Analyzes 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.png
Terminal Output:
Generated Matplotlib Visualization:
cleanup — Remove Orphaned Processes
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 confirmation
pty-snapshot — PTY Forensic Capture
Captures 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)
What It Monitors
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
Target Selection
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 Insiders
Alternatively, set SURFMON_TARGET in your environment to avoid passing -t every time:
export SURFMON_TARGET=insiders
surfmon check
The --target flag is required for check, watch, and cleanup. Commands that operate on saved data (analyze) do not require it.
Exit Codes
Diagnostic commands (check, ls-snapshot, pty-snapshot)
0— No issues detected1— Warnings only (non-critical, e.g. extension errors, moderate PTY count)2— Critical issues present (e.g. orphaned workspaces, OOM, PTY exhaustion)130— Interrupted (Ctrl+C)
Data & utility commands (history, trend, analyze, cleanup)
0— Success1— Error (invalid input, operational failure)
Common Issues
| 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 |
Development
Package Structure
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
Running Tests
poe test # Run tests
poe test-cov # Run with coverage
poe lint # Ruff check
poe typecheck # ty check
Dependencies
- 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
Requirements
- Python 3.14+
- macOS (tested), Linux (untested), Windows (untested) though it should work
- Windsurf IDE installed
Creating Screenshots
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
Metadata
Release files for surfmon 0.22.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| surfmon-0.22.0.tar.gz | 46.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| surfmon-0.22.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 96.8 kB
Release files / surfmon-0.22.0.tar.gz
| Download URL | surfmon-0.22.0.tar.gz |
|---|---|
| Size | 46.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e9ae624790acaeab7ae041fb74f3ffd8aa2a5ddacae431ce36b8bc449cc97ec8
|
|
BLAKE2b-256 checksum How to use checksums |
c8e9411e909f74cab0034595925f6f681ac02e78c238bc6f2c0795976fd0eeac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / surfmon-0.22.0-py3-none-any.whl
| Download URL | surfmon-0.22.0-py3-none-any.whl |
|---|---|
| Size | 50.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a888a6494e19323b3caeacdc5219a134191657d240308e73d1e2a8ed0f73f8f
|
|
BLAKE2b-256 checksum How to use checksums |
0c277d15137698acce05aa3678dbb272bc5f596866c76e2a0a9420c39150ea7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|