Commands
SAL commands operate on a Git-backed project and the generated data under .sal/data.
For a step-by-step flow, start with Getting Started.

sal init
Section titled “sal init”Initializes a SAL project in the current Git repository. The repository must not be your home directory and must already have a Git remote.
sal init creates:
.sal/datain the project for generated data.~/.sal/cachefor user-level cache data.~/.sal/config.jsonldfor user-level SAL configuration.- A
.gitignoreentry for.sal/data.

sal validate
Section titled “sal validate”Validates RDF source files without committing a new data product. Use it while editing Turtle or JSON-LD files:
sal validate data/Important flags:
--prefix-maps: apply prefix mappings assource=targetentries or source/target pairs.--format: chooseicebergornq; defaults toiceberg.--no-cache: clear SAL’s temp cache before validating, while still caching new fetches during the run.
An undefined term is reported with the file and the line number it appears on:

Validating a file that references a SAL module clones and builds that module so its vocabulary can be checked.
sal validate does not run module tasks; only sal build does.
sal build
Section titled “sal build”Validates RDF source files and writes the merged graph into the local data product.
sal build data/By default, sal build requires a clean Git working tree.
Use --force only for test or debugging builds.
Important flags:
--prefix-maps: apply prefix mappings before validation.--format: chooseicebergornq; defaults toiceberg.--typed: split distinct RDF data types into separate output columns.--force: build even when the Git working tree has uncommitted changes.--no-cache: clear SAL’s temp cache before building, while still caching new fetches during the run.
Only triples that are not already in the table are committed, so rebuilding unchanged sources creates no new snapshot:

sal build also materializes any SAL module the source files reference.
It clones each referenced module, builds the Dockerfile in its repository root, runs the task instance
declared in the RDF, and merges the triples the module produced into the data product.
See Using SAL Modules.
See Data Layout for the generated table structure.
sal query
Section titled “sal query”Opens an interactive SQL shell with a triples view over the built Iceberg table.
DuckDB is linked into sal, so nothing has to be installed alongside it.
sal query
The shell opens on the requested info query and leaves the triples view there to
explore. Ctrl + R runs the editor’s statement, Ctrl + H lists the other keys,
and Ctrl + D exits.
Info modes:
head: show the first rows fromtriples.properties: show Iceberg table properties.snapshots: show Iceberg snapshots and SAL Git tags.column-stats: show Iceberg column statistics.
To compare snapshots:
sal query --snapshot-diff latestsal get
Section titled “sal get”Looks up the RDF resources inside a built data product.
Where sal query is about the Iceberg table that stores the triples, sal get is about the RDF the table describes.
sal get classes
Section titled “sal get classes”Lists every class the data product types a resource with, most instantiated first:
sal get classesclass instanceshttps://schema.org/Organization 75http://www.w3.org/ns/dcat#Dataset 2https://schema.org/AdministrativeArea 1A class is the object of an rdf:type statement, and instances counts the distinct subjects declared to be of that class.
sal get datatypes
Section titled “sal get datatypes”Lists every datatype the data product declares, with the annotations each one carries:
sal get datatypesdatatype label commenthttps://w3id.org/sal/cgs-earth/sal-module-spec/salmodule#inbou... Inbound Listener Literal representing a [host:]<port>https://w3id.org/sal/cgs-earth/sal-module-spec/salmodule#outbo... Outbound Endpoint Literal representing a URL or <host>:<port>A datatype is a subject declared to be an rdfs:Datatype, so a data product that only holds instance data lists none.
rdfs:label and rdfs:comment are optional; a column that no datatype states is left out of the table entirely.
Note that this lists the datatypes a data product defines, not the datatypes its literals are tagged with.
The built triples table stores the lexical value of a literal rather than its datatype IRI, so ^^xsd:date and friends cannot be listed back out of it.
sal get instances
Section titled “sal get instances”Lists every resource the data product instantiates, with the class it is typed with:
sal get instancesinstance classhttps://geoconnex.us/ref/dams/1078 http://www.w3.org/ns/dcat#Datasethttps://geoconnex.us/ref/dams/1079 http://www.w3.org/ns/dcat#Datasethttps://example.org/org/reclamation https://schema.org/OrganizationWhere sal get classes counts the instances of each class, this lists them.
A resource typed with several classes is listed once per class.
The class is not required to be declared an rdfs:Class or an owl:Class in the data product, since a data product commonly types its resources with a vocabulary it does not itself carry.
What is left out is the other direction: a subject that is itself an rdfs:Class, owl:Class, rdf:Property, owl:ObjectProperty, owl:DatatypeProperty, owl:AnnotationProperty, rdfs:Datatype, or owl:Ontology describes the schema rather than instantiating it, so it is not reported as an instance.
sal describe
Section titled “sal describe”Shows every statement the data product makes about one subject:
sal describe https://github.com/cgs-earth/sal/Bobpredicate objecthttp://schema.org/jobTitle Professorhttp://schema.org/name Jane Doehttp://schema.org/url http://www.janedoe.comhttp://www.w3.org/1999/02/22-rdf-syntax-ns#type http://schema.org/PersonThis is the <subject> ?p ?o pattern, so it is a filter on the subject column rather than a SPARQL query.
A subject with no scheme is a term the project defined itself, so it is resolved against the project base the same way sal build resolves a relative term in the project’s RDF. In a checkout of https://github.com/cgs-earth/sal, the command above can be written as:
sal describe BobThe project base comes from the git remote, so a relative subject only works inside a checkout that has one.
A prefixed name such as schema:Bob is not expanded; a scheme is what makes a subject absolute, and schema: is one.
An IRI copied out of Turtle or a SPARQL pattern can be passed with the angle brackets it is written in:
sal describe '<https://geoconnex.us/ontologies/method/pastor>'A subject with no statements is reported rather than printed as an empty table.
sal serve
Section titled “sal serve”Serves the built triples table as a read-only SPARQL endpoint on port 8080:
sal serveThe endpoint implements the SPARQL Protocol query operation at /sparql.
It accepts GET requests with a query parameter and POST requests using either application/sparql-query or application/x-www-form-urlencoded, and it answers with application/sparql-results+json.
--with-ui
Section titled “--with-ui”Adds a web UI at / alongside the SPARQL endpoint:
sal serve --with-uiThe UI is a React app compiled into the sal binary, so it works offline and needs no extra install.
It has five tabs:
- Stats: triple, subject, predicate, and object counts, plus the Iceberg snapshots, table properties, and column statistics that
sal query --infoprints. - SQL: a DuckDB editor over the same
triplesviewsal queryopens, with sample queries andCtrl/Cmd+Enterto run. - SPARQL: a YASGUI editor pointed at the local
/sparqlendpoint. - Modules: the browser form of
sal salmodule inspect. Enter a module reference and the JSON-LD ontology it publishes is shown as formatted JSON. Every module the build downloaded is offered as a chip and as an autocompletion in the input, read from thesal.salmodulestable property. - Map: reserved for rendering the
object_geometrycolumn. Not implemented yet.
Enabling the UI also exposes the JSON endpoints it reads:
POST /api/sqlwith a{"sql": "..."}body runs a DuckDB statement and returns its header and rows. Results are capped at 1000 rows, and the response message reports the full count when it truncates.GET /api/statsreturns the counts and Iceberg metadata shown on the Stats tab, including themoduleslist the Modules tab suggests from.GET /geometries?limit=&offset=returns up to 100object_geometryvalues at a time as GeoJSON.GET /api/salmodule?module=clones, builds, and runs a SAL module, returning{"module": ..., "ontology": ...}. The first request for a module has to build its image, so it can take minutes.
/api/sql runs arbitrary DuckDB statements against your machine, and /api/salmodule builds and runs container images from repositories a caller names, so only enable --with-ui on a network you trust.
sal push
Section titled “sal push”Publishes .sal/data as an OCI artifact:
sal push ghcr.io/my-org/my-data-product --username "$OCI_USERNAME" --password "$OCI_PASSWORD"SAL uploads generated data files as OCI layers and annotates the artifact with the source Git remote and current commit hash. See Publishing Data.
sal clone
Section titled “sal clone”Restores a published OCI artifact and its source repository:
sal clone ghcr.io/my-org/my-data-product:latestSAL reads the artifact metadata, clones the recorded source repository, checks out the recorded commit, runs sal init, and restores the artifact layers into .sal/data.
Use --destination to choose the local clone path.
sal pull
Section titled “sal pull”Pulls data from an OCI artifact.
It uses the same artifact retrieval command shape as sal clone.
sal upload
Section titled “sal upload”Uploads the built data product to an object store:
sal upload --bucket gs://my-bucket/sal/triplesSAL stages a temporary copy, rewrites staged Iceberg metadata to point at the target location, then uploads data and metadata in reader-friendly order. See Publishing Data.
sal edit
Section titled “sal edit”Rewrites local Iceberg metadata so a copied table can be read from a new table root:
sal edit --new-table-root gs://my-bucket/sal/triplesThis command changes metadata references only. It does not rewrite Parquet data files.
sal clean
Section titled “sal clean”Removes or reshapes local build artifacts.
Use --wipe to delete the local data product, or --squash to condense local snapshots ahead of a remote artifact.
sal salmodule
Section titled “sal salmodule”Outputs SAL module information.
The ontology subcommand prints SAL’s ontology information, and run runs a SAL project.
See the SAL Module TTL Spec for the Turtle source.
The inspect subcommand prints the ontology that a remote module publishes:
sal salmodule inspect salmodule://github.com/adplincinst/sample-salmodule-1SAL clones the module’s repository, builds the Dockerfile in its root, and runs the module’s ontology command, printing the JSON-LD it returns.
Docker’s layer cache makes inspecting an unchanged module cheap after the first build.
The salmodule:// scheme is optional, so adplincinst/sample-salmodule-1 and the repository’s HTTPS URL both work.
A host is only needed for modules that are not on GitHub.
The same thing is available in the browser from the Modules tab of sal serve --with-ui.
sal test
Section titled “sal test”Reserved for tests on built SAL data products. This command is not yet implemented.