Metadata-Version: 2.4
Name: doriemon
Version: 0.1.0
Summary: Terminal multi-process monitor (TUI)
Author-email: Sidharth Bhatla <sidharth.bhatla@convegenius.ai>
License-Expression: MIT
Project-URL: Homepage, https://github.com/s-bhatla/DorieMon
Project-URL: Issues, https://github.com/s-bhatla/DorieMon/issues
Keywords: tui,process,monitor,logs,devtools
Classifier: Environment :: Console
Classifier: Operating System :: POSIX
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Debuggers
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: textual<9,>=8
Dynamic: license-file

# DorieMon

**D**evelopment **Ori**ented **Mon**itor — run, watch, and control several local dev processes in one terminal UI.

Point it at your backend, frontend, and workers; DorieMon launches them all, gives each its own log pane, color-codes errors and warnings, and lets you pause any process **at the OS level** to read its output line-by-line — without touching your source.

```
┌ backend ─────────────┐ ┌ frontend ────────────┐ ┌ worker ──────────────┐
│ INFO  listening :8000│ │ ready in 412 ms      │ │ picked up job #1204  │
│ ERROR db timeout     │ │ WARN  slow HMR update│ │ done in 1.2s         │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
```

## Why

`&`-ing five shell scripts into one terminal interleaves their output into mush. Separate terminal tabs lose the shared view. DorieMon keeps each process isolated in its own pane, and adds the thing tabs can't: **freeze a runaway process mid-flood** with `SIGSTOP`, step it forward one burst at a time, then let it run again — no debugger, no code changes.

## Features

- **One TUI, many processes** — each in its own log pane, launched in parallel or in sequence.
- **OS-level step & pause** — freeze/resume a process with POSIX `SIGSTOP`/`SIGCONT`; step through its output burst by burst. Works for any language, no instrumentation.
- **Focus & live filter** — zoom into a single process, or filter its lines as you type.
- **Error/warning highlighting** — `ERROR`, `CRITICAL`, `WARN`, … color-coded (word-boundary matched, so "0 errors" stays quiet).
- **Grab the last error** — `e` highlights the crash and everything after it, `↑`/`↓` adjust the region, `c` copies it. Straight into a search box or a chat window, stack trace intact.
- **State-colored panes** — each pane's frame reflects its process at a glance: green running, **yellow while paused**, dull once it exits cleanly, red when it doesn't.
- **Exit codes you can read** — a finished pane says `exited 0`, `exited (3)`, or `killed SIGKILL`, so a clean shutdown never looks like a crash and an OOM-kill never looks like `exit 1`.
- **Real TTY behavior** — processes run under a PTY, so output is line-buffered like a real terminal, and signals hit the whole process group, not just the launcher shell.
- **Restart** any process (normally or into step mode) without leaving the UI.

## Requirements

- Python ≥ 3.9 (Textual 8 requires it)
- Linux or macOS (uses POSIX signals + PTYs; no Windows)

## Install

```bash
pip install .
# or, for development:
pip install -e .
```

This installs the `doriemon` command.

## Quick start

Run some scripts directly:

```bash
doriemon examples/backend.sh examples/frontend.sh
```

Or set up a project config once and just run `doriemon`:

```bash
doriemon init      # scans for .sh scripts, writes doriemon.py
doriemon           # runs the processes in doriemon.py
```

Start everything paused and step through output:

```bash
doriemon --step examples/*.sh
```

## Configuration

`doriemon init` writes a `doriemon.py` in your project root — plain Python, no YAML to fight:

```python
PROCESSES = [
    {"label": "backend",  "script": "backend/run.sh"},
    {"label": "frontend", "script": "frontend/run.sh"},
]
# SEQUENTIAL = True    # launch in order, each waiting for the last (same as --sequential)
# STEP = True          # start every process paused (same as --step)
```

Script paths are resolved relative to `doriemon.py`. CLI flags override these. DorieMon searches from the current directory upward for the config.

> `doriemon.py` is **executed**, not parsed — same trust model as a `Makefile` or a `conftest.py`. Since the search walks *upward*, `doriemon` in a fresh clone runs that repo's config as code. Read it first, as you would any build file.

### Flags

| Flag | Effect |
|------|--------|
| `--step` | Start every process paused; advance output with `Space` |
| `--sequential` | Launch in order (each waits for the last) instead of all at once |

## Keys

Press `?` in the app for this list at any time.

| Key | Action |
|-----|--------|
| `1`–`9` | Focus a process (show just its log) |
| `s` | Toggle step mode on the focused process |
| `Space` | Advance a paused process by one output burst — the focused one, or (in overview) whichever has been paused longest |
| `S` | Restart every process in step mode |
| `e` | Select the last error (press again to step back to an older one) |
| `↑` / `↓` | Widen / narrow the error selection from the top |
| `c` | Copy the selection to the clipboard |
| `:` | Open the command bar |
| `?` | Show the key reference |
| `Esc` | Back / close the command bar / cancel a selection |
| `q` | Quit |

### Grab an error

Press `e` on a focused pane and DorieMon highlights from the last thing that looks like an error down to the end of the log — then you adjust it and copy:

| Key | Action |
|-----|--------|
| `↑` | Pull the top edge up (more context above the error) |
| `↓` | Push it down (narrow the selection) |
| `e` | Jump the anchor back to an older error |
| `c` | Copy the highlighted region to the clipboard |
| `Esc` | Cancel |

The anchor is a guess — it often lands part-way into a stack trace, and `↑` is how you take the rest. Patterns live in [`doriemon/errors.py`](doriemon/errors.py), grouped by ecosystem (Python, Node/tsc, Java, Go, Rust, Ruby, plus generic level keywords and test-runner failures); every pattern is tried against every process, since one pane can run several runtimes. Add your own there if your logs have a house format. If nothing matches at all, `e` selects the tail so you still have something to paste.

### Command bar

Open with `:`. Commands are number-first — `<n>` is a process number; blank means the focused process (or all):

| Command | Action |
|---------|--------|
| `f` / `<n>f` | Live search: filter lines as you type (`Enter` keeps it, `Esc` clears) |
| `<n>s` | Toggle step on process `n` |
| `<n>S` | Restart process `n` in step mode |
| `<n>r` | Restart process `n` normally |
| `<n>` | Focus process `n` — the only route to panes past the `1`–`9` hotkeys |
| `<n>e` | Zoom to process `n` and select its last error |
| `help` | Show the key reference (same as `?`) |

## How step mode works

Each process runs in its own session and process group (`setsid`) under a PTY. When you step or pause, DorieMon sends `SIGSTOP` to the whole process **group** (`killpg`) — the kernel freezes it wherever it was. `Space` (or resume) sends `SIGCONT`. Because this is the OS suspending the process, it needs zero cooperation from your code and works identically across Python, Node, Go, or a shell script.

## Development

```bash
python -m doriemon.palette     # module self-check (every role resolves to a hue)
python -m doriemon.highlight   # module self-check (log-level detection)
python -m doriemon.errors      # module self-check (error anchor scan, per ecosystem)
python -m doriemon.process     # module self-check (PTY, group signals, teardown)
python -m doriemon.manager     # module self-check (launch, restart, SIGKILL escalation)
python -m doriemon.cli         # module self-check (config, overwrite guard, flags)
python test_app.py             # headless UI smoke test
python -m build                # build sdist + wheel into dist/
```

## License

No license yet — add one before publishing if you want others to reuse it.
