Headless terminal (ht) emulator.
ht-go
is a performant headless terminal that provides programmatic access to terminal sessions via JSON commands over STDIN/STDOUT and WebSocket APIs.
- Full VT100/ANSI Terminal Emulation - Complete terminal compatibility
- Real-time WebSocket Streaming - Live terminal output via WebSocket
- JSON Command Interface - Programmatic control via JSON over STDIN/STDOUT
- Session Management - Create, manage, and monitor multiple terminal sessions
- TUI testing Framework - Go Testing Framework (TUITest) for Terminal UIs
- Asciicast Support - Asciinema (v2) session record & playback
┌─────────────────────────────────────────────────────────────┐
│ ht-go Architecture │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Fiber │ │ WebSocket │ │ Session Manager │ │
│ │ HTTP Server │ │ Server │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ PTY │ │ Terminal │ │ Event Broadcaster │ │
│ │ Manager │ │ Emulator │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Memory Pools│ │ Worker Pool │ │ urfave/cli + zerolog │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Go 1.25.1+ (required for optimal performance)
# Clone the repository
git clone https://github.com/instagrim-dev/htgo.git
cd htgo
# Install dependencies
make deps
# Build with optimizations
make build
# Or install globally
make install
# Interactive mode with WebSocket server
./build/ht --http-addr=127.0.0.1:8080 --command=bash
# Headless mode via STDIN/STDOUT
./build/ht --no-http --command=bash
# Send input to terminal
echo '{"type":"input","data":{"payload":"ls -la\n"}}' | ./build/ht --no-http --command=bash
# Send key combinations
echo '{"type":"send_keys","data":{"keys":["ctrl+c"]}}' | ./build/ht --no-http --command=bash
# Resize terminal
echo '{"type":"resize","data":{"cols":120,"rows":40}}' | ./build/ht --no-http --command=bash
# Take snapshot
echo '{"type":"snapshot"}' | ./build/ht --no-http --command=bash
// Connect to WebSocket endpoint
const ws = new WebSocket('ws://localhost:8080/ws/events?sub=output,snapshot');
// Send commands
ws.send(JSON.stringify({
type: "input",
data: {payload: "htop\n"}
}));
// Receive real-time terminal events
ws.onmessage = (event) => {
const terminalEvent = JSON.parse(event.data);
console.log('Terminal event:', terminalEvent);
};
Command | Description | Example |
---|---|---|
input |
Send raw input to terminal | {"type":"input","data":{"payload":"ls\n"}} |
send_keys |
Send key combinations | {"type":"send_keys","data":{"keys":["ctrl+c","enter"]}} |
resize |
Resize terminal dimensions | {"type":"resize","data":{"cols":80,"rows":24}} |
snapshot |
Capture current terminal state | {"type":"snapshot"} |
status |
Get session status | {"type":"status"} |
close |
Close terminal session | {"type":"close"} |
Event | Description | Data Fields |
---|---|---|
output |
Terminal output data | seq (string) |
input |
Input echo | payload (string) |
resize |
Terminal resized | cols , rows (int) |
snapshot |
Terminal state | text , cursor , cols , rows |
status |
Session status change | status , pid |
error |
Error occurred | message , code |
GET /api/v1/health
- Server health checkGET /api/v1/metrics
- Performance metricsPOST /api/v1/sessions
- Create new sessionGET /api/v1/sessions/:id
- Get session infoDELETE /api/v1/sessions/:id
- Delete sessionPOST /api/v1/sessions/:id/input
- Send input to sessionPOST /api/v1/sessions/:id/resize
- Resize session terminalGET /api/v1/sessions/:id/snapshot
- Get session snapshot
GET /ws/events
- Real-time terminal eventsGET /ws/alis
- asciinema live streaming protocol
We use a comprehensive Makefile with mold linker integration for optimal build performance:
# Development commands
make build # Development build with mold linker
make build-release # Optimized production build (-w -s)
make build-debug # Debug build with race detection
# Testing
make test # Run all tests with coverage
make test-race # Race condition detection
make test-integration # Integration tests
make bench # Performance benchmarks
# Quality assurance
make fmt # Format code
make vet # Static analysis
make lint # Comprehensive linting
make check # All quality checks
make security-scan # Security vulnerability scan
# Development workflow
make dev # Build and run development server
make ci # Full CI pipeline locally
make clean # Clean build artifacts
# CPU profiling
make profile-cpu
# Memory profiling
make profile-mem
# Load testing
make load-test
# Benchmark comparison
make bench-compare
# Build container
make docker-build
# Run in container
make docker-run
# Multi-architecture builds supported
docker buildx build --platform linux/amd64,linux/arm64 .
# Run all tests
make test
# Race detection
make test-race
# Integration tests only
make test-integration
# Generate coverage report
make test-coverage
# Memory stability test
go test -timeout=2h -memprofile=mem.prof ./...
export HT_HTTP_ADDR="0.0.0.0:8080"
export HT_LOG_LEVEL="info"
export HT_ENABLE_METRICS="true"
export HT_MAX_SESSIONS="100"
export HT_SESSION_TIMEOUT="3600s"
# config.yaml
server:
host: "0.0.0.0"
port: 8080
read_timeout: "30s"
write_timeout: "30s"
websocket:
enable: true
max_connections: 1000
ping_interval: "30s"
terminal:
default_cols: 80
default_rows: 24
max_history: 1000
logging:
level: "info"
format: "json"