Skip to main content
Markdown

Exaloop CLI

The exaloop CLI builds Codon projects, runs their tests, and packages applications for deployment. It accepts Codon compiler commands and adds project configuration, SDK selection, profiling, and optimization. Its Python environment is bundled with the distribution; native applications do not require that environment to run.

For a first working project, follow the quickstart. Use this page to look up the compiler commands, SDK registration, project configuration, server builds, Python extensions, SDK tools, and testing and packaging.

Install​

The installation guide covers the tarball supplied by Exaloop. Once installed, the CLI and its SDK registrations are ready to use:

Terminal
exaloop --help
exaloop plugin list

Codon Compatibility​

Replace codon with exaloop for ordinary compiler commands:

Terminal
exaloop run -release program.codon argument1 argument2
exaloop build -release -o program program.codon
exaloop build -llvm program.codon
exaloop doc src/
exaloop jit
exaloop jupyter connection.json

Codon's -plugin and other compiler options remain available. Use exaloop build --help for compiler help, or exaloop doctor to see which compiler and SDKs will be used.

Wrapper options precede the command. Nothing following run is reparsed as an Exaloop option, so application arguments such as --with remain intact.

Terminal
exaloop --codon "$HOME/.codon/bin/codon" run program.codon
exaloop --with data --with kafka build -release processor.codon
exaloop --dry-run --with kafka build consumer.codon

--verbose prints the command before executing it. --dry-run prints the planned commands without creating files or invoking the compiler. Avoid passing credentials in command arguments, especially with verbose logging; use the application's environment or a protected runtime configuration instead.

Register SDKs​

Skip manual registration for SDKs supplied by your active all-SDK distribution. Register trusted, built or installed SDK directories containing plugin.toml:

Terminal
exaloop plugin add kafka --path /opt/exaloop/kafka
exaloop plugin add data --path /opt/exaloop/data
exaloop plugin list
exaloop plugin inspect kafka
exaloop plugin remove kafka

Registration gives an installed SDK a name; it does not download or copy it. Select that name with --with or add it to a project's plugins list. Use --replace to update a registration after moving an SDK. Removing a registration leaves its files intact.

The CLI checks selected SDKs before compilation, but they must still come from a trusted source and match your compiler. Run exaloop doctor after changing your toolchain.

Application and Server Builds​

Terminal
exaloop --kind postgres-udf build -release functions.codon -o dist/functions.so
exaloop --kind duckdb-extension build functions.codon -o dist/functions.duckdb_extension
exaloop --kind redis-module build commands.codon -o dist/commands.so
exaloop --kind mysql-udf build functions.codon -o dist/functions.so
exaloop --kind kafka-consumer build -release consumer.codon -o dist/consumer
KindAutomatically selected SDKOutput
nativeNoneCodon's selected output format
python-extensionNoneImportable CPython module; an installable wheel when packaged
aws-lambdaaws-lambdaNative handler; Linux container build context and SAM template when packaged
duckdb-extensionduckdbDuckDB extension with native metadata
postgres-udfpostgresShared library, SQL, and extension control file
mysql-udfmysqlShared library, registration and removal SQL
redis-moduleredisRedis-loadable module
kafka-producerkafkaNative executable
kafka-consumerkafkaNative executable
kafka-processorkafkaNative executable

Server builds default to release mode and Python numerics. They accept -debug, -release, -numerics=py|c, -o, and repeated -plugin arguments. Native and Kafka builds keep Codon's defaults.

A successful server build produces a library, not a running service. Follow the database's guide to install the library and register its functions; the build command does not change a server.

For AWS Lambda, use a named aws-lambda target. run event.json invokes a compiled handler locally; package requires a matching Linux environment and bundles its runtime dependencies automatically.

Python Extensions​

Exaloop compiles and links Codon modules for Python without a setup.py, Python headers, or setuptools in the destination environment. Start with an exported, typed add(left: int, right: int) -> int function:

Terminal
exaloop init fastmath --kind python-extension --name fastmath
cd fastmath
python3 -m venv .venv
exaloop --target fastmath package --python .venv/bin/python
.venv/bin/python -m pip install packages/fastmath/*.whl
.venv/bin/python -c 'import fastmath; print(fastmath.add(20, 22))'

package builds the module, collects its non-system native runtime dependencies, rewrites their loader paths, and writes a wheel under packages/NAME/. Runtime bundling is automatic for Python extensions. Installing the wheel does not require Exaloop or Codon. Each package destination must be new; use --output packages/fastmath-v2 when packaging another version.

For development, build only the importable module:

Terminal
exaloop --target fastmath build --python .venv/bin/python
PYTHONPATH=dist/fastmath .venv/bin/python -c 'import fastmath; print(fastmath.add(20, 22))'

Exaloop generates the interpreter's ABI filename, such as fastmath.cpython-312-darwin.so. For this kind, output and build -o specify an output directory, defaulting to dist/NAME/ for a named target and dist/ otherwise. Dotted modules such as acme.fastmath create matching namespace-package directories. A standalone build is also supported:

Terminal
exaloop --kind python-extension build fastmath.codon --python .venv/bin/python -o dist

Configure persistent module and wheel settings in the target:

Configuration
[targets.fastmath]
kind = "python-extension"
source = "fastmath.codon"
codon_args = ["-release"]

[targets.fastmath.options]
module = "fastmath"
distribution = "fastmath"
version = "0.1.0"
python = ".venv/bin/python"

module defaults to the source basename, distribution to its top-level module, and version to 0.1.0. python defaults to Exaloop's own interpreter, which may be different from your application's Python. Both build --python and package --python override it. Build accepts --module, -debug, -release, -numerics=py|c, and repeated -plugin arguments. Project plugins and wrapper --with selections work as usual. Use doctor with the target selected to check the configured interpreter, linker, and Codon runtime.

Build separately for each GIL-enabled CPython version and architecture. Supported hosts are macOS and Linux with CPython 3.9 or newer. Wheels are platform-specific, not abi3, universal2, or manylinux wheels; the build host's OS/libc baseline and SDK requirements still apply. Codon source is compiled for a generic CPU on the host architecture. Native libraries loaded dynamically need an explicit package --runtime-library PATH; Python dependencies and application data are managed separately. Distribution license inventories are included when building with an Exaloop distribution; review redistribution requirements for custom toolchains and additional libraries. See production deployment.

Projects​

Create a starter project, without overwriting existing files:

Terminal
exaloop init events --kind kafka-consumer
exaloop --project events --target app build
exaloop --project events --target app run localhost:9092 readers events 1000

This creates a consumer project and runs it against the events topic until it has processed 1,000 records. Create the topic first and adapt the connection settings for your cluster. The Kafka guide explains processing, commits, and recovery.

init supports every build kind in the table above. Use --name to choose the target and source name; server targets need lowercase identifiers such as scoring_udf.

Projects use exaloop.toml, discovered in the current directory or its ancestors:

Configuration
[targets.scoring]
kind = "postgres-udf"
source = "scoring.codon"
plugins = ["data"]
codon_args = ["-release"]

[targets.scoring.options]
schema = "analytics"
version = "0.1.0"

[targets.events]
kind = "kafka-consumer"
source = "events.codon"
codon_args = ["-release"]

Use --project DIRECTORY_OR_FILE to select a project, or --no-project to disable discovery. Targets are never selected implicitly. Relative project paths are resolved from the manifest's directory; named-target commands run there as well. Project plugin paths override user registrations.

Compiler selection is --codon, then project toolchain.codon, then EXALOOP_CODON, then codon on PATH. --stdlib overrides toolchain.stdlib; otherwise an inherited CODON_PATH remains intact. Always select a compiler, standard library, and runtime from the same distribution.

Target output defaults to dist/NAME/NAME, with the appropriate server suffix. Python extensions instead use the output-directory convention described above. Set output in the target to override it. For build, command-line -o, -debug/-release, and -numerics override their target defaults. Other Codon flags follow Codon's own combination rules. For a named-target run, arguments after run are application arguments; compiler flags belong in codon_args.

Host settings belong in the target's options table:

KindAvailable settings
DuckDBplatform, version
PostgreSQLschema, version
MySQLmysql_config
Python extensionmodule, python, distribution, version

These settings do not cross-compile code. In particular, DuckDB's platform sets extension metadata; it must describe the platform actually being built. PostgreSQL uses the matching host tooling recorded in its SDK.

SDK Tools​

Run the SDK's generators and builders through the same CLI:

Terminal
exaloop avrogen event.avsc event.codon
exaloop protoc -Ischemas --codon_out=generated schemas/event.proto
exaloop profdata -o merged.profdata capture.profraw
exaloop --with data --dry-run avrogen event.avsc event.codon
exaloop tool --list
exaloop --with data tool --list

Create Protobuf output directories before invoking protoc. The CLI locates the generator and standard schemas in the Data SDK for you.

CommandDefault SDKStandalone tool
avrogendatabin/avrogen-codon
protocdataBundled protoc, with Codon plugin discovery
protoc-gen-codondataRaw binary Protobuf generator protocol
profdataextexaloop-profdata
duckdb-buildduckdbComplete DuckDB build.py interface
postgres-buildpostgresComplete PostgreSQL build.py interface
mysql-buildmysqlComplete MySQL build.py interface
redis-buildredisComplete Redis build.py interface

Use --with NAME to select another SDK alias. Arguments after the command belong to that tool, including --help. The direct database builders use --mode release; the higher-level --kind KIND build uses Codon's -release.

The generic dispatcher also runs tools included in a selected SDK or a tool specified by an explicit path:

Terminal
exaloop --with data tool avrogen-codon event.avsc event.codon
exaloop --with redis tool build.py --help
exaloop tool /absolute/path/to/native-tool --help

Tools run from the project directory when a project is selected, or from the current directory otherwise. Tool execution has the same permissions as the CLI; --dry-run shows the planned command without executing it.

Diagnose, Test, Package​

For function timings and memory measurements, see the profiling guide. exaloop --profile run ... enables capture; --profile=memory requests memory statistics without XRay.

Terminal
exaloop doctor
exaloop --target scoring doctor --json
exaloop doctor --optimization --optimizer-sdk /path/to/sdk/ext --json
exaloop --target scoring test
exaloop --target scoring package --output packages/scoring-v1

doctor checks your compiler and SDKs, including the host tools needed by a server target. Resolve its errors before building. For optimization, it also compiles and runs a small PGO check; the PGO walkthrough then takes you through optimizing your own program.

test first builds a named target, then runs its explicit test argument array without a shell. For example, set test = ["python3", "tests/check.py"] inside the target table. The command receives EXALOOP_ARTIFACT with the absolute output path, and arguments after test -- are forwarded to it. Test commands are trusted project code; no database or Kafka service is started automatically.

package builds a target and collects its output, checksums, and deployment notes in a new directory. By default it includes build artifacts only, not their runtime libraries. Review generated SQL before deployment; PostgreSQL's unversioned SQL still refers to the local build path.

Python-extension targets are the exception: package produces an installable wheel and always bundles its native runtime dependencies, as described above.

For runtime-only packaging, request it explicitly:

Terminal
exaloop --target events package --bundle-runtime --output packages/events-v1

This includes the native libraries needed by the application. The runtime-package guide explains target requirements and what you still need to supply. Packaging does not deploy the application or install database functions.

The distribution workflow also supports verified release installation, rollback, and project locks. Use a project lock when a team needs to build with the same distribution.

For installation or execution problems, see troubleshooting.