@elaraai/e3-cli
v1.0.97
Published
East Execution Engine CLI - Command-line tool for managing e3 repositories and tasks
Maintainers
Readme
@elaraai/e3-cli
Command-line interface for e3 (East Execution Engine).
Installation
npm install -g @elaraai/e3-cliCommands
Every command that takes <repo> accepts either a local path or an http(s):// URL. The transport is detected from the argument shape. Set E3_REPO to default the repo argument when omitted (where the positional is optional).
Repository
e3 repo create <repo> [--exist-ok] # Create a new repository
e3 repo status <repo> # Show repository status
e3 repo remove <repo> [-r] # Remove a repository (-r removes workspaces first)
e3 repo gc <repo> [--dry-run] [--keep-runs <n>] [--keep-days <d>] # Remove old history and unreferenced objects
e3 repo list <server-url> # List repositories on a serverrepo gc keeps each workspace's last 10 runs (--keep-runs), every run from
the last 7 days (--keep-days) and the run its current state came from, with
the executions they used; every execution a workspace's current state is served
from, so a re-run stays cached; and every execution from the last 7 days. The
rest of the history goes, with the outputs only it kept.
Packages
e3 package import <repo> <zip> # Import package from .zip
e3 package export <repo> <pkg> <zip> # Export package to .zip
e3 package list <repo> # List installed packages
e3 package remove <repo> <pkg> # Remove a packageWorkspaces
e3 workspace create <repo> <name> # Create empty workspace
e3 workspace copy <repo> <from> <to> # Make <to> what <from> is now: made, or replaced whole
e3 workspace deploy <repo> <ws> <pkg>[@<ver>] # Deploy a package
e3 workspace deploy <repo> <ws> --from-zip <path.zip> # Import + create + deploy in one shot
e3 workspace deploy <repo> <ws> --from-source <file.ts> # Bundle a TypeScript source into a package, then import + create + deploy
e3 workspace deploy <repo> <ws> … --skip-file-sources # Leave `file`-source inputs unset
e3 workspace deploy <repo> <ws> … --functions <path...> # Function manifests for East.importFunction packages built elsewhere
e3 workspace deploy <repo> <ws> … --schema <policy> # A record that cannot be kept as it is: migrate (default), fail, or reset
e3 workspace deploy <repo> <ws> … --inputs <policy> # An input someone set: reset (default) or keep-edited
e3 workspace deploy <repo> <ws> … --allow-drop-records # Drop a record the package no longer declares, with its state and history
e3 workspace deploy <repo> <ws> … --plan # Say what the deploy would do to each record, index and input; write nothing
e3 workspace deploy <repo> <ws> … --quiet # Errors only: no progress
e3 workspace export <repo> <ws> <zip> # Export workspace as a package
e3 workspace list <repo> # List workspaces
e3 workspace status <repo> <ws> # Detailed workspace status
e3 workspace remove <repo> <ws> # Remove a workspaceA deploy decides what to do with each record before it writes anything. It
mints a new record's $init commit from its initial value (a record declared
with none is left unassigned until e3 seed commits its first state, the
tasks over it waiting), keeps
one whose migrations have all been applied (with a $deploy commit when the
package changed), and runs the migrations a workspace has not applied, a
$migrate:<name> commit each. A record whose type changed with no migration,
or whose applied steps the package's chain does not start with, is refused,
and so is a record the package no longer declares, unless
--allow-drop-records. --schema fail runs no migration and refuses instead;
--schema reset resets such a record to the package's initial value, with a
$reset commit, or sends one declared with none back to unassigned. --plan prints the plan
and writes nothing. From a zip or a source it imports nothing: it reads the
package from the zip where it is. A server plans only a package it holds, so
there it is refused: e3 package import the zip, then plan the package by
name.
Each input takes the new package's value, and so does one someone set, unless
--inputs keep-edited, which keeps it while its type is the new package's. One
whose type changed takes the new package's value, and the deploy says why. An
input the new package takes from a file takes its file, and one the package no
longer declares goes. A deploy prints each input it keeps, resets or drops, and
--plan prints every input's fate.
workspace copy makes <to> the workspace <from> is now — its package and
every input, record and task output, so nothing needs to run again — writing
refs only, so its cost follows the number of datasets, never their size. A
<to> that exists is replaced whole, its runs going with it, and a write to
either afterwards leaves the other as it was. It is refused while a dataflow
runs in <to> or a deploy, a removal or an export holds <from>.
A deploy takes the package's file sources in on this machine, locally -j at
a time. A collection is taken in by intake units on the runners — east-c, or
east-node where e3 finds no east-c — in pieces of its segments, under the same
budget, and a deploy stopped part way takes up again from the pieces it
finished. The deploy says how far it has got on stderr. Each file prints a line
once it is in: its size, time and rate, and how it was taken in (unchanged,
already in the store, taken in by east-c, or carried for a value that is
not a collection), with why the first time a runner fell back to another. A
terminal also keeps a live line for the files in flight, with their pieces, the
rate and the time left. Against a server, the deploy line says what the server's job is doing;
the deliveries then upload a few at a time, each printing a line once it is in,
and a terminal's live line names those in flight: how far each hash has got,
then what the server's commit is doing with it.
Datasets
Dataset paths use the flat form <ws>.<name>. The CLI resolves <name> against inputs and task outputs automatically.
e3 dataset get <repo> <ws.name> [-f east|json|beast2]
e3 dataset set <repo> <ws.name> <file> [--type <spec>] [--type-file <path>]
e3 dataset set <repo> <ws.name> --from-file <path.beast2> [-j <n>] [--memory <size>] # Take a beast2 file in as the value, as a deploy does
e3 dataset list <repo> <ws> [-l] # List dataset paths (with -l for table view)
e3 dataset status <repo> <ws.name> # Show one dataset's kind/type/status/size
e3 dataset find <repo> <ws> <pattern> # Substring or glob (`*`, `?`) match across namesRecords
A record is written only through its mutations — a raw dataset set on one is
refused — and -w names the workspace that holds it. Read its state with
dataset get, like any dataset.
e3 mutate <repo> <record.mutation> [args...] -w <ws> [-v] # Apply a mutation; args are .east literals or .beast2/.json/.east files
e3 seed <repo> <record> <file.beast2> -w <ws> [-j <n>] [--memory <size>] # Commit a record's first state from a beast2 file, as its $init (a record declared with no initial value; local repositories)
e3 history <repo> <record> -w <ws> [--limit <n>] [--from <hash>] [--delta] # The commit chain, newest first (--delta: local repositories)
e3 reindex <repo> <record> -w <ws> [--index <name>] # Rebuild an index from the record (every one by default)
e3 compact <repo> <record> -w <ws> # Collapse the history to a $compact root; the state is keptTasks
e3 task list <repo> <ws> # List tasks with execution status
e3 task logs <repo> <ws.task> # The last 200 lines of a task's logs (-n <lines> for more, --all for the whole log)
e3 task logs <repo> <ws.task> --follow # Tail, then stream live output
e3 task logs <repo> --execution <taskHash>/<inputsHash>/<executionId> # One execution's own log — a unit a split task's log names (local repositories)Dataflow execution
e3 dataflow run <repo> <ws> [--filter <task>] [-j <n>] [--memory <size>] [--force | --force-task <task>...] [-v]--filter <task> runs one task, by its exact name, and the tasks it depends
on. --force re-runs every task the run runs, even where the cache holds its
result; under --filter, the filter's task alone. --force-task <task>,
given once for each, re-runs the tasks it names, such as a task whose platform
function changed or one reading data from outside e3; the tasks downstream re-run when
its output changes, as they always do. A run given both flags, a task the
workspace does not have, or a task --filter leaves out is refused before
anything runs.
-j / --jobs <n> and --memory <size> are the budget of the runner processes
e3 spawns. -j is its cores: the runners in flight at once, across the
dataflow's tasks and the pieces and merge units of its split tasks alike (every
runner takes one, first come first served, whatever launched it). --memory is
the memory those runners may reserve between them, as 8G or 512M. They
default to E3_JOBS and E3_MEMORY, else to what e3 may use: the CPUs of its
affinity mask, capped by a cgroup quota, and the cgroup's memory.max or else
physical memory, less a reserve for e3 and the OS.
A unit of a split task reserves the largest peak memory a unit of its stage (its pieces, or one level of its merges) has reached in the run, so each stage runs its first unit alone and then fans out. Anything else reserves nothing. On Linux and macOS a guard stops the newest such unit when the runners together pass the budget, and runs it again once there is room.
e3 watch, e3 run, e3 call, e3 mutate, e3 reindex and
e3 workspace deploy take the same two flags for a local repository, a deploy
taking its file sources in -j at a time; e3 dataset set --from-file and
e3 seed take both for their intake units. Against a server the CLI refuses them, since the
server runs the work under its own budget (e3-api-server -j / --memory).
A local run's per-execution scratch directories are created inside the
repository, under <repo>/tmp/scratch — on the object store's filesystem, so
an output that is not a collection is stored by a link rather than a copy — or
under E3_SCRATCH_DIR when it is set. A scratch directory left by a dead process is removed by the
next run or e3 repo gc.
-v / --verbose forwards -v to each task's runner so it prints a timing/perf
block to the task's logs (e3 task logs <repo> <ws.task>) — identical across
east-node, east-py and east-c. It is a runtime-only toggle that never affects
caching (a cached task stays cached; add --force to see the block for one).
Also on e3 run, e3 call, and e3 mutate — local and remote repositories
(remote carries it as a ?verbose=1 query param).
A task whose input nothing has set — an input never set, or a record declared
with no initial value whose first state is not yet committed — is left
waiting, and so are the tasks downstream of it: the run prints [WAIT] for
each, naming the input, completes without them, counts them under Waiting:,
and runs them once the input is set — in the same run, when it is set while
the run is in flight.
After a successful run, the CLI prints the task output paths so you can read them straight away:
Summary:
Executed: 2
Cached: 0
Failed: 0
Skipped: 0
Waiting: 0
Duration: 412ms
Outputs:
dev.greet 14 B
dev.shout 16 BAd-hoc task execution
e3 run <repo> <pkg.task> <inputs...> -o <out>
e3 run <repo> <[email protected]> <in.beast2> -o <out.beast2> [--force] [-v] [-j <n>] [--memory <size>]Function calls
e3 call <repo> <pkg.fn> [args...] # Call by package: pkg.fn or [email protected]
e3 call <repo> -w <ws> <fn> [args...] # Call the workspace's deployed package
e3 call <repo> -w <ws> <fn> @.inputs.sales 5 # Pass a dataset of the workspace
e3 call <repo> <pkg.fn> 2 3 -o sum.beast2 # Write the raw result to a fileArguments are .east literals or paths to .beast2 / .json / .east files,
parsed against the function's parameter types. With -w, an argument written
@<keypath> is that dataset of the workspace: the function reads it where it
is stored, at the hash it holds when the call starts, rather than a copy sent
with the call. Without -w one is refused. A call triggers no dataflow and
writes nothing to the repository.
Watch / live development
e3 watch <source.ts> <repo> <ws> [--start] [--schema <policy>] [--inputs <policy>] [-j <n>] [--memory <size>] [--abort-on-change] [--functions <path...>]--schema and --inputs are the deploy's (e3 workspace deploy); a record
whose type changes with no migration stops the watch, naming --schema=reset,
and each save says which inputs someone set it resets.
Authentication
e3 auth login <server> # OAuth2 device-flow login
e3 auth logout <server> # Clear saved credentials
e3 auth status # List saved credentials
e3 auth token <server> # Print access token (curl integration)
e3 auth whoami [server] # Show current identitycurl -H "Authorization: Bearer $(e3 auth token https://example.com)" \
https://example.com/api/repos/my-repo/statusUtilities
e3 convert [input] [--from <fmt>] [--to <fmt>] [-o <out>] [--type <spec>]
e3 completion install # Detect your shell and wire up tab completion
e3 completion uninstall # Undo the above
e3 completion {bash|zsh|fish} # Print the raw script (manual install)e3 completion install is the one-shot setup — it detects $SHELL, appends eval "$(e3 completion bash)" (or the zsh/fish equivalent) to your rc file, and is idempotent on re-run. Override detection with --shell <bash|zsh|fish>.
If you'd rather wire it up yourself, e3 completion bash > /etc/bash_completion.d/e3 (and equivalents) work too.
The completion script delegates dynamic lookups (workspace names, dataset paths, package names) to a hidden e3 __complete handler.
Defaulting the repository
When the positional <repo> is optional (every command that takes one as the first argument, except run, call, mutate, seed, history, compact, reindex and watch), the value is resolved in this order:
- Explicit positional argument.
E3_REPOenvironment variable..(current directory).
So once you're inside a repo, export E3_REPO=. lets you drop the leading .:
export E3_REPO=.
e3 dataset get dev.greet
e3 dataflow run devInternal entry
@elaraai/e3-cli/internal re-exports the pieces of the e3 binary that another
first-party binary shares rather than re-implements: parseRepoLocation /
defaultRepoArg (the <repo> argument grammar and E3_REPO precedence), the
credential store and device-flow login behind e3 auth (getValidToken,
createAuthCommand, …), the dataset path resolver, the progress reporter and the
CLI formatters. @elaraai/e3-ui-cli mounts these so e3-ui auth login and
e3 auth login are the same code and the same ~/.e3/credentials.json.
It is not a semver-stable API — it exists for the workspace's own binaries and a
release may reshape it. Application code should use
@elaraai/e3-api-client
(remote) or @elaraai/e3-core
(local) instead.
Migration from earlier versions
| Old | New |
|--------------------------------------------------|-------------------------------------------------------|
| e3 get <repo> <ws>.tasks.<name>.output | e3 dataset get <repo> <ws>.<name> |
| e3 set <repo> <ws>.inputs.<name> | e3 dataset set <repo> <ws>.<name> |
| e3 list <repo> | e3 workspace list <repo> |
| e3 list <repo> <ws> | e3 dataset list <repo> <ws> |
| e3 status <repo> <path> | e3 dataset status <repo> <path> |
| e3 logs <repo> <ws> | e3 task list <repo> <ws> |
| e3 logs <repo> <ws>.<task> | e3 task logs <repo> <ws>.<task> |
| e3 start <repo> <ws> | e3 dataflow run <repo> <ws> |
| e3 login <server> / e3 logout <server> | e3 auth login <server> / e3 auth logout <server> |
| e3 workspace import <repo> <ws> <zip> | e3 workspace deploy <repo> <ws> --from-zip <zip> |
| e3 run <repo> <pkg>/<task> | e3 run <repo> <pkg>.<task> |
| e3 watch <repo> <ws> <source> | e3 watch <source> <repo> <ws> |
| --concurrency <n>, --partition-concurrency <n> | -j <n> / --jobs <n> |
Example
# Create a repository, deploy a package, run the dataflow
e3 repo create ./my-project
e3 workspace deploy ./my-project dev --from-zip ./hello.zip
e3 dataset set ./my-project dev.name ./name.east
e3 dataflow run ./my-project dev
# Read the results
e3 dataset get ./my-project dev.greetClaude Code plugin
The East ecosystem also ships a Claude Code plugin — East language skills, example search, and preemptive diagnostics for East code — installed separately from the elaraai marketplace:
# Inside Claude Code
/plugin marketplace add elaraai/east-workspace
/plugin install east@elaraai# From a terminal
claude plugin marketplace add elaraai/east-workspace
claude plugin install east@elaraaiLicense
BSL 1.1. See LICENSE.md.
Ecosystem
East: Statically typed, expression-based language with serializable IR. Run portable logic across TypeScript, Python, C, and other runtimes.
- @elaraai/east: Core language SDK with type system, expressions, and reference JS compiler
East Node: Node.js platform functions for I/O, databases, and system operations.
- @elaraai/east-node-std: Console, FileSystem, Fetch, Crypto, Time, Path, Random
- @elaraai/east-node-io: SQLite, PostgreSQL, MySQL, MongoDB, Redis, S3, FTP, SFTP, XLSX, XML, compression
- @elaraai/east-node-cli: CLI for running East IR programs in Node.js
East C: C11 native runtime for executing East IR. Distributed via npm (launcher + per-platform optional dependencies) and as tarballs on each GitHub Release.
- @elaraai/east-c-cli: npm launcher — installs the matching native binary as an optional dependency
east-c: Core runtime — type system, IR interpreter, builtins, serialization (Beast2, JSON, CSV, East text)east-c-std: Console, FileSystem, Fetch, Crypto, Time, Path, Randomeast-c-cli: CLI for running East IR programs natively
East Python: Python runtime, standard platform, I/O, and data-science platform functions. Published to PyPI.
- east-py: Core Python runtime — type system, IR compiler, 212+ builtins, Cython-accelerated hot paths
- east-py-std: Console, FileSystem, Fetch, Crypto, Time, Path, Random
- east-py-io: SQLite, PostgreSQL, MySQL, MongoDB, Redis, S3, FTP, SFTP, XLSX, XML, compression
- east-py-cli: CLI for running East IR programs in Python
- east-py-datascience (PyPI) + @elaraai/east-py-datascience (npm): Optimization (MADS, Optuna, ALNS, GoogleOR), ML (XGBoost, LightGBM, NGBoost, PyTorch, Lightning, GP), Bayesian inference (PyMC), explainability (SHAP), conformal prediction (MAPIE)
East UI: Typed UI component definitions and React renderer, plus VS Code preview.
- @elaraai/east-ui: 50+ typed UI components for layouts, forms, charts, tables, dialogs
- @elaraai/east-ui-components: React renderer with Chakra UI v3 styling
- @elaraai/e3-ui: e3 + UI bridge — Data bindings,
e3.ui()task, manifest - @elaraai/e3-ui-components: React Query hooks and preview components for the e3 API
- east-ui-preview: VS Code extension for live East UI component preview
e3 — East Execution Engine: Durable execution engine for running East pipelines at scale. Git-like content-addressable storage, automatic memoization, reactive dataflow, real-time monitoring.
- @elaraai/e3: SDK for authoring e3 packages with typed tasks and pipelines
- @elaraai/e3-core: Object store, dataflow orchestrator, execution state
- @elaraai/e3-types: Shared type definitions for e3 packages
- @elaraai/e3-cli:
e3 repo,e3 package,e3 workspace,e3 dataflow run,e3 watch,e3 task logscommands - @elaraai/e3-api-client: HTTP client for remote e3 repositories
- @elaraai/e3-api-server: REST API server for e3 repositories
- @elaraai/e3-api-tests: Shared API compliance test suites
Links
About Elara
East is developed by Elara AI Pty Ltd, an AI-powered platform that creates economic digital twins of businesses that optimize performance. Elara combines business objectives, decisions and data to help organizations make data-driven decisions across operations, purchasing, sales and customer engagement, and project and investment planning. East powers the computational layer of Elara solutions, enabling the expression of complex business logic and data in a simple, type-safe and portable language.
Developed by Elara AI Pty Ltd.
Developed by Elara AI Pty Ltd
