> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wirekite.io/llms.txt
> Use this file to discover all available pages before exploring further.

# The sumatra shell

> Complete reference for the sumatra command-line shell and the offline sumatra-compile inspector — flags, statements, DSN files, exit codes, and diagnostics.

The toolchain ships two binaries. `sumatra` is the shell — the one
command you use day to day: it compiles programs against your live
database, builds them, runs them, and manages stored procedures.
`sumatra-compile` is an offline inspector for looking at what a program
compiles into, and is never required to run anything.

## The sumatra binary

```text theme={null}
usage: sumatra --dsn <dsnfile> [statement…]
```

There are exactly two flags:

| Flag              | Meaning                                            |
| ----------------- | -------------------------------------------------- |
| `--dsn <dsnfile>` | Path to the DSN file (required for any statement). |
| `--version`       | Print the sumatra version and exit.                |

There are no subcommands and no environment-variable configuration —
statements do everything.

### Interactive mode

Run `sumatra --dsn my.dsn` with no statement and you get a prompt:

```text theme={null}
sumatra shell — @prog.sumatra [args…] · EXEC name(lits…) · DROP PROCEDURE name · help · exit
sumatra>
```

One statement per line. There is no multi-line input, no paste mode, and
no statement terminator at the prompt — source code always lives in
files, never typed into the shell. There is also no SQL passthrough: the
shell speaks Sumatra statements only, and you keep using your normal SQL
client alongside it for queries.

Leave with `exit`, `quit`, or Ctrl-D.

### One-shot mode

Anything after the flags is joined with spaces and parsed as **one**
prompt line; the process runs it and exits with the statement's outcome:

```bash theme={null}
sumatra --dsn my.dsn @nightly_rollup.sumatra
sumatra --dsn my.dsn "EXEC score_accounts(500, 'july')"
```

This is the form for scripts and cron — the exit code is the program's
outcome (see below), so schedulers can branch on it without parsing
output. Quote values that contain spaces exactly as you would at the
prompt: `"EXEC p('North America')"`.

## The statement set

The `help` statement prints the whole surface:

```text theme={null}
  @prog.sumatra [args…]     compile + build + run the file's program (one-shot; never stored)
                        args… = the program's PARAM values, declaration order
                        quote a value containing spaces: @p.sumatra "North America"
                        a CREATE OR REPLACE PROCEDURE file stores + compiles instead
                        (the file IS the CREATE statement; a CREATE takes no args)
  EXEC name(lits…)      run a stored procedure; literals only — 42 · 3.14 · 'text' · TRUE
                        (compiles only when needed, always announced; EXEC p() = zero args)
  DROP PROCEDURE name   delete a stored procedure (+ this host's cache entries)
  help                  this text
  exit                  leave (also: quit, Ctrl-D)
```

### `@prog.sumatra [args…]`

Submits a file. For an ordinary program: compile against the live
catalog → build with `g++` in a temporary directory → run → discard the
binary. Nothing is stored; `@` is the run-once form.

Arguments after the file name are the program's `PARAM` values, in
declaration order. Double quotes group a value containing spaces
(`@p.sumatra "North America"`); `""` is a legal empty value.

If the file's program is a `CREATE OR REPLACE PROCEDURE`, submitting it
**stores** the procedure instead of running anything — the file is the
CREATE statement. A CREATE submission takes no arguments; argument
values belong to `EXEC`.

### `EXEC name(lits…)`

Runs a stored procedure. Parentheses are always required — `EXEC p()`
means zero arguments. Arguments are positional literals only:

* bare tokens: `42`, `3.14`, `2026-01-01`, `TRUE`
* single-quoted text: `'july'`, `'North America'`

There is no escape mechanism for quotes in the current release: a text
value containing `'` cannot be passed and is rejected loudly. `EXEC` is
one statement with no trailing semicolon. Keywords are case-insensitive
and procedure names fold to lowercase.

### `DROP PROCEDURE name`

Deletes the stored procedure's database record and this host's cached
binaries for it. Dropping a name that does not exist is a loud error,
never a silent no-op.

## Exit codes

| Code | Printed at the prompt                                        | Meaning                                                                                       |
| ---- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| `0`  | `Completed (exit 0)`                                         | Ran to the end, or a clean `RETURN;`.                                                         |
| `2`  | `Stopped — STOP handled; committed prefix retained (exit 2)` | A handler caught a fault and chose `STOP`. Every batch committed before the fault is durable. |
| `1`  | —                                                            | Unhandled fault, `RAISE`, compile error, bad arguments, or infrastructure failure.            |

Shell-side failures (bad flags, unreadable files) also exit `1`.

<Note>
  There is one internal code you may observe indirectly: a compiled stored
  procedure refuses to run if the database schema changed since it was
  compiled. The shell reacts by announcing
  `[sumatra] compiling <name> (schema changed)`, recompiling the stored
  source, and rerunning once — see
  [stored procedures](/sumatra/procedures#when-recompiles-happen). You do
  not need to handle this case yourself.
</Note>

## DSN files

A DSN file is one line of text naming the target database:

```text theme={null}
firebolt:///<database>?account_name=<account>&client_id=<id>&client_secret=<secret>&engine=<engine>
```

* The URL scheme selects the backend. `firebolt` is the only registered
  backend in the current release; an unknown scheme is an immediate,
  loud error.
* The database path is required — programs compile against that
  database's catalog, and stored procedures live in it.
* `engine` is optional; without it the system engine is used.
* The file holds a credential: `chmod 600 my.dsn`. In the current
  release the DSN is a plain file — there is no encrypted-DSN or
  stdin-secret mechanism yet.

The shell connects with this DSN to compile and to manage procedures;
each compiled program binary makes its **own** connection from the same
file when it runs.

## Toolchain preflight

Before the first build in a session, the shell verifies the host can
compile: `g++` on PATH, `pkg-config`, libcurl development headers, and
the `runtime/` + `exec/` directories sitting next to the real `sumatra`
binary. Each missing piece fails with a specific install hint, e.g.:

```text theme={null}
g++ not found on PATH — install the g++ package (sumatra compiles the generated C++ on this host)
```

The check is lazy: a host that only runs already-cached stored
procedures never compiles, so it never needs the toolchain.

## sumatra-compile: the offline inspector

```text theme={null}
usage: sumatra-compile [-emit sql|cpp] <file.sumatra>   (use - for stdin)
       sumatra-compile -emit profile                (the backend Profile header; no source file)
```

`sumatra-compile` runs entirely offline — no DSN, no connection. It
compiles against a **built-in sample schema** (the tables of the example
corpus: `sumatra_orders`, `sumatra_customers`, `sumatra_sessions`, and
friends), so it is a way to inspect what programs lower to, not a way to
compile against your own tables — the `sumatra` shell does that against
the live catalog.

| Invocation                               | Prints                                                                                                         |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `sumatra-compile prog.sumatra`           | The server-side SQL the program lowers to (Firebolt dialect). Default, same as `-emit sql`.                    |
| `sumatra-compile -emit cpp prog.sumatra` | The generated C++ for the client-compute route — the code the shell builds and runs.                           |
| `sumatra-compile -emit profile`          | The backend profile header: the semantic constants (rounding, overflow, type widths) the toolchain guarantees. |
| `sumatra-compile -version`               | Version, then exit.                                                                                            |

`-` as the file name reads source from stdin. Compile errors exit `1`;
an unknown `-emit` value exits `2`.

## Diagnostics

Errors are positioned and specific. The shapes you will see:

```text theme={null}
sumatra-compile: parse error 10:5: COMMIT is unwriteable inside a compute loop (spec §2 #1)
lex error 3:14: <message>
sema: <a prose explanation of a semantic error>
catalog: unknown target table "nosuchtable" (not registered)
```

Positions are `line:column`, 1-based. In the shell the same errors are
prefixed with the file name: `sumatra: prog.sumatra: <error>`. Semantic
errors favor prose that names the rule and the fix — for example, a
variable read before it is ever assigned, or an `ORDER KEY` missing from
a chunked read.

## Debugging a running program

Setting the environment variable `SUMATRA_TRACE` (to any value) makes a
compiled program dump each request to stderr: the head of the SQL, the
HTTP status, and up to 2000 bytes of the response body. The shell's
child processes inherit it:

```bash theme={null}
SUMATRA_TRACE=1 sumatra --dsn my.dsn @prog.sumatra 2>trace.log
```

<Warning>
  The trace includes SQL text and raw engine responses — treat the output
  as sensitive, and use it as a diagnostic aid only.
</Warning>
