The Satsuma CLI checks your mappings and answers precise questions about them — one field’s lineage, every PII tag, the fields still unmapped. Answers come as readable text or JSON, straight from the parse tree.
validate, fmt and lint are the everyday commands. The rest query a workspace, whether you run them yourself, from CI, or through an AI assistant.
The CLI reports facts from the parse tree. It never interprets natural language. It also powers the VS Code extension's diagnostics, lineage views, and code intelligence.
# Check a mapping $ satsuma validate examples/sfdc-to-snowflake/pipeline.stm valid — 0 errors, 0 warnings # Summarise the workspace $ satsuma summary examples/sfdc-to-snowflake/pipeline.stm Workspace Summary examples/sfdc-to-snowflake/pipeline.stm Schemas: 8 Mappings: 5 Metrics: 2 Fragments: 1 Files scanned: 6 $ satsuma lineage --from loyalty_sfdc loyalty_sfdc -> sat_customer_demographics (loyalty to demographics) -> mart_customer_360 (demographics to mart)
These three are the commands you will run most. Use them before committing, in CI, or from the editor; the VS Code extension runs them too.
"Is my workspace well-formed?"
Checks parse errors, undefined schema references, missing fields, and invalid paths. Run it before every commit.
$ satsuma validate examples/sfdc-to-snowflake/pipeline.stm valid — 0 errors, 0 warnings $ satsuma validate --json { "valid": true, "errors": 0, "warnings": 0 }
"One canonical style, zero config."
Opinionated formatter backed by the tree-sitter CST. Semantics-preserving. Use --check in CI.
$ satsuma fmt examples/sfdc-to-snowflake/pipeline.stm Formatted 1 file(s) $ satsuma fmt --check examples/sfdc-to-snowflake/pipeline.stm 0 file(s) would be reformatted $ satsuma fmt --diff mapping.stm
"Does this follow best practices?"
Policy and convention checks with --fix for safe autofix. Catches hidden NL dependencies and duplicate definitions.
$ satsuma lint --fix Fixed 2 issue(s) $ satsuma lint --rules hidden-source-in-nl (fixable) unresolved-nl-ref duplicate-definition
Each command answers one structural question. Combine them for bigger jobs — impact analysis, PII audits, coverage checks — whether you run them yourself or an AI assistant runs them for you.
You can trace any data element from source to destination across the whole workspace. Start with lineage for schema-level paths, then drill into arrows for field-level detail.
When an arrow is classified as nl, its natural-language intent needs a reader to interpret it. When it's structural, the transform pipeline is fully specified — no interpretation needed.
lineage --from traces all downstream consumers of a schema
arrows --as-source follows each field through its transforms
nl extracts NL intent at [nl] hops for a reader to interpret
where-used finds every reference to a schema or fragment
# Schema-level: where does this data go? $ satsuma lineage --from loyalty_sfdc loyalty_sfdc -> sat_customer_demographics -> mart_customer_360 # Field-level: trace LoyaltyTier through transforms $ satsuma arrows loyalty_sfdc.LoyaltyTier --as-source --json { "target": "sat_customer_demographics.loyalty_tier", "classification": "structural", "transform": "UPPER | TRIM" } # Follow the chain — next hop is NL $ satsuma arrows sat_customer_demographics.loyalty_tier --as-source [nl] loyalty_tier -> mart_customer_360.tier_label "Map Gold/Silver/Bronze to internal codes" # Agent reads the NL and decides what to do
Satsuma uses natural-language strings for intent that can't be expressed as deterministic pipelines. The nl command extracts these verbatim — notes, transform descriptions, and comments — so you, or an assistant, can review, critique or summarise them.
Use this to review business logic, check if NL descriptions match the structural transforms around them, identify ambiguities, or generate documentation from the intent strings.
@ref references in NL are machine-extractable — the CLI traces them
# All NL content in a mapping $ satsuma nl 'demographics to mart' mart_customer_360.full_name [transform] "Concatenate first and last name from `@ref sat_customer_demographics`" mart_customer_360.tier_label [transform] "Map Gold/Silver/Bronze to internal codes per the tier mapping in `@ref lookup_tiers`" mart_customer_360 [note] "This mart combines demographic and loyalty data into a single customer view for BI" # Field-level NL only $ satsuma nl mart_customer_360.email "Hash with SHA-256 before loading into the mart. Original plaintext stays in the sat."
Satsuma's metadata system is open-ended — any word can be a tag. An AI assistant uses meta and find --tag to extract these, then combines them with your organisation's guidelines to drive code generation.
For example, if your team follows the Data Vault standard, an assistant reads pk, bk, hash_diff tags from schema metadata and generates hub, satellite, and link DDL accordingly. If your team uses pii and encrypt tags, it knows to emit encryption logic.
The CLI doesn't know what hash_diff means — it just extracts the tag. An assistant that has read your organisation’s standards interprets it.
# Read metadata on a target schema $ satsuma meta hub_customer hub_customer customer_hk (pk, hash_key) customer_bk (bk, required) load_date (required) record_source (required) # Find all PII fields across the workspace $ satsuma find --tag pii --json [ { "schema": "loyalty_sfdc", "field": "Email", "tags": ["pii", "encrypt"] }, { "schema": "loyalty_sfdc", "field": "SSN", "tags": ["pii", "encrypt", "mask"] } ] # Agent reads your org's Data Vault standard, # sees pk + hash_key, and generates: # CREATE TABLE hub_customer ( # customer_hk BINARY(32) NOT NULL, # customer_bk VARCHAR(255) NOT NULL, # ...
For complex analysis, graph --json exports the complete semantic graph in a single call — all nodes, edges, field-level data flow, and unresolved NL arrows. Load it once and analyse it however you need, with no further calls.
--schema-only and --no-nl reduce payload for large workspaces
--namespace scopes the export to a single namespace
unresolved_nl section surfaces all NL arrows awaiting interpretation
$ satsuma graph examples/sfdc-to-snowflake/pipeline.stm --json { "nodes": [ { "name": "loyalty_sfdc", "type": "schema" }, { "name": "sat_customer_demographics", ... }, { "name": "mart_customer_360", ... } ], "schema_edges": [ { "from": "loyalty_sfdc", "to": "sat_customer_demographics", "role": "source" }, ... ], "edges": [ ... ], "unresolved_nl": [ ... ] } # Narrow scope for large workspaces $ satsuma graph examples/sfdc-to-snowflake/pipeline.stm --json --namespace warehouse
"What breaks if I change this field?"
$ satsuma arrows loyalty_sfdc.LoyaltyTier --as-source --json $ satsuma arrows sat_customer_demographics.loyalty_tier --as-source --json $ satsuma nl mart_customer_360.loyalty_tier
"Does PII survive through the pipeline unencrypted?"
$ satsuma find --tag pii --json $ satsuma arrows loyalty_sfdc.Email --as-source --json $ satsuma nl mart_customer_360.email
"Which target fields have no mapping?"
$ satsuma fields mart_customer_360 --unmapped-by 'demographics to mart' $ satsuma fields mart_customer_360 --unmapped-by 'online to mart'
"Match source to target and write the mapping"
$ satsuma match-fields --source loyalty_sfdc --target sat_customer $ satsuma nl sat_customer $ satsuma meta sat_customer.country_code
satsuma agent-reference prints a compact reference for AI assistants: the Satsuma grammar, the CLI commands and the recommended ways of working. Add it to your assistant’s instructions file.
Append the reference to whichever file your assistant reads at startup. This works with Claude Code, Copilot, Cursor, Windsurf, or any assistant that reads its instructions from a file.
# Claude Code $ satsuma agent-reference >> CLAUDE.md # GitHub Copilot $ satsuma agent-reference >> .github/copilot-instructions.md # Cursor $ satsuma agent-reference >> .cursor/rules/satsuma.mdc # Or paste into any conversation $ satsuma agent-reference | pbcopy
.stm files
satsuma agent-reference with no flags always prints the whole document — that never changes, so anything already piping it keeps working. If your assistant only writes Satsuma or only reads it, give it just that part:
# Generating or converting into Satsuma — grammar, conventions, examples $ satsuma agent-reference --profile write >> AGENTS.md # Tracing lineage, coverage, or impact in an existing workspace $ satsuma agent-reference --profile read >> AGENTS.md # List every section's id and size $ satsuma agent-reference --list
Download a prebuilt package from the v0.14.0 release and install globally with npm.
# Universal — works on macOS, Linux, and Windows (WASM-based) $ npm install -g https://github.com/EqualExperts/satsuma-lang/releases/download/v0.14.0/satsuma-cli-v0.14.0.tgz $ satsuma --help satsuma <command> [options] 23 commands available
# Universal — works on macOS, Linux, and Windows (WASM-based) $ npm install -g https://github.com/EqualExperts/satsuma-lang/releases/download/latest/satsuma-cli-latest.tgz
All commands accept --json for structured output and --help for usage details. Many support --compact for minimal output.
This page shows how the commands fit together, not a catalogue of all 23. They fall into a few families — block extractors like summary and schema, fine-grained primitives like arrows and meta, the one-shot graph export, and the human-facing analysis trio above — but the fastest way to get the exhaustive, always-current list is to ask the CLI itself.
satsuma agent-reference gives an AI assistant this same list with usage patterns included, so it rarely needs --help at all.
$ satsuma --help satsuma <command> [options] Workspace extractors summary, schema, mapping, metric, lineage, ... Structural primitives arrows, nl, meta, fields, coverage, ... Graph export graph --json | --compact | --schema-only Analysis fmt, validate, lint, diff Agent setup agent-reference # 23 commands total — run --help on any of them for full usage
Transform strings, notes, and comments are extracted verbatim. The CLI never assesses whether an NL transform is correct or complete.
There are no impact or audit commands. These are workflows built from smaller commands — including coverage, which reports one schema's mapped/unmapped fields but doesn't itself trace impact or run an audit.
The CLI is deterministic, fast, and reproducible. Same input, same output, every time.
Commands take explicit structural arguments. You, or your assistant, choose which commands answer a question.
One npm package that runs on every platform. Install it, then run satsuma validate on your first mapping.