Arrivals

May 3, 2026 · View on GitHub

Arrivals is a Kotlin Multiplatform project for live public transit times. It supports 3 targets: a macOS toolbar app, a CLI, and a desktop app (for e.g. Raspberry Pi kiosk displays).

Dot MatrixLCD
Screenshot: macOS status bar, dot matrix styleScreenshot: macOS status bar, LCD style

There's a separate Python renderer in the arrivals-led repo, which drives a physical 128x32 LED panel.

Supported transit systems

SystemSource
LondonUnderground, Overground, DLRTfL API
UKNational RailDarwin API
NYCSubwayMTA GTFS
SF Bay AreaBART511.org GTFS
BerlinU-Bahn, S-Bahn, Tramtransport.rest

... or any custom GTFS-RT feed

Run

The macOS toolbar app can be downloaded from releases and copied to your Applications folder. Other targets can to be built from source with the instructions below.

Build

Prerequisites

  1. Get API keys for any authenticated sources you plan to use:
  2. Create shared/secret.properties and add your keys:
    tfl_key=YOURKEY
    darwin_key=YOURKEY
    org_511_key=YOURKEY
    
  3. Make sure you have a JDK configured at $JAVA_HOME

Targets

TargetPlatformDescriptionQuick start
macOSmacOSSwiftUI status bar appOpen macOS/Arrivals.xcodeproj in Xcode and click the Run button
DesktopLinux (incl. Raspberry Pi), macOS, WindowsCompose Multiplatform window with fullscreen mode./gradlew :desktop:run
CLILinux, macOS, JVMCommand-line interface./cli/install

macOS toolbar app

Native status bar application for macOS, built with SwiftUI.

  1. Open macOS/Arrivals.xcodeproj in Xcode
  2. Press the Run button
  3. Configure via the settings UI

Desktop window

Cross-platform desktop UI, built with Compose Multiplatform. Includes a fullscreen mode for kiosk displays and configuration via a YAML file.

Run from Gradle

# Windowed mode
./gradlew :desktop:run

# Fullscreen with custom dimensions
./gradlew :desktop:run --args="-pi 1280 400"

Build native distribution

# Executable in desktop/build/compose/binaries/main/app/
./gradlew :desktop:createDistributable

Configuration via YAML

Create a .arrivals.yml in the user home directory to configure:

# Mode: "tfl", "darwin", "bvg", or "gtfs"
mode: tfl

# Shared config fields
stop: 910GSHRDHST           # Station/stop ID (all modes)
platform: 2                 # Optional platform (all but GTFS)
line:                       # Optional line (BVG only: U8, M10, etc.)
direction:                  # Optional direction (TfL only: "inbound" or "outbound")

# GTFS-specific config
gtfs_realtime: https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-g
gtfs_schedule: http://web.mta.info/developers/data/nyct/subway/google_transit.zip
# Optional for authenticated feeds
gtfs_api_key_param:         # Param or header (e.g. "app_id", "header:Authorization")
gtfs_api_key:               # API key

CLI

Command-line interface, compiled as a native binary. Run ./cli/install to build and install the arrivals command for your platform, or run it via Gradle with ./gradlew :cli:jvmRun.

Screenshot: arrivals CLI command

TfL example

arrivals tfl --station 910GSHRDHST --platform 2

GTFS example

arrivals gtfs --station G28S \
  --realtime https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-g \
  --schedule http://web.mta.info/developers/data/nyct/subway/google_transit.zip

Search for station codes

arrivals search tfl "shoreditch high street" # or use list-stops for GTFS

Attribution