CLI Reference#
embedl-hub run start creates a run and prints only its ID to stdout, so
shell scripts can capture it (RUN=$(embedl-hub run start --type training)).
With --pending the run is created without being started, for work that
something else will run later.
The embedl-hub log commands push metrics, params, tags, links,
artifacts, and dashboards to a run chosen with --run <id>, the
EMBEDL_HUB_RUN environment variable, or the directory context
set with embedl-hub use run (the nearest .ehub/use.cfg, found like
git finds .git).
embedl-hub log dashboard <file> uploads a dashboard written by the Python
builder’s Dashboard.save(). A run can carry several, so --set-default
marks the one its Dashboard tab opens on and --opens-run opens the run
itself on it rather than on the run’s details; the second implies the first.
Without either the run keeps opening on its details.
embedl-hub run list shows the project’s runs with live state from
Embedl Hub, including runs created elsewhere; run list --local shows
the runs recorded on this machine. run show prints everything logged
on a run — with --commands, also the CLI invocations that touched it
on this machine — and run url prints its web address.
For high-frequency logging, embedl-hub batch start creates a local
batch; log commands with --batch (or after embedl-hub use batch)
queue entries instead of sending them, and embedl-hub batch send
delivers everything in consolidated requests. Interrupted sends
resume where they left off with only the entries that did not
succeed. Entries the hub rejects outright stay pending unless the
send is re-run with --skip-rejected, which marks them skipped so
the batch can complete.
embedl-hub exec --type <type> <command...> wraps any command in a run: it
creates the run, runs the command with EMBEDL_HUB_RUN set so embedl-hub log
calls inside it attach to that run, then completes the run from the command’s
exit status (zero finishes it, non-zero fails it, a signal kills it), and
passes termination signals on to the command so a scheduler can cancel it.
A signal arriving when there is no command to pass it to – before it starts,
or while the run is being completed – is acted on once the run is settled,
and still exits 128 + N rather than reporting anything of its own. These
signal statuses are POSIX ones; on Windows a forwarded signal surfaces as an
ordinary exit code instead, and the run is completed as failed rather than
killed.
A command that cannot be launched reports the status a shell reports – 127
when it cannot be found, 126 when it cannot be run – so $? means the same
with the wrapper as without it. A script with no #! line still runs, as it
does at the prompt; a file the system cannot load and that does not read as
text is refused rather than run, so a corrupt file cannot be reported as a
finished run.
With --use-pending-run RUN_ID no run is created: the pending run named, made
earlier with run start --pending and annotated with embedl-hub log, is
started as the command starts and completed the same way, so what was recorded
before launch and what the command logs end up on one run. It cannot be
combined with --type, --name or --parent; --project narrows where the
run is looked up, and without it the run is found by its ID. A run that is not
pending stops the command with exit status 1 whatever --safe says; with
--safe an unreachable Hub still runs the command, untracked.
Any inherited EMBEDL_HUB_RUN is dropped, so the command never logs into an
unrelated run. A Python command can pick up the run exec made for it with
Client.use_inherited_run(), which reads EMBEDL_HUB_RUN and
EMBEDL_HUB_PROJECT and logs into that run rather than starting another; it
returns None, with a warning, when tracking was skipped. Wrap the logging
that follows in client.safe_log() for the same script to work with and
without --safe: logging with no run adopted otherwise raises, and the outage
--safe absorbed would reach the command by another route. --safe also
exports EMBEDL_HUB_SAFE, which makes the adoption itself tolerant, so a Hub
that goes down between starting the run and adopting it warns rather than
raising. Completing the run stays with exec, which
sets its outcome from the command’s exit status. The
command need not be Python – a shell script, a Makefile target or a binary
all work – and everything after it is passed through untouched, so its own
flags are never read as exec’s. exec exits with the command’s own status
(128 + N when signalled), with two exceptions. A cancellation you sent wins,
exiting 128 + N even when the command had already finished on its own. And
without --safe, a command that succeeded but whose run could not be
completed exits 1, so that a lost run record is not reported as a clean
finish; a command that failed on its own terms keeps its own status either
way. With --safe, a Hub outage costs the run record but still runs the
command and still reports its status.