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.