gtfs-cli
CLI tool to fetch, process, and explore GTFS transit data — both realtime (GTFS-RT) and static schedules. Follows Unix philosophy: each command does one thing and writes to stdout, composing naturally with tools like curl, unzip, and jq.
Note:
gtfs-cliis in active development. All0.x.xreleases are subject to breaking changes.
Goal
To become a Swiss Army knife CLI for working with public transit open data — GTFS static schedules, GTFS-RT real-time feeds, bike share data, and more.
Installation
uv tool install gtfs-cli
After installation, the gtfs-cli command is available globally.
Commands
static info
Inspect a static GTFS feed (a folder of .txt files). Shows agency, valid dates, feed age, stop/route/trip counts, route types, service days, and file inventory.
# Download and unzip a feed, then inspect it
curl -L "https://ckan0.cf.opendata.inter.prod-toronto.ca/dataset/7795b45e-e65a-4465-81fc-c36b9dfff169/resource/cfb6b2b8-6191-41e3-bda1-b175c51148cb/download/TTC%20Routes%20and%20Schedules%20Data.zip" -o ttc.zip
unzip ttc.zip -d ttc/
gtfs-cli static info ttc/
# Inspect the current directory
gtfs-cli static info
Example output:
Agency TTC
Timezone America/Toronto
Language en
Valid 2026-05-03 → 2026-06-06 (34 days)
Feed age 9 days · expires in 25 days
Stops 9,378
Routes 232
Trips 134,882
Stop times 4,261,259
Shapes 434,460 points across 1,550 shapes
Route types
Bus 210
Tram / Light Rail 19
Subway / Metro 3
Service days
Mon Tue Wed Thu Fri Sat Sun
Files
Required agency stops routes trips stop_times calendar
Optional shapes calendar_dates
Missing feed_info frequencies transfers fare_attributes fare_rules
Largest files
stop_times.txt 203 MB 4,261,259 rows
shapes.txt 18 MB 434,460 rows
trips.txt 12 MB 134,882 rows
For all available options, run:
gtfs-cli static info --help
fetch
Fetch a GTFS-RT feed from a URL or local file and output it as JSON.
Example output:
{
"header": {
"gtfs_realtime_version": "2.0",
"incrementality": "FULL_DATASET",
"timestamp": "1778642963"
},
"entity": [
{
"id": "1",
"trip_update": {
"trip": {
"trip_id": "39051020",
"route_id": "73",
"schedule_relationship": "SCHEDULED"
},
"stop_time_update": [
{
"stop_sequence": 31,
"arrival": { "time": "1778642961" },
"stop_id": "1732",
"schedule_relationship": "SCHEDULED"
}
]
}
}
]
}
# Fetch live trip updates
gtfs-cli fetch "https://gtfsrt.ttc.ca/trips/update?format=binary"
# Fetch vehicle positions
gtfs-cli fetch "https://gtfsrt.ttc.ca/vehicles/position?format=binary"
# Fetch service alerts
gtfs-cli fetch "https://gtfsrt.ttc.ca/alerts/all?format=binary"
# Inspect a previously saved .pb file
gtfs-cli fetch trips.pb
Filtering with jq:
# List all active alerts
gtfs-cli fetch "https://gtfsrt.ttc.ca/alerts/all?format=binary" | jq '.entity[] | .alert'
# Count entities in a feed
gtfs-cli fetch "https://gtfsrt.ttc.ca/trips/update?format=binary" | jq '.entity | length'
# Extract all trip IDs
gtfs-cli fetch "https://gtfsrt.ttc.ca/trips/update?format=binary" \
| jq '[.entity[].trip_update.trip.trip_id]'
Watch mode — continuously poll a feed and stream NDJSON (one JSON object per line):
# Poll every 30 seconds
gtfs-cli fetch --watch 30 "https://gtfsrt.ttc.ca/trips/update?format=binary"
# Count entities on each snapshot
gtfs-cli fetch --watch 30 "https://gtfsrt.ttc.ca/trips/update?format=binary" \
| jq --unbuffered '.entity | length'
# Save a long-running collection to a file
gtfs-cli fetch --watch 30 "https://gtfsrt.ttc.ca/trips/update?format=binary" \
>> snapshots.ndjson
Watch mode handles transient failures gracefully: HTTP and network errors are retried with exponential backoff (1s → 2s → 4s … capped at 60s). Stop with Ctrl+C or SIGTERM.
For all available options, run:
gtfs-cli fetch --help
Development
# Install dependencies
uv sync
# Run a command
uv run gtfs-cli fetch "https://gtfsrt.ttc.ca/trips/update?format=binary"
# Run tests
uv run pytest tests/ -v
Release files for gtfs-cli 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gtfs_cli-0.4.1.tar.gz | 249.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gtfs_cli-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 261.3 kB
Release files / gtfs_cli-0.4.1.tar.gz
| Download URL | gtfs_cli-0.4.1.tar.gz |
|---|---|
| Size | 249.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f5c9416e7610b8acb9d35fc57c8ffd2041ec0f470b3f3332aab50ea2d9aaead5
|
|
BLAKE2b-256 checksum How to use checksums |
357aa7c1b3d3c751dfab2eb2ae78c9d0ea586f430aceec4e88def267e0bf9f07
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.9
|
Release files / gtfs_cli-0.4.1-py3-none-any.whl
| Download URL | gtfs_cli-0.4.1-py3-none-any.whl |
|---|---|
| Size | 11.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec9a54debad19de03abcbace8c3167b0f56d588035d97d4538a527567d866d2f
|
|
BLAKE2b-256 checksum How to use checksums |
cd487c0a797b5ff3c486b0c0e79ce54847722a36c969329cc96f1ddec8634f98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.9
|