Ion Fusion Documentation
Release 0.38a1-SNAPSHOT (2026-04-16T19:45:37.790Z)

About the fusion CLI

The fusion command-line interface is intended to support evaluation of Fusion code across a variety of use cases. It provides a number of commands that can be composed in a sequence of steps within a single execution of the CLI.

⚠️ This document is a work in progress! We'd love to hear your feedback in this Discussion thread.

The fusion executable requires at least one argument: a command to perform.

% fusion
No command given.
Type 'fusion help' for more information.

To see the possible commands, use the help command:

% fusion help

Usage: fusion [OPTIONS ...] <command> [ARGS ...] [; <command> [ARGS ...]] ...

Type 'fusion help <command>' for help on a specific command.

Available commands:
  repl             Enter the interactive Read-Eval-Print Loop.
  load             Load and evaluate a script.
  eval             Evaluate an inline script.
  require          Import bindings from a Fusion module.
  report_coverage  Generate a code coverage report.
  -----            -------------------------
  help             Describe the usage of this program or its commands.
  version          Writes version information about this program.

...and so on.

Passing Options

As shown above, the CLI follows the command/subcommand pattern common in modern projects. To tune behavior, it supports options following both the fusion executable name (so-called "global options"), affecting the entire execution, and following an individual command, affecting just that segment.

Options start with "--", and come in three forms:

--key=value
--key value
--key

The first two forms are used for all non-boolean option types. The third form is used for boolean options, which are always set to true when present on the command line.

When using the first form above, the entire form must be a single word (from the perspective of your shell), without whitespace around the "=".

No sanity checking is performed on the value, so if you type...

--key = value

...the option named "key" will get the value "=".

Evaluating an Inline Expression

The most straightforward use case for the CLI is to evaluate some code provided on the command line. The command for this is eval, mirroring the Fusion procedure eval. Here's a trivial example:

% fusion eval '(+ 1 2)'
3

The output (to stdout) of an eval command is the value returned by its final expression, using the format defined by write, which renders non-Ion data using a non-Ion but human-understandable syntax:

% fusion eval "{ first: first, last: (quote last) }"
{first:{{{procedure 'first'}}},last:last}

While eval only accepts a single argument, that argument string can contain multiple top-level syntax forms:

% fusion eval '(define now (timestamp_now)) (displayln "The year is " (timestamp_year now))'
The year is 2025

If the final result is void, it is ignored. That's the case above: the output is emitted by displayln, which returns void so nothing else is rendered.

Running a Script

Since it's awkward to pass nontrivial code to eval through the command line, it is perhaps more common to evaluate a script on the local file system. The command for this is load, mirroring the Fusion procedure of the same name. Suppose you have a script in the current directory called script.fusion:

% cat script.fusion
(define (add1 num)
  (+ 1 num))
(add1 252)

You can run this script with the following command:

% fusion load script.fusion
253

ℹ️ The script doesn't write the result seen above; that's done by the CLI-level load command.

Of course, you're likely to be processing some input, so the CLI ties its standard input stream to the current input port used during evaluation, and you can consume that stream as Ion data using the read procedure to parse one value at a time:

% cat add1.fusion
(define (add1 num)
  (+ num 1))
(add1 (read))

% echo 41 | fusion load add1.fusion
42

Running Multiple Commands

So far, each invocation of the CLI runs a single command, evaluating a single script or program fragment. However, in many scenarios it's helpful to evaluate several program fragments in sequence. The CLI accommodates this by breaking its arguments into segments, each containing one command.

In general, an invocation of the fusion CLI:

Because all commands share the same namespace, the side effects of each command are visible to those that follow. For example, suppose that you want to invoke a library procedure that's not provided by /fusion (the module whose exports are used to bootstrap the namespace):

% fusion eval '(unsafe_list_add [] "new")'
Bad syntax: unbound identifier. The symbol 'unsafe_list_add' has no binding
where it's used, so check for correct spelling and imports.

To access that function, you need to require it into the namespace. You can accomplish this by evaluating more than one expression:

% fusion eval '(require "/fusion/unsafe/list") (unsafe_list_add [] "new")'
["new"]

That can be awkward, though, so you can instead use two eval commands:

% fusion eval '(require "/fusion/unsafe/list")' ';' eval '(unsafe_list_add [] "new")'
["new"]

ℹ️ The quotes around the semicolon prevent it from being interpreted by your shell (like Bash).

To better support this pattern, the CLI has a require command that's easier to use from a shell script:

% fusion require '/fusion/unsafe/list' ';' eval '(unsafe_list_add [] "new")'
["new"]

The load command also shares the common namespace, so you can do things before or after running a script. The next example redefines + within the namespace to perform subtraction; the new definition takes precedence when + is referenced in the definition of add1:

% echo 100 | fusion eval '(define + -)' ';' load add1.fusion
99

ℹ️ The primary difference between eval and load is whether the source code comes from the command line or the file system.

Using an Ion Catalog

One of the flagship features of the Amazon Ion data format is its ability to extract common symbols into separate data structures called shared symbol tables. To use a shared symbol table when decoding data, it must be available to the Ion implementation in a catalog, which is simply an abstraction for a set of shared symbol tables indexed by name and version.

To accommodate this, the Fusion CLI provides a simple, static catalog interface via the file system. The global --catalogs option gives the CLI file paths that contain shared symbol tables. If a given path is a file, it must contain (only) shared symbol tables in their canonical serialized form. When a path is a directory, it is traversed recursively and all files are added to the catalog.

To declare multiple catalog files/directories, the --catalogs option can be given more than once, and/or one --catalogs option can declare multiple paths using the OS-specific path separator:

$ fusion --catalogs catalog.ion --catalogs /Users/susan/.ion/catalog/ ...
$ fusion --catalogs catalog.ion:/Users/susan/.ion/catalog/ ...

The REPL

TODO