Metadata-Version: 2.4
Name: termish
Version: 0.1.2
Summary: Virtual terminal with shell-like commands over a pluggable filesystem.
Author: ashenfad
License-Expression: MIT
Project-URL: Homepage, https://github.com/ashenfad/termish
Project-URL: Bug Tracker, https://github.com/ashenfad/termish/issues
Project-URL: Documentation, https://github.com/ashenfad/termish#readme
Project-URL: Source, https://github.com/ashenfad/termish
Keywords: terminal,shell,virtual,filesystem,commands,jq
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Shells
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: ruff; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: monkeyfs; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: monkeyfs; extra == "test"
Dynamic: license-file

# termish 📺

Virtual terminal with shell-like commands over a pluggable filesystem.

Parses and executes shell scripts (pipelines, redirects, semicolons) against any object that implements the `FileSystem` protocol. Zero runtime dependencies. Pure Python.

## Features

- **Shell parser** -- pipes, redirects (`>`, `>>`, `<`), semicolons, quoted strings, line continuation
- **30 builtins** -- ls, cat, grep, find, sed, tr, sort, uniq, cut, wc, diff, tar, gzip, zip, jq, xargs, basename, dirname, ...
- **jq engine** -- built-in jq filter parser and evaluator (field access, pipes, functions, conditionals)
- **Pluggable filesystem** -- `FileSystem` is a `typing.Protocol`; any object with the right methods works
- **MemoryFS included** -- in-memory filesystem for testing and lightweight use

## Install

```bash
pip install termish
```

## Quick example

```python
from termish import execute, MemoryFS

fs = MemoryFS()

execute("mkdir -p src", fs)
execute("echo 'def main(): pass' > src/app.py", fs)
execute("echo 'import os' > src/utils.py", fs)

# Pipelines work
output = execute("grep -r 'def' src | wc -l", fs)
print(output)  # 1

# jq works
execute('echo \'{"name": "alice", "score": 42}\' > data.json', fs)
output = execute('jq -r ".name" data.json', fs)
print(output)  # alice
```

## FileSystem protocol

Any object implementing these 16 methods works with termish -- no inheritance required:

```python
class FileSystem(Protocol):
    def getcwd(self) -> str: ...
    def chdir(self, path: str) -> None: ...
    def read(self, path: str) -> bytes: ...
    def write(self, path: str, content: bytes, mode: str = "w") -> None: ...
    def exists(self, path: str) -> bool: ...
    def isfile(self, path: str) -> bool: ...
    def isdir(self, path: str) -> bool: ...
    def stat(self, path: str) -> FileMetadata: ...
    def mkdir(self, path: str, parents: bool = False, exist_ok: bool = False) -> None: ...
    def makedirs(self, path: str, exist_ok: bool = True) -> None: ...
    def remove(self, path: str) -> None: ...
    def rmdir(self, path: str) -> None: ...
    def rename(self, src: str, dst: str) -> None: ...
    def list(self, path: str = ".", recursive: bool = False) -> list[str]: ...
    def list_detailed(self, path: str = ".", recursive: bool = False) -> list[FileInfo]: ...
    def glob(self, pattern: str) -> list[str]: ...
```

## Compatible filesystems

[monkeyfs](https://github.com/ashenfad/monkeyfs) `VirtualFS` and `IsolatedFS` both satisfy the termish `FileSystem` protocol and can be passed directly to `execute()`.

## Builtin commands

| Category | Commands |
|----------|----------|
| Filesystem | `pwd`, `cd`, `mkdir`, `ls`, `touch`, `cp`, `mv`, `rm`, `basename`, `dirname` |
| I/O | `echo`, `cat`, `head`, `tail`, `tee` |
| Search | `grep`, `find` |
| Text | `wc`, `sort`, `uniq`, `cut`, `sed`, `tr` |
| Diff | `diff` |
| Archive | `tar`, `gzip`, `gunzip`, `zip`, `unzip` |
| Meta | `xargs` |
| JSON | `jq` |

## Development

```bash
uv sync --extra dev
uv run pytest
```
