Skip to main content

sioba_subprocess — subprocess/PTY interface for sioba

sioba_subprocess adds an exec:// interface to sioba so you can drive a local shell or program as an interactive terminal session behind the same async Interface API (screen buffer, cursor, callbacks, etc.).

  • POSIX: forks a child attached to a PTY (via pty, subprocess, termios) and mirrors stdout/stderr to the sioba buffer; window size changes are propagated with ioctl(TIOCSWINSZ) + SIGWINCH.
  • Windows: uses pywinpty to spawn and attach to a console app (e.g., cmd.exe or PowerShell), forwarding I/O to sioba’s buffer.

The package is discovered by sioba via entry point:
"sioba.interface".exec = "sioba_subprocess.interface:ShellInterface"


Installation

# sioba core + this plugin
pip install sioba sioba_subprocess
# or with uv
uv pip install sioba sioba_subprocess
  • Python ≥ 3.10
  • Windows: pywinpty installs automatically via extras.

Quickstart

Start your default shell

import asyncio
from sioba import interface_from_uri

async def main():
    # POSIX default: /bin/bash; Windows default: cmd.exe
    sh = await interface_from_uri("exec://").start()

    # capture everything the program prints
    screen = []
    sh.on_send_to_frontend(lambda _i, data: screen.append(data))

    # run a command
    await sh.receive_from_frontend(b"echo hello from sioba\r\n")
    await asyncio.sleep(0.2)  # give the subprocess a moment

    print(b"".join(screen).decode("utf-8", errors="replace"))
    await sh.shutdown()

asyncio.run(main())

Launch a specific program (absolute path)

import asyncio, sys, pathlib
from sioba import interface_from_uri

async def main():
# Start an interactive Python REPL
    py = pathlib.Path(sys.executable)
    iface = await interface_from_uri(f"exec:///{py}").start()

    await iface.receive_from_frontend(b"import hashlib\n")
    await iface.receive_from_frontend(b'hashlib.md5(b\"hello world\").hexdigest()\n')
    await asyncio.sleep(0.5)

    print(iface.get_terminal_buffer().decode("utf-8", "replace"))
    await iface.receive_from_frontend(b"exit()\n")
    await asyncio.sleep(0.2)

asyncio.run(main())

Pass arguments & working directory

You can pass arguments either as kwargs or via query params:

# kwargs (recommended)
sh = await interface_from_uri(
    "exec:///bin/bash",
    invoke_args=["-lc", "echo $PWD && ls -1"],
    invoke_cwd="/tmp",
).start()

# or query params (repeatable ?arg=…; values are strings)
sh = await interface_from_uri("exec:///bin/bash?arg=-lc&arg=echo%20hello").start()

Resizing the terminal & reading the screen

# tell the interface (and the PTY/console) about UI size changes
sh.update_terminal_metadata({"rows": 40, "cols": 120})

# snapshot of what the user would see
buf = sh.get_terminal_buffer()
print(buf.decode("utf-8", "replace"))

What you get

  • Interface: ShellInterface (scheme exec://) — inherits sioba’s Interface

  • Context: ShellContext (extends InterfaceContext)

    • invoke_args: list[str] — CLI args for the child process
    • invoke_cwd: Optional[str] — working directory for the child
  • Discovery: installed as a sioba plugin via entry point; after installation:

from sioba import list_schemes
assert "exec" in list_schemes()

URI reference

exec:///<ABSOLUTE_PATH>?arg=<value>&arg=<value>&invoke_cwd=<path>
  • Path: absolute path to the program. If omitted, defaults to:

    • POSIX: /bin/bash
    • Windows: cmd.exe
  • Query params

    • arg: repeatable; each occurrence becomes the next CLI argument.
    • invoke_cwd: working directory string.
  • General sioba params (handled by InterfaceContext.from_uri):

    • rows, cols, encoding, convertEol, auto_shutdown,
    • scrollback_buffer_uri (terminal:// by default), scrollback_buffer_size, etc.

Windows path tip: prefer exec:///C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe (leading slash is stripped automatically; forward slashes are OK).


Lifecycle & behavior

  • await iface.start() spawns the child attached to a PTY/console and begins reader threads.

  • I/O

    • await iface.receive_from_frontend(b"...\n") → writes to the child stdin/console.
    • Child output → await iface.send_to_frontend(...) → Buffer (ANSI aware if terminal://) → your callbacks.
    • End-of-line normalization honors convertEol (enabled by default).
  • Resize: update_terminal_metadata({"rows": R, "cols": C}) adjusts PTY/console size.

  • Shutdown

    • POSIX tries SIGTERM on the process group, then escalates to SIGKILL if needed.
    • Windows terminates via pywinpty.
    • If the child exits by itself, the interface transitions to InterfaceState.SHUTDOWN automatically and runs on_shutdown hooks.

Examples

Drop into PowerShell (Windows)

sh = await interface_from_uri(
    "exec:///C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe"
).start()

Minimal echo of everything printed

out = []
sh.on_send_to_frontend(lambda _i, data: out.append(data))

Troubleshooting

  • No output? Make sure you send a newline (\n) so the shell executes a line. On Windows, convertEol=True will handle \r\n vs \n.
  • Windows path parsing: Use exec:///C:/path/to/app.exe (triple slash + absolute path with drive letter). The implementation strips the leading / on Windows.
  • Separate stdout/stderr? Not currently split — both are merged into the PTY stream (see tests). TODO: consider optional channels for stderr.

Security

Launching exec:// runs arbitrary local programs. Do not feed untrusted URIs or user input to interface_from_uri without validation.


Developing & testing

# in this repo
uv sync
uv run pytest -q
# (or) pytest -q

The test suite demonstrates:

  • Spawning exec:///python and evaluating expressions interactively
  • Clean shutdown when the child exits or on request
  • Passing CLI args via ?arg= and handling error exit codes

License

MIT — see LICENSE.

Metadata

Release files for sioba-subprocess 0.4.20250925

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

Source distribution (sdist)

Source distribution for sioba-subprocess 0.4.20250925
File Size Uploaded Provenance
sioba_subprocess-0.4.20250925.tar.gz 8.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sioba-subprocess 0.4.20250925
File Interpreter ABI Platform
sioba_subprocess-0.4.20250925-py3-none-any.whl Python 3 none any Details

Total release size: 19.9 kB

Release files / sioba_subprocess-0.4.20250925.tar.gz

Download URL sioba_subprocess-0.4.20250925.tar.gz
Size 8.6 kB
Tags Source
SHA-256 checksum
How to use checksums
4470d07e685a9badcf36d3558908094faf204d3fc6dac88a5e92206003908955
BLAKE2b-256 checksum
How to use checksums
ea6e2a587bc37fccb7ca34e637d7b0f6dbed4a846556e78aa8483b008ab3907a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.14

Release files / sioba_subprocess-0.4.20250925-py3-none-any.whl

Download URL sioba_subprocess-0.4.20250925-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
441a5dbb47bf4ae76212e17c387d9794f6e1e80ea42e4969f8c514540a2cec0d
BLAKE2b-256 checksum
How to use checksums
511b7814b6902d2ff2e88c73df9a4133c9e349cb1cb1da37e78c454c6a3ec8db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.14

Security for sioba-subprocess 0.4.20250925

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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