Skip to content

Repository files navigation

LagCulprit app icon

LagCulprit

Know where the lag starts.

A native macOS utility that monitors connection quality, explains likely causes, and keeps exact evidence when something goes wrong.

Download the latest release · Build from source

Platform Native UI Engine License

What LagCulprit does

LagCulprit continuously measures latency, jitter, packet loss, router reachability, independent internet controls, DNS health, and available Wi-Fi context. It turns those signals into a readable state and an evidence-backed culprit domain:

  • Local network or router
  • ISP or upstream path
  • DNS resolver
  • Remote service or application path
  • Inconclusive, when the evidence cannot safely separate the cause

Attribution is probabilistic by design. LagCulprit reports uncertainty instead of turning an ambiguous ping result into a confident but misleading verdict.

Highlights

Live diagnosis

  • Near-instant state changes — a packet-loss pipeline combines consecutive failures, rolling metrics, and hysteresis to react quickly without flickering.
  • Independent controls — gateway, DNS, and multiple public controls help distinguish local, upstream, and resolver failures.
  • Adaptive probing — monitoring runs at roughly five samples per second while healthy and accelerates during instability.
  • Application-path context — the app conservatively detects active latency-sensitive sessions, follows helper processes, and monitors a stable remote endpoint as a separate leg when direct probing is supported.
  • Wi-Fi and route evidence — signal strength and a one-shot path trace add context when an incident opens.

History and proof

  • Exact incident timeline — incidents preserve their first bad sample, recovery boundary, duration, local timestamps with milliseconds, evidence checks, charts, network context, and trace results.
  • Lag Recap — detected calls, games, and other real-time sessions receive a local score, stable time, P95 latency, loss, incident attribution, and a recommended action.
  • Mark Lag Now — press Option-Shift-M to correlate a felt problem with the measurements recorded at that moment.
  • Session Preflight — an eight-second latency-under-load check helps reveal bufferbloat before an important call or session.
  • Network Report — summarize uptime, incidents, affected time, worst hour, latency trends, and per-network health.
  • Local exports — create self-contained incident reports, session HTML reports, and PNG recap cards without uploading history.

Native surfaces

  • Menu-bar app — no permanent main window; built natively with SwiftUI and AppKit.
  • Floating overlay — three sizes, click-through support, modifier-drag positioning, incident expansion, and a global visibility shortcut.
  • Protected local API and browser overlay — optional localhost-only status JSON and an OBS-compatible browser source secured by an installation-specific token.
  • Notifications and updates — native incident/recovery notifications plus Sparkle updates.

Privacy model

  • No root access or privileged network helper is required.
  • Measurements, incidents, sessions, and settings stay in local application storage.
  • The optional HTTP surface binds to loopback and requires a token.
  • Reports and recap images are generated locally.
  • Preflight sends temporary, capped download traffic; it performs no upload test and does not retain the payload.
  • Monitoring necessarily sends network probes and DNS requests. LagCulprit does not claim to make zero network requests.

How it works

┌──────────────────────────────────────────────────────┐
│ Native macOS app: SwiftUI/AppKit                     │
│ menu bar · history · reports · overlay               │
└──────────────────────────┬───────────────────────────┘
                           │ Unix socket
                           │ length-prefixed protobuf
┌──────────────────────────┴───────────────────────────┐
│ Bundled Rust daemon                                  │
│ probes · metrics · verdicts · incidents · SQLite     │
│ sessions · reports · localhost API/browser overlay   │
└──────────────────────────────────────────────────────┘

The Rust engine is the source of truth. The native app renders the state, verdict, evidence, and history published over the protobuf contract; it does not independently reinterpret measurements.

Rust workspace

Crate Responsibility
lc-core Pure metrics, packet-loss state machine, scoring, incident, and session logic
lc-ipc Protobuf types and length-prefixed Unix-socket transport
lc-daemon Probing, orchestration, persistence, reports, and local HTTP surface
lc-cli Human-readable status, watch, and --json automation output

Install

  1. Download the current DMG from the latest GitHub release.
  2. Open the disk image and drag LagCulprit.app to /Applications.

The DMG includes its matching Rust daemon. The native app starts it on launch and stops it on quit; there is no separate service or privileged helper to install.

Develop

Requirements

  • macOS 14 or later
  • Xcode 16
  • Rust
  • XcodeGen: brew install xcodegen

Run locally

Start the development daemon:

cd rust-core
cargo run -p lc-daemon

Then generate and open the app project:

cd macos-app
xcodegen generate
open LagCulprit.xcodeproj

Press Command-R in Xcode. Local Xcode builds do not contain the packaged helper, so they connect to the daemon running from the first terminal. Both Debug and Release configurations compile the live-daemon path; simulation remains available only for previews and explicit fixtures.

To force an incident during development, run the daemon with an unreachable documentation address:

LC_TARGET=192.0.2.1 cargo run -p lc-daemon

Test

# Rust workspace
cd rust-core
cargo test --workspace --locked

# Swift wire-layer proof
cd ../swift-proof
swift build

# Native app tests
cd ../macos-app
xcodegen generate
xcodebuild \
  -project LagCulprit.xcodeproj \
  -scheme LagCulprit \
  -destination 'platform=macOS' \
  test

CI runs the locked Rust workspace and compiles the native macOS app. Tagged releases produce a signed and notarized DMG.

Release workflow

Pushing a version tag such as v1.2.0 starts .github/workflows/release.yml. The workflow:

  1. Tests the Rust workspace and native macOS app.
  2. Bundles lc-daemon inside the app.
  3. Signs, notarizes, staples, and Sparkle-signs the DMG.
  4. Publishes the DMG and appcast to the tagged GitHub release.

The app checks this stable feed URL:

https://github.com/SarKurd/LagCulprit/releases/latest/download/appcast.xml

Each appcast points to the DMG attached to its immutable, versioned GitHub Release. See BUILD.md for local packaging commands and required CI secrets.

Repository layout

proto/          Shared daemon-to-app protobuf contract
rust-core/      Rust engine, daemon, IPC, and CLI crates
macos-app/      SwiftUI/AppKit app and XcodeGen project specification
swift-proof/    SwiftPM build proof for the generated wire layer
packaging/      DMG signing and notarization script

Contributing

  • Edit macos-app/project.yml, not the generated .xcodeproj.
  • Treat proto/lagculprit/v1/lagculprit.proto as the wire-contract source of truth and run scripts/generate-proto.sh after schema changes.
  • Keep lc-core free of I/O and platform-specific behavior.
  • Run the relevant Rust and native-app checks before opening a pull request.
  • Update this README and BUILD.md when user-visible behavior or distribution changes.

Known limitations

  • App-path detection is conservative and cannot identify or directly probe every relay, encrypted transport, VPN path, or UDP-only IPv6 endpoint.
  • Fault attribution says “likely” because endpoint behavior alone cannot prove every remote or upstream cause.
  • The native overlay cannot guarantee visibility over every exclusive-fullscreen render pipeline.

License

MIT. See LICENSE.

About

A native macOS menu bar app that monitors network quality, identifies likely causes of lag, and preserves detailed evidence for connection issues.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages