SFTP Workflows
sshx supports one-shot SFTP actions for common file tasks. It is not an interactive file manager; each invocation performs one clear upload, download, list, mkdir, or remove operation.
Plans and effect evidence
SFTP and server-to-server transfer accept --dry-run --json, --expect-plan,
--host-timeout and --global-timeout. Dry-run is offline and write-free.
Binding checks the public endpoints/operation and local upload payload, not
unread remote content or recursive directory membership.
Use --json to consume the CLI operation result, shared execution identity,
effects, change_state, nullable executed, and verification status.
Size/metadata evidence is not a content-digest guarantee. Downloads record local
writes even when the remote operation is risk=read; relay reads the source
and writes the destination.
The operation result includes entries, bytes_transferred, partial, and
directory_atomic (false). Each entry records its path/type/size/mode, copied
bytes, started/published state and verification; content-checked file copies
also expose source_sha256 / sha256. Known staging/cleanup evidence is
retained as staging_path / cleanup_error on errors. Use the actual entry verification rather than assuming
every operation (such as listing) has content hashes.
Upload/relay stage each file before publication. Overwriting an existing remote
destination requires supported atomic replacement; when unavailable, fail
without deleting that destination. Ordinary SFTP rename can publish a new
destination. Downloads stage beside the local destination and use the local
OS’s rename semantics; POSIX guarantees are not assumed on Windows.
After connection loss, remote staging cleanup may be impossible and is reported.
The publication methods are posix_rename, new-file sftp_rename_no_replace,
and download local_rename. Successful file verification includes post-copy
readback SHA-256 and metadata; mkdir verifies type/existence, removal verifies
absence, and listing supplies metadata only. Earlier published entries remain
in a partial result if a later directory entry fails.
Single-file staging, where supported, does not provide directory-wide atomicity, arbitrary-writer CAS, or automatic rollback. A failed/interrupted recursive transfer can have partial destination effects; inspect before retrying. See Plans, Outcomes, and Safe Retries.
Upload A File
sshx -h=prod-web --upload=./deploy/nginx.conf --to=/tmp/nginx.conf
To overwrite an existing remote file with a backup and hash precondition, use Guarded File Apply instead of assembling upload + install yourself:
sshx apply -h=prod-web --path=/etc/nginx/nginx.conf --from=./deploy/nginx.conf --sudo --json
sshx run --target=prod-web --json -- "sudo nginx -t"
Download A File
sshx -h=prod-web --download=/var/log/nginx/error.log --to=./error.log
Incident collection example:
mkdir -p incident-2026-07-01/prod-web
sshx -h=prod-web --download=/var/log/nginx/error.log --to=incident-2026-07-01/prod-web/error.log
sshx -h=prod-web --download=/etc/os-release --to=incident-2026-07-01/prod-web/os-release
List And Create Directories
sshx -h=prod-web --list=/var/log
sshx -h=prod-web --mkdir=/tmp/sshx-upload
Remove A Remote File
sshx -h=prod-web --rm=/tmp/old-upload.txt
Treat remote deletion as production change. Prefer listing the parent directory first:
sshx -h=prod-web --list=/tmp
sshx -h=prod-web --rm=/tmp/old-upload.txt
Path Boundary
Local paths use your local operating system rules. Remote paths are SFTP paths and should be written as slash-separated remote paths, even when sshx is run from Windows.
# Local Windows path, remote POSIX path
sshx -h=prod-web --upload=C:\Users\alice\release.zip --to=/tmp/release.zip
When To Use Plain SSH Instead
Use an SSH command when the operation needs remote validation or privilege changes:
sshx -h=prod-web "sudo ls -l /etc/nginx"
sshx -h=prod-web "sudo install -m 0644 /tmp/nginx.conf /etc/nginx/nginx.conf"
Use SFTP for direct file movement. Use remote commands for checks, ownership changes, service reloads, and cleanup that requires sudo.