Discover API specs across repositories and emit one draft
Lathe sources.yaml, plus an audit report
and human-readable gaps.
lathe-scan is local, offline, and read-only with respect to scanned inputs. It
aggregates APIs from multiple repositories without executing their code or
generating a CLI. Lathe consumes the output only after human confirmation.
go install github.com/lathe-cli/lathe-scan@latest
# From a clone
make build
./bin/lathe-scan --versionGo 1.25 or newer is required when building from source.
Run the scan from a Lathe application repository (one with go.mod and
cli.yaml; lathe init creates it) and point --out at its specs/
directory, which is where Lathe reads sources.yaml by default:
# Build one manifest from multiple services
lathe-scan ../billing ../inventory --out ./specs
# Add or refresh a service while preserving existing entries and policy
lathe-scan ../shipping --out ./specs --merge
# Generate a CLI after reviewing specs/sources.yaml and specs/GAPS.md
lathe bootstrapAny other --out works too; pass it explicitly when generating:
lathe bootstrap -sources <out>/sources.yaml. Relative local_path entries
resolve against the directory containing sources.yaml, so the scan output
directory moves as one unit.
Inputs may be repository directories or .zip archives. Discovery supports:
- OpenAPI 3, Swagger 2, Proto, GraphQL, and Postman collections. OpenAPI and Swagger documents are recognized by content, whatever the file is named.
- Static route extraction for FastAPI, Flask, Django, Spring, NestJS, Express, Fastify, Gin, Echo, Chi, Rails, Laravel, ASP.NET, Ktor, Actix, and Axum.
An existing native spec takes precedence over static extraction. Unresolved or unsafe assumptions are reported, not silently guessed.
lathe-scan <input>... --out <dir> [--name <source>] [--prefer <backend>] [--merge] [--force] [--json]
--outselects the output directory and is required.--nameoverrides the name when exactly one source is recommended.--prefer openapi3|swagger|proto|graphqlbreaks otherwise equal backend choices; it never outranks a source that would generate more commands.--mergeupdates sources owned by the scanned inputs while preserving foreign sources and hand-written policy. A failed input keeps its previous entries.--forcepermits writing into a non-empty output directory.--jsonalso printsreport.jsonto stdout.
Run lathe-scan --help for the current flag reference.
Exit codes are 0 for at least one usable source, 1 for usage errors, 2 when
nothing usable is found, and 3 for write failures.
<out>/
sources.yaml # draft Lathe source map
report.json # candidates, provenance, confidence, and gaps
GAPS.md # blocking and advisory review items
<source>/... # copied material for local_path sources
Only the recommended candidate for each logical source is emitted. Historical
or alternate candidates for that source remain in report.json and GAPS.md;
independent APIs are emitted separately. Both audit files are still written for
an empty result. Identical inputs produce deterministic manifests and reports.
--merge never widens a hand-trimmed GraphQL exposure policy. It also never
deletes copied directories from earlier runs; only sources.yaml may be
rewritten or removed when the current result requires it.
- Design defines architecture, merge, confidence, and safety contracts.
- Contributing covers development commands and pull requests.
Apache License 2.0 © lathe-cli