ride
Experimental. Run a plain script (map / filter / simple comprehensions / independent indexed for). DistSSHKit rewrites those forms and may pmap them on Distributed workers (parent and SSH child:). Inspect first with plan.
julia --project=. -m DistSSHKit plan SCRIPT.jl
julia --project=. -m DistSSHKit ride parent:2 SCRIPT.jl
julia --project=. -m DistSSHKit ride parent:1 child:host1:2 SCRIPT.jlListed tokens need :N (no tokens → parent:1). SSH children use the same worker-add path as drive. Prepare remotes with setup first. Distributed vocabulary (pmap, @everywhere, …) is an error; that script belongs on drive. Listed child: hosts are fail-closed.
for i in iter; dest[i] = expr; end is rewritten when expr does not read dest, does not return / break / continue, and every index in expr is i (so dest[i] = alias[i - 1] stays sequential). If runtime effect analysis rejects distribution, or dest may alias an array the RHS captures (including nested in a struct), or a Main array aliases dest (including const globals the closure does not capture), or iterate on the loop iterator is not effect-free, the iterator is not collected first; each dest[i] = expr runs in order. Distributed fills collect then map. SPI compares mapped RHS values before dest writes, so it does not catch that aliasing; the runtime overlap check does (including fail-closed if the capture walk hits its depth limit). Broadcast, reduce, and accumulating for stay out of scope.
--spi-check is off by default. Pass it to also run each rewritten map / filter (including values from indexed for) sequentially and compare. --no-spi-check is an explicit skip. Under --progress, a successful compare prints SPI check: passed after the script stdout. With the compare off, or when the script stayed sequential, that line is SPI check: skipped (sequential or off).
ride distributes only what the compiler can prove safe. The guarantee follows from the discussion in JuliaLang/julia#43910: if f and getindex are :effect_free, parallel map does not introduce new data races. Thread-parallel POC and this SSH/process ride are not the same implementation.
Default artifacts: {script}/.distsshkit/ride/{stem}_{UTC}/. Sidecars (run.toml, pid, stdio): {script}/.distsshkit/runs/ride/{stem}_{UTC}/ (same project / tempdir() fallbacks as go when the script dir is not writable).
Also: ride --help. API: ride!, execute! (:ride, including detached=true for DistSSHQueue).