A WebSocket daemon for remote shell execution and interactive terminal sessions
Project description
shellwire
WebSocket daemon for remote shell access.
shellwire runs as a WebSocket server, providing a bridge that lets remote clients execute shell commands with full system access. It's designed to be a generic, client-agnostic solution that any WebSocket-compatible application can connect to.
Features
- Stable token auth — token generated once, persists across restarts
- Single client — one active connection at a time, with reconnection support
- Concurrent execution — up to 4 simultaneous commands
- Interactive PTY sessions (POSIX) — full pseudo-terminal support with dynamic resizing
- Environment Tracking — persistent working directory (CWD) and exported environment variables across commands
- Compound Command Rewriting — automatically rewrites bash chains (e.g.
A && B &->A && { B & }) for standard backgrounding - Robust Process Isolation — prevents zombie processes via process-group escalation kills (SIGTERM → SIGKILL) and protects against runaway output
- Health endpoint — HTTP GET
/healthon the same port
Installation
# Via pip
pip install shellwire
Or install from source:
git clone https://github.com/shantoislamdev/shellwire.git
cd shellwire
pip install -e ".[dev]"
Auto-venv Runners
If you clone the repository directly, you can use the included runner scripts which will automatically create a virtual environment (venv) and install dependencies for you:
- Unix / Linux:
./run.sh— Bootstraps the daemon insidevenv./test.sh— Runs the test suite insidevenv
- Windows:
run.bat— Bootstraps the daemon insidevenvtest.bat— Runs the test suite insidevenv
Quick Start
# Start the daemon (foreground)
shellwire start
# Start as background daemon
shellwire start --daemon
# Check status
shellwire status
# View your auth token
shellwire token show
# Stop the daemon
shellwire stop
On first start, a stable auth token is generated and displayed. Save it — you'll need it to connect your client.
Commands Reference
| Command | Description |
|---|---|
shellwire start |
Start the daemon |
shellwire start --daemon |
Start in background |
shellwire start --port 8080 |
Use a custom port |
shellwire run |
Run in foreground (alias) |
shellwire stop |
Stop the running daemon |
shellwire status |
Check if daemon is running |
shellwire version |
Print version |
shellwire token |
Show the auth token |
shellwire token show |
Show the auth token |
shellwire token rotate |
Generate a new token |
shellwire clients list |
List known clients |
shellwire clients revoke ID |
Revoke a client |
Connecting a Client
To connect a client to shellwire:
- Install
shellwirein your target environment - Run
shellwire startto start the daemon - Copy the auth token shown on first start
- In your client application, configure:
- Host: The IP address or hostname where shellwire is running (default:
127.0.0.1) - Port: The port shellwire is listening on (default:
7842) - Token: The auth token from step 3
- Host: The IP address or hostname where shellwire is running (default:
- Connect via WebSocket
The protocol is documented below for client implementers.
Protocol
All communication uses JSON over WebSocket. The client must send an auth message first:
{
"type": "auth",
"token": "your-auth-token",
"client_id": "my-client-abc123"
}
Then send commands:
{
"type": "execute",
"id": "cmd-001",
"command": "ls -la",
"cwd": "/var/log",
"env": {"FOO": "bar"},
"stdin_data": "optional input\n",
"is_pty": true,
"cols": 120,
"rows": 40,
"timeout": 30
}
Interactive PTY sessions can be dynamically resized:
{
"type": "resize",
"id": "cmd-001",
"cols": 150,
"rows": 50
}
The server streams output:
{"type": "output", "id": "cmd-001", "data": "total 42\n...", "stream": "stdout"}
{"type": "result", "id": "cmd-001", "exit_code": 0, "duration_ms": 123.4}
Health Check
curl http://127.0.0.1:7842/health
{
"status": "ok",
"version": "0.1.0",
"uptime_seconds": 3600.5,
"active_commands": 0,
"active_sessions": 0,
"python_version": "3.11.4"
}
Client-Side Utilities
If you are building a Python client that connects to shellwire, you can import and use several robust utilities we export for downstream consumers:
shellwire.output.strip_ansi(text: str) -> str: Fast ECMA-48 compliant regex utility for stripping terminal ANSI colors and escape sequences from output.shellwire.output.truncate_output(text: str, max_chars: int) -> tuple[str, bool]: Safely truncates massive output payloads while preserving the first 40% and last 60% of the stream so critical context isn't lost.
Configuration
All configuration is via CLI flags. Defaults:
| Setting | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Bind address |
--port |
7842 |
Listen port |
--log-level |
INFO |
Logging verbosity |
Data files are stored in ~/.shellwire/:
auth.token— the auth tokendaemon.pid— PID filedaemon.log— log fileclients.json— revoked client list
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=shellwire
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shellwire-0.0.0a2.tar.gz.
File metadata
- Download URL: shellwire-0.0.0a2.tar.gz
- Upload date:
- Size: 51.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5783c6932aecb40ba03eaf4417a8001c2d03693c65a989ff15fc60aa825a687
|
|
| MD5 |
d4607039851542fe227a1d3a4bfc95f9
|
|
| BLAKE2b-256 |
0d5009a4c38646dc83f28d39e3a95e7fd8b95e99e977ffce20822728d0b74e20
|
Provenance
The following attestation bundles were made for shellwire-0.0.0a2.tar.gz:
Publisher:
publish.yml on shantoislamdev/shellwire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shellwire-0.0.0a2.tar.gz -
Subject digest:
e5783c6932aecb40ba03eaf4417a8001c2d03693c65a989ff15fc60aa825a687 - Sigstore transparency entry: 1763429257
- Sigstore integration time:
-
Permalink:
shantoislamdev/shellwire@ec6ff6a67d5344c495e5315f05966227b4618697 -
Branch / Tag:
refs/tags/v0.0.0-alpha2 - Owner: https://github.com/shantoislamdev
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ec6ff6a67d5344c495e5315f05966227b4618697 -
Trigger Event:
push
-
Statement type:
File details
Details for the file shellwire-0.0.0a2-py3-none-any.whl.
File metadata
- Download URL: shellwire-0.0.0a2-py3-none-any.whl
- Upload date:
- Size: 45.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b04dbcfcd84cd34a5ab1e329562f5bc4c531843658abb498ccd544c89a0d789
|
|
| MD5 |
24c67f15b848344a911cade514cee006
|
|
| BLAKE2b-256 |
8e4ddf0aca0aa50abd8754ebacf3238633fceb8eaec539c411dcc61c73a8be1c
|
Provenance
The following attestation bundles were made for shellwire-0.0.0a2-py3-none-any.whl:
Publisher:
publish.yml on shantoislamdev/shellwire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shellwire-0.0.0a2-py3-none-any.whl -
Subject digest:
2b04dbcfcd84cd34a5ab1e329562f5bc4c531843658abb498ccd544c89a0d789 - Sigstore transparency entry: 1763429374
- Sigstore integration time:
-
Permalink:
shantoislamdev/shellwire@ec6ff6a67d5344c495e5315f05966227b4618697 -
Branch / Tag:
refs/tags/v0.0.0-alpha2 - Owner: https://github.com/shantoislamdev
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ec6ff6a67d5344c495e5315f05966227b4618697 -
Trigger Event:
push
-
Statement type: