Go Services

🦫 Go Services Architecture

SkySpy's high-performance terminal radar interface, built with love in Go

SkySpy includes a lightning-fast Go-based CLI application (skyspy-go) that delivers a rich terminal-based radar experience for real-time aircraft tracking. This document covers the architecture, configuration, and operation of the Go components.


🎯 Overview

The SkySpy Go CLI is a feature-rich terminal application built using the Bubble Tea framework. It connects to the Django backend via Socket.IO to receive real-time aircraft data and presents it in an interactive radar display with VU meters, spectrum visualization, and customizable themes.

πŸ“˜

Built with Bubble Tea

The CLI leverages Charm's excellent Bubble Tea framework for a delightful terminal UI experience with smooth animations and responsive controls.


πŸ–₯️ Platform Support

PlatformArchitectureStatus
Linuxamd64 / arm64βœ… Supported
macOSamd64 / arm64βœ… Supported
Windowsamd64 / arm64βœ… Supported

✨ Key Features

πŸ“‘ Real-time Radar Display

Interactive ASCII radar scope with sweep animation and range rings

πŸ›« Aircraft Trail Tracking

Historical position trails for each aircraft with configurable history

🚨 Alert Engine

Configurable rules for emergency squawks, military aircraft, geofence monitoring

πŸ”Š Audio Alerts

Sound notifications for new aircraft, emergencies, and military contacts

πŸ—ΊοΈ Geographic Overlays

Support for GeoJSON, Shapefiles, and KML/KMZ formats

🎨 Multiple Themes

10 built-in color schemes from Classic Green to Cyberpunk

πŸ“€ Data Export

CSV, JSON, and HTML screenshot exports

πŸ” OIDC Authentication

Browser-based SSO login flow with token refresh


πŸ—οΈ Architecture Diagram

graph TB
    subgraph CLI["πŸ–₯️ SkySpy Go CLI (Terminal)"]
        subgraph Display["Display Layer"]
            RS[πŸ“‘ Radar Scope]
            SA[πŸ“Š Spectrum Analyzer]
            VU[🎚️ VU Meters]
        end

        subgraph Processing["Processing Layer"]
            AE[🚨 Alert Engine]
            GF[πŸ—ΊοΈ Geofence Manager]
            TT[✈️ Trail Tracker]
        end

        subgraph Support["Support Layer"]
            OM[πŸ“‚ Overlay Manager]
            TS[🎨 Theme System]
            EX[πŸ“€ Export Module]
        end

        subgraph Network["Network Layer"]
            SIO[πŸ”Œ Socket.IO Client]
        end
    end

    subgraph Backend["☁️ Django Backend"]
        AC["/aircraft namespace"]
        AR["/acars namespace"]
    end

    RS --> SIO
    SA --> SIO
    VU --> SIO
    AE --> SIO
    GF --> SIO
    TT --> SIO
    SIO --> AC
    SIO --> AR

    style CLI fill:#1a1a2e,stroke:#16213e,color:#fff
    style Backend fill:#0f3460,stroke:#16213e,color:#fff

πŸ“ Package Structure

skyspy-go/
β”‚
β”œβ”€β”€ πŸ“‚ cmd/skyspy/              # Main application entry point
β”‚   β”œβ”€β”€ πŸš€ main.go              # CLI setup and root command
β”‚   β”œβ”€β”€ πŸ” auth.go              # Authentication commands (login/logout/status)
β”‚   β”œβ”€β”€ πŸ“» radio.go             # Basic radio command
β”‚   β”œβ”€β”€ πŸ“» radio_pro.go         # Advanced radio features
β”‚   └── βš™οΈ configure.go         # Configuration wizard
β”‚
β”œβ”€β”€ πŸ“‚ internal/                # Private packages
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ app/                 # Bubble Tea application model
β”‚   β”‚   β”œβ”€β”€ app.go              # Main application state and logic
β”‚   β”‚   β”œβ”€β”€ view.go             # UI rendering
β”‚   β”‚   β”œβ”€β”€ alerts.go           # Alert state management
β”‚   β”‚   └── alert_rules_view.go
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ alerts/              # Alert system
β”‚   β”‚   β”œβ”€β”€ engine.go           # Alert processing engine
β”‚   β”‚   β”œβ”€β”€ rules.go            # Rule definitions and matching
β”‚   β”‚   └── geofence.go         # Geographic boundary monitoring
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ auth/                # Authentication
β”‚   β”‚   β”œβ”€β”€ auth.go             # Auth manager (OIDC/API key)
β”‚   β”‚   β”œβ”€β”€ browser.go          # Browser launcher for OIDC
β”‚   β”‚   β”œβ”€β”€ callback.go         # OAuth callback server
β”‚   β”‚   β”œβ”€β”€ config.go           # Auth configuration fetching
β”‚   β”‚   └── tokens.go           # Token storage and refresh
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ audio/               # Audio alerts
β”‚   β”‚   β”œβ”€β”€ alerts.go           # Alert player
β”‚   β”‚   └── sounds.go           # WAV generation
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ config/              # Configuration management
β”‚   β”‚   └── config.go           # Settings load/save
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ export/              # Data export
β”‚   β”‚   β”œβ”€β”€ csv.go              # CSV export
β”‚   β”‚   β”œβ”€β”€ json.go             # JSON export
β”‚   β”‚   └── screenshot.go       # HTML screenshot
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ geo/                 # Geographic utilities
β”‚   β”‚   β”œβ”€β”€ overlay.go          # GeoJSON/overlay rendering
β”‚   β”‚   β”œβ”€β”€ shapefile.go        # Shapefile parsing
β”‚   β”‚   └── kml.go              # KML/KMZ parsing
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ radar/               # Radar display
β”‚   β”‚   └── scope.go            # Radar scope rendering
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ search/              # Search and filtering
β”‚   β”‚   └── filter.go           # Query parser and filter
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ spectrum/            # Signal visualization
β”‚   β”‚   └── analyzer.go         # RSSI spectrum analysis
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ theme/               # Color themes
β”‚   β”‚   └── theme.go            # Theme definitions
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ trails/              # Aircraft trails
β”‚   β”‚   └── tracker.go          # Position history tracking
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ ui/                  # UI components
β”‚   β”‚   β”œβ”€β”€ vumeter.go          # VU meter rendering
β”‚   β”‚   └── spectrum.go         # Spectrum display
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ ws/                  # Socket.IO client
β”‚   β”‚   └── client.go           # Connection and message handling
β”‚   β”‚
β”‚   └── πŸ“‚ testutil/            # Test utilities
β”‚
β”œβ”€β”€ πŸ“„ Makefile                 # Build automation
β”œβ”€β”€ πŸ“„ .golangci.yml            # Linter configuration
└── πŸ“‚ .github/workflows/       # CI/CD pipelines

πŸ”§ Core Components

1. πŸ”Œ Socket.IO Client (internal/ws)

The Socket.IO client maintains persistent connections to the Django backend for real-time data streaming.

ℹ️

Message Types

The client handles snapshot, update, new, and remove events for both aircraft and ACARS data streams.

// Message types from the server
const (
    AircraftSnapshot MessageType = "aircraft:snapshot"
    AircraftUpdate   MessageType = "aircraft:update"
    AircraftNew      MessageType = "aircraft:new"
    AircraftRemove   MessageType = "aircraft:remove"
    ACARSMessage     MessageType = "acars:message"
    ACARSSnapshot    MessageType = "acars:snapshot"
)

Connection Configuration:

// Creating a Socket.IO client with authentication
client := ws.NewClientWithAuth(
    host,           // Server hostname
    port,           // Server port
    reconnectDelay, // Seconds between reconnection attempts
    authProvider,   // Function returning auth token
)

// Start the connection (non-blocking)
client.Start()

// Receive aircraft messages
for msg := range client.AircraftMessages() {
    // Process aircraft data
}

Authentication Support:

The client supports both OIDC tokens and API keys via Socket.IO auth parameters:

// Bearer token authentication
authData := map[string]interface{}{
    "token": token,
}

// API key authentication
authData := map[string]interface{}{
    "token": apiKey,
}

2. 🚨 Alert Engine (internal/alerts)

The alert engine evaluates configurable rules against aircraft data to trigger notifications.

Condition Types

ConditionDescriptionExample
squawkMatch squawk codes (supports wildcards)77* for emergencies
callsignMatch callsign patternUAL* for United
hexMatch ICAO hex codeA12345
militaryCheck military flagtrue
altitude_aboveMinimum altitude (ft)35000
altitude_belowMaximum altitude (ft)1000
distance_withinMaximum distance (nm)50
entering_geofenceGeofence entry detectionhome_area
speed_aboveMinimum ground speed (kts)500

Action Types

ActionIconDescription
soundπŸ”ŠPlay audio alert
notifyπŸ’¬Display notification message
logπŸ“Write to log file
highlight✨Highlight aircraft on radar

Creating Custom Rules:

rule := alerts.NewAlertRule("my_rule", "Custom Alert")
rule.AddCondition(alerts.ConditionSquawk, "7700")
rule.AddCondition(alerts.ConditionDistanceWithin, "25")
rule.AddAction(alerts.ActionNotify, "Emergency at {distance}nm!")
rule.AddAction(alerts.ActionSound, "emergency")
rule.SetCooldown(time.Minute * 5)
rule.SetPriority(100)

engine.AddRule(rule)
⚠️

Default Rules Included

Three default rules are pre-configured:

  1. Emergency Squawk (Priority 100) - Triggers on 75xx, 76xx, 77xx squawks
  2. Military Aircraft Nearby (Priority 50) - Military aircraft within 50nm
  3. Low Altitude Aircraft (Priority 30) - Aircraft below 1000ft within 25nm

3. πŸ—ΊοΈ Geofence Manager (internal/alerts/geofence.go)

Supports polygon and circular geofences for boundary monitoring.

// Create a circular geofence (5nm radius)
geofence := alerts.NewCircleGeofence(
    "home_area",           // ID
    "Home Area",           // Name
    52.3676,               // Center latitude
    4.9041,                // Center longitude
    5.0,                   // Radius in nautical miles
)

// Create a polygon geofence
polygon := alerts.NewPolygonGeofence(
    "restricted_area",
    "Restricted Airspace",
    []alerts.GeofencePoint{
        {Lat: 52.0, Lon: 4.0},
        {Lat: 52.5, Lon: 4.0},
        {Lat: 52.5, Lon: 5.0},
        {Lat: 52.0, Lon: 5.0},
    },
)

// Check if aircraft entered a geofence
entered := manager.CheckEntering(prevLat, prevLon, currLat, currLon)

Loading from GeoJSON:

geofence, err := alerts.LoadGeofenceFromGeoJSON("/path/to/area.geojson")
if err == nil {
    manager.AddGeofence(geofence)
}

4. πŸ“‘ Radar Scope (internal/radar)

Renders aircraft positions on an ASCII radar display with range rings, compass, and sweep animation.

// Create a radar scope
scope := radar.NewScope(theme, maxRange, rangeRings, showCompass)

// Render cycle
scope.Clear()
scope.DrawRangeRings()
scope.DrawCompass()
scope.DrawOverlays(overlays, receiverLat, receiverLon, color)
scope.DrawTrails(trails, receiverLat, receiverLon)
scope.DrawSweep(sweepAngle)
sortedTargets := scope.DrawTargets(aircraft, selectedHex, militaryOnly, hideGround, showLabels, blink)

output := scope.Render()

Target Symbols

SymbolMeaning
*✈️ Regular aircraft
!🚨 Emergency (blinking)
X⚠️ Emergency (alternate)
β—†πŸŽ–οΈ Military aircraft
β—πŸ”˜ Selected aircraft

5. πŸ“Š Spectrum Analyzer (internal/spectrum)

Visualizes aircraft signal distribution by distance band.

analyzer := spectrum.NewAnalyzer()

// Add aircraft data
analyzer.AddAircraft(hex, rssi, distance)

// Get smoothed spectrum values (0.0 to 1.0)
spectrum := analyzer.GetSpectrumSmoothed(24) // 24 bins

// Get peak hold values
peaks := analyzer.GetPeaks(24)

Distance Bands

BandRange (nm)Coverage
10-10🟒 Near
210-25🟒 Near
325-50🟑 Medium
450-75🟑 Medium
575-100🟑 Medium
6100-150🟠 Far
7150-200🟠 Far
8200-300πŸ”΄ Extended
9300-400πŸ”΄ Extended
10400+πŸ”΄ Maximum

6. πŸ—ΊοΈ Geographic Overlays (internal/geo)

Load and render geographic data on the radar display.

Supported Formats

FormatExtensionIconDescription
GeoJSON.geojson, .jsonπŸ“„Standard GeoJSON features
Shapefile.shpπŸ“ŠESRI Shapefile format
KML.kml🌍Keyhole Markup Language
KMZ.kmzπŸ“¦Compressed KML
// Load an overlay
overlay, err := geo.LoadOverlay("/path/to/airspace.geojson")
if err == nil {
    manager.AddOverlay(overlay, "airspace")
}

// Render to radar
points := geo.RenderOverlayToRadar(
    overlay,
    receiverLat, receiverLon,
    maxRange,
    radarWidth, radarHeight,
    color,
)

7. ✈️ Trail Tracker (internal/trails)

Maintains position history for each aircraft to render flight paths.

tracker := trails.NewTrailTracker()

// Add position (automatically deduplicates)
tracker.AddPosition(hex, lat, lon)

// Get trail for rendering
trail := tracker.GetTrail(hex)

// Cleanup stale trails (>5 minutes old)
removed := tracker.Cleanup()
πŸ“˜

Trail Configuration

  • Default trail length: 20 positions
  • Stale timeout: 5 minutes
  • Deduplication threshold: ~100m movement

βš™οΈ Configuration

Configuration File Location

~/.config/skyspy/settings.json

Configuration Schema

{
  "display": {
    "theme": "classic",
    "show_labels": true,
    "show_trails": false,
    "refresh_rate": 10,
    "compact_mode": false,
    "show_acars": true,
    "show_target_list": true,
    "show_vu_meters": true,
    "show_spectrum": true,
    "show_frequencies": true,
    "show_stats_panel": true
  },
  "radar": {
    "default_range": 100,
    "range_rings": 4,
    "sweep_speed": 6,
    "show_compass": true,
    "show_grid": false,
    "show_overlays": true,
    "overlay_color": "cyan"
  },
  "filters": {
    "military_only": false,
    "min_altitude": null,
    "max_altitude": null,
    "min_distance": null,
    "max_distance": null,
    "hide_ground": false
  },
  "connection": {
    "host": "localhost",
    "port": 80,
    "receiver_lat": 52.3676,
    "receiver_lon": 4.9041,
    "auto_reconnect": true,
    "reconnect_delay": 2
  },
  "audio": {
    "enabled": false,
    "new_aircraft_sound": true,
    "emergency_sound": true,
    "military_sound": false
  },
  "overlays": {
    "overlays": [
      {
        "path": "/path/to/airspace.geojson",
        "enabled": true,
        "color": "cyan"
      }
    ],
    "custom_range_rings": []
  },
  "export": {
    "directory": ""
  },
  "alerts": {
    "enabled": true,
    "rules": [],
    "geofences": [],
    "log_file": "",
    "sound_dir": ""
  }
}

🌐 Environment Variables

VariableDescriptionExample
SKYSPY_API_KEYAPI key for authenticationsk_live_abc123...

πŸ–₯️ Command Line Flags

# Connection
--host string       Server hostname
--port int          Server port

# Display
--lat float         Receiver latitude
--lon float         Receiver longitude
--range int         Initial range (nm)
--theme string      Color theme name
--overlay string    Load overlay file (repeatable)
--list-themes       List available themes

# Authentication
--api-key string    API key for authentication

# Export
--export-dir string Directory for export files

# Audio
--no-audio          Disable audio alerts

πŸ”— Django Backend Integration

Socket.IO Namespaces

The Go CLI connects to Socket.IO namespaces on the Django backend:

sequenceDiagram
    participant CLI as πŸ–₯️ Go CLI
    participant SIO as πŸ”Œ Socket.IO
    participant Django as ☁️ Django Backend

    CLI->>SIO: Connect to /aircraft namespace
    CLI->>SIO: Connect to /acars namespace
    SIO->>Django: Establish connection
    Django-->>SIO: Connection acknowledged
    CLI->>SIO: Subscribe to topics
    loop Real-time Updates
        Django-->>SIO: aircraft:update
        SIO-->>CLI: Aircraft data
        Django-->>SIO: acars:message
        SIO-->>CLI: ACARS data
    end

Message Protocol

Subscription:

{
  "action": "subscribe",
  "topics": ["aircraft"]
}

Aircraft Data (from server):

{
  "type": "aircraft:update",
  "data": {
    "hex": "A12345",
    "flight": "UAL123",
    "lat": 52.3676,
    "lon": 4.9041,
    "alt_baro": 35000,
    "gs": 450.5,
    "track": 270.0,
    "baro_rate": -500,
    "squawk": "1234",
    "rssi": -15.5,
    "t": "A320",
    "military": false,
    "distance_nm": 25.5,
    "bearing": 180.0
  }
}

πŸ” Authentication Flow

flowchart LR
    subgraph OIDC["πŸ” OIDC Login"]
        A[skyspy login] --> B[Start callback server]
        B --> C[Open browser]
        C --> D[User authenticates]
        D --> E[Receive callback]
        E --> F[Exchange code for tokens]
        F --> G[Store tokens]
    end

    subgraph APIKey["πŸ”‘ API Key"]
        H[--api-key flag] --> I[Header authentication]
        J[SKYSPY_API_KEY env] --> I
    end
  1. OIDC Login:

    skyspy login --host myserver.com --port 443
  2. API Key:

    skyspy --api-key sk_live_abc123...
    # or
    export SKYSPY_API_KEY=sk_live_abc123...
    skyspy
  3. Token Refresh:

    • Tokens auto-refresh when within 5 minutes of expiry
    • Refresh tokens stored securely with access tokens

πŸ“Š Data Processing Pipeline

Aircraft Update Flow

flowchart TD
    A[πŸ“₯ Socket.IO receives message] --> B[πŸ”„ Parse JSON to Aircraft struct]
    B --> C[✏️ Create/Update radar.Target]
    C --> D{Receiver coords set?}
    D -->|Yes| E[πŸ“ Calculate distance/bearing]
    D -->|No| F[Skip calculation]
    E --> G[πŸ“ Add position to TrailTracker]
    F --> G
    G --> H[🚨 Check alert rules]
    H --> I[πŸ“Š Update spectrum analyzer]
    I --> J{Alert triggered?}
    J -->|Yes| K[πŸ”Š Trigger audio alerts]
    J -->|No| L[⏱️ Update UI on next tick]
    K --> L

    style A fill:#2d5a27,stroke:#1e3d19
    style L fill:#1a4d6e,stroke:#0f2d42

Alert Evaluation Flow

flowchart TD
    A[πŸ“₯ Receive aircraft state] --> B[πŸ” Get previous state from tracking]
    B --> C[πŸ“‹ For each enabled rule by priority]
    C --> D{Check cooldown}
    D -->|On cooldown| C
    D -->|Available| E{Evaluate conditions}
    E -->|No match| C
    E -->|Match| F[βœ… Create TriggeredAlert]
    F --> G[⏱️ Record trigger time]
    G --> H[⚑ Execute actions]
    H --> I[✨ Update aircraft highlight status]
    I --> J[πŸ“ Add to recent alerts history]

πŸ“‘ ADS-B Data Ingestion

ℹ️

Data Flow

The Go CLI does not directly ingest ADS-B data. It relies on the Django backend which receives data from dump1090 or readsb via Beast protocol.

Data Fields Consumed

FieldTypeDescription
hexstringπŸ”’ ICAO 24-bit address
flightstring✈️ Callsign/flight number
latfloat64🌐 Latitude (WGS84)
lonfloat64🌐 Longitude (WGS84)
alt_barointπŸ“ Barometric altitude (ft)
altintπŸ“ Altitude (ft, fallback)
gsfloat64πŸ’¨ Ground speed (knots)
trackfloat64🧭 Track angle (degrees)
baro_ratefloat64↕️ Vertical rate (ft/min)
vrfloat64↕️ Vertical rate (fallback)
squawkstringπŸ“Ÿ Transponder code
rssifloat64πŸ“Ά Signal strength (dBm)
tstringπŸ›©οΈ Aircraft type code
militaryboolπŸŽ–οΈ Military aircraft flag
distance_nmfloat64πŸ“ Pre-calculated distance
bearingfloat64🧭 Pre-calculated bearing

⚑ Performance Considerations

Memory Management

🧹

Automatic Cleanup

The CLI automatically manages memory through periodic cleanup tasks.

TaskIntervalDescription
Trail Cleanup30 secondsPurge stale trails (5+ minutes)
Alert CooldownsPeriodicClean old trigger records
Message BuffersContinuousSocket.IO channels buffered to 100 messages
Spectrum DecayPer updateOld signal data decays at 15% per cycle

CPU Optimization

OptimizationImpact
πŸ–₯️ Render RateUI updates every 150ms (not per message)
πŸ“ Haversine CalculationsOnly when receiver coordinates set
πŸ“‚ Lazy LoadingOverlays parsed only on demand
πŸ”Œ Socket.IO ClientReal-time streaming client

Network Efficiency

FeatureBenefit
πŸ“‹ Topic SubscriptionOnly subscribes to needed topics
πŸ”„ Reconnection BackoffConfigurable delay between attempts
πŸ“¦ Message BatchingHandles snapshot messages with multiple aircraft

πŸ’» Recommended System Requirements

RequirementMinimumRecommended
πŸ”² CPU1 core2+ cores
🧠 RAM64 MB128 MB
πŸ–₯️ Terminal80x24120x40+
🌐 Network1 Mbps5+ Mbps

πŸ”¨ Building and Running

Prerequisites

  • 🦫 Go 1.22 or later
  • πŸ› οΈ Make (optional, for build automation)

πŸš€ Quick Start

cd skyspy-go

# Build for current platform
make build

# Run the CLI
./bin/skyspy --host myserver.com --port 80

# Or build and run in one step
make run

πŸ“¦ Build Commands

Development

CommandDescription
make buildπŸ”¨ Build for current platform
make runπŸš€ Build and run
make fmt🎨 Format code
make lintπŸ” Run linter

Testing

CommandDescription
make testβœ… Run tests
make test-coverageπŸ“Š Tests with coverage
make test-race🏁 Tests with race detector
make ciπŸ”„ Full CI pipeline

Release

CommandDescription
make build-all🌍 Cross-compile all platforms
make installπŸ“₯ Install to $GOPATH/bin
make clean🧹 Clean build artifacts

Docker

CommandDescription
docker build -t skyspy-cli .🐳 Build image
docker run -it --rm skyspy-cli🐳 Run container

🌍 Cross-Compilation Targets

# Build creates binaries for all platforms:
make build-all
PlatformArchitectures
🐧 Linuxamd64 arm64
🍎 macOSamd64 arm64
πŸͺŸ Windowsamd64 arm64

πŸ“‹ Version Information

Builds include embedded version information via ldflags:

VERSION=$(git describe --tags --always --dirty)
COMMIT=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

go build -ldflags "-X main.version=$VERSION -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME"

⌨️ Keyboard Controls

Radar View

Navigation

KeyAction
j↓Select next aircraft
k↑Select previous aircraft
+=Zoom out (increase range)
-_Zoom in (decrease range)

Display Toggles

KeyAction
LToggle labels
MToggle military-only filter
GToggle ground aircraft
AToggle ACARS panel
VToggle VU meters
SToggle spectrum
BToggle trails

Panels & Menus

KeyAction
TOpen theme selector
OOpen overlay manager
ROpen alert rules
/Enter search mode

Quick Filters

KeyFilter
F1All aircraft
F2Military only
F3Emergencies
F4Low altitude

Export

KeyAction
PExport screenshot (HTML)
EExport to CSV
Ctrl+EExport to JSON

Help & Exit

KeyAction
? / HShow help
QQuit

Search Mode

KeyAction
EnterApply filter
EscCancel search
↑ / ↓Navigate results

πŸ” Search Syntax

# Plain text search (callsign or hex)
UAL

# Squawk filter
sq:7700
sq:7500,7600,7700

# Altitude filters
alt:>35000
alt:<10000
alt:5000-10000

# Distance filters
dist:<50
dist:>10
dist:10-50

# Military only
mil

# Combined
UAL alt:>35000 dist:<100

🎨 Themes

Available Themes

ThemePreviewDescription
classic🟒Traditional green phosphor display
amber🟠Vintage amber monochrome
iceπŸ”΅Cold blue tactical display
cyberpunk🟣Neon futuristic display
military🟀Tactical military style
high_contrastβšͺMaximum visibility white
phosphor🟒Realistic CRT phosphor glow
sunset🟠Warm orange sunset tones
matrix🟒Matrix digital rain inspired
oceanπŸ”΅Deep blue oceanic display

πŸ“‹ Listing Themes

skyspy --list-themes

🎨 Selecting a Theme

# Via command line
skyspy --theme cyberpunk

# Via configuration
{
  "display": {
    "theme": "cyberpunk"
  }
}

# Runtime: Press 't' to open theme selector

πŸ“€ Export Formats

CSV Export

hex,callsign,lat,lon,altitude,speed,track,vertical_rate,squawk,distance_nm,bearing,military,rssi,aircraft_type,timestamp
A12345,UAL123,52.367600,4.904100,35000,450.500000,270.000000,-500.000000,1234,25.500000,180.000000,false,-15.500000,A320,2024-01-15T12:30:45Z

JSON Export

[
  {
    "hex": "A12345",
    "callsign": "UAL123",
    "lat": 52.3676,
    "lon": 4.9041,
    "altitude": 35000,
    "speed": 450.5,
    "track": 270.0,
    "vertical_rate": -500,
    "squawk": "1234",
    "distance_nm": 25.5,
    "bearing": 180.0,
    "military": false,
    "rssi": -15.5,
    "aircraft_type": "A320",
    "timestamp": "2024-01-15T12:30:45Z"
  }
]

HTML Screenshot

πŸ“Έ

Screenshots are exported as styled HTML files preserving the terminal appearance with theme colors.


πŸ”§ Troubleshooting

Connection Issues

# Check server connectivity
curl http://myserver.com/api/v1/status/

# Verify Socket.IO endpoint
wscat -c "ws://myserver.com/ws/aircraft/?topics=aircraft"

# Check auth configuration
skyspy auth status --host myserver.com

Authentication Problems

# Clear stored tokens and re-login
skyspy logout
skyspy login

# Use API key instead
skyspy --api-key sk_live_...

Display Issues

⚠️

Terminal Requirements

  • Ensure terminal supports Unicode characters
  • Use a terminal with 256-color support
  • Minimum recommended size: 120x40 characters

Audio Not Working

πŸ”Š

Audio Troubleshooting

  • Check that audio is enabled in config
  • Verify sound files exist in ~/.config/skyspy/sounds/
  • Try --no-audio flag to disable audio

πŸ”„ CI/CD Pipeline

GitHub Actions Workflows

Test Workflow (.github/workflows/test.yml)

  • πŸ”€ Runs on push and pull requests
  • 🦫 Tests with Go 1.22
  • βœ… Runs go test -v -race ./...
  • πŸ” Includes linting with golangci-lint

Release Workflow (.github/workflows/release.yml)

  • 🏷️ Triggered on version tags (v*)
  • πŸ”¨ Builds binaries for all platforms
  • πŸ“¦ Creates GitHub release with:
    • Platform-specific archives
    • SHA256 checksums
    • Auto-generated changelog
  • 🐳 Builds and pushes Docker image to GHCR

πŸš€ Creating a Release

# Tag a new version
git tag v1.0.0
git push origin v1.0.0

# The release workflow will automatically:
# 1. Run tests
# 2. Build all binaries
# 3. Create GitHub release
# 4. Push Docker image

πŸ“š API Reference

For detailed Go API documentation, generate with:

cd skyspy-go
go doc -all ./...

Or view online documentation after pushing to a public repository:

https://pkg.go.dev/github.com/skyspy/skyspy-go