Metadata-Version: 2.4
Name: stui-terminal
Version: 0.1.0rc2
Summary: A tiny Streamlit-inspired terminal UI experiment.
Author: MarMar Labs
License-Expression: MIT
Project-URL: Homepage, https://github.com/marmar9615-cloud/stui-terminal
Project-URL: Repository, https://github.com/marmar9615-cloud/stui-terminal
Project-URL: Issues, https://github.com/marmar9615-cloud/stui-terminal/issues
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rich>=13.7
Requires-Dist: textual>=0.89
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.8; extra == "dev"
Requires-Dist: twine>=5.1; extra == "dev"
Dynamic: license-file

# stui

[![CI](https://github.com/marmar9615-cloud/stui-terminal/actions/workflows/ci.yml/badge.svg)](https://github.com/marmar9615-cloud/stui-terminal/actions/workflows/ci.yml)

`stui` is a tiny Streamlit-inspired framework for building terminal-native
Python apps. Write a short script, run it in your terminal, and get a Textual UI
with stateful controls.

It is built for local tools, demos, data scripts, model debug panels, SSH
sessions, and headless environments where opening a browser, binding a port, or
running a dashboard server is unnecessary ceremony. The public API is
deliberately small and readable.

`stui` is not official Streamlit, is not affiliated with Streamlit, and is not a
Streamlit compatibility layer. The API intentionally feels familiar, but this
project keeps its own smaller surface area.

## Preview

![stui model demo terminal screenshot](assets/model_demo.svg)

```text
┌─ stui ───────────────────────────────────────────┐
│ stui demo                                        │
│                                                  │
│ x                                                │
│ [██░░░░░░░░░░░░] 10                              │
│                                                  │
│ [ Increment ]                                    │
│                                                  │
│ x = 10                                           │
│ count = 0                                        │
│                                                  │
│ q Quit   r Rerun   tab Focus next                │
└──────────────────────────────────────────────────┘
```

## Install

Use Python 3.11 or newer.

Install the PyPI distribution named `stui-terminal`:

```bash
python3.11 -m pip install stui-terminal
```

The PyPI distribution name is `stui-terminal`, but the import package and CLI
are both `stui`:

```python
import stui as st
```

For local development from a checkout, use an editable install with the dev
extra:

```bash
python3.11 -m venv .venv
. .venv/bin/activate
python3.11 -m pip install -e ".[dev]"
```

For runtime-only local use, install without the dev extra:

```bash
python3.11 -m pip install -e .
```

## Quickstart

Install from PyPI, then run your app:

```bash
python3.11 -m pip install stui-terminal
stui run app.py
```

Or set up the project from source and run the basic example:

```bash
git clone https://github.com/marmar9615-cloud/stui-terminal.git
cd stui-terminal
python3.11 -m venv .venv
. .venv/bin/activate
python3.11 -m pip install -e ".[dev]"
stui run examples/basic.py
```

You can also run through the module entry point:

```bash
python3.11 -m stui run examples/counter.py
```

Scripts use the public `stui` API:

```python
import stui as st

st.title("stui demo")

if "count" not in st.session_state:
    st.session_state.count = 0

value = st.slider("value", 0, 100, 25)

if st.button("Increment"):
    st.session_state.count += 1

st.write("value =", value)
st.write("count =", st.session_state.count)
```

More examples:

```bash
stui run examples/counter.py
stui run examples/model_demo.py
```

## Why terminal-native?

Some useful Python apps do not need a browser runtime. `stui` keeps the
interface inside the terminal so it can fit naturally into:

- SSH sessions, remote machines, and headless boxes.
- Internal tools where opening ports or managing local server URLs is friction.
- Offline or locked-down environments where browser access is limited.
- Model, data, and DevOps workflows that already start from a shell.

That also keeps the boundary simple: `stui` does not start a web server, use
websockets, require port-forwarding, or depend on Streamlit at runtime.

## Commands

```bash
# Install the project for local development.
python3.11 -m venv .venv
. .venv/bin/activate
python3.11 -m pip install -e ".[dev]"

# Run the smoke-size example app.
stui run examples/basic.py

# Run the stateful counter example.
stui run examples/counter.py

# Run the deterministic model-parameter demo.
stui run examples/model_demo.py

# Run the test suite.
python3.11 -m pytest
```

## Keyboard Shortcuts

- `q`: quit the app
- `r`: rerun the script
- `tab`: focus the next widget
- `enter`: press the focused button
- `left` or `h`: decrease the focused slider
- `right` or `l`: increase the focused slider
- `home`: set the focused slider to its minimum value
- `end`: set the focused slider to its maximum value

## Current API

The current public API is intentionally small:

- `st.title(body, *, key=None)`: render a title.
- `st.header(body, *, key=None)`: render a section header.
- `st.text(body)`: render plain text.
- `st.markdown(body)`: render Markdown-flavored text.
- `st.divider()`: render a horizontal divider.
- `st.info(body)`, `st.success(body)`, `st.warning(body)`, `st.error(body)`: render status messages.
- `st.write(*args)`: render simple text output.
- `st.button(label, key=None, help=None, disabled=False, on_click=None, args=None, kwargs=None)`: render a button and return `True` for the run where it was pressed.
- `st.slider(label, min_value=0, max_value=100, value=None, step=1, *, key=None, help=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a numeric slider and return its current value.
- `st.text_input(label, value="", *, key=None, placeholder=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a single-line text input and return its current value.
- `st.checkbox(label, value=False, *, key=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a checkbox and return its current value.
- `st.session_state`: persist values across reruns with dict-style or attribute-style access.
- `st.rerun()`: request a script rerun.

Import the API as:

```python
import stui as st
```

## Examples

### Counter

`examples/counter.py` shows a minimal stateful app with increment, decrement, and
reset controls.

```bash
stui run examples/counter.py
```

### Model Demo

`examples/model_demo.py` shows a small model-parameter playground using text
input, checkbox, sliders, status messages, session state, and deterministic
scoring. It is intentionally local and fake: there are no network calls or model
dependencies.

```bash
stui run examples/model_demo.py
```

## Limitations

- No browser, web server, websocket, or port-forwarding runtime.
- No Streamlit dependency and no promise of Streamlit compatibility.
- No charts, tables, dataframes, forms, columns, sidebars, or file upload yet.
- Slider input supports numeric values only.
- Layout is currently linear and script-driven.
- The app reruns the script as interactions change state, so examples should keep top-level work lightweight.
- Error handling is still early and meant for development feedback.
- The package is an MVP and has not stabilized a long-term compatibility policy.

## Roadmap

- Add small text output helpers such as `caption`.
- Add common controls such as `selectbox`, `radio`, and number inputs.
- Add simple display primitives for tables and progress.
- Improve focus behavior, accessibility hints, and keyboard discoverability.
- Expand example coverage for data scripts, model controls, DevOps panels, and internal tools.
- Keep the implementation clean-room, readable, and based on Textual first-party widgets where possible.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for the local development workflow and
project boundaries.
