Metadata-Version: 2.4
Name: shout-run-sdk
Version: 0.1.0
Summary: Python SDK for shout.run — programmatic terminal broadcasting
Project-URL: Homepage, https://shout.run
Project-URL: Repository, https://github.com/pavanmadiraju91/shout-run
Project-URL: Documentation, https://github.com/pavanmadiraju91/shout-run/tree/main/packages/sdk-python
Author: Pavan Madiraju
License-Expression: MIT
License-File: LICENSE
Keywords: agent,ai,broadcast,live,sdk,streaming,terminal
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: requests>=2.28.0
Requires-Dist: websocket-client>=1.6.0
Description-Content-Type: text/markdown

# shout-run-sdk

Python SDK for [shout.run](https://shout.run) — programmatic terminal broadcasting.

Let AI agents and scripts broadcast live terminal sessions that anyone can watch.

## Install

```bash
pip install shout-run-sdk
```

## Quick Start

```python
from shout_sdk import ShoutSession

session = ShoutSession(api_key='shout_sk_...')
info = session.start(title='My Agent Session')
print(f"Live at: {info['url']}")

session.write('Hello, world!\r\n')
# ... do work ...

session.end()
```

## Context Manager

```python
from shout_sdk import ShoutSession

with ShoutSession(api_key='shout_sk_...') as session:
    info = session.start(title='My Agent')
    session.write('Working...\r\n')
    # session.end() called automatically
```

## Getting an API Key

1. Log in to shout.run with GitHub
2. Create an API key:

```bash
curl -X POST https://api.shout.run/api/keys \
  -H "Authorization: Bearer <your-jwt>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Agent"}'
```

The response includes your `key` — save it securely, it's shown only once.

## API Reference

### `ShoutSession(api_key, **kwargs)`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | `str` | *required* | API key (starts with `shout_sk_`) |
| `title` | `str` | `'SDK Session'` | Session title shown to viewers |
| `visibility` | `str` | `'public'` | `'public'`, `'followers'`, or `'private'` |
| `cols` | `int` | `80` | Terminal columns |
| `rows` | `int` | `24` | Terminal rows |
| `api_url` | `str` | `'https://api.shout.run'` | API base URL |

### Methods

- **`start()`** — Creates the session and connects WebSocket. Returns `{'session_id', 'url', 'ws_url'}`.
- **`write(data)`** — Sends terminal output (`str` or `bytes`). Automatically buffered, rate-limited, and chunked.
- **`resize(cols, rows)`** — Updates terminal dimensions.
- **`end()`** — Flushes buffer, sends end frame, closes session.

### Properties

- **`state`** — Current state: `SessionState.IDLE`, `.CONNECTING`, `.LIVE`, `.ENDING`, `.ENDED`
- **`viewers`** — Current viewer count
- **`session_id`** — Session ID (`None` before start)

### Events

```python
session.on('connected', lambda: print('Connected!'))
session.on('disconnected', lambda code, reason: print(f'Disconnected: {code}'))
session.on('reconnecting', lambda attempt: print(f'Reconnecting #{attempt}'))
session.on('viewers', lambda count: print(f'Viewers: {count}'))
session.on('error', lambda err: print(f'Error: {err}'))
session.on('state_change', lambda state: print(f'State: {state}'))
```

### Piping Subprocess Output

```python
import subprocess
from shout_sdk import ShoutSession

session = ShoutSession(api_key='shout_sk_...')
info = session.start(title='Running tests')

proc = subprocess.Popen(
    ['pytest', '-v'],
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
)

for line in proc.stdout:
    session.write(line)

proc.wait()
session.end()
```

## License

MIT
