Skip to main content

SSHScript

CI CodeQL

SSHScript is a Python automation library and .spy script runner for executing commands locally or over SSH. It provides a regular Python Session API and a compact dollar syntax for automation scripts.

Installation

SSHScript requires Python 3.11 or newer.

Use sshscript --version to display the installed version, or sshscript --check-updates to query PyPI for a newer stable release compatible with the current Python version. The check only prints an upgrade command; it does not install anything. --check remains an alias. A failed query exits with status 1; a successful check exits with status 0, whether an update exists or not. This checks release Python requirements, not dependency resolution or platform availability.

python3 -m pip install sshscript

For a release checkout containing src/sshscript/, python3 -m pip install . installs that checkout. The flat development checkout is not an installable package; use the following checks instead:

python3 -m pip install 'paramiko>=2.11,<5' 'packaging>=21' build twine
python3 tools/run_checks.py
python3 tools/check_release.py --output /tmp/sshscript-candidate-UNIQUE

See RELEASING.md for synchronization and publishing. SSHScript 3.1 is the supported production line; a GitHub source update does not by itself publish a new version to PyPI. See the v3.1 documentation.

Python API

from sshscript import Session

session = Session()
try:
    stdout, stderr = session.exec_command("uname -a", shell=False)
    print(str(stdout))
    print(session.exitcode)
finally:
    session.close(strict=True)

Pass command arguments as a safely quoted string, for example with shlex.join(), and use shell=False when shell expansion is not required.

Running .spy files

sshscript automation.spy

The CLI and run_file() execute exactly one file. Directories, globs, and multiple paths are intentionally unsupported. Compose larger automation with SSHScript include syntax or ordinary Python imports.

Importing SSHScript does not globally enable Python imports of .spy files. Use the explicit, temporary importer when a regular Python program needs one:

import sshscript

with sshscript.spy_imports():
    import automation  # loads automation.spy

run_file() enables this importer only for the duration of the script, so imports between .spy files continue to work without additional setup. Threads created with threading.Thread(...) inside a .spy file inherit the session that is active when the thread is constructed, without patching the process-wide threading.Thread class.

SSH host-key security

SSH connections verify system host keys by default and reject unknown or changed keys. Load the server key into known_hosts before connecting.

Accepting a new key without verification must be an explicit decision:

import paramiko

remote = session.connect(
    "user@new-host.example",
    policy=paramiko.AutoAddPolicy(),
)

Do this only in a trusted bootstrap environment. Interactive SSH sessions do not forward the complete local process environment; only terminal/locale defaults and values explicitly supplied through env={...} are sent.

Tests

The canonical credential-free release gate is:

python3 tools/run_checks.py

It includes normal and optimized unit tests, compile checks, the package assert scan, and the .spy language smoke suite. Public CI additionally provisions a disposable loopback OpenSSH server to validate real SSH, SFTP, host-key, PTY, sudo/su and timeout behavior against the built wheel.

The .spy language smoke suite can also be run directly:

python3 sshscript.py unittest/dollar_syntax.spy

Site-specific and credentialed SSH tests live under unittest-v3/ and are not part of the default release gate. See CONTRIBUTING.md before running them.

Project status

Version 3.1 is production/stable software. Public behavior is covered by the credential-free release gates and isolated OpenSSH integration CI. Operators should still validate site-specific PAM, sudoers, network and host-key policy in a disposable environment before production rollout.

SSHScript is released under the MIT License. See SUPPORT.md, SECURITY.md, CONTRIBUTING.md, and CHANGELOG.md for project policies and release history.

Production exception contract

SSHScript validates runtime inputs in both normal and optimized Python modes. See the stable exception matrix. AssertionError was never a supported SSHScript API contract. User-written .spy assertions remain ordinary Python assertions: python -O removes them. Production scripts must use explicit status checks or check=True for command-success handling.

with Session() as session:
    session.exec_command("false", check=True)

A nonzero exit status otherwise remains result data, available as session.exitcode.

Release files for sshscript 3.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sshscript 3.1.4
File Size Uploaded
sshscript-3.1.4.tar.gz 125.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sshscript 3.1.4
File Interpreter ABI Platform
sshscript-3.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 218.6 kB

Release files / sshscript-3.1.4.tar.gz

Download URL sshscript-3.1.4.tar.gz
Size 125.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e479fb93ad3fac4fd7f5e6b25fcc09d774c0b648999f26db85dab6f7549ca43b
BLAKE2b-256 checksum
How to use checksums
e37dbdba376d8ea576199865fdc347b42526f382c9bbf773a3b2f80188c7055c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / sshscript-3.1.4-py3-none-any.whl

Download URL sshscript-3.1.4-py3-none-any.whl
Size 93.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c9a9a05bd7567e2800515a56e86a1820c9c930e67bf479070948bb86a5aeddb
BLAKE2b-256 checksum
How to use checksums
e30376030b63606837d58f08c47b27647c6f1b5518227c513b919a0692204335
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.1.4 This release

2 release files

2.0.2

1 release file

1.1.17

1 release file

1.1.16

1 release file

1.1.14

1 release file

1.1.12

1 release file

1.1.7

1 release file

1.1.6

1 release file

0.992

1 release file

0.986

1 release file

0.985

1 release file

0.984

1 release file

0.983

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page