Skip to main content

Terminal-native GIS tool for vector data

Project description

geo-tool

Terminal-native GIS tool for vector data. No QGIS, no GUI, no bloat.

Inspect, convert, reproject, filter, and visualize geospatial datasets entirely from the command line. Renders maps as Unicode braille characters directly in your terminal.

Supported Formats

Format Read Write
Shapefile Yes Yes
GeoPackage Yes Yes
GeoJSON Yes Yes
FlatGeobuf Yes Yes
TopoJSON Yes No

Installation

Recommended: Use uv for the smoothest experience.

# Add to your project
uv add gis-terminal

# Run the tool
gis-tool --help

⚠️ Note: This package is in active development (beta). Requires Python 3.12+.
Do not use pip install — use uv for reliable dependency resolution.

Development Setup

To contribute or modify the source:

git clone <repo-url>
cd "GIS Terminal"
uv sync

Run without activating:

# Windows:
.venv\Scripts\gis-tool.exe --help
# Linux/macOS:
.venv/bin/gis-tool --help

Dependencies

Four runtime dependencies, all pulling from GDAL/OGR, PROJ, and GEOS under the hood:

  • click -- CLI framework
  • fiona -- vector I/O (GDAL/OGR bindings with streaming support)
  • shapely -- geometry operations (GEOS bindings)
  • pyproj -- CRS transformations (PROJ bindings)

Commands

geo-tool info -- Inspect metadata

geo-tool info countries.shp
File:      countries.shp
Driver:    ESRI Shapefile
CRS:       EPSG:4326
Geometry:  Polygon
Features:  177
Extent:    -180.000000, -90.000000, 180.000000, 83.645130

Fields:
  NAME        str
  POP_EST     int64
  GDP_MD      float
  ISO_A3      str

Machine-readable output for scripting:

geo-tool --json info countries.shp
{
  "path": "countries.shp",
  "driver": "ESRI Shapefile",
  "crs": "EPSG:4326",
  "geometry_type": "Polygon",
  "feature_count": 177,
  "bounds": [-180.0, -90.0, 180.0, 83.64513],
  "fields": [
    {"name": "NAME", "type": "str"},
    {"name": "POP_EST", "type": "int64"}
  ]
}

For multi-layer formats (GeoPackage):

geo-tool info data.gpkg --layer boundaries

geo-tool convert -- Format conversion

Convert between any supported writable formats. The output format is detected from the file extension.

# Shapefile to GeoPackage
geo-tool convert input.shp output.gpkg

# GeoJSON to FlatGeobuf
geo-tool convert input.geojson output.fgb

# Convert and reproject in one step
geo-tool convert input.shp output.geojson --crs EPSG:4326

geo-tool reproject -- Change coordinate reference system

# WGS84 to Web Mercator
geo-tool reproject input.geojson output.geojson --crs EPSG:3857

# To a UTM zone
geo-tool reproject input.shp output.gpkg --crs EPSG:32633

The --crs flag accepts any string that pyproj understands: EPSG:XXXX, WKT, or PROJ strings.

geo-tool filter -- Spatial and attribute filtering

Filter by bounding box (west, south, east, north):

geo-tool filter countries.gpkg --bbox -10,35,30,60

Filter by attribute expression (OGR SQL syntax):

geo-tool filter countries.gpkg --where "POP_EST > 50000000"

Combine both:

geo-tool filter countries.gpkg --bbox -10,35,30,60 --where "POP_EST > 10000000"

Write results to a file instead of stdout:

geo-tool filter countries.gpkg --bbox 0,0,10,10 -o subset.geojson

When no -o is given, GeoJSON is written to stdout -- pipe it wherever you want:

geo-tool filter data.gpkg --where "type = 'highway'" | jq '.features | length'

geo-tool view -- Terminal map preview

Renders geometries as Unicode braille characters directly in your terminal.

geo-tool view countries.shp

Interactive controls:

Key Action
+ Zoom in
- Zoom out
Arrows Pan
r Reset view
q Quit

For non-interactive (pipe-friendly) output:

geo-tool view countries.shp --static

Restrict the initial view to a bounding box:

geo-tool view countries.shp --bbox -20,30,45,72

How it works: Each terminal character cell is a 2x4 braille dot pattern (Unicode block U+2800). This gives 8x the pixel resolution of regular characters. An 80-column terminal renders at 160x84 effective pixels. A 200-column terminal reaches 400x192 pixels -- enough to recognize coastlines, boundaries, and road networks.

Geometries are rasterized using Bresenham's line algorithm for lines and polygon outlines. Points are drawn as small crosses. For large datasets (>10,000 features), the renderer samples features and displays a notice.

geo-tool serve -- Browser map

Opens the dataset on a Leaflet map in your browser. No external server or build step required.

geo-tool serve countries.gpkg
Serving countries.gpkg at http://localhost:8080
Press Ctrl+C to stop.

Options:

# Custom port
geo-tool serve data.geojson --port 3000

# Don't auto-open the browser
geo-tool serve data.geojson --no-open

The server uses Python's built-in http.server with Leaflet loaded from CDN. Features are spatially filtered on each map pan/zoom -- only the visible extent is sent to the browser (max 5,000 features per request). Click any feature to see its attributes in a popup.

Global Options

These go before the subcommand:

geo-tool --json info data.shp        # JSON output
geo-tool -q convert in.shp out.gpkg  # Suppress status messages
geo-tool --version                   # Show version
Flag Effect
--json Machine-readable JSON output
-q/--quiet Suppress non-essential stderr output
-v/--verbose Debug-level logging
--version Print version and exit

Piping and Scripting

geo-tool is designed to be Unix-pipe friendly. Combine commands:

# Get the CRS of a file
geo-tool --json info data.shp | python -m json.tool

# Filter then inspect the result
geo-tool filter big.gpkg --bbox 0,0,10,10 -o subset.geojson && geo-tool info subset.geojson

# Count features matching a query
geo-tool --json filter data.gpkg --where "pop > 1000000" | python -c "
import json, sys
fc = json.load(sys.stdin)
print(len(fc['features']))
"

When stdout is not a TTY (i.e., output is piped), geo-tool view automatically uses static mode.

Project Structure

src/geo/
  cli.py                  Entry point, Click command group
  formats.py              File extension to OGR driver mapping
  output.py               Human-readable and JSON formatters
  errors.py               Exception hierarchy
  commands/
    info.py               geo-tool info
    convert.py            geo-tool convert
    reproject.py          geo-tool reproject
    filter.py             geo-tool filter
    view.py               geo-tool view
    serve.py              geo-tool serve
  core/
    reader.py             Dataset opening via Fiona
    writer.py             Dataset writing via Fiona
    inspector.py          Metadata extraction
    transform.py          CRS reprojection via pyproj
    query.py              Spatial/attribute filtering via OGR
  render/
    canvas.py             Boolean pixel grid
    braille.py            Pixel-to-braille encoding
    viewport.py           Geographic-to-pixel coordinate transform
    rasterizer.py         Bresenham lines, geometry rasterization
    display.py            Interactive terminal loop
  server/
    app.py                HTTP server startup
    handler.py            Request routing and feature API
    templates.py          Leaflet HTML template

Design Decisions

  • Click over Typer -- explicit argument handling, no type-hint magic
  • Fiona over pyogrio -- streaming iteration instead of bulk memory load
  • Braille over block characters -- 8x pixel resolution per character cell
  • Leaflet over MapLibre -- 40KB from CDN, zero build step, native GeoJSON support
  • No rich/tabulate -- the tool has ~3 tables total; str.ljust() is enough
  • always_xy=True in pyproj -- prevents silent lon/lat axis swap that corrupts data
  • src/ package layout -- PyPA standard, prevents accidental local imports

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gis_terminal-0.2.1.tar.gz (6.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gis_terminal-0.2.1-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

Details for the file gis_terminal-0.2.1.tar.gz.

File metadata

  • Download URL: gis_terminal-0.2.1.tar.gz
  • Upload date:
  • Size: 6.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for gis_terminal-0.2.1.tar.gz
Algorithm Hash digest
SHA256 c14fe1342cfb8efdd4ccbf1ec73e8e1ac59d002ef9fa8d5d43f75cd813e5ba7e
MD5 9db57926d56b3e07b0d900fae628e684
BLAKE2b-256 2ad5764aef7ac4adeb2d0dffbf4b876357fd98e6c18658911f46803f411cd205

See more details on using hashes here.

File details

Details for the file gis_terminal-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: gis_terminal-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 23.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for gis_terminal-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 793e35313f7cef30e55cdb3a3a58bd51dcb9eb094b88b7bc8671b6ee08d0fc93
MD5 68a7b480571d398a0eb3e9ed37258ccb
BLAKE2b-256 30e11cbcd189c394e3fd6844e2794c84538f9d4b690e36f530af0bf71266f5d0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page