Metadata-Version: 2.4
Name: netscript
Version: 2.1
Summary: toml version
Author: Grey Liedtke
Author-email: grey.liedtke@gmail.com
License-Expression: MIT
Project-URL: Homepage, https://github.com/pypa/sampleproject
Project-URL: Issues, https://github.com/pypa/sampleproject/issues
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: author-email
Dynamic: license-file

# NetScript

A lightweight Python utility for running and monitoring scripts (`.py`, `.sh`, or any shell command) from a live web dashboard. Built on Flask with no external dependencies beyond the standard library and Flask itself.

## features

- start and stop scripts from a browser UI
- live log streaming via server-sent events — no page reloads
- per-line log colorization (errors, warnings, info)
- status polling every 2 seconds with in-place card updates
- clean process teardown: SIGTERM with a 5s timeout, SIGKILL fallback
- works with Python scripts, shell scripts, or any arbitrary command

## install

```bash
pip install netscript
```

## usage

```python
from pathlib import Path
from process_manager import ProcessManager, ScriptSpec

scripts = {
    "pipeline": ScriptSpec(
        Path("jobs/data_pipeline.py"),
        ["python", "jobs/data_pipeline.py"]
    ),
    "server": ScriptSpec(
        Path("jobs/api_server.py"),
        ["python", "jobs/api_server.py", "--port", "8080"]
    ),
    "backup": ScriptSpec(
        Path("jobs/backup.sh"),
        ["bash", "jobs/backup.sh"]
    ),
}

manager = ProcessManager(job_root=Path("jobs"), scripts=scripts)
app = manager.create_flask_app()

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
```

Then open `http://localhost:5000` in your browser.

## dynamic commands

If the command needs to be constructed at runtime (e.g. pulling config from a file or environment), pass a callable instead of a list:

```python
import os

def build_cmd():
    return ["python", "worker.py", "--env", os.environ["APP_ENV"]]

scripts = {
    "worker": ScriptSpec(Path("worker.py"), build_cmd)
}
```

The callable is invoked each time the script is started.

## log files

Each script writes stdout and stderr to a `.log` file next to the script file. For a script at `jobs/data_pipeline.py`, the log is written to `jobs/data_pipeline.log`. Logs persist across restarts and can be tailed directly from the terminal:

```bash
tail -f jobs/data_pipeline.log
```

## api endpoints

The Flask app exposes a small REST API alongside the dashboard UI.

| method | path | description |
|--------|------|-------------|
| GET | `/` | dashboard UI |
| GET | `/api/status` | JSON status of all scripts |
| POST | `/api/start/<key>` | start a script by key |
| POST | `/api/stop/<key>` | stop a script by key |
| GET | `/api/log/<key>` | last 200 lines of log |
| GET | `/api/log/<key>/stream` | SSE stream of new log lines |

Example status response:

```json
{
  "pipeline": { "label": "data_pipeline.py", "status": "running", "pid": 12345 },
  "server":   { "label": "api_server.py",    "status": "stopped", "pid": null }
}
```

## notes

- processes that daemonize themselves (fork and detach) will not be tracked correctly — this tool is intended for foreground processes
- the dashboard does not persist state across server restarts; any running processes will be orphaned if the Flask server exits
- for always-on services, consider systemd instead; this tool is best suited for on-demand or development workloads
