diff --git a/README.md b/README.md index 64c6cb5..b6c91db 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ๐Ÿš€ macOS Development Setup +# ๐Ÿš€ macOS & Windows Development Setup -Complete, automated setup for macOS development environments. Get up and running with essential dev tools, a beautiful terminal, tmux workflow, and a live Claude Code monitoring dashboard. +Complete, automated setup for macOS and Windows development environments. Get up and running with essential dev tools, a beautiful terminal, tmux workflow, and a live Claude Code monitoring dashboard. ## โœจ What This Does @@ -52,7 +52,42 @@ This launches an interactive menu: 6. **Verify Setup** - Check what's already installed 7. **Exit** -## ๐Ÿ“‹ Prerequisites +## ๐ŸชŸ Windows Setup + +### One-Command Setup + +```powershell +powershell -ExecutionPolicy Bypass -File setup-windows.ps1 +``` + +Same interactive menu, adapted for Windows: + +1. **Full Setup** - Dev tools + Terminal + Multiplexer +2. **Dev Environment Only** - Git, Python (pyenv-win), Node.js, utilities via winget + scoop +3. **Terminal Only** - Oh My Posh + PSReadLine + modern CLI tools + Catppuccin theme +4. **Multiplexer Only** - Windows Terminal panes + optional WSL2/tmux +5. **Claude Monitor** - Live dashboard for Claude Code instances +6. **Verify Setup** - Check what's already installed + +### Windows Equivalents + +| macOS | Windows | +|-------|---------| +| Homebrew | winget + scoop | +| Oh My Zsh + Powerlevel10k | Oh My Posh + Catppuccin theme | +| zsh-autosuggestions | PSReadLine PredictiveIntelliSense | +| zsh-syntax-highlighting | PSReadLine inline predictions | +| tmux | Windows Terminal panes + optional WSL/tmux | +| .zshrc | PowerShell $PROFILE | + +### Windows Prerequisites + +- Windows 10 or later +- PowerShell 5.1+ (pre-installed) +- Internet connection +- winget (pre-installed on Windows 10/11) + +## ๐Ÿ“‹ macOS Prerequisites - macOS 11.0 or later - Terminal with zsh (default on modern macOS) @@ -63,15 +98,26 @@ This launches an interactive menu: ``` MacDev/ -โ”œโ”€โ”€ setup-macos.sh # Main entry point (interactive menu) -โ”œโ”€โ”€ scripts/ # Core setup scripts +โ”œโ”€โ”€ setup-macos.sh # macOS entry point (interactive menu) +โ”œโ”€โ”€ setup-windows.ps1 # Windows entry point (interactive menu) +โ”œโ”€โ”€ scripts/ # macOS/Linux setup scripts โ”‚ โ”œโ”€โ”€ setup-dev-env.sh # Development environment installer โ”‚ โ”œโ”€โ”€ pimp-my-terminal.sh # Terminal customization installer โ”‚ โ”œโ”€โ”€ setup-tmux.sh # tmux + theme + plugins installer โ”‚ โ”œโ”€โ”€ setup-claude-monitor.sh # Claude Code Monitor installer -โ”‚ โ”œโ”€โ”€ claude-monitor.py # Live dashboard (rich TUI) +โ”‚ โ”œโ”€โ”€ claude-monitor.py # Live dashboard (rich TUI, cross-platform) โ”‚ โ””โ”€โ”€ verify-setup.sh # Verification script -โ”œโ”€โ”€ configs/ # Configuration files +โ”œโ”€โ”€ windows/ # Windows setup scripts (PowerShell) +โ”‚ โ”œโ”€โ”€ setup-dev-env.ps1 # Dev tools via winget + scoop +โ”‚ โ”œโ”€โ”€ pimp-my-terminal.ps1 # Oh My Posh + PSReadLine + CLI tools +โ”‚ โ”œโ”€โ”€ setup-tmux.ps1 # Windows Terminal + optional WSL/tmux +โ”‚ โ”œโ”€โ”€ setup-claude-monitor.ps1 # Claude Monitor installer +โ”‚ โ”œโ”€โ”€ dev-session.ps1 # Multi-pane layout via wt CLI +โ”‚ โ”œโ”€โ”€ verify-setup.ps1 # Verification script +โ”‚ โ””โ”€โ”€ configs/ # Windows-specific configs +โ”‚ โ”œโ”€โ”€ oh-my-posh-theme.json # Catppuccin Mocha for Oh My Posh +โ”‚ โ””โ”€โ”€ windows-terminal-settings.json # Color scheme for Windows Terminal +โ”œโ”€โ”€ configs/ # macOS configuration files โ”‚ โ”œโ”€โ”€ tmux.conf # tmux config (Catppuccin Mocha theme) โ”‚ โ””โ”€โ”€ dev-session.sh # Dev session layout launcher โ”œโ”€โ”€ docs/ # Documentation @@ -271,6 +317,7 @@ This setup installs and configures these open-source projects: - [tmux](https://github.com/tmux/tmux) ยท [Catppuccin](https://github.com/catppuccin/tmux) ยท [TPM](https://github.com/tmux-plugins/tpm) - [eza](https://github.com/eza-community/eza) ยท [bat](https://github.com/sharkdp/bat) ยท [fzf](https://github.com/junegunn/fzf) ยท [fd](https://github.com/sharkdp/fd) - [rich](https://github.com/Textualize/rich) ยท [uv](https://github.com/astral-sh/uv) +- [Oh My Posh](https://ohmyposh.dev/) ยท [Scoop](https://scoop.sh/) ยท [Windows Terminal](https://github.com/microsoft/terminal) --- diff --git a/scripts/claude-monitor.py b/scripts/claude-monitor.py index c0669a2..d51e5a8 100755 --- a/scripts/claude-monitor.py +++ b/scripts/claude-monitor.py @@ -46,7 +46,13 @@ class ClaudeData: HISTORY_PATH = Path.home() / ".claude" / "history.jsonl" def get_processes(self) -> list[dict]: - """Get running Claude Code CLI instances via ps + lsof.""" + """Get running Claude Code CLI instances via ps (Unix) or wmic (Windows).""" + if sys.platform == "win32": + return self._get_processes_windows() + return self._get_processes_unix() + + def _get_processes_unix(self) -> list[dict]: + """Get processes on macOS/Linux via ps.""" try: result = subprocess.run( ["ps", "-eo", "pid,etime,pcpu,pmem,command"], @@ -68,7 +74,6 @@ def get_processes(self) -> list[dict]: cpu = parts[2] mem = parts[3] - # Get working directory via lsof project = self._get_project(pid) instances.append({ @@ -79,12 +84,97 @@ def get_processes(self) -> list[dict]: "project": project, }) - # Sort by CPU descending + instances.sort(key=lambda x: float(x["cpu"]), reverse=True) + return instances + + def _get_processes_windows(self) -> list[dict]: + """Get processes on Windows via wmic/powershell.""" + try: + # Use PowerShell to get Claude processes with details + result = subprocess.run( + ["powershell", "-NoProfile", "-Command", + "Get-Process -Name 'claude' -ErrorAction SilentlyContinue | " + "Select-Object Id, CPU, WorkingSet64, StartTime, Path | " + "ConvertTo-Json"], + capture_output=True, text=True, timeout=10 + ) + except (subprocess.TimeoutExpired, FileNotFoundError): + return [] + + if not result.stdout.strip(): + return [] + + instances = [] + try: + data = json.loads(result.stdout) + # Ensure it's a list (single process returns a dict) + if isinstance(data, dict): + data = [data] + + for proc in data: + pid = str(proc.get("Id", "")) + cpu = f"{proc.get('CPU', 0):.1f}" + mem_bytes = proc.get("WorkingSet64", 0) + mem_mb = mem_bytes / (1024 * 1024) + + # Calculate elapsed time + start_time = proc.get("StartTime", {}) + etime = "?" + if start_time: + try: + # PowerShell returns DateTime as a string or object + if isinstance(start_time, str): + from datetime import datetime as dt + start = dt.fromisoformat(start_time) + else: + # Handle .NET DateTime ticks + ticks = start_time.get("/Date(", start_time) + if isinstance(ticks, (int, float)): + start = datetime.fromtimestamp(ticks / 1000) + else: + start = datetime.now() + delta = datetime.now() - start + total_min = int(delta.total_seconds() / 60) + if total_min >= 1440: + etime = f"{total_min // 1440}d {(total_min % 1440) // 60}h" + elif total_min >= 60: + etime = f"{total_min // 60}h {total_min % 60}m" + else: + etime = f"{total_min}m" + except (ValueError, TypeError, KeyError): + etime = "?" + + project = self._get_project(pid) + + instances.append({ + "pid": pid, + "etime": etime, + "cpu": cpu, + "mem": f"{mem_mb:.0f}", + "project": project, + }) + except (json.JSONDecodeError, KeyError): + pass + instances.sort(key=lambda x: float(x["cpu"]), reverse=True) return instances def _get_project(self, pid: str) -> str: """Get project name from process working directory.""" + # On Windows, use PowerShell to get the working directory + if sys.platform == "win32": + try: + result = subprocess.run( + ["powershell", "-NoProfile", "-Command", + f"(Get-Process -Id {pid} -ErrorAction SilentlyContinue).Path | Split-Path -Parent"], + capture_output=True, text=True, timeout=5 + ) + if result.stdout.strip(): + return Path(result.stdout.strip()).name + except (subprocess.TimeoutExpired, FileNotFoundError): + pass + return "unknown" + # On Linux, /proc//cwd is a symlink to the working directory if sys.platform == "linux": try: @@ -166,7 +256,9 @@ def get_today_stats(self) -> dict: ts = entry.get("timestamp") if ts is None: continue - entry_date = datetime.fromtimestamp(ts / 1000).date().isoformat() + # Auto-detect ms vs seconds: ms timestamps are > 1e11 + entry_dt = datetime.fromtimestamp(ts / 1000 if ts > 1e11 else ts) + entry_date = entry_dt.date().isoformat() if entry_date == today_str: messages += 1 sid = entry.get("sessionId") @@ -263,7 +355,7 @@ def build_compact_dashboard(data: ClaudeData) -> Panel: for p in processes: proj = p["project"][:12] cpu_val = float(p["cpu"]) - cpu_style = RED if cpu_val > 50 else PEACH if cpu_val > 10 else SUBTEXT + cpu_style = RED if cpu_val > 500 else PEACH if cpu_val > 100 else SUBTEXT item = Text(proj, style=PINK) item.append(f" {p['cpu']}%", style=cpu_style) item.append(f" {p['etime']}", style=SUBTEXT) @@ -277,7 +369,7 @@ def build_compact_dashboard(data: ClaudeData) -> Panel: parts.append(Text("โ—‹ No active instances", style=SUBTEXT)) # === TODAY: inline with bars === - today_date = date.today().strftime("%b %-d") + today_date = date.today().strftime("%b %d") msg_line = Text(f"TODAY {today_date} ", style=f"bold {BLUE}") msg_line.append("Msgs ") msg_line.append_text(make_bar(today["messages"], max(today["messages"], 200), width=8)) @@ -379,7 +471,7 @@ def build_dashboard(data: ClaudeData, compact: bool = False) -> Panel: if len(proj) > 12: proj = proj[:11] + "โ€ฆ" cpu_val = float(p["cpu"]) - cpu_style = RED if cpu_val > 50 else PEACH if cpu_val > 10 else SUBTEXT + cpu_style = RED if cpu_val > 500 else PEACH if cpu_val > 100 else SUBTEXT proc_table.add_row( proj, f"PID {p['pid']}", @@ -390,7 +482,7 @@ def build_dashboard(data: ClaudeData, compact: bool = False) -> Panel: parts.append(Text("")) # === Today Stats === - today_date = date.today().strftime("%b %-d") + today_date = date.today().strftime("%b %d") parts.append(Text(f" TODAY {today_date}", style=f"bold {BLUE}")) msg_max = max(today["messages"], 200) @@ -442,7 +534,7 @@ def build_dashboard(data: ClaudeData, compact: bool = False) -> Panel: first_date = stats.get("firstSessionDate", "") if first_date: try: - since = datetime.fromisoformat(first_date.replace("Z", "+00:00")).strftime("%b %-d, %Y") + since = datetime.fromisoformat(first_date.replace("Z", "+00:00")).strftime("%b %d, %Y") except (ValueError, AttributeError): since = "?" else: diff --git a/setup-windows.ps1 b/setup-windows.ps1 new file mode 100644 index 0000000..f41edf0 --- /dev/null +++ b/setup-windows.ps1 @@ -0,0 +1,149 @@ +# ============================================ +# Windows Development Setup +# ============================================ +# One-stop script for setting up your Windows development environment +# +# Options: +# 1. Complete setup (Dev tools + Terminal + Multiplexer) +# 2. Development environment only +# 3. Terminal customization only +# 4. Multiplexer setup (Windows Terminal + optional WSL/tmux) +# 5. Claude Monitor +# 6. Verify Setup +# 7. Exit +# +# Usage: powershell -ExecutionPolicy Bypass -File setup-windows.ps1 +# ============================================ + +$ErrorActionPreference = "Stop" + +# Get script directory +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +function Print-Header { + Clear-Host + Write-Host "" + Write-Host "+===========================================================" -ForegroundColor Magenta + Write-Host "| |" -ForegroundColor Magenta + Write-Host "| Windows Development Environment Setup |" -ForegroundColor Magenta + Write-Host "| |" -ForegroundColor Magenta + Write-Host "+===========================================================" -ForegroundColor Magenta + Write-Host "" +} + +function Print-Info { param([string]$Message) Write-Host $Message -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } +function Print-Error { param([string]$Message) Write-Host "[X] $Message" -ForegroundColor Red } +function Print-Warning { param([string]$Message) Write-Host "[!] $Message" -ForegroundColor Yellow } + +function Show-Menu { + Write-Host "What would you like to set up?" -ForegroundColor Yellow + Write-Host "" + Write-Host " 1) " -NoNewline; Write-Host "Full Setup" -ForegroundColor Green -NoNewline; Write-Host " - Dev tools + Terminal + Multiplexer" + Write-Host " 2) " -NoNewline; Write-Host "Dev Environment Only" -ForegroundColor Blue -NoNewline; Write-Host " - Essential development tools" + Write-Host " 3) " -NoNewline; Write-Host "Terminal Only" -ForegroundColor Magenta -NoNewline; Write-Host " - Beautiful terminal with Oh My Posh" + Write-Host " 4) " -NoNewline; Write-Host "Multiplexer Only" -ForegroundColor Yellow -NoNewline; Write-Host " - Windows Terminal panes + optional WSL/tmux" + Write-Host " 5) " -NoNewline; Write-Host "Claude Monitor" -ForegroundColor Magenta -NoNewline; Write-Host " - Live dashboard for Claude Code instances" + Write-Host " 6) " -NoNewline; Write-Host "Verify Setup" -ForegroundColor Cyan -NoNewline; Write-Host " - Check what's already installed" + Write-Host " 7) Exit" + Write-Host "" +} + +function Run-Script { + param([string]$ScriptPath, [string]$Description) + if (Test-Path $ScriptPath) { + Print-Info "Starting $Description..." + Write-Host "" + & $ScriptPath + } else { + Print-Error "$ScriptPath not found!" + exit 1 + } +} + +function Main { + Print-Header + + # Check Windows version + $osVersion = [System.Environment]::OSVersion.Version + if ($osVersion.Major -lt 10) { + Print-Error "Windows 10 or later is required." + exit 1 + } + Print-Info "Running on Windows $($osVersion.Major).$($osVersion.Minor) (Build $($osVersion.Build))" + + # Check execution policy + $policy = Get-ExecutionPolicy -Scope CurrentUser + if ($policy -eq "Restricted") { + Print-Warning "PowerShell execution policy is Restricted." + Print-Info "Run: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser" + Print-Info "Then re-run this script." + exit 1 + } + + Write-Host "" + Show-Menu + + $choice = Read-Host "Enter your choice (1-7)" + + switch ($choice) { + "1" { + Write-Host "" + Write-Host "Full Setup Selected" -ForegroundColor Green + Write-Host "" + Run-Script "$ScriptDir\windows\setup-dev-env.ps1" "development environment setup" + Write-Host "" + Run-Script "$ScriptDir\windows\pimp-my-terminal.ps1" "terminal customization" + Write-Host "" + Run-Script "$ScriptDir\windows\setup-tmux.ps1" "multiplexer setup" + } + "2" { + Write-Host "" + Write-Host "Dev Environment Setup Selected" -ForegroundColor Blue + Write-Host "" + Run-Script "$ScriptDir\windows\setup-dev-env.ps1" "development environment setup" + } + "3" { + Write-Host "" + Write-Host "Terminal Customization Selected" -ForegroundColor Magenta + Write-Host "" + Run-Script "$ScriptDir\windows\pimp-my-terminal.ps1" "terminal customization" + } + "4" { + Write-Host "" + Write-Host "Multiplexer Setup Selected" -ForegroundColor Yellow + Write-Host "" + Run-Script "$ScriptDir\windows\setup-tmux.ps1" "multiplexer setup" + } + "5" { + Write-Host "" + Write-Host "Claude Monitor Setup Selected" -ForegroundColor Magenta + Write-Host "" + Run-Script "$ScriptDir\windows\setup-claude-monitor.ps1" "Claude Monitor setup" + } + "6" { + Write-Host "" + Run-Script "$ScriptDir\windows\verify-setup.ps1" "setup verification" + } + "7" { + Write-Host "" + Print-Info "Goodbye!" + exit 0 + } + default { + Write-Host "" + Print-Error "Invalid choice. Please run the script again." + exit 1 + } + } + + Write-Host "" + Write-Host "+===========================================================" -ForegroundColor Green + Write-Host "| Setup Complete! |" -ForegroundColor Green + Write-Host "+===========================================================" -ForegroundColor Green + Write-Host "" + Print-Info "Check the docs/ folder for detailed guides and documentation." + Write-Host "" +} + +Main diff --git a/windows/configs/oh-my-posh-theme.json b/windows/configs/oh-my-posh-theme.json new file mode 100644 index 0000000..f740081 --- /dev/null +++ b/windows/configs/oh-my-posh-theme.json @@ -0,0 +1,140 @@ +{ + "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json", + "version": 2, + "final_space": true, + "console_title_template": "{{ .Folder }}", + "blocks": [ + { + "type": "prompt", + "alignment": "left", + "newline": true, + "segments": [ + { + "type": "os", + "style": "diamond", + "leading_diamond": "\ue0b6", + "trailing_diamond": "", + "foreground": "#1e1e2e", + "background": "#89b4fa", + "template": " {{ if .WSL }}WSL{{ else }}\ue62a{{ end }} " + }, + { + "type": "path", + "style": "powerline", + "powerline_symbol": "\ue0b0", + "foreground": "#cdd6f4", + "background": "#313244", + "properties": { + "style": "agnoster_short", + "max_depth": 3, + "folder_icon": "\uf115", + "home_icon": "\uf015" + }, + "template": " {{ .Path }} " + }, + { + "type": "git", + "style": "powerline", + "powerline_symbol": "\ue0b0", + "foreground": "#1e1e2e", + "background": "#a6e3a1", + "background_templates": [ + "{{ if or (.Working.Changed) (.Staging.Changed) }}#fab387{{ end }}", + "{{ if and (gt .Ahead 0) (gt .Behind 0) }}#f38ba8{{ end }}", + "{{ if gt .Ahead 0 }}#f5c2e7{{ end }}", + "{{ if gt .Behind 0 }}#f5c2e7{{ end }}" + ], + "properties": { + "branch_icon": "\ue725 ", + "fetch_status": true, + "fetch_stash_count": true + }, + "template": " {{ .HEAD }}{{ if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} \uf044 {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} \uf046 {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} \ueb4b {{ .StashCount }}{{ end }} " + } + ] + }, + { + "type": "prompt", + "alignment": "right", + "segments": [ + { + "type": "python", + "style": "plain", + "foreground": "#f9e2af", + "properties": { + "display_virtual_env": true, + "display_default": false + }, + "template": "\ue235 {{ if .Venv }}{{ .Venv }}{{ else }}{{ .Full }}{{ end }} " + }, + { + "type": "node", + "style": "plain", + "foreground": "#a6e3a1", + "properties": { + "display_mode": "files" + }, + "template": "\ue718 {{ .Full }} " + }, + { + "type": "time", + "style": "plain", + "foreground": "#a6adc8", + "properties": { + "time_format": "15:04:05" + }, + "template": "\uf017 {{ .CurrentDate | date .Format }} " + } + ] + }, + { + "type": "prompt", + "alignment": "left", + "newline": true, + "segments": [ + { + "type": "text", + "style": "plain", + "foreground_templates": [ + "{{ if gt .Code 0 }}#f38ba8{{ else }}#a6e3a1{{ end }}" + ], + "template": "\u276f " + } + ] + } + ], + "transient_prompt": { + "foreground_templates": [ + "{{ if gt .Code 0 }}#f38ba8{{ else }}#a6e3a1{{ end }}" + ], + "template": "\u276f " + }, + "palette": { + "rosewater": "#f5e0dc", + "flamingo": "#f2cdcd", + "pink": "#f5c2e7", + "mauve": "#cba6f7", + "red": "#f38ba8", + "maroon": "#eba0ac", + "peach": "#fab387", + "yellow": "#f9e2af", + "green": "#a6e3a1", + "teal": "#94e2d5", + "sky": "#89dceb", + "sapphire": "#74c7ec", + "blue": "#89b4fa", + "lavender": "#b4befe", + "text": "#cdd6f4", + "subtext1": "#bac2de", + "subtext0": "#a6adc8", + "overlay2": "#9399b2", + "overlay1": "#7f849c", + "overlay0": "#6c7086", + "surface2": "#585b70", + "surface1": "#45475a", + "surface0": "#313244", + "base": "#1e1e2e", + "mantle": "#181825", + "crust": "#11111b" + } +} diff --git a/windows/configs/windows-terminal-settings.json b/windows/configs/windows-terminal-settings.json new file mode 100644 index 0000000..795a9f3 --- /dev/null +++ b/windows/configs/windows-terminal-settings.json @@ -0,0 +1,39 @@ +{ + "_comment": "Catppuccin Mocha color scheme for Windows Terminal. Import this scheme into your Windows Terminal settings.json under 'schemes' array.", + "scheme": { + "name": "Catppuccin Mocha", + "cursorColor": "#f5e0dc", + "selectionBackground": "#585b70", + "background": "#1e1e2e", + "foreground": "#cdd6f4", + "black": "#45475a", + "red": "#f38ba8", + "green": "#a6e3a1", + "yellow": "#f9e2af", + "blue": "#89b4fa", + "purple": "#cba6f7", + "cyan": "#94e2d5", + "white": "#bac2de", + "brightBlack": "#585b70", + "brightRed": "#f38ba8", + "brightGreen": "#a6e3a1", + "brightYellow": "#f9e2af", + "brightBlue": "#89b4fa", + "brightPurple": "#cba6f7", + "brightCyan": "#94e2d5", + "brightWhite": "#a6adc8" + }, + "recommended_profile_settings": { + "_comment": "Add these to your default profile in Windows Terminal settings for the best experience", + "colorScheme": "Catppuccin Mocha", + "font": { + "face": "CaskaydiaCove Nerd Font", + "size": 12, + "weight": "normal" + }, + "opacity": 95, + "useAcrylic": true, + "padding": "8, 8, 8, 8", + "cursorShape": "bar" + } +} diff --git a/windows/dev-session.ps1 b/windows/dev-session.ps1 new file mode 100644 index 0000000..7270da7 --- /dev/null +++ b/windows/dev-session.ps1 @@ -0,0 +1,107 @@ +# ============================================ +# Dev Session - Windows Terminal multi-pane layout +# ============================================ +# Creates a pre-configured Windows Terminal layout with: +# - Left (65%): Claude Code +# - Top-right: Dev server pane +# - Bottom-right: System monitor (btop) +# +# Uses the Windows Terminal CLI (wt.exe) to create split panes. +# +# Usage: +# dev-session # uses current dir +# dev-session C:\path\to\project # uses given path +# +# Aliases (add to profile): +# Set-Alias -Name sc -Value dev-session +# ============================================ + +param( + [Parameter(Position = 0)] + [string]$ProjectPath = (Get-Location).Path +) + +# Resolve to absolute path +if ($ProjectPath -and (Test-Path $ProjectPath)) { + $ProjectPath = (Resolve-Path $ProjectPath).Path +} + +$ProjectName = Split-Path -Leaf $ProjectPath + +# Colors +function Print-Info { param([string]$Message) Write-Host $Message -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } + +# Check if Windows Terminal is installed +if (-not (Get-Command wt -ErrorAction SilentlyContinue)) { + Write-Host "Windows Terminal (wt) is not installed." -ForegroundColor Yellow + Write-Host "Install it via: winget install Microsoft.WindowsTerminal" -ForegroundColor Yellow + exit 1 +} + +# Determine monitor command +$monitorCmd = "echo System monitor pane" +if (Get-Command btop -ErrorAction SilentlyContinue) { + $monitorCmd = "btop" +} elseif (Get-Command htop -ErrorAction SilentlyContinue) { + $monitorCmd = "htop" +} + +# Determine claude-monitor command +$claudeMonitorCmd = "" +if (Get-Command claude-monitor -ErrorAction SilentlyContinue) { + $claudeMonitorCmd = "claude-monitor --compact" +} + +Print-Info "Starting dev session: $ProjectName" +Print-Info "Project directory: $ProjectPath" +Write-Host "" + +# โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +# โ”‚ โ”‚ Dev Server โ”‚ +# โ”‚ Claude Code โ”‚ โ”‚ +# โ”‚ (65% width) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# โ”‚ โ”‚ Monitor โ”‚ +# โ”‚ โ”‚ (btop) โ”‚ +# โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +# 65% width 35% width + +# Build the wt command +# Windows Terminal CLI uses semicolons to separate pane commands +# split-pane -H splits horizontally (side by side), -V splits vertically (top/bottom) + +$wtArgs = @( + "--title", $ProjectName, + "-d", $ProjectPath, + "powershell", "-NoExit", "-Command", "cd '$ProjectPath'; Write-Host 'Claude Code pane - run: claude' -ForegroundColor Cyan" +) + +# Add right pane (35% width) - dev server +$wtArgs += @( + ";", "split-pane", "-H", "--size", "0.35", + "-d", $ProjectPath, + "powershell", "-NoExit", "-Command", "cd '$ProjectPath'; Write-Host 'Dev server pane - run your server here (e.g., npm run dev)' -ForegroundColor Cyan" +) + +# Split right pane vertically for monitor (bottom-right) +$wtArgs += @( + ";", "split-pane", "-V", "--size", "0.5", + "-d", $ProjectPath, + "powershell", "-NoExit", "-Command", "$monitorCmd" +) + +# If claude-monitor is available, split left pane for it (bottom-left) +if ($claudeMonitorCmd) { + $wtArgs += @( + ";", "move-focus", "left", + ";", "split-pane", "-V", "--size", "0.2", + "-d", $ProjectPath, + "powershell", "-NoExit", "-Command", "$claudeMonitorCmd" + ) +} + +# Focus on the first (Claude Code) pane +$wtArgs += @(";", "focus-tab", "-t", "0") + +Print-Success "Launching Windows Terminal layout..." +Start-Process wt -ArgumentList $wtArgs diff --git a/windows/pimp-my-terminal.ps1 b/windows/pimp-my-terminal.ps1 new file mode 100644 index 0000000..fe2f4fe --- /dev/null +++ b/windows/pimp-my-terminal.ps1 @@ -0,0 +1,364 @@ +# ============================================ +# PIMP MY TERMINAL - Windows Setup Script +# ============================================ +# Installs and configures a modern, beautiful terminal on Windows: +# - Oh My Posh (prompt theme engine) +# - PSReadLine (autosuggestions + syntax highlighting) +# - Modern CLI tools (eza, bat, fzf, fd) +# - Terminal-Icons module +# - Windows Terminal Catppuccin theme +# +# Usage: powershell -ExecutionPolicy Bypass -File pimp-my-terminal.ps1 +# ============================================ + +$ErrorActionPreference = "Stop" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +function Print-Header { + Write-Host "" + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "| PIMP MY TERMINAL SETUP |" -ForegroundColor Magenta + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "" +} + +function Print-Step { param([string]$Message) Write-Host "`n>> $Message" -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } +function Print-Error { param([string]$Message) Write-Host "[X] $Message" -ForegroundColor Red } +function Print-Info { param([string]$Message) Write-Host "[i] $Message" -ForegroundColor Yellow } + +# Ensure Scoop is available +function Ensure-Scoop { + if (-not (Get-Command scoop -ErrorAction SilentlyContinue)) { + Print-Info "Installing Scoop (needed for CLI tools)..." + Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression + scoop bucket add extras + } +} + +# Install Oh My Posh +function Install-OhMyPosh { + Print-Step "Installing Oh My Posh..." + + if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) { + Print-Success "Oh My Posh already installed" + } else { + Print-Info "Installing Oh My Posh via winget..." + winget install --id JanDeDobbeleer.OhMyPosh --accept-source-agreements --accept-package-agreements + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + Print-Success "Oh My Posh installed successfully" + } + + # Deploy Catppuccin Mocha theme + $themeDir = Join-Path $env:USERPROFILE ".config\oh-my-posh" + if (-not (Test-Path $themeDir)) { + New-Item -ItemType Directory -Path $themeDir -Force | Out-Null + } + + $themeSrc = Join-Path $ScriptDir "configs\oh-my-posh-theme.json" + $themeDest = Join-Path $themeDir "catppuccin-mocha.omp.json" + + if (Test-Path $themeSrc) { + Copy-Item $themeSrc $themeDest -Force + Print-Success "Catppuccin Mocha theme deployed to $themeDest" + } else { + Print-Error "Theme file not found at $themeSrc" + } +} + +# Install and configure PSReadLine +function Configure-PSReadLine { + Print-Step "Configuring PSReadLine (autosuggestions + highlighting)..." + + # PSReadLine ships with PowerShell 5.1+, but update to latest + $currentVersion = (Get-Module PSReadLine -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).Version + Print-Info "Current PSReadLine version: $currentVersion" + + try { + Install-Module PSReadLine -Force -AllowPrerelease -Scope CurrentUser -ErrorAction SilentlyContinue + Print-Success "PSReadLine updated" + } catch { + Print-Info "PSReadLine is up to date or update skipped" + } +} + +# Install Terminal-Icons module +function Install-TerminalIcons { + Print-Step "Installing Terminal-Icons (file icons in directory listings)..." + + if (Get-Module -ListAvailable -Name Terminal-Icons) { + Print-Success "Terminal-Icons already installed" + } else { + Install-Module -Name Terminal-Icons -Repository PSGallery -Force -Scope CurrentUser + Print-Success "Terminal-Icons installed" + } +} + +# Install modern CLI tools via Scoop +function Install-CLITools { + Print-Step "Installing modern CLI tools..." + + Ensure-Scoop + + $tools = @( + @{ Name = "eza"; Desc = "modern ls replacement" }, + @{ Name = "bat"; Desc = "better cat with syntax highlighting" }, + @{ Name = "fzf"; Desc = "fuzzy finder" }, + @{ Name = "fd"; Desc = "faster find" } + ) + + foreach ($tool in $tools) { + if (Get-Command $tool.Name -ErrorAction SilentlyContinue) { + Print-Success "$($tool.Name) already installed ($($tool.Desc))" + } else { + Print-Info "Installing $($tool.Name) ($($tool.Desc))..." + scoop install $tool.Name + Print-Success "$($tool.Name) installed" + } + } +} + +# Install a Nerd Font for icon support +function Install-NerdFont { + Print-Step "Installing Nerd Font (for icons and glyphs)..." + + # Check if scoop nerd-fonts bucket exists + $buckets = scoop bucket list 2>$null + if ($buckets -notmatch "nerd-fonts") { + scoop bucket add nerd-fonts + } + + # Install CaskaydiaCove Nerd Font (recommended for Windows Terminal) + $fontName = "CascadiaCode-NF" + $installed = scoop list $fontName 2>$null + if ($installed -match $fontName) { + Print-Success "CascadiaCode Nerd Font already installed" + } else { + Print-Info "Installing CascadiaCode Nerd Font..." + scoop install $fontName + Print-Success "CascadiaCode Nerd Font installed" + } +} + +# Deploy Windows Terminal color scheme +function Deploy-TerminalSettings { + Print-Step "Deploying Windows Terminal Catppuccin theme..." + + $settingsSrc = Join-Path $ScriptDir "configs\windows-terminal-settings.json" + if (-not (Test-Path $settingsSrc)) { + Print-Info "Windows Terminal settings fragment not found, skipping" + return + } + + # Windows Terminal settings location + $wtSettingsDir = Join-Path $env:LOCALAPPDATA "Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState" + $wtSettingsPath = Join-Path $wtSettingsDir "settings.json" + + if (-not (Test-Path $wtSettingsPath)) { + # Try Windows Terminal Preview + $wtSettingsDir = Join-Path $env:LOCALAPPDATA "Packages\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\LocalState" + $wtSettingsPath = Join-Path $wtSettingsDir "settings.json" + } + + if (Test-Path $wtSettingsPath) { + # Backup existing settings + $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" + Copy-Item $wtSettingsPath "$wtSettingsPath.backup.$timestamp" + Print-Info "Windows Terminal settings backed up" + + # Read and merge color scheme + try { + $wtSettings = Get-Content $wtSettingsPath -Raw | ConvertFrom-Json + $catppuccin = Get-Content $settingsSrc -Raw | ConvertFrom-Json + + # Add color scheme if not already present + if (-not $wtSettings.schemes) { + $wtSettings | Add-Member -NotePropertyName "schemes" -NotePropertyValue @() + } + + $existingScheme = $wtSettings.schemes | Where-Object { $_.name -eq "Catppuccin Mocha" } + if (-not $existingScheme) { + $wtSettings.schemes += $catppuccin.scheme + $wtSettings | ConvertTo-Json -Depth 10 | Set-Content $wtSettingsPath + Print-Success "Catppuccin Mocha color scheme added to Windows Terminal" + } else { + Print-Success "Catppuccin Mocha scheme already exists in Windows Terminal" + } + } catch { + Print-Info "Could not auto-merge settings. See windows/configs/ for manual import." + } + } else { + Print-Info "Windows Terminal settings not found. Install Windows Terminal first." + Print-Info "Color scheme saved to: $settingsSrc" + } +} + +# Create PowerShell profile +function Create-Profile { + Print-Step "Creating PowerShell profile..." + + $profilePath = $PROFILE.CurrentUserAllHosts + $profileDir = Split-Path -Parent $profilePath + + if (-not (Test-Path $profileDir)) { + New-Item -ItemType Directory -Path $profileDir -Force | Out-Null + } + + # Backup existing profile + if (Test-Path $profilePath) { + $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" + Copy-Item $profilePath "$profilePath.backup.terminal.$timestamp" + Print-Info "Existing profile backed up" + } + + # Check if terminal config already exists + $existingContent = "" + if (Test-Path $profilePath) { + $existingContent = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue + } + + if ($existingContent -notmatch "=== Terminal Customization ===") { + $terminalConfig = @' + +# === Terminal Customization === +# Added by Windows terminal setup script + +# Oh My Posh prompt +$ompTheme = "$env:USERPROFILE\.config\oh-my-posh\catppuccin-mocha.omp.json" +if ((Get-Command oh-my-posh -ErrorAction SilentlyContinue) -and (Test-Path $ompTheme)) { + oh-my-posh init pwsh --config $ompTheme | Invoke-Expression +} + +# PSReadLine configuration (autosuggestions + history) +if (Get-Module -ListAvailable -Name PSReadLine) { + Import-Module PSReadLine + Set-PSReadLineOption -PredictionSource History + Set-PSReadLineOption -PredictionViewStyle ListView + Set-PSReadLineOption -EditMode Windows + Set-PSReadLineOption -HistorySearchCursorMovesToEnd + Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete + Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward + Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward + Set-PSReadLineKeyHandler -Chord "Ctrl+RightArrow" -Function ForwardWord +} + +# Terminal-Icons +if (Get-Module -ListAvailable -Name Terminal-Icons) { + Import-Module Terminal-Icons +} + +# FZF integration +if (Get-Command fzf -ErrorAction SilentlyContinue) { + $env:FZF_DEFAULT_OPTS = "--height 40% --layout=reverse --border --margin=1 --padding=1" + if (Get-Command fd -ErrorAction SilentlyContinue) { + $env:FZF_DEFAULT_COMMAND = "fd --type f --hidden --follow --exclude .git" + } +} + +# === Modern CLI Aliases === +# eza (modern ls) +if (Get-Command eza -ErrorAction SilentlyContinue) { + function ls_eza { eza --icons --group-directories-first @args } + Set-Alias -Name ls -Value ls_eza -Force -Option AllScope + function la_eza { eza --icons --group-directories-first -a @args } + Set-Alias -Name la -Value la_eza -Force + function ll_eza { eza --icons --group-directories-first -lh @args } + Set-Alias -Name ll -Value ll_eza -Force + function lla_eza { eza --icons --group-directories-first -lha @args } + Set-Alias -Name lla -Value lla_eza -Force + function lt_eza { eza --icons --group-directories-first --tree @args } + Set-Alias -Name lt -Value lt_eza -Force +} + +# bat (better cat) +if (Get-Command bat -ErrorAction SilentlyContinue) { + function cat_bat { bat --paging=never @args } + Set-Alias -Name cat -Value cat_bat -Force -Option AllScope +} + +# Git shortcuts +function gs { git status @args } +function ga { git add @args } +function gc { git commit @args } +function gp { git push @args } +function gl { git log --oneline --graph --decorate --all @args } +function gd { git diff @args } + +# Navigation +function .. { Set-Location .. } +function ... { Set-Location ..\.. } +function .... { Set-Location ..\..\.. } + +# System +function c { Clear-Host } +Set-Alias -Name h -Value Get-History -Force + +# Custom Functions +function mkcd { param([string]$dir) New-Item -ItemType Directory -Path $dir -Force | Out-Null; Set-Location $dir } +function search { param([string]$pattern) Get-ChildItem -Recurse | Select-String $pattern } + +# Git commit all and push +function gcap { param([string]$message) git add .; git commit -m $message; git push } + +# === End Terminal Customization === +'@ + Add-Content -Path $profilePath -Value $terminalConfig + Print-Success "Terminal configuration added to PowerShell profile" + } else { + Print-Success "Terminal configuration already exists in profile" + } +} + +# Print completion message +function Print-Completion { + Write-Host "" + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "| TERMINAL PIMPING COMPLETE! |" -ForegroundColor Green + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "" + + Write-Host "What's installed:" -ForegroundColor Cyan + Write-Host " - Oh My Posh - Beautiful prompt themes" + Write-Host " - PSReadLine - Autosuggestions + history predictions" + Write-Host " - Terminal-Icons - File icons in listings" + Write-Host " - eza - Modern ls with icons" + Write-Host " - bat - Better cat with syntax highlighting" + Write-Host " - fzf - Fuzzy finder (Ctrl+R for history)" + Write-Host " - fd - Faster find" + Write-Host " - CascadiaCode Nerd Font - Icon support" + Write-Host " - Catppuccin Mocha - Color theme" + + Write-Host "" + Write-Host "Next steps:" -ForegroundColor Yellow + Write-Host " 1. Restart your terminal or run: . `$PROFILE" + Write-Host " 2. Set 'CaskaydiaCove Nerd Font' as your terminal font" + Write-Host " 3. In Windows Terminal: Settings > Color scheme > Catppuccin Mocha" + Write-Host " 4. Try: ll, cat `$PROFILE, Ctrl+R, or use Tab for completions" + + Write-Host "" + Write-Host "Pro tips:" -ForegroundColor Magenta + Write-Host " - Press Tab for menu-style completions" + Write-Host " - Use Up/Down arrows for history search" + Write-Host " - PSReadLine shows inline predictions from history" + Write-Host " - Type 'lt' for tree view of directories" + Write-Host "" +} + +# Main +function Main { + Print-Header + + Install-OhMyPosh + Configure-PSReadLine + Install-TerminalIcons + Install-CLITools + Install-NerdFont + Deploy-TerminalSettings + Create-Profile + + Print-Completion +} + +Main diff --git a/windows/setup-claude-monitor.ps1 b/windows/setup-claude-monitor.ps1 new file mode 100644 index 0000000..99fb16b --- /dev/null +++ b/windows/setup-claude-monitor.ps1 @@ -0,0 +1,177 @@ +# ============================================ +# Claude Code Monitor Setup (Windows) +# ============================================ +# Installs the Claude Code Monitor dashboard: +# - Checks/installs uv (Python package runner) +# - Deploys claude-monitor to ~/.local/bin +# - Adds shell alias +# +# Usage: powershell -ExecutionPolicy Bypass -File setup-claude-monitor.ps1 +# ============================================ + +$ErrorActionPreference = "Stop" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = Split-Path -Parent $ScriptDir + +function Print-Header { + Write-Host "" + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "| Claude Code Monitor Setup (Windows) |" -ForegroundColor Magenta + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "" +} + +function Print-Step { param([string]$Message) Write-Host "`n>> $Message" -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } +function Print-Error { param([string]$Message) Write-Host "[X] $Message" -ForegroundColor Red } +function Print-Info { param([string]$Message) Write-Host "[i] $Message" -ForegroundColor Yellow } + +# Install uv if not present (or broken shim) +function Install-UV { + Print-Step "Checking uv (Python package runner)..." + + $uvWorks = $false + try { + $version = uv --version 2>&1 + if ($LASTEXITCODE -eq 0) { + $uvWorks = $true + Print-Success "uv already installed ($version)" + } + } catch { + # uv command not found or broken shim + } + + if (-not $uvWorks) { + # Try scoop first + if (Get-Command scoop -ErrorAction SilentlyContinue) { + Print-Info "Installing uv via scoop..." + scoop install uv + } else { + Print-Info "Installing uv via installer..." + Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression + } + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + Print-Success "uv installed ($(uv --version))" + } +} + +# Deploy claude-monitor script +function Deploy-Monitor { + Print-Step "Deploying claude-monitor..." + + $monitorSrc = Join-Path $ProjectRoot "scripts\claude-monitor.py" + $binDir = Join-Path $env:USERPROFILE ".local\bin" + $monitorDest = Join-Path $binDir "claude-monitor.py" + + # Ensure bin directory exists + if (-not (Test-Path $binDir)) { + New-Item -ItemType Directory -Path $binDir -Force | Out-Null + } + + if (Test-Path $monitorSrc) { + Copy-Item $monitorSrc $monitorDest -Force + Print-Success "claude-monitor.py installed to $monitorDest" + + # Create a wrapper batch file for easy execution + $wrapperPath = Join-Path $binDir "claude-monitor.cmd" + $wrapperContent = "@echo off`r`nuv run --script `"%~dp0claude-monitor.py`" %*" + Set-Content -Path $wrapperPath -Value $wrapperContent + Print-Success "claude-monitor.cmd wrapper created" + } else { + Print-Error "claude-monitor.py not found at $monitorSrc" + exit 1 + } +} + +# Warm up dependencies +function Warmup-Dependencies { + Print-Step "Warming up dependencies (first-run uv install)..." + + $monitorPath = Join-Path $env:USERPROFILE ".local\bin\claude-monitor.cmd" + try { + & $monitorPath --once 2>$null | Out-Null + Print-Success "Dependencies installed and monitor works" + } catch { + Print-Info "First run may take a moment while uv installs rich..." + try { + & $monitorPath --once 2>$null + } catch {} + Print-Success "Dependencies resolved" + } +} + +# Add alias to PowerShell profile +function Configure-Shell { + Print-Step "Adding shell alias..." + + $profilePath = $PROFILE.CurrentUserAllHosts + $profileDir = Split-Path -Parent $profilePath + + if (-not (Test-Path $profileDir)) { + New-Item -ItemType Directory -Path $profileDir -Force | Out-Null + } + + $profileContent = "" + if (Test-Path $profilePath) { + $profileContent = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue + } + + if ($profileContent -notmatch "=== Claude Monitor ===") { + $monitorConfig = @' + +# === Claude Monitor === +# Added by MacDev claude-monitor setup +$clMonBin = "$env:USERPROFILE\.local\bin" +if (Test-Path $clMonBin) { + $env:Path = "$clMonBin;$env:Path" +} +function cmon { claude-monitor @args } +# === End Claude Monitor === +'@ + Add-Content -Path $profilePath -Value $monitorConfig + Print-Success "Alias 'cmon' added to PowerShell profile" + } else { + Print-Success "Claude Monitor config already exists in profile" + } +} + +# Print completion +function Print-Completion { + Write-Host "" + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "| Claude Code Monitor Setup Complete! |" -ForegroundColor Green + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "" + + Write-Host "What's installed:" -ForegroundColor Cyan + Write-Host " - uv - Python package runner (zero-setup deps)" + Write-Host " - claude-monitor - Live dashboard for Claude Code instances" + Write-Host " - cmon alias - Quick launch shortcut" + + Write-Host "" + Write-Host "Quick Start:" -ForegroundColor Yellow + Write-Host " Live dashboard: claude-monitor" + Write-Host " Single snapshot: claude-monitor --once" + Write-Host " Custom interval: claude-monitor --interval 10" + Write-Host " Quick alias: cmon" + + Write-Host "" + Write-Host "Restart your terminal or run: . `$PROFILE" -ForegroundColor Green + Write-Host "" +} + +# Main +function Main { + Print-Header + + Install-UV + Deploy-Monitor + Warmup-Dependencies + Configure-Shell + + Print-Completion +} + +Main diff --git a/windows/setup-dev-env.ps1 b/windows/setup-dev-env.ps1 new file mode 100644 index 0000000..a5640b8 --- /dev/null +++ b/windows/setup-dev-env.ps1 @@ -0,0 +1,261 @@ +# ============================================ +# Windows Development Environment Setup +# ============================================ +# Installs essential development tools for Windows: +# - Scoop (package manager) +# - Git (via winget) +# - Python (via pyenv-win) +# - Node.js & npm (via winget) +# - Common utilities (via scoop) +# +# Usage: powershell -ExecutionPolicy Bypass -File setup-dev-env.ps1 +# ============================================ + +$ErrorActionPreference = "Stop" + +function Print-Header { + Write-Host "" + Write-Host "+===========================================" -ForegroundColor Blue + Write-Host "| Development Environment Setup |" -ForegroundColor Blue + Write-Host "+===========================================" -ForegroundColor Blue + Write-Host "" +} + +function Print-Step { param([string]$Message) Write-Host "`n>> $Message" -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } +function Print-Error { param([string]$Message) Write-Host "[X] $Message" -ForegroundColor Red } +function Print-Info { param([string]$Message) Write-Host "[i] $Message" -ForegroundColor Yellow } + +# Install Scoop +function Install-Scoop { + Print-Step "Installing Scoop (package manager)..." + + if (Get-Command scoop -ErrorAction SilentlyContinue) { + Print-Success "Scoop already installed" + Print-Info "Updating Scoop..." + scoop update + } else { + Print-Info "Installing Scoop..." + Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression + # Add extras bucket for additional packages + scoop bucket add extras + Print-Success "Scoop installed successfully" + } +} + +# Ensure winget is available +function Ensure-Winget { + Print-Step "Checking winget..." + + if (Get-Command winget -ErrorAction SilentlyContinue) { + Print-Success "winget is available" + } else { + Print-Error "winget is not available. It should be pre-installed on Windows 10/11." + Print-Info "Install 'App Installer' from the Microsoft Store if missing." + throw "winget not found" + } +} + +# Install Git +function Install-Git { + Print-Step "Installing Git..." + + if (Get-Command git -ErrorAction SilentlyContinue) { + $version = git --version + Print-Success "Git already installed: $version" + } else { + Print-Info "Installing Git via winget..." + winget install --id Git.Git --accept-source-agreements --accept-package-agreements + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + Print-Success "Git installed successfully" + } +} + +# Install Python via pyenv-win +function Install-Python { + Print-Step "Installing Python (via pyenv-win)..." + + # Install pyenv-win + if (Get-Command pyenv -ErrorAction SilentlyContinue) { + Print-Success "pyenv-win already installed" + } else { + Print-Info "Installing pyenv-win via scoop..." + scoop install pyenv + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + Print-Success "pyenv-win installed" + } + + # Install Python 3.11 + Print-Info "Installing Python 3.11..." + $installedVersions = pyenv versions 2>&1 + if ($installedVersions -match "3\.11") { + Print-Success "Python 3.11 already installed" + } else { + pyenv install 3.11.9 + pyenv global 3.11.9 + Print-Success "Python 3.11 installed and set as global" + } + + # Install essential pip packages + Print-Info "Installing essential Python packages..." + python -m pip install --upgrade pip 2>$null + python -m pip install virtualenv ipython requests 2>$null + Print-Success "Essential Python packages installed" +} + +# Install Node.js +function Install-Node { + Print-Step "Installing Node.js..." + + if (Get-Command node -ErrorAction SilentlyContinue) { + $nodeVersion = node --version + $npmVersion = npm --version + Print-Success "Node.js already installed: $nodeVersion" + Print-Success "npm already installed: $npmVersion" + } else { + Print-Info "Installing Node.js via winget..." + winget install --id OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + Print-Success "Node.js and npm installed successfully" + } + + # Setup npm global directory + Print-Info "Configuring npm global directory..." + $npmGlobal = Join-Path $env:USERPROFILE ".npm-global" + if (-not (Test-Path $npmGlobal)) { + New-Item -ItemType Directory -Path $npmGlobal -Force | Out-Null + } + npm config set prefix $npmGlobal + Print-Success "npm configured" +} + +# Install common utilities +function Install-Utilities { + Print-Step "Installing common utilities..." + + $tools = @("jq", "wget", "curl", "btop", "tree") + + foreach ($tool in $tools) { + if (Get-Command $tool -ErrorAction SilentlyContinue) { + Print-Success "$tool already installed" + } elseif ((scoop list $tool 2>$null) -match $tool) { + Print-Success "$tool already installed (via scoop)" + } else { + Print-Info "Installing $tool..." + scoop install $tool + Print-Success "$tool installed" + } + } +} + +# Configure PowerShell profile +function Configure-Shell { + Print-Step "Configuring PowerShell profile..." + + $profilePath = $PROFILE.CurrentUserAllHosts + $profileDir = Split-Path -Parent $profilePath + + # Ensure profile directory exists + if (-not (Test-Path $profileDir)) { + New-Item -ItemType Directory -Path $profileDir -Force | Out-Null + } + + # Backup existing profile if it exists + if (Test-Path $profilePath) { + $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" + $backup = "$profilePath.backup.devenv.$timestamp" + Print-Info "Backing up existing profile to $backup" + Copy-Item $profilePath $backup + } + + # Check if dev env config already exists + $profileContent = "" + if (Test-Path $profilePath) { + $profileContent = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue + } + + if ($profileContent -notmatch "=== Development Environment Setup ===") { + $devConfig = @' + +# === Development Environment Setup === +# Added by Windows dev setup script + +# pyenv-win for Python version management +if (Get-Command pyenv -ErrorAction SilentlyContinue) { + $env:PYENV = "$env:USERPROFILE\.pyenv\pyenv-win" + $env:Path = "$env:PYENV\bin;$env:PYENV\shims;$env:Path" +} + +# Node.js npm global +$npmGlobal = "$env:USERPROFILE\.npm-global" +if (Test-Path $npmGlobal) { + $env:Path = "$npmGlobal;$env:Path" +} + +# Aliases +Set-Alias -Name python3 -Value python -ErrorAction SilentlyContinue +Set-Alias -Name pip3 -Value pip -ErrorAction SilentlyContinue + +# === End Development Environment Setup === +'@ + Add-Content -Path $profilePath -Value $devConfig + Print-Success "PowerShell profile updated" + } else { + Print-Success "Development environment configuration already exists in profile" + } +} + +# Print completion message +function Print-Completion { + Write-Host "" + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "| [OK] Development Environment Setup Complete! |" -ForegroundColor Green + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "" + + Write-Host "Installed Tools:" -ForegroundColor Cyan + Write-Host " - Scoop - Package manager" + Write-Host " - winget - Microsoft package manager" + Write-Host " - Git - Version control" + Write-Host " - Python 3.11 (via pyenv-win) - Programming language" + Write-Host " - pip - Python package manager" + Write-Host " - Node.js - JavaScript runtime" + Write-Host " - npm - Node package manager" + Write-Host " - jq, wget, curl, btop, tree - Utilities" + + Write-Host "" + Write-Host "Next Steps:" -ForegroundColor Yellow + Write-Host " 1. Restart your terminal or run: . `$PROFILE" + Write-Host " 2. Verify installation: run verify-setup.ps1" + Write-Host " 3. Start developing!" + Write-Host "" +} + +# Main installation flow +function Main { + Print-Header + + Write-Host "This script will install essential development tools on your Windows machine." + Write-Host "" + $reply = Read-Host "Continue? (y/n)" + + if ($reply -notin @("y", "Y", "yes")) { + Print-Error "Installation cancelled" + exit 1 + } + + Ensure-Winget + Install-Scoop + Install-Git + Install-Python + Install-Node + Install-Utilities + Configure-Shell + + Print-Completion +} + +Main diff --git a/windows/setup-tmux.ps1 b/windows/setup-tmux.ps1 new file mode 100644 index 0000000..19cce4b --- /dev/null +++ b/windows/setup-tmux.ps1 @@ -0,0 +1,273 @@ +# ============================================ +# Terminal Multiplexer Setup (Windows) +# ============================================ +# Sets up terminal multiplexing on Windows: +# - Windows Terminal pane/tab configuration +# - Optional WSL2 + tmux installation +# - btop system monitor +# - Dev session launcher (via wt CLI) +# +# Usage: powershell -ExecutionPolicy Bypass -File setup-tmux.ps1 +# ============================================ + +$ErrorActionPreference = "Stop" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = Split-Path -Parent $ScriptDir + +function Print-Header { + Write-Host "" + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "| TERMINAL MULTIPLEXER SETUP (Windows) |" -ForegroundColor Magenta + Write-Host "+===========================================" -ForegroundColor Magenta + Write-Host "" +} + +function Print-Step { param([string]$Message) Write-Host "`n>> $Message" -ForegroundColor Cyan } +function Print-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } +function Print-Error { param([string]$Message) Write-Host "[X] $Message" -ForegroundColor Red } +function Print-Info { param([string]$Message) Write-Host "[i] $Message" -ForegroundColor Yellow } + +# Ensure Windows Terminal is installed +function Ensure-WindowsTerminal { + Print-Step "Checking Windows Terminal..." + + if (Get-Command wt -ErrorAction SilentlyContinue) { + Print-Success "Windows Terminal is available" + } else { + Print-Info "Installing Windows Terminal via winget..." + winget install --id Microsoft.WindowsTerminal --accept-source-agreements --accept-package-agreements + Print-Success "Windows Terminal installed" + } +} + +# Install btop +function Install-Btop { + Print-Step "Installing btop (system monitor)..." + + if (Get-Command btop -ErrorAction SilentlyContinue) { + Print-Success "btop already installed" + } else { + if (-not (Get-Command scoop -ErrorAction SilentlyContinue)) { + Print-Info "Installing Scoop first..." + Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression + } + Print-Info "Installing btop via scoop..." + scoop install btop + Print-Success "btop installed" + } +} + +# Offer WSL + tmux installation +function Install-WSL-Tmux { + Print-Step "WSL + tmux Setup (Optional)" + Write-Host "" + Write-Host " WSL (Windows Subsystem for Linux) lets you run Linux tools natively." -ForegroundColor Cyan + Write-Host " This includes tmux with the full Catppuccin Mocha theme from this project." -ForegroundColor Cyan + Write-Host "" + + $reply = Read-Host " Install WSL2 + tmux? (y/n)" + + if ($reply -notin @("y", "Y", "yes")) { + Print-Info "Skipping WSL setup" + return + } + + # Check if WSL is already installed + $wslInstalled = $false + try { + $wslOutput = wsl --status 2>&1 + if ($LASTEXITCODE -eq 0) { + $wslInstalled = $true + } + } catch {} + + if ($wslInstalled) { + Print-Success "WSL is already installed" + } else { + Print-Info "Installing WSL2 (requires admin privileges)..." + Print-Info "You may be prompted for administrator access." + + # Check if running as admin + $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + + if ($isAdmin) { + wsl --install --no-launch + Print-Success "WSL2 installed. A restart may be required." + } else { + Print-Info "Re-launching with admin privileges..." + Start-Process powershell -Verb RunAs -ArgumentList "-Command", "wsl --install --no-launch" + Print-Info "WSL2 installation started in admin window." + Print-Info "Restart your computer, then re-run this script to continue setup." + return + } + } + + # Check if Ubuntu is installed + $distros = wsl --list --quiet 2>$null + if ($distros -match "Ubuntu") { + Print-Success "Ubuntu is installed in WSL" + } else { + Print-Info "Installing Ubuntu in WSL..." + wsl --install -d Ubuntu --no-launch + Print-Success "Ubuntu installed. Run 'wsl' to complete initial setup." + Print-Info "After Ubuntu setup, re-run this script to install tmux inside WSL." + return + } + + # Install tmux inside WSL + Print-Info "Installing tmux inside WSL..." + wsl -d Ubuntu -- bash -c "sudo apt-get update && sudo apt-get install -y tmux" + Print-Success "tmux installed in WSL" + + # Deploy tmux config to WSL + $tmuxConfSrc = Join-Path $ProjectRoot "configs\tmux.conf" + if (Test-Path $tmuxConfSrc) { + $wslHome = wsl -d Ubuntu -- bash -c 'echo $HOME' 2>$null + $wslHome = $wslHome.Trim() + wsl -d Ubuntu -- bash -c "cp '$(wslpath -a $tmuxConfSrc)' '$wslHome/.tmux.conf'" 2>$null + + # Try direct file copy via \\wsl$ path + $wslPath = "\\wsl$\Ubuntu$wslHome\.tmux.conf" + try { + Copy-Item $tmuxConfSrc $wslPath -Force -ErrorAction Stop + Print-Success "tmux.conf deployed to WSL" + } catch { + # Fallback: use wsl command + $tmuxContent = Get-Content $tmuxConfSrc -Raw + $escapedContent = $tmuxContent -replace "'", "'\\''" + wsl -d Ubuntu -- bash -c "cat > ~/.tmux.conf << 'TMUXEOF' +$tmuxContent +TMUXEOF" + Print-Success "tmux.conf deployed to WSL (via pipe)" + } + } + + # Install TPM in WSL + Print-Info "Installing TPM (Tmux Plugin Manager) in WSL..." + wsl -d Ubuntu -- bash -c 'if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then git clone https://github.com/tmux-plugins/tpm "$HOME/.tmux/plugins/tpm"; fi' + Print-Success "TPM installed in WSL" + + # Install btop in WSL + wsl -d Ubuntu -- bash -c "sudo apt-get install -y btop 2>/dev/null || sudo snap install btop 2>/dev/null || true" + Print-Info "btop installation attempted in WSL" +} + +# Deploy dev-session script +function Deploy-DevSession { + Print-Step "Setting up dev session launcher..." + + $sessionSrc = Join-Path $ScriptDir "dev-session.ps1" + $binDir = Join-Path $env:USERPROFILE ".local\bin" + + if (-not (Test-Path $binDir)) { + New-Item -ItemType Directory -Path $binDir -Force | Out-Null + } + + if (Test-Path $sessionSrc) { + Copy-Item $sessionSrc (Join-Path $binDir "dev-session.ps1") -Force + Print-Success "dev-session.ps1 installed to $binDir" + } else { + Print-Info "dev-session.ps1 not found, skipping" + } + + # Add to PATH and create alias in profile + $profilePath = $PROFILE.CurrentUserAllHosts + $profileContent = "" + if (Test-Path $profilePath) { + $profileContent = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue + } + + if ($profileContent -notmatch "=== Multiplexer Configuration ===") { + $muxConfig = @' + +# === Multiplexer Configuration === +# Added by Windows multiplexer setup + +# Dev session launcher (creates multi-pane Windows Terminal layout) +$devSessionBin = "$env:USERPROFILE\.local\bin" +if (Test-Path $devSessionBin) { + $env:Path = "$devSessionBin;$env:Path" +} + +function dev-session { & "$env:USERPROFILE\.local\bin\dev-session.ps1" @args } +Set-Alias -Name dev -Value dev-session -Force +Set-Alias -Name sc -Value dev-session -Force + +# === End Multiplexer Configuration === +'@ + $profileDir = Split-Path -Parent $profilePath + if (-not (Test-Path $profileDir)) { + New-Item -ItemType Directory -Path $profileDir -Force | Out-Null + } + Add-Content -Path $profilePath -Value $muxConfig + Print-Success "Shell aliases added to PowerShell profile" + } else { + Print-Success "Multiplexer config already exists in profile" + } +} + +# Print completion +function Print-Completion { + Write-Host "" + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "| TERMINAL MULTIPLEXER SETUP COMPLETE! |" -ForegroundColor Green + Write-Host "+==========================================================" -ForegroundColor Green + Write-Host "" + + Write-Host "What's installed:" -ForegroundColor Cyan + Write-Host " - Windows Terminal - Modern terminal with built-in panes" + Write-Host " - btop - Beautiful system monitor" + Write-Host " - dev-session - Multi-pane layout launcher" + + $wslCheck = wsl --status 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Host " - WSL2 + tmux - Linux terminal multiplexer" + Write-Host " - TPM - Tmux Plugin Manager" + Write-Host " - Catppuccin - Beautiful Mocha color theme" + } + + Write-Host "" + Write-Host "Quick Start:" -ForegroundColor Yellow + Write-Host " Start a dev session: dev-session" + Write-Host " Start with project: dev-session C:\path\to\project" + Write-Host " System monitor: btop" + + if ($LASTEXITCODE -eq 0) { + Write-Host "" + Write-Host "WSL tmux:" -ForegroundColor Yellow + Write-Host " Start tmux in WSL: wsl -d Ubuntu -- tmux" + Write-Host " Prefix key: Ctrl+a" + Write-Host " Install plugins: Ctrl+a then I (capital I)" + } + + Write-Host "" + Write-Host "Windows Terminal Shortcuts:" -ForegroundColor Magenta + Write-Host " +----------------------------------------------------+" + Write-Host " | Alt+Shift+D Split pane (auto direction) |" + Write-Host " | Alt+Shift+- Split pane horizontally |" + Write-Host " | Alt+Shift++ Split pane vertically |" + Write-Host " | Alt+arrows Navigate between panes |" + Write-Host " | Ctrl+Shift+W Close pane |" + Write-Host " | Ctrl+Shift+T New tab |" + Write-Host " | Ctrl+Alt+arrows Resize pane |" + Write-Host " +----------------------------------------------------+" + + Write-Host "" + Write-Host "Restart your terminal or run: . `$PROFILE" -ForegroundColor Green + Write-Host "" +} + +# Main +function Main { + Print-Header + + Ensure-WindowsTerminal + Install-Btop + Install-WSL-Tmux + Deploy-DevSession + + Print-Completion +} + +Main diff --git a/windows/verify-setup.ps1 b/windows/verify-setup.ps1 new file mode 100644 index 0000000..38b5a81 --- /dev/null +++ b/windows/verify-setup.ps1 @@ -0,0 +1,268 @@ +# ============================================ +# Development Environment Verification (Windows) +# ============================================ +# Checks that all development tools are installed correctly +# Usage: powershell -ExecutionPolicy Bypass -File verify-setup.ps1 +# ============================================ + +Write-Host "Verifying Development Environment..." -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" + +$allOk = $true +$issues = @() + +function Check-Command { + param( + [string]$Command, + [string]$Name, + [string]$VersionFlag = "--version" + ) + + try { + $result = & $Command $VersionFlag 2>&1 | Select-Object -First 1 + Write-Host "[OK] ${Name}: $result" -ForegroundColor Green + return $true + } catch { + Write-Host "[X] ${Name}: Not found" -ForegroundColor Red + $script:issues += "$Name is not installed" + $script:allOk = $false + return $false + } +} + +function Check-CommandExists { + param( + [string]$Command, + [string]$Name + ) + + if (Get-Command $Command -ErrorAction SilentlyContinue) { + $version = & $Command --version 2>&1 | Select-Object -First 1 + Write-Host "[OK] ${Name}: $version" -ForegroundColor Green + return $true + } else { + Write-Host "[X] ${Name}: Not found" -ForegroundColor Red + $script:issues += "$Name is not installed" + $script:allOk = $false + return $false + } +} + +# === Package Managers === +Write-Host "Package Managers:" -ForegroundColor Blue +Write-Host "-----------------" + +if (Get-Command winget -ErrorAction SilentlyContinue) { + Write-Host "[OK] winget: Available" -ForegroundColor Green +} else { + Write-Host "[X] winget: Not found" -ForegroundColor Red + $issues += "winget is not available - Install 'App Installer' from Microsoft Store" + $allOk = $false +} + +if (Get-Command scoop -ErrorAction SilentlyContinue) { + Write-Host "[OK] Scoop: Available" -ForegroundColor Green +} else { + Write-Host "[X] Scoop: Not found" -ForegroundColor Red + $issues += "Scoop is not installed" + $allOk = $false +} + +# === Core Development Tools === +Write-Host "" +Write-Host "Core Development Tools:" -ForegroundColor Blue +Write-Host "-----------------------" + +Check-CommandExists "git" "Git" | Out-Null +Check-CommandExists "python" "Python" | Out-Null +Check-CommandExists "pip" "pip" | Out-Null + +if (Get-Command pyenv -ErrorAction SilentlyContinue) { + Write-Host "[OK] pyenv-win: Available" -ForegroundColor Green +} else { + Write-Host "[!] pyenv-win: Not installed (run setup-dev-env.ps1)" -ForegroundColor Yellow +} + +Check-CommandExists "node" "Node.js" | Out-Null +Check-CommandExists "npm" "npm" | Out-Null + +# === Utilities === +Write-Host "" +Write-Host "Utilities:" -ForegroundColor Blue +Write-Host "----------" + +$utils = @("tree", "jq", "wget", "curl") +foreach ($util in $utils) { + if (Get-Command $util -ErrorAction SilentlyContinue) { + Write-Host "[OK] ${util}: Available" -ForegroundColor Green + } else { + Write-Host "[!] ${util}: Not installed (optional)" -ForegroundColor Yellow + } +} + +# === Terminal Customization === +Write-Host "" +Write-Host "Terminal Customization:" -ForegroundColor Blue +Write-Host "------------------------" + +if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) { + $ompVersion = oh-my-posh --version 2>&1 + Write-Host "[OK] Oh My Posh: $ompVersion" -ForegroundColor Green +} else { + Write-Host "[!] Oh My Posh: Not installed (run pimp-my-terminal.ps1)" -ForegroundColor Yellow +} + +# Check Oh My Posh theme +$ompTheme = Join-Path $env:USERPROFILE ".config\oh-my-posh\catppuccin-mocha.omp.json" +if (Test-Path $ompTheme) { + Write-Host "[OK] Catppuccin Mocha theme: Found" -ForegroundColor Green +} else { + Write-Host "[!] Catppuccin Mocha theme: Not deployed (run pimp-my-terminal.ps1)" -ForegroundColor Yellow +} + +if (Get-Module -ListAvailable -Name PSReadLine) { + $prlVersion = (Get-Module -ListAvailable -Name PSReadLine | Select-Object -First 1).Version + Write-Host "[OK] PSReadLine: $prlVersion" -ForegroundColor Green +} else { + Write-Host "[!] PSReadLine: Not found" -ForegroundColor Yellow +} + +if (Get-Module -ListAvailable -Name Terminal-Icons) { + Write-Host "[OK] Terminal-Icons: Installed" -ForegroundColor Green +} else { + Write-Host "[!] Terminal-Icons: Not installed (run pimp-my-terminal.ps1)" -ForegroundColor Yellow +} + +# Modern CLI tools +Write-Host "" +Write-Host "Modern CLI Tools (Optional):" -ForegroundColor Blue +Write-Host "-----------------------------" + +$cliTools = @( + @{ Name = "eza"; Desc = "modern ls" }, + @{ Name = "bat"; Desc = "better cat" }, + @{ Name = "fzf"; Desc = "fuzzy finder" }, + @{ Name = "fd"; Desc = "faster find" } +) + +foreach ($tool in $cliTools) { + if (Get-Command $tool.Name -ErrorAction SilentlyContinue) { + Write-Host "[OK] $($tool.Name) ($($tool.Desc)): Available" -ForegroundColor Green + } else { + Write-Host "[!] $($tool.Name) ($($tool.Desc)): Not installed (optional)" -ForegroundColor Yellow + } +} + +# === Multiplexer === +Write-Host "" +Write-Host "Terminal Multiplexer:" -ForegroundColor Blue +Write-Host "---------------------" + +if (Get-Command wt -ErrorAction SilentlyContinue) { + Write-Host "[OK] Windows Terminal: Available" -ForegroundColor Green +} else { + Write-Host "[!] Windows Terminal: Not installed (run setup-tmux.ps1)" -ForegroundColor Yellow +} + +if (Get-Command btop -ErrorAction SilentlyContinue) { + Write-Host "[OK] btop: Available" -ForegroundColor Green +} else { + Write-Host "[!] btop: Not installed (run setup-tmux.ps1)" -ForegroundColor Yellow +} + +# Check dev-session +$devSessionPath = Join-Path $env:USERPROFILE ".local\bin\dev-session.ps1" +if (Test-Path $devSessionPath) { + Write-Host "[OK] dev-session: Available" -ForegroundColor Green +} else { + Write-Host "[!] dev-session: Not installed (run setup-tmux.ps1)" -ForegroundColor Yellow +} + +# Check WSL +try { + $wslCheck = wsl --status 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Host "[OK] WSL: Installed" -ForegroundColor Green + + # Check tmux in WSL + $tmuxCheck = wsl -d Ubuntu -- which tmux 2>$null + if ($tmuxCheck) { + Write-Host "[OK] tmux (WSL): Available" -ForegroundColor Green + } else { + Write-Host "[!] tmux (WSL): Not installed (run setup-tmux.ps1)" -ForegroundColor Yellow + } + } else { + Write-Host "[!] WSL: Not installed (optional)" -ForegroundColor Yellow + } +} catch { + Write-Host "[!] WSL: Not installed (optional)" -ForegroundColor Yellow +} + +# === Claude Monitor === +Write-Host "" +Write-Host "Claude Code Monitor:" -ForegroundColor Blue +Write-Host "---------------------" + +if (Get-Command uv -ErrorAction SilentlyContinue) { + $uvVersion = uv --version 2>&1 + Write-Host "[OK] uv: $uvVersion" -ForegroundColor Green +} else { + Write-Host "[!] uv: Not installed (run setup-claude-monitor.ps1)" -ForegroundColor Yellow +} + +$monitorPath = Join-Path $env:USERPROFILE ".local\bin\claude-monitor.cmd" +if (Test-Path $monitorPath) { + Write-Host "[OK] claude-monitor: Available" -ForegroundColor Green +} else { + Write-Host "[!] claude-monitor: Not installed (run setup-claude-monitor.ps1)" -ForegroundColor Yellow +} + +# === Shell Configuration === +Write-Host "" +Write-Host "Shell Configuration:" -ForegroundColor Blue +Write-Host "---------------------" + +$profilePath = $PROFILE.CurrentUserAllHosts +if (Test-Path $profilePath) { + Write-Host "[OK] PowerShell profile: Found" -ForegroundColor Green + + $content = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue + if ($content -match "Development Environment Setup") { + Write-Host "[OK] Dev environment: Configured in profile" -ForegroundColor Green + } else { + Write-Host "[!] Dev environment: Not configured (run setup-dev-env.ps1)" -ForegroundColor Yellow + } + + if ($content -match "Terminal Customization") { + Write-Host "[OK] Terminal customization: Configured in profile" -ForegroundColor Green + } else { + Write-Host "[!] Terminal customization: Not configured (run pimp-my-terminal.ps1)" -ForegroundColor Yellow + } +} else { + Write-Host "[!] PowerShell profile: Not found" -ForegroundColor Yellow + $issues += "PowerShell profile not found" +} + +# === Summary === +Write-Host "" +Write-Host "========================================" -ForegroundColor Cyan + +if ($allOk) { + Write-Host "[OK] All core tools are installed correctly!" -ForegroundColor Green + Write-Host "" + Write-Host "Your development environment is ready!" -ForegroundColor Green +} else { + Write-Host "[X] Some tools are missing or not configured properly." -ForegroundColor Red + Write-Host "" + Write-Host "Issues found:" -ForegroundColor Yellow + foreach ($issue in $issues) { + Write-Host " - $issue" + } + Write-Host "" + Write-Host "Recommended actions:" -ForegroundColor Yellow + Write-Host " 1. Run: .\setup-windows.ps1" + Write-Host " 2. Or install missing tools individually" +} + +Write-Host ""