Metadata-Version: 2.4
Name: pycmdrun
Version: 1.2.2
Summary: Run shell commands with persistent directory context, logging, and color output.
Author: 
Author-email: Fede <fefindev@gmail.com>
License: MIT
Project-URL: Repository, https://github.com/FefinDev/cmdrun
Keywords: shell,subprocess,cli,command,runner,logging
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Shells
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: color
Requires-Dist: colorama>=0.4; extra == "color"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: colorama>=0.4; extra == "dev"
Dynamic: license-file
Dynamic: requires-python

# pycmdrun

[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![PyPI](https://img.shields.io/badge/pypi-pycmdrun-orange)](https://pypi.org/project/pycmdrun)

Run shell commands with **persistent directory context**, **full logging**, **color output**, and **log export**.

---

## Installation

```bash
pip install pycmdrun
```

With color support:

```bash
pip install pycmdrun[color]
```

---

## Quick start

```python
from pycmdrun import cmd

cmd.cd(r"C:\Users\Fede\Desktop")
cmd.run("echo Hello from pycmdrun")
cmd.run(["pip", "install", "numpy"])   # list form also works

print(cmd.log)
cmd.save_log("session.json", fmt="json")
```

---

## API

### `cmd.cd(path)` → `self`

Changes the working directory for all subsequent `run()` calls.

- Expands `~` and environment variables
- Raises `ValueError` if the directory does not exist
- Returns `self` so it can be chained: `cmd.cd("/tmp").run("ls")`

---

### `cmd.run(command, *, timeout, encoding, raise_on_error, env)` → `CommandResult`

Executes a command in the current working directory.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `command` | `str` or `list[str]` | — | Command to run |
| `timeout` | `float` | `None` | Kill after N seconds |
| `raise_on_error` | `bool` | `False` | Raise `RuntimeError` on non-zero exit |
| `env` | `dict` | `None` | Extra environment variables |

**`CommandResult` attributes:**

| Attribute | Type | Description |
|---|---|---|
| `.stdout` | `str` | Standard output |
| `.stderr` | `str` | Standard error |
| `.returncode` | `int` | Exit code (0 = success) |
| `.ok` | `bool` | `True` when `returncode == 0` |
| `.cwd` | `str` | Directory where the command ran |

---

### `cmd.log` *(property)*

Returns a formatted string with the full history of every `cd()` and `run()` call.

```
[1] 2026-01-15 10:30:00  |  cwd: /tmp
    $ echo Hello
    exit: 0
    stdout:
    Hello
```

---

### `cmd.save_log(path, *, fmt="txt")`

Exports the log to a file. `fmt` can be `"txt"` or `"json"`.

```python
cmd.save_log("session.txt")
cmd.save_log("session.json", fmt="json")
```

---

### `cmd.log_entries` *(property)*

Raw log as a `list[dict]` for programmatic access. Each entry has:
`timestamp`, `command`, `stdout`, `stderr`, `returncode`, `cwd`.

---

### `cmd.clear_log()`

Clears all log entries.

---

### `cmd.cwd` *(property)*

Returns the current working directory.

---

## Verbose mode

Prints each command and its result in real time as it runs:

```python
from pycmdrun import CommandRunner

cmd = CommandRunner(verbose=True)
cmd.cd("/tmp")
cmd.run("echo Hello")
```

Output:
```
  → cwd: /tmp
  $ echo Hello
  ✓ exit: 0
    Hello
```

---

## Color support

Install `colorama` to get colored output in the log and verbose mode:

```bash
pip install pycmdrun[color]
# or
pip install colorama
```

When saving logs to file with `save_log()`, ANSI color codes are automatically stripped.

---

## License

MIT © Fede
