mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
* Add Linux implementation of VibeTunnel This commit introduces a complete Linux port of VibeTunnel, providing feature parity with the macOS version. The implementation includes: - Full Go-based server with identical REST API and WebSocket endpoints - Terminal session management using PTY (pseudo-terminal) handling - Asciinema recording format for session playback - Compatible CLI interface matching the macOS `vt` command - Support for all VibeTunnel features: password protection, network modes, ngrok integration - Comprehensive build system with Makefile supporting various installation methods - Systemd service integration for running as a system daemon The Linux version maintains 100% compatibility with the existing web UI and can be used as a drop-in replacement for the macOS app on Linux systems. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Add comprehensive ngrok integration to Linux VibeTunnel Implements full ngrok tunnel support for the Go/Linux version to match the macOS Swift implementation, enabling secure public access to local VibeTunnel instances. - **ngrok Service**: Complete lifecycle management with status tracking - **HTTP API**: RESTful endpoints matching macOS version - **CLI Support**: Command-line ngrok flags and integration - **Auto-forwarding**: Built-in HTTP request forwarding to local server - `POST /api/ngrok/start` - Start tunnel with auth token - `POST /api/ngrok/stop` - Stop active tunnel - `GET /api/ngrok/status` - Get current tunnel status - Uses `golang.ngrok.com/ngrok` SDK for native Go integration - Thread-safe service with mutex protection - Comprehensive error handling and logging - Real-time status updates (disconnected/connecting/connected/error) - Proper context cancellation for graceful shutdown ```bash vibetunnel --serve --ngrok --ngrok-token "your_token" vibetunnel --serve --port 4030 --ngrok --ngrok-token "your_token" ``` - Added golang.ngrok.com/ngrok v1.13.0 - Updated web packages (security fixes for puppeteer) Maintains full API compatibility with macOS VibeTunnel for seamless cross-platform operation and consistent web frontend integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * up * Fix SSE streaming performance with byte-based approach Addresses @badlogic's review feedback to prevent performance issues with line-based file reading in processNewContent(). ## Changes Made ### Performance Fix - **Byte-based seeking**: Replace line counting with file position tracking - **Efficient reads**: Only read new content since last position using file.Seek() - **Memory optimization**: Avoid reading entire file on each update - **Incomplete line handling**: Properly handle partial lines at file end ### Technical Details - Changed lastLineCount *int → seenBytes *int64 - Use file.Seek(seenBytes, 0) to jump to last read position - Read only new content with currentSize - seenBytes - Handle incomplete lines by adjusting seek position - Maintains same functionality with better performance ### Benefits - **Scalability**: No longer reads entire file for each update - **Performance**: O(new_content) instead of O(total_content) - **Memory**: Constant memory usage regardless of file size - **Reliability**: Handles concurrent writes and partial lines correctly This prevents the SSE streaming from exploding in our faces as @badlogic warned, especially for long-running sessions with large output files. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Optimize streaming performance to reduce 1+ second delays Implements multiple optimizations to address user-reported 1+ second delay between typing and stream rendering: ## PTY Reading Optimizations - **Reduced sleep times**: 100ms → 1ms for EOF checks - **Faster polling**: 10ms → 1ms for zero-byte reads - **FIFO optimization**: 1s → 100ms for stdin EOF polling ## UTF-8 Buffering Improvements - **Timeout-based flushing**: 5ms timer for incomplete UTF-8 sequences - **Real-time streaming**: Don't wait for complete sequences in interactive mode - **Smart buffering**: Balance correctness with responsiveness ## File I/O Optimizations - **Immediate sync**: Call file.Sync() after each write for instant fsnotify - **Reduced SSE timeout**: 1s → 100ms for session alive checks - **Better responsiveness**: Ensure file changes trigger immediately ## Technical Changes - Added StreamWriter.scheduleFlush() with 5ms timeout - Enhanced writeEvent() with conditional file syncing - Optimized PTY read/write loop timing - Improved SSE streaming frequency These changes target the main bottlenecks identified in the PTY → file → fsnotify → SSE → browser pipeline. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix critical stdin polling delay causing 1+ second input lag - Reduced FIFO EOF polling from 100ms to 1ms - Reduced EAGAIN polling from 1ms to 100µs - Added immediate continue after successful writes - This eliminates the major input delay bottleneck 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix critical performance issues causing resource leaks and CPU burns Performance optimizations based on code review feedback: 1. **Fix SSE goroutine leaks**: - Added client disconnect detection to SSE streams - Propagate write errors to detect when clients close connections - Prevents memory leaks from abandoned streaming goroutines 2. **Fix PTY busy-loop CPU burn**: - Increased sleep from 1ms to 10ms in idle scenarios - Reduces CPU wake-ups from 1000/s to 100/s (10x improvement) - Significantly reduces CPU usage when PTY is idle 3. **Multi-stream disconnect detection**: - Added error checking to multi-stream write operations - Prevents goroutine leaks in multi-session streaming These fixes address the "thing of the things" - performance\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Standardize session creation API response format to match Rust server Changes: - Updated Go server session creation response to include success/message/error fields - Now returns: {"success": true, "message": "Session created successfully", "error": null, "sessionId": "..."} - Maintains backward compatibility with existing sessionId field - Go server already supported both input formats (cmdline/command, cwd/workingDir) This achieves protocol compatibility between Go and Rust implementations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix delete endpoint to return 200 OK with JSON response - Changed handleKillSession to return 200 OK instead of 204 No Content - Added JSON response with success/message fields for consistency - Fixes benchmark tool compatibility expecting 200 response 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Update Go server API to match Rust format exactly - Use 'command' array instead of 'cmdline' - Use 'workingDir' instead of 'cwd' - Remove compatibility shims for cleaner API - Better error messages matching Rust server 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Major performance optimizations for Go server - Remove 100ms artificial delay in session creation (-100ms per session) - Optimize PTY I/O handling with reduced polling intervals - Implement persistent stdin pipes to avoid repeated open/close - Batch file sync operations to reduce I/O overhead (5ms batching) - Remove blocking status updates from API handlers - Increase SSE session check interval from 100ms to 1s Target: Match Rust performance (60ms avg latency, 16+ ops/sec) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix O_NONBLOCK compilation issue * Add comprehensive TLS/HTTPS support with Caddy integration Features: - Optional TLS support via CLI flags (defaults to HTTP like Rust) - Self-signed certificate generation for localhost development - Let's Encrypt automatic certificate management for domains - Custom certificate support for production environments - HTTP to HTTPS redirect capability - Maintains 100% backward compatibility with Rust version Usage examples: - Default HTTP: ./vibetunnel --serve (same as Rust) - HTTPS with self-signed: ./vibetunnel --serve --tls - HTTPS with domain: ./vibetunnel --serve --tls --tls-domain example.com - HTTPS with custom certs: ./vibetunnel --serve --tls --tls-cert cert.pem --tls-key key.pem 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix terminal sizing issues and implement dynamic resize support Backend changes: - Add handleResizeSession API endpoint for dynamic terminal resizing - Implement Session.Resize() and PTY.Resize() methods with proper validation - Add session registry in Manager to track running sessions with PTY access - Fix stdin error handling to prevent session crashes on EAGAIN errors - Write resize events to asciinema stream for frontend synchronization - Update default terminal dimensions from 80x24 to 120x30 Frontend changes: - Add width/height parameters to SessionCreateData interface - Calculate appropriate terminal dimensions when creating sessions - Implement automatic resize API calls when terminal dimensions change - Add terminal-resize event dispatch for backend synchronization - Ensure resize events bubble properly for session management Fixes nvim being stuck at 80x24 by implementing proper terminal dimension management and dynamic resizing capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Add client-side resize caching and Hack Nerd Font support - Implement resize request caching to prevent redundant API calls - Add debouncing to terminal resize events (250ms delay) - Replace ResizeObserver with window.resize events only to eliminate pixel-level jitter - Add Hack Nerd Font Mono as primary terminal font with Fira Code fallback - Update session creation to use conservative 120x30 defaults - Fix terminal dimension calculation in normal mode 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Add comprehensive XTerm color and rendering enhancements - Complete 256-color palette support with CSS variables (0-255) - Enhanced XTerm configuration with proper terminal options - True xterm-compatible 16-color theme - Text attribute support: bold, italic, underline, dim, strikethrough, inverse, invisible - Cursor blinking with CSS animation - Font rendering optimizations (disabled ligatures, antialiasing) - Terminal-specific CSS styling for better rendering - Mac option key as meta, alt-click cursor movement - Selection colors and inactive selection support 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
134 lines
No EOL
4.5 KiB
Makefile
134 lines
No EOL
4.5 KiB
Makefile
# VibeTunnel Linux Makefile
|
|
# Compatible with VibeTunnel macOS app
|
|
|
|
.PHONY: build clean test install dev deps web help
|
|
|
|
# Variables
|
|
APP_NAME := vibetunnel
|
|
VERSION := 1.0.0
|
|
BUILD_DIR := build
|
|
WEB_DIR := ../web
|
|
DIST_DIR := $(WEB_DIR)/dist
|
|
|
|
# Go build flags
|
|
GO_FLAGS := -ldflags "-X main.version=$(VERSION)"
|
|
GO_BUILD := go build $(GO_FLAGS)
|
|
|
|
# Default target
|
|
all: build
|
|
|
|
help: ## Show this help message
|
|
@echo "VibeTunnel Linux Build System"
|
|
@echo "Available targets:"
|
|
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-12s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
|
|
|
deps: ## Install dependencies
|
|
go mod download
|
|
go mod tidy
|
|
|
|
web: ## Build web assets (requires npm in ../web)
|
|
@echo "Building web assets..."
|
|
@if [ -d "$(WEB_DIR)" ]; then \
|
|
cd $(WEB_DIR) && npm install && npm run build; \
|
|
else \
|
|
echo "Warning: Web directory not found at $(WEB_DIR)"; \
|
|
echo "Make sure you're running from the linux/ subdirectory"; \
|
|
fi
|
|
|
|
build: deps ## Build the binary
|
|
@echo "Building $(APP_NAME)..."
|
|
@mkdir -p $(BUILD_DIR)
|
|
$(GO_BUILD) -o $(BUILD_DIR)/$(APP_NAME) ./cmd/vibetunnel
|
|
|
|
build-static: deps ## Build static binary
|
|
@echo "Building static $(APP_NAME)..."
|
|
@mkdir -p $(BUILD_DIR)
|
|
CGO_ENABLED=0 GOOS=linux $(GO_BUILD) -a -installsuffix cgo -o $(BUILD_DIR)/$(APP_NAME)-static ./cmd/vibetunnel
|
|
|
|
dev: build ## Build and run in development mode
|
|
@echo "Starting VibeTunnel in development mode..."
|
|
@if [ ! -d "$(DIST_DIR)" ]; then \
|
|
echo "Web assets not found. Building..."; \
|
|
$(MAKE) web; \
|
|
fi
|
|
$(BUILD_DIR)/$(APP_NAME) --serve --debug --localhost --static-path=$(DIST_DIR)
|
|
|
|
install: build ## Install to /usr/local/bin
|
|
@echo "Installing $(APP_NAME) to /usr/local/bin..."
|
|
sudo cp $(BUILD_DIR)/$(APP_NAME) /usr/local/bin/
|
|
@echo "Installation complete. Run 'vibetunnel --help' to get started."
|
|
|
|
install-user: build ## Install to ~/bin
|
|
@echo "Installing $(APP_NAME) to ~/bin..."
|
|
@mkdir -p ~/bin
|
|
cp $(BUILD_DIR)/$(APP_NAME) ~/bin/
|
|
@echo "Installation complete. Make sure ~/bin is in your PATH."
|
|
@echo "Run 'vibetunnel --help' to get started."
|
|
|
|
test: ## Run tests
|
|
go test -v ./...
|
|
|
|
test-coverage: ## Run tests with coverage
|
|
go test -v -coverprofile=coverage.out ./...
|
|
go tool cover -html=coverage.out -o coverage.html
|
|
|
|
clean: ## Clean build artifacts
|
|
rm -rf $(BUILD_DIR)
|
|
rm -f coverage.out coverage.html
|
|
|
|
release: web build-static ## Build release package
|
|
@echo "Creating release package..."
|
|
@mkdir -p $(BUILD_DIR)/release
|
|
@cp $(BUILD_DIR)/$(APP_NAME)-static $(BUILD_DIR)/release/$(APP_NAME)
|
|
@cp README.md $(BUILD_DIR)/release/ 2>/dev/null || echo "README.md not found"
|
|
@echo "Release package created in $(BUILD_DIR)/release/"
|
|
|
|
docker: ## Build Docker image
|
|
docker build -t vibetunnel-linux .
|
|
|
|
# Package targets for different distributions
|
|
.PHONY: deb rpm appimage
|
|
|
|
deb: build-static ## Create Debian package
|
|
@echo "Creating Debian package..."
|
|
@mkdir -p $(BUILD_DIR)/deb/usr/local/bin
|
|
@mkdir -p $(BUILD_DIR)/deb/DEBIAN
|
|
@cp $(BUILD_DIR)/$(APP_NAME)-static $(BUILD_DIR)/deb/usr/local/bin/$(APP_NAME)
|
|
@echo "Package: vibetunnel\nVersion: $(VERSION)\nArchitecture: amd64\nMaintainer: VibeTunnel\nDescription: Remote terminal access for Linux\n Provides remote terminal access via web browser, compatible with VibeTunnel macOS app." > $(BUILD_DIR)/deb/DEBIAN/control
|
|
@dpkg-deb --build $(BUILD_DIR)/deb $(BUILD_DIR)/$(APP_NAME)_$(VERSION)_amd64.deb
|
|
@echo "Debian package created: $(BUILD_DIR)/$(APP_NAME)_$(VERSION)_amd64.deb"
|
|
|
|
# Development helpers
|
|
.PHONY: fmt lint vet
|
|
|
|
fmt: ## Format Go code
|
|
go fmt ./...
|
|
|
|
lint: ## Lint Go code (requires golangci-lint)
|
|
golangci-lint run
|
|
|
|
vet: ## Vet Go code
|
|
go vet ./...
|
|
|
|
check: fmt vet lint test ## Run all checks
|
|
|
|
# Service management (systemd)
|
|
.PHONY: service-install service-enable service-start service-stop service-status
|
|
|
|
service-install: install ## Install systemd service
|
|
@echo "Installing systemd service..."
|
|
@echo "[Unit]\nDescription=VibeTunnel Linux\nAfter=network.target\n\n[Service]\nType=simple\nUser=$(USER)\nExecStart=/usr/local/bin/vibetunnel --serve\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target" | sudo tee /etc/systemd/system/vibetunnel.service
|
|
sudo systemctl daemon-reload
|
|
@echo "Service installed. Use 'make service-enable' to enable auto-start."
|
|
|
|
service-enable: ## Enable systemd service
|
|
sudo systemctl enable vibetunnel
|
|
|
|
service-start: ## Start systemd service
|
|
sudo systemctl start vibetunnel
|
|
|
|
service-stop: ## Stop systemd service
|
|
sudo systemctl stop vibetunnel
|
|
|
|
service-status: ## Show systemd service status
|
|
systemctl status vibetunnel
|