eudr-check runs the same rules as the web checker, on your own machine. Nothing is uploaded. The one option that uses the network is --forest, and it sends nothing from your file.

Usage

eudr-check <file...> [options]
cat plots.geojson | eudr-check

Files can be GeoJSON, KML, KMZ, GPX, CSV, or a shapefile (the .zip, or the .shp with its .dbf and .prj beside it). Anything that is not GeoJSON is converted first, and every decision the conversion made is printed before the findings.

Options

OptionMeaning
--jsonMachine-readable output, one JSON object per run
--commodity <name>cattle, cocoa, coffee, oil-palm, rubber, soya, wood. Only cattle changes the result
--crs <EPSG>The coordinate system of a file that does not say, e.g. 32630
--country <CC>The country the plots are in, so unlabelled UTM can be recognised
-o, --output <file>Write the converted GeoJSON here (one input file only)
--forestAlso measure each plot's forest cover in 2020 on the JRC's map. A risk indicator; it does not change the exit code
--forest-wms <url>Read the forest map from another server, such as a mirror. Implies --forest
--forest-loss-tiles <template>Read the loss tiles from another server ({z}/{x}/{y}). Implies --forest
--errors-onlyHide warnings and notes
--strictExit non-zero on warnings as well as errors
-q, --quietPrint only the summary line
--no-colorDisable colour
-v, --versionShow the version and the rule-set version

Exit codes

CodeMeaning
0No errors (and, with --strict, no warnings)
1At least one error
2The file could not be read, or the arguments were wrong

Output

plots.geojson

  error This polygon is not closed [GEOM-001]
    why  Every polygon must end where it started. An open shape encloses nothing, and the system rejects it.
    fix  Repeat the first coordinate pair at the end of the ring. This adds no area and is always safe.
    · plot 1, line 27:13, This polygon does not close: it starts at -5.123456, 6.123456 and ends at -5.123456, 6.124456.

  1 plot  ·  1 error, 0 warnings, 0 notes  ·  would be rejected  ·  (Type I, rules 2026.09.2)

With --json, each finding carries ruleId, slug, severity, title, message, whyItMatters, howToFix, fixable, fixId (the automatic fix for it, or null), featureIndex, jsonPath, offset (character range), position (line and column), location (longitude, latitude) and sources; the run carries fileHash (SHA-256), ruleSetVersion, checkedAt and a summary.

Forest in 2020 and loss since

With --forest, each file's findings are followed by the forest check, the same as the web checker's Forest tab: each plot's forest cover in 2020 on the JRC's Global Forest Cover 2020 map (version 4), and the tree cover lost there since on Hansen's Global Forest Change map (v1.13). Plots whose 2020 forest was lost in 2021 or later are listed first:

  Forest cover in 2020 (JRC Global Forest Cover 2020 V4)
    2 of 2 plots had forest on 5 % or more of their area in 2020
    · plot 1 100 % forest, 3.99 of 3.99 ha  Novo Progresso lot 57
    · plot 2 100 % forest, 4.00 of 4.00 ha  Tai edge farm

  Tree cover loss since 2021 (Hansen Global Forest Change v1.13)
    1 of 2 plots lost forest mapped in 2020 in 2021 or later (2.69 ha)
    by year: 2022: 0.43 ha, 2024: 2.26 ha
    · plot 1 2.69 ha of 2020 forest lost in 2022, 2024  Novo Progresso lot 57

To do this, the tool asks the JRC's map server (ies-ows.jrc.ec.europa.eu) and Global Forest Watch's tile server (tiles.globalforestwatch.org) for the maps around your plots, in fixed squares of about 10 km. It does not send plot outlines, coordinates from the file or names. If a server cannot be reached, the file's forest section says so and the rest of the check stands. --forest-wms and --forest-loss-tiles point it at mirrors.

With --json, the run carries a forest object: the dataset (name, version, DOI, licence, citation), the reviewShare (0.05), a summary, and plots with each plot's index, status, method, sampledHa, forestHa, share and band (none, low or review), plus each plot's loss (sampledHa, lossHa, forestLossHa for loss on 2020 forest, byYear and band). The run-level loss summary counts plots by band and sums the hectares by year; lossDataset cites the loss map. When a map could not be read the object carries error instead.

In CI

eudr-check exports/*.geojson --strict --errors-only

fails the job on any error or warning and prints only what failed.

The JSON is the same as the API's /validate response, so code written for one reads the other.

As an MCP server

eudr-check mcp --root ~/plots

runs a local MCP server over stdio, so an AI assistant can check, fix and convert the files in that folder, with the same rules. Files are read from that folder only and never leave your computer; new files are written there and never overwrite one. --forest adds the forest check.