CLI and Environment Variables
Next-release API: This page describes the updated source checkout. The published 3.1.4 wheel retains the earlier command/config/check behavior.
SSHScript v3.1 can run a regular Python file or a .spy file from the command line. The CLI deliberately accepts one script file at a time.
Run one script
After installing the package:
sshscript automation.spy
From a source checkout:
python3 src/sshscript/sshscript.py automation.spy
This form assumes the public release checkout’s src/ package layout. Ordinary users should use the installed sshscript command.
The path must name one existing regular file. Directories, globs, iterables, and multiple file paths are not supported. Compose a larger automation project with ordinary Python imports; run_file() temporarily enables peer .spy imports.
Arguments not consumed by the SSHScript CLI remain available to the script through sys.argv.
CLI options
| Option | Purpose |
|---|---|
-s, --script | Show converted Python source without executing it. |
-v, --verbose | Stream command stdout and stderr to the console. |
--stderr | Stream stderr only. |
-d, --debug [LEVEL] | Enable debug logging; the default debug level is 10. |
--traceback | Show the full exception traceback. |
--version | Print the installed SSHScript version. |
--check-updates | Check the latest compatible stable PyPI release; this requires Internet access. |
--check FILE | Compile Python/dollar syntax without executing user code, imports, or commands. |
--check without a file | Legacy alias for --check-updates; this accesses PyPI. |
For ordinary runtime exceptions, the default error record avoids printing command payloads. Syntax errors are different: even without --traceback, Python can print the filename, line, source text, and caret. Use --traceback only when its diagnostic value outweighs the risk; keep secrets out of source and review every diagnostic before sharing it.
Normal completion returns status 0. $.break(code) becomes the CLI process status, while $.exit(code) exits with the requested status.
Validate syntax without execution
sshscript --check automation.spy
The check accepts one file and returns 0 on success, 1 for syntax/read failure, and 2 for invalid CLI usage. It does not connect or execute user imports. It checks Python/dollar grammar, not shell syntax or import/host availability. Errors display the original filename, line, source, and caret without an internal traceback. --script remains the generated-source inspection option; it cannot be combined with --check FILE.
The Python equivalent is sshscript.check_file(path): it returns 0 on success and raises source-located SyntaxError or filesystem errors on failure.
Run from Python
sshscript.run_file() applies the same one-file rule:
import sshscript
status = sshscript.run_file("automation.spy")
The function accepts a str or os.PathLike path to one existing regular file and returns 0 after normal completion or the status supplied to $.break(status). It creates and closes a local Session, sets __name__ to "__main__", supplies __file__, and temporarily adds the script directory to sys.path.
Use sshscript.run_script(source) when the program already has source text in memory.
Import .spy modules explicitly
Importing SSHScript does not globally teach Python to load .spy files. Enable the importer only around imports that need it:
import sshscript
with sshscript.spy_imports():
import automation # loads automation.spy
spy_imports() is temporary, reversible, and safe to nest. run_file() enables it only while the selected script runs, so imports between .spy files work without leaving a process-wide importer installed.
Environment variables
Pass only the values a command needs:
from sshscript import Session
session = Session()
try:
session.exec_command(
"python3 -c \"import os; print(os.environ['DEPLOY_ENV'])\"",
shell=False,
env={"DEPLOY_ENV": "staging"},
)
finally:
session.close(strict=True)
Interactive SSH channels do not forward the complete local process environment. They send terminal and locale defaults (TERM, LC_ALL, and LANG) plus values explicitly provided by the caller. This prevents an unrelated local token or secret from being copied to a remote process.
KEEPALIVE_INTERVAL controls the SSH transport keepalive interval. Its default is 60 seconds; set it to 0 to disable keepalives for a process.
Process-wide behavior
Importing sshscript is intentionally quiet and scoped. It does not install the .spy importer, replace threading.Thread, change warning formatting, configure application logging, alter the environment, or replace the asyncio event-loop policy. CLI-specific logging and warning formatting are enabled only by the CLI.
See Contributing and Testing for the credential-free release gate and isolated integration-test guidance.
Last Updated: 2026-09-26 16:11:31