Files
timban c08fc277a9 Initial commit: NetworkCity — network traffic as a neon city
A native macOS network monitor that renders live traffic as a top-down
neon city: your Mac is downtown, remote orgs are glowing districts, and
traffic is cars of light driving the roads.

Architecture:
- NetworkCityCore: swappable data layer behind a ConnectionSource protocol
  (nettop-backed today), plus pure/tested logic — traffic diffing, org
  classification (reverse-DNS + CIDR), traffic classes, hub-and-spoke
  expansion policy, label anti-overlap, and latency→distance layout.
- NetworkCityApp: SwiftUI + SpriteKit city — auto-expanding districts,
  protocol-coloured cars, click-to-inspect panel, and latency-as-distance
  (districts glide to their measured RTT).
- nettop-probe: CLI proof of the data layer.

44 tests passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 08:43:32 -07:00

46 lines
1.8 KiB
Swift

import Foundation
import NetworkCityCore
// Phase-1 proof of concept. Polls nettop, diffs successive snapshots, and prints
// the busiest external flows as live KB/s i.e. the raw material that will
// become cars driving to buildings.
setvbuf(stdout, nil, _IONBF, 0) // unbuffered: see output live even when piped
let interval: TimeInterval = 2.0
let source = NettopSource()
let differ = TrafficDiffer()
var warmedUp = false
func pad(_ s: String, _ width: Int) -> String {
s.count >= width ? String(s.prefix(width)) : s + String(repeating: " ", count: width - s.count)
}
print("📡 NetworkCity probe — sampling every \(Int(interval))s. Ctrl-C to stop.\n")
for await snap in source.snapshots(every: interval) {
let deltas = differ.ingest(snap).filter { $0.connection.isExternal }
let external = snap.connections.filter(\.isExternal).count
if !warmedUp {
warmedUp = true
print("… warming up (need two samples to compute rates) …\n")
continue
}
let active = deltas.sorted { ($0.inBytesPerSec + $0.outBytesPerSec) > ($1.inBytesPerSec + $1.outBytesPerSec) }
let ts = DateFormatter.localizedString(from: snap.timestamp, dateStyle: .none, timeStyle: .medium)
print("─── \(ts) \(active.count) active / \(external) external connections ───")
print("\(pad("PROCESS", 18)) \(pad("DESTINATION", 24)) ↓ KB/s ↑ KB/s")
if active.isEmpty {
print(" (quiet — no measurable traffic this interval)")
}
for d in active.prefix(15) {
let dest = d.connection.remote.display
print("\(pad(d.connection.processName, 18)) \(pad(dest, 24)) "
+ "\(String(format: "%9.1f", d.inBytesPerSec / 1024)) \(String(format: "%9.1f", d.outBytesPerSec / 1024))")
}
print("")
}