Remotes¶
For operators who need to reach another machine. A remote is a bundle that
combines transport, file movement, and command execution: it can move a job or
workspace tree, invoke httk there, and report status. A remote never schedules
managers. Scheduling belongs to the launcher selected by the destination
workspace; see Launchers for that side of the workflow.
A remote bundle contains remote.json and one executable named adapter, with
optional credentials.json for values that should not enter the shareable
metadata. Project remotes live at httk_project/remotes/NAME; global remotes
live at ~/.config/httk/remotes/NAME. Project definitions take precedence over
global definitions with the same name.
Setting one up¶
Create an SSH remote, configure its connection, and verify that a compatible
httk answers on the other machine:
$ httk workflow remote add --template ssh kappa
$ httk workflow remote configure \
--set host=login.example.org \
--set username=me \
--set check_connectivity=yes kappa
$ httk workflow remote check kappa
remote check invokes the adapter’s historical install operation; despite
that protocol name, the maintained adapters verify the remote and do not
install anything. Settings that are credentials are stored in
credentials.json, which is excluded from signed project manifests. Use
remote show [--json] to inspect a definition without printing credential
values; remote list, remote remove, and remote import-v1 cover the other
common management tasks.
Making httk available over SSH¶
ssh runs its command in a non-interactive shell, so the environment your
login files set up interactively — module load lines, a virtualenv — is not
applied, and httk is often not even on PATH. Put that setup in the remote’s
prelude setting rather than in ~/.bashrc, so it applies to httk’s ssh
commands only and does not disturb every other tool that logs in over ssh:
$ httk workflow remote configure --set prelude='module load Python/3.13.5-bundle
source ~/venv/bin/activate' kappa
The prelude runs (under set -e, so a failing line aborts before anything
else) ahead of every command the adapter sends over ssh — including the
httk workspace status that remote check uses to find httk in the first
place. When only the httk program lives somewhere non-standard but the
environment is otherwise ready, the narrower httk_command=/path/to/httk
setting is enough.
This adapter prelude is distinct from a workspace’s environment.prelude
(below): the adapter prelude bootstraps the shell so httk can run at all,
while environment.prelude is applied later by the manager once it is already
running on the remote.
Initialize a named workspace on the remote by putting the remote name before the path:
$ httk workspace init --name runs kappa:/scratch/me/httk/runs
$ httk workspace status kappa:runs
The NAME:WORKSPACE spelling is a binding, not a filesystem path. Transfer a
job into that workspace and run its manager there:
$ httk workflow transfer --job JOB default kappa:runs
$ httk workflow run --workspace kappa:runs --count 4
The remote invocation asks the owning machine to run
httk workflow manager run --workspace runs --detach …. The target workspace
then applies its own manager.launch, manager.workers, scheduler settings,
and environment.prelude, exactly as if the command had been run on the
login node. Fetch finished jobs back with the reverse transfer:
$ httk workflow transfer kappa:runs default
Names listed in machine_names are self-addressing: login:runs is treated as
a local workspace binding when login is configured as one of this machine’s
names, so it does not invoke a remote adapter. To use a second tree on the
same host through the adapter contract, create a distinct remote with the
local template:
$ httk workflow remote add --template local local-tree
$ httk workspace init --name scratch local-tree:/tmp/me/httk/scratch
From Python¶
The low-level adapter API is in httk.workflow.adapters. This example uses the
local template so it can be exercised without an SSH server; use the CLI to
configure an SSH remote’s persisted settings, because there is no single
high-level Python equivalent of remote configure --set:
from pathlib import Path
from httk.workflow.adapters import (
add_remote,
probe_remote_workspace,
resolve_remote,
run_adapter,
)
from httk.workflow.registry import resolve_workspace
project = Path(".").resolve()
add_remote("local-tree", template="local", project=project)
target = resolve_remote("local-tree", project=project)
# The workspace named runs must already exist in the local registry.
result = run_adapter(
target.bundle,
"status",
{"argv": ["httk", "workspace", "status", "--json", "runs"]},
timeout=None,
)
workspace_id, root = probe_remote_workspace(target, "runs", timeout=None)
binding = resolve_workspace("local-tree:runs", project=project)
print(result, workspace_id, root, binding)
add_remote creates a maintained adapter bundle, resolve_remote applies
project-before-global resolution, and run_adapter executes one of the six
adapter operations. probe_remote_workspace validates the remote status
document and returns the remote workspace UUID and root. The registry’s
resolve_workspace keeps the NAME:WORKSPACE binding in one place; a remote
workspace has no local path until the adapter reports it.
Writing a remote adapter¶
A custom remote is a versioned bundle with remote.json, one executable named
adapter, and optional credentials.json. The dispatcher answers six
operations — configure, install (the operation behind remote check),
invoke, push, pull, and status — with one JSON result per invocation.
It must implement transport, file movement, and remote command execution while
leaving manager scheduling to the destination workspace’s launcher. The engine
refuses malformed metadata, a missing or non-executable dispatcher, unavailable
required binaries, unsupported operations, non-zero dispatcher exits, and
malformed or unsuccessful result documents.
The complete bundle layout, operation request and result documents, settings and credential handling, and refusal rules are in Writing a remote adapter in detail.