library(gdalviz)library(gdalviz)Modern GDAL (>= 3.11) ships a composable CLI where vector operations chain into pipelines:
gdal vector pipeline ! read ... ! filter ... ! reproject ... ! write ...Pipelines can be saved as .gdalg.json files (the command line without the final write step) and reused as streamed datasets. gdalviz parses these pipelines, validates them against GDAL’s own algorithm contract, and renders them as static or interactive dataflow diagrams for people who think in maps, not command lines.
parse_pipeline() accepts a raw command line, with or without the gdal vector pipeline prefix:
cmd <- paste(
"gdal vector pipeline",
"--config GDAL_NUM_THREADS=ALL_CPUS",
"! read --input parcels.gpkg --input-layer parcels",
"! filter --where \"statefp = '13'\"",
"! make-valid",
"! reproject --output-crs EPSG:4326",
"! write --output parcels.fgb --output-format FlatGeobuf"
)
p <- parse_pipeline(cmd)
p
#> ── <gdalviz_pipeline> ────────────────────────────────── gdal vector pipeline ──
#> global: `--config GDAL_NUM_THREADS=ALL_CPUS`
#> 5 steps:
#> 1. read `--input parcels.gpkg --input-layer parcels`
#> 2. filter `--where "statefp = '13'"`
#> 3. make-valid
#> 4. reproject `--output-crs EPSG:4326`
#> 5. write `--output parcels.fgb --output-format FlatGeobuf`read_gdalg() additionally accepts paths to .gdalg.json files, raw pipeline text files, and pasted multiline bash / PowerShell scripts – line continuations, heredocs, and PowerShell \" quoting are normalized automatically:
script <- "gdal vector pipeline `
read --input parcels.gpkg `
! reproject --output-crs 'EPSG:4326' `
! write --output out.fgb"
read_gdalg(script)
#> ── <gdalviz_pipeline> ────────────────────────────────── gdal vector pipeline ──
#> 3 steps:
#> 1. read `--input parcels.gpkg`
#> 2. reproject `--output-crs EPSG:4326`
#> 3. write `--output out.fgb`The single source of truth for valid steps and arguments is GDAL’s own --json-usage output. A snapshot is bundled with the package, and gdalviz_refresh_contract() regenerates it from your locally installed GDAL.
lint_pipeline() returns one row per issue; validate_pipeline() wraps the result into a pass/fail object:
bad <- "read --input in.gpkg ! reproject ! write --output out.fgb --append --upsert"
lint_pipeline(bad)
#> # A tibble: 2 × 5
#> step_index command level code message
#> <int> <chr> <chr> <chr> <chr>
#> 1 2 reproject error missing_required_args Missing required argument(…
#> 2 3 write error mutually_exclusive_args Arguments --append, --upse…Unknown steps and arguments, missing required arguments, invalid enum choices, and mutually exclusive combinations (like --append + --upsert above) are all reported.
pipeline_graph() turns a pipeline into a renderer-agnostic dataflow model: nodes carry a semantic category (source, filter, geometry, …), a plain-language description, and the propagated feature-stream state (CRS, geometry type, field schema); edges carry “what changed” badges.
g <- pipeline_graph(cmd)
g$nodes[, c("command", "category", "description")]
#> # A tibble: 6 × 3
#> command category description
#> <chr> <chr> <chr>
#> 1 config runtime Runtime configuration (1 config option)
#> 2 read source Read layer 'parcels'
#> 3 filter filter Keep features where statefp = '13'
#> 4 make-valid geometry Repair invalid geometries
#> 5 reproject crs Reproject to EPSG:4326
#> 6 write sink Write to parcels.fgb as FlatGeobufA few GDAL nuances get dedicated treatment:
--config, --progress) group into a single runtime configuration node feeding the source,write; the graph adds an implicit streamed output sink so the flow reads complete,set-field-type chains needed for schema overrides) merge into one stacked node. Opt out with merge_repeated = FALSE.render_reactflow() produces the interactive React Flow widget bundled with the package (no node toolchain required). Drag to pan, scroll to zoom, and click any node to open an inspector with the step’s arguments, the propagated stream state, and a link to its GDAL documentation.
render_reactflow(g, theme = "light", height = 460)Layout direction ("TB", "LR", …), light/dark themes, and the minimap/controls/legend overlays are all arguments. For static output use render_diagrammer() (Graphviz), or render_g6() for an AntV G6 alternative. See the pipeline gallery article for larger real-world examples (tee branching, config-heavy runs, merged schema chains).
Parsed pipelines serialize back out losslessly:
render_command_line(p)
#> [1] "gdal vector pipeline --config GDAL_NUM_THREADS=ALL_CPUS ! read --input parcels.gpkg --input-layer parcels ! filter --where \"statefp = '13'\" ! make-valid ! reproject --output-crs EPSG:4326 ! write --output parcels.fgb --output-format FlatGeobuf"and can be formatted as ready-to-run shell scripts for either bash or PowerShell, optionally reflowing SQL into heredocs:
cat(render_script(p, shell = "bash"))
#> gdal vector pipeline \
#> --config GDAL_NUM_THREADS=ALL_CPUS \
#> ! read --input parcels.gpkg --input-layer parcels \
#> ! filter --where "statefp = '13'" \
#> ! make-valid \
#> ! reproject --output-crs EPSG:4326 \
#> ! write --output parcels.fgb --output-format FlatGeobufas_gdalg() / write_gdalg() produce GDALG JSON specifications directly.