Skip to main content

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

Project description

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 (>, >>, <), heredocs (<<EOF), semicolons, quoted strings, line continuation
  • 33 builtins -- ls, cat, grep, find, sed, tr, sort, uniq, cut, wc, diff, tar, gzip, zip, jq, xargs, file, true, false, basename, dirname, ...
  • Custom commands -- inject your own command handlers alongside builtins; injected commands override builtins and compose in pipelines
  • 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

pip install termish

Quick example

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

Custom commands

Inject your own commands via the commands parameter. They receive a CommandContext and compose naturally with builtins in pipelines:

from termish import execute, MemoryFS, CommandContext, CommandResult

def greet(ctx: CommandContext) -> CommandResult | None:
    name = ctx.args[0] if ctx.args else "world"
    ctx.stdout.write(f"hello {name}\n")
    return None

fs = MemoryFS()
output = execute("greet alice | wc -c", fs, commands={"greet": greet})
print(output)  # 12

# Injected commands override builtins with the same name

All commands — builtin and injected — use the same CommandContext signature. See CommandContext, CommandResult, and CommandFunc in termish.context and termish.errors.

FileSystem protocol

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

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]: ...

Part of the agex stack

termish provides shell commands for AI agents in agex, operating over virtual filesystems from monkeyfs.

Compatible filesystems

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

uv sync --extra dev
uv run pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

termish-0.1.7.tar.gz (87.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

termish-0.1.7-py3-none-any.whl (66.7 kB view details)

Uploaded Python 3

File details

Details for the file termish-0.1.7.tar.gz.

File metadata

  • Download URL: termish-0.1.7.tar.gz
  • Upload date:
  • Size: 87.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for termish-0.1.7.tar.gz
Algorithm Hash digest
SHA256 5e910bbc377afbed1d20954655f4d21e49e1fb10eff10e3ba340564e0aca5cde
MD5 472da4b8fd987b9eba5be2f8f6fdae0d
BLAKE2b-256 e53d55ddd9bc9bcd76673a0b9ca21150f90c3a705664d7e1309a65b93830d115

See more details on using hashes here.

File details

Details for the file termish-0.1.7-py3-none-any.whl.

File metadata

  • Download URL: termish-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 66.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for termish-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 94036d53334474a4da9a598d1ddc62a47eaf323abd721bc09b34fd65ce70ffcc
MD5 1878d28ef84f372920e877fa7df35851
BLAKE2b-256 32d4be1bbf725523482f4ca173d1c191716caff7a796da0a4bd1b81399f52727

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page