Metadata-Version: 2.4
Name: doriemon
Version: 0.1.1
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.

Give it your backend, frontend, and workers. DorieMon starts them all and gives each one its own log pane. It colors errors and warnings. It can also pause any process **at the OS level**, so you can read its output line by line. Your source code stays as it is.

```
┌ 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

If you start five shell scripts with `&` in one terminal, their output mixes line by line. Separate terminal tabs lose the shared view. DorieMon keeps each process in its own pane. It also does what tabs cannot: it stops a noisy process with `SIGSTOP`, steps it forward one burst at a time, then lets it run again. You need no debugger and no code changes.

## Features

- **One TUI, many processes**: each process gets its own log pane. Start them all at once, or in order.
- **OS-level step and pause**: stop and resume a process with POSIX `SIGSTOP`/`SIGCONT`. Step through its output burst by burst. This works for any language, with no changes to your code.
- **Focus and live filter**: show one process only, or filter its lines as you type.
- **Error and warning colors**: DorieMon colors `ERROR`, `CRITICAL`, `WARN`, and similar words. It matches whole words only, so "0 errors" stays plain.
- **Copy the last error**: `e` selects the crash and all lines after it. `↑`/`↓` change the selection, and `c` copies it. Paste it into a search box or a chat, with the stack trace in one piece.
- **Scroll up to read**: a pane follows new output only while you are at the bottom. Scroll up, and the view stays where you are while new lines collect below. Scroll back to the bottom, and the pane follows again.
- **Pane colors show the state**: green while the process runs, **yellow while it is paused**, dim after a clean exit, and red after a failure.
- **Clear exit codes**: a finished pane shows `exited 0`, `exited (3)`, or `killed SIGKILL`. A clean exit does not look like a crash, and an out-of-memory kill does not look like `exit 1`.
- **Real TTY behavior**: each process runs under a PTY, so its output comes line by line, as in a real terminal. Signals go to the whole process group, not only to the shell that started it.
- **Scripts run from their own folder**: DorieMon starts each script in the folder that holds it. A line such as `source venv/bin/activate` or `npm run dev` finds the files next to the script, wherever you start `doriemon`.
- **Restart** any process, in normal mode or in step mode, from inside the UI.

## Requirements

- Python 3.9 or later (Textual 8 needs it)
- Linux or macOS. DorieMon uses POSIX signals and PTYs, so it does not run on Windows.

## Install

```bash
pip install doriemon
```

This installs the `doriemon` command. To work on DorieMon itself, clone the repository and run:

```bash
pip install -e .
```

## Quick start

Run some scripts:

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

Or write a project config one time, then run `doriemon` with no arguments:

```bash
doriemon init      # finds .sh scripts, asks which to use, writes doriemon.py
doriemon           # runs the processes in doriemon.py
```

`doriemon init` can also wrap a command such as `npm run dev` in a new `.sh` script for you.

Start all processes paused, then step through their output:

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

## Scripts

DorieMon runs a script with the execute bit (`chmod +x`) as a program, so the shebang line picks the interpreter. It runs all other scripts with `/bin/sh`. If a script has the execute bit but no shebang line, DorieMon also runs it with `/bin/sh`.

Each script starts in its own folder, not in the folder where you started `doriemon`.

## Configuration

`doriemon init` writes a `doriemon.py` file in your project root. The file is plain Python:

```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 relative to `doriemon.py`. Command-line flags override these settings. DorieMon looks for the config in the current folder first, then in each parent folder.

> DorieMon **runs** `doriemon.py` as code. It does not only read it. This is the same trust model as a `Makefile` or a `conftest.py`. The search goes up through the parent folders, so `doriemon` in a new clone runs the config of that repository. Read the file first, as you read any build file.

### Flags

| Flag | Effect |
|------|--------|
| `--step` | Start every process paused. Advance the output with `Space` |
| `--sequential` | Start the processes in order, each after the last one starts. The default starts them all at once |

## Keys

Press `?` in the app to see this list.

| Key | Action |
|-----|--------|
| `1`–`9` | Focus a process (show only its log) |
| `s` | Turn step mode on or off for the focused process |
| `Space` | Advance a paused process by one output burst. In focus view, this is the focused process. In the overview, it is the process that is paused for the longest time |
| `S` | Restart all processes in step mode |
| `e` | Select the last error. Press again to go back to an older one |
| `↑` / `↓` | Make the error selection larger or smaller from the top |
| `c` | Copy the selection to the clipboard |
| `:` | Open the command bar |
| `?` | Show the key reference |
| `Esc` | Go back, close the command bar, or cancel a selection |
| `q` | Quit |

### Copy an error

Press `e` on a focused pane. DorieMon selects the lines from the last error to the end of the log. Then change the selection and copy it:

| Key | Action |
|-----|--------|
| `↑` | Move the top edge up (more lines above the error) |
| `↓` | Move the top edge down (a smaller selection) |
| `e` | Move the start back to an older error |
| `c` | Copy the selection to the clipboard |
| `Esc` | Cancel |

The start of the selection is a guess. It often lands part of the way into a stack trace, and `↑` gets the rest. The patterns are in [`doriemon/errors.py`](doriemon/errors.py), in groups for each language: Python, Node/tsc, Java, Go, Rust, Ruby, plus general level words and test-runner failures. DorieMon tries every pattern on every process, because one pane can run more than one language. If your logs use a format of their own, add a pattern there. If no pattern matches, `e` selects the last lines of the log, so you still get text to paste.

### Command bar

Press `:` to open it. Each command starts with a number. `<n>` is a process number. With no number, the command acts on the focused process, or on all processes:

| Command | Action |
|---------|--------|
| `f` / `<n>f` | Live search: filter the lines as you type (`Enter` keeps the filter, `Esc` clears it) |
| `<n>s` | Turn step mode on or off for process `n` |
| `<n>S` | Restart process `n` in step mode |
| `<n>r` | Restart process `n` in normal mode |
| `<n>` | Focus process `n`. Use this for panes past the `1`–`9` keys |
| `<n>e` | Focus 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. To step or pause, DorieMon sends `SIGSTOP` to the whole process **group** (`killpg`), and the kernel stops the process where it is. `Space` (or resume) sends `SIGCONT`. The OS stops the process, so your code does not need to help. It works the same for 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, no-shebang, script dir)
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

MIT. See [LICENSE](LICENSE).
