go
Run a standalone script as-is (the job file does not call DistSSHKit). Each parent:N / child:NAME:N slot is one full script run, started concurrently — not Distributed workers.
julia --project=. -m DistSSHKit go [options] \
[parent:N] [child:NAME:N...] SCRIPT.jl [script_args...]Also: First Steps · Demo, drive, go --help. Flag vocabulary and a short go vs drive table: User Guide.
parent:N / child:NAME:N stay explicit counts. Omitting :N on a listed host is an error unless --repeat (then it is an uncapped pool host, not a count). Drive / ride also require :N. go SCRIPT.jl with no host tokens is still one parent slot. Estimate with size, then paste the printed tokens. A bare julia -m DistSSHKit SCRIPT.jl is not go; name the command. --repeat N still spreads N runs; explicit :N is a cap, while omitted :N stays uncapped and does not use size!.
vs drive: each child:NAME:N is N full script runs (not Distributed workers). There is no --require-git; for commit parity use drive --require-git. Prepare remotes with setup --rsync or --clone, then --instantiate. One-shot onto an empty/missing path: go --rsync (instantiates if needed). Later git updates (setup --sync / go --sync) need a --clone / git-managed remote, not an rsync tree.
Flags
--sync: git push/pull before remote slots (opt-in; default is none; confirm unless-y)--rsync: rsync working tree first (empty/missing remote, or aftersetup --delete); then instantiate if deps are missing--skip-sync: compat: no pre-run sync (already the default)--skip-git-guard: alias of--skip-sync(shared name with drive)--julia PATH: Julia on remotes (default: auto /JULIA_DISTRIBUTED_EXE)--output-dir PATH: batch root; slots write underPATH/{slot}/(notdrive --output-dir)--hosts CSV: comma-separated slot specs (same form as CLI tokens /DISTSSHKIT_HOSTS)-q/--quiet: hide terminal detail;go_*.logand per-slot logs still written--progress: live status (TTY default)--verbose: full detail (non-TTY default)-y/--yes: non-interactive confirmations--hosts-file PATH: append slot specs (child:NAME:Npreserved)--repeat N: N independent runs in total. Spread round-robin across listed hosts (none → all on parent). Omit:Non a host to leave it uncapped;parent:N/child:NAME:Nare per-host caps.-v/--version: print DistSSHKit version and exit-h/--help: full help
--sync / --rsync / --skip-sync (and --skip-git-guard) are mutually exclusive. Default pre-run sync is none (same as drive); prepare remotes with setup, or pass --sync / --rsync. --rsync instantiates when the copied tree still lacks deps. go checks Project.toml after that copy (empty remotes are allowed until then).
Output
Default batch root (next to the script):
{script}/.distsshkit/go/{stem}_{UTC}/{slot}/If the script is outside the project, {project}/.distsshkit/go/{stem}_{UTC}/. --output-dir PATH replaces the batch root. The run sets DISTRIBUTED_OUTPUT_DIR to each slot directory. Sidecars for that invocation (run.toml, pid, stdio) live under {script}/.distsshkit/runs/go/{stem}_{UTC}/, not in the batch root. If that path is not writable, {project}/.distsshkit/runs/go/…, then tempdir()/distsshkit-runs/go/…. Add .distsshkit/ to the job project's .gitignore so these paths stay untracked and setup --rsync does not push them (rsync also excludes that name). See User Guide.
From the API, go!(...; output_dir=PATH) sets the same batch root (matching drive!). collect_spec::String still works as a backward-compatible alias, but passing both output_dir and collect_spec::String is an error. collect_spec=false skips collect and is orthogonal to output_dir.
Collect after remote slots: slot-overwrite (rsync whole slot dir). A failed slot pull is a failed slot, not an empty directory. Any explicit slot that does not run (remote path missing, run ✗, collect ✗) fails the batch (ok=false). There is no partial success.
External watchers: begin / item always go to kit.progress (even -q). The kit log still gets those lines only with --progress or DISTSSHKIT_PROGRESS=1. progress: done is always written.
Wall time
Same as drive: run go as usual (-q hides the table). The Time table prints at the end, after slot stdout, with a progress DIR line to replay:
julia --project=. -m DistSSHKit go -y parent:2 \
distsshkit_demos/without_kit/pi_echo.jl --n 5000
julia --project=. -m DistSSHKit progress DIRDIR is the batch root (--output-dir, or {script}/.distsshkit/go/…). --progress is the TTY default; you do not need a scratch --output-dir just to time a run.
Labels: ready (remote project / Julia, when remotes are listed), sync (optional), run (all slot scripts), then collect (remote pulls). Nested rows are NAME/run and NAME/collect. Scripts overlap with each other; pulls wait until every script has finished (same order as drive: collect then the rsync). Percentages are of the whole run and may sum past 100%.
Concurrent runs
Two go runs (or go! calls) against the same batch root fail fast: a .kit.lock file (this run's pid) is written under the batch root, and a second run against the same directory raises immediately instead of interleaving slot output. A lock left behind by a crashed/killed run is detected as stale (dead pid) and reclaimed automatically. Since the default batch root already includes a UTC timestamp, this mainly matters when you pass an explicit --output-dir / output_dir=.
job_id
execute!(:go, …; job_id=) and ENV["DISTSSHKIT_JOB_ID"] tag each slot so terminate! / terminate_run! can pkill -f distsshkit-job:<id> without matching other Julias. The tag is a no-op -L file named distsshkit-job:<id> in the slot directory; the user script remains PROGRAM_FILE with the usual ARGS. Drive workers use a comment-only --eval=#distsshkit-job:<id> instead (Distributed starts the worker; the driver includes later). Unset job_id: no tag. Details: API.
Where a slot stopped
go does not pass --trace-eval. Put this at the top of the script when a failure should name the last top-level expression:
Base.TRACE_EVAL = :locA slot that exits non-zero then adds last top-level: path:line to its ✗ line. That text is read from the slot's julia.stdout.log (a remote slot keeps the captured log locally when collect does not run). Only top-level expressions are recorded. include counts. A function body does not. Work that lives in main() shows the main() call unless the steps are top-level or split across included files. Julia writes the trace with color codes even when the log is a file. go strips those codes. The -L job mark (distsshkit-job:) is not reported.
Hosts
CLI tokens, --hosts, --hosts-file, and/or DISTSSHKIT_HOSTS. parent:0 skips parent slots when remotes are listed. Omitting hosts is one parent slot (parent/).