Skip to main content

Cross-platform Linux terminal emulation layer for Python - practice Linux commands anywhere.

Project description

🐧 Virtux

A realistic Linux terminal, simulated entirely in Python - runs anywhere Python runs.

PyPI version Python versions License: MIT Downloads Tests

Virtux gives you a full Linux shell experience - filesystem, permissions, piping, 40+ coreutils-style commands - without a VM, container, Docker daemon, or WSL install. It's pure Python, starts in milliseconds, and behaves close enough to a real shell that it's genuinely useful for teaching, testing, and sandboxed scripting.

pip install virtux
user@virtux:~$ mkdir -p projects/my-app && cd projects/my-app
user@virtux:~/projects/my-app$ echo "Hello World!" > README.md
user@virtux:~/projects/my-app$ cat README.md | grep Hello
Hello World!

Table of Contents


Why Virtux?

Most "learn Linux" tools fall into two camps: a real VM/container (heavy, slow to spin up, needs admin rights) or a toy JS terminal in a browser (not scriptable, no real Python integration). Virtux sits in between:

Need Virtux Real VM / Docker Browser sandbox
Works on Windows without WSL
Starts in under a second
Real piping, redirection, exit codes ⚠️ limited
Embeddable in a Python app/test suite ⚠️ awkward
Zero system dependencies
Persistent state between runs ⚠️ varies

If you need to teach shell basics, test CLI tools without touching the real filesystem, or embed a sandboxed shell inside another Python app, Virtux is built for exactly that.

Features

  • 🖥️ Realistic shell - colorized prompt, tab completion, reverse-search history (Ctrl+R), multi-line editing
  • 📁 Virtual filesystem - a full hierarchical tree (/home, /etc, /tmp, /var, …) backed by an in-memory or on-disk store
  • 🔗 Real piping & redirection - |, >, >>, <, 2>, &>, &&, ||, ;, subshells with ()
  • 🔒 Users & permissions - chmod, chown, chgrp, umask, sudo, su, full rwx + octal permission model with enforcement
  • 📝 40+ built-in commands - see the full reference below
  • 💾 Persistent sessions - your virtual filesystem and history survive across runs (stored in ~/.virtux/)
  • 🔌 Plugin system - add your own commands via Python entry points, no fork required
  • 🛡️ Fully sandboxed - nothing Virtux does ever touches your real filesystem, network, or processes
  • 🧪 Scriptable & testable - drive it from pytest, assert on output/exit codes, reset state between tests
  • 🌍 Cross-platform - identical behavior on Windows, macOS, and Linux since it isn't backed by the host shell

Installation

pip install virtux

Requires Python 3.9+. No compiled extensions, no system packages, no admin/root access needed.

To verify:

virtux --version

Quick Start

Interactive Shell

virtux
 ╦  ╦╦╦═╗╔╦╗╦ ╦═╗ ╦
 ╚╗╔╝║╠╦╝ ║ ║ ║╔╩╦╝
  ╚╝ ╩╩╚═ ╩ ╚═╝╩ ╚═
  Linux Terminal Emulator v0.1.0

user@virtux:~$ mkdir -p projects/my-app
user@virtux:~$ echo "Hello World!" > projects/my-app/README.md
user@virtux:~$ cat projects/my-app/README.md
Hello World!
user@virtux:~$ ls -la projects/
drwxr-xr-x  2 user user  4096 Jun 23 12:00 my-app
user@virtux:~$ find / -name "*.md"
/home/user/projects/my-app/README.md
user@virtux:~$ chmod 600 projects/my-app/README.md && ls -l projects/my-app/
-rw-------  1 user user  13 Jun 23 12:00 README.md

One-Off Command

Run a single command and exit - handy for quick checks or shell scripts:

virtux -c "ls -la /etc"

Script Execution

Run a .sh file just like bash script.sh would:

virtux script.sh
# script.sh
#!/usr/bin/env virtux
mkdir -p /tmp/build
for f in *.txt; do
  cp "$f" /tmp/build/
done
echo "Build staged: $(ls /tmp/build | wc -l) files"

Usage Modes

Mode Command Best for
Interactive virtux Learning, exploring, manual testing
One-shot virtux -c "cmd" Scripts, CI checks, quick lookups
Script file virtux script.sh Reusable automation, classroom exercises
Embedded API from virtux import VirtuxShell Apps, test suites, custom tooling

Command Reference

📁 Filesystem (15 commands)

ls cd pwd mkdir rmdir rm cp mv touch ln find stat du df tree

📝 Text processing (13 commands)

cat head tail grep wc sort uniq cut sed awk echo tee diff

⚙️ System (23 commands)

whoami uname hostname date cal uptime env export unset alias unalias history clear exit man help which type id printenv true false sleep

🔒 Shell & permissions (9 commands)

chmod chown chgrp umask sudo su source bash sh

🌐 Network (6 commands, simulated)

ping ifconfig ip curl wget ssh

Network commands return realistic, deterministic output but never make real network calls - safe to script against without side effects.

📦 Archives & compression (5 commands)

tar gzip gunzip zip unzip

📊 Process management (4 commands, simulated)

ps top kill jobs

Run man <command> or help inside the shell for full usage and flags for any of the above.

Python API

Embed Virtux directly in your own application or test suite:

from virtux import VirtuxShell

shell = VirtuxShell()
output = shell.execute("echo 'Hello from Python!'")
print(output)  # Hello from Python!

Capturing exit codes and errors

result = shell.run("ls /nonexistent")
print(result.stdout)      # ""
print(result.stderr)      # "ls: /nonexistent: No such file or directory"
print(result.exit_code)   # 2

Resetting state between tests

import pytest
from virtux import VirtuxShell

@pytest.fixture
def shell():
    s = VirtuxShell(persist=False)  # fresh, in-memory filesystem
    yield s
    s.reset()

def test_mkdir_creates_directory(shell):
    shell.execute("mkdir /tmp/demo")
    assert shell.execute("test -d /tmp/demo && echo yes") == "yes\n"

Pre-seeding a virtual filesystem

shell = VirtuxShell()
shell.fs.write_file("/etc/myapp.conf", "debug=true\n")
shell.execute("cat /etc/myapp.conf")  # debug=true

Plugin System

Add custom commands without forking the project, using standard Python entry points:

# my_virtux_plugin/plugin.py
def register(registry):
    @registry.register("mycommand", help_text="My custom command")
    def cmd_mycommand(ctx):
        ctx.writeln("Hello from my plugin!")
        return 0
# pyproject.toml
[project.entry-points."virtux.plugins"]
my_plugin = "my_virtux_plugin.plugin:register"

Once installed (pip install . or pip install my-virtux-plugin), mycommand is available automatically in every Virtux session - no extra registration step needed.

ctx gives plugin authors access to:

Member Purpose
ctx.writeln(text) / ctx.write(text) Write to stdout
ctx.error(text) Write to stderr
ctx.args Parsed argument list
ctx.fs Virtual filesystem handle
ctx.env Current environment variables
ctx.cwd Current working directory

Configuration

CLI flag Effect
virtux Launch interactive shell
virtux -c "command" Execute a single command and exit
virtux script.sh Run a script file
virtux --reset Wipe the persisted virtual filesystem and start clean
virtux --no-persist Run with an in-memory filesystem that discards on exit
virtux --version Print the installed version

By default, session state (filesystem + history) is stored at ~/.virtux/. Override with the VIRTUX_HOME environment variable:

export VIRTUX_HOME=/tmp/my-virtux-sandbox
virtux

How It Compares

Virtux WSL Docker container xterm.js + node-pty
Install footprint pip install OS feature, GBs Docker daemon required Node + native pty bindings
Cold start Milliseconds Seconds–minutes Seconds Seconds
Cross-platform parity Identical everywhere Windows-only Needs Docker Desktop Needs a real OS shell underneath
Touches real filesystem Never Yes Yes (namespaced) Yes
Embeds in a Python test suite Native Awkward Possible via SDK, heavy Not applicable

Virtux isn't a replacement for a real Linux box when you need actual binaries, real networking, or kernel-level behavior - it's a lightweight, safe stand-in for teaching, prototyping, and testing shell-driven workflows.

FAQ

Does Virtux run real binaries? No. Every command is a Python implementation that mimics real Linux behavior closely enough for scripting, teaching, and testing - but nothing is shelled out to your OS.

Can it break my actual files? No. The virtual filesystem is fully isolated, whether it's in-memory (--no-persist) or persisted under ~/.virtux/.

Does sudo/su do anything real? They simulate the permission model (UID/GID switching, permission checks) within the virtual filesystem only - there's no real privilege escalation possible.

Can I use it in CI? Yes - virtux --no-persist -c "..." is ideal for CI: deterministic, no host side effects, no setup steps.

Contributing

Issues and PRs are welcome. Before opening a PR:

git clone https://github.com/RishiBuilds/virtux.git
cd virtux
pip install -e ".[dev]"
pytest

Please include tests for new commands or behavior changes - see tests/ for examples of the expected style.

License

MIT License - see LICENSE for details.

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

virtux-0.1.0.tar.gz (62.7 kB view details)

Uploaded Source

Built Distribution

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

virtux-0.1.0-py3-none-any.whl (60.8 kB view details)

Uploaded Python 3

File details

Details for the file virtux-0.1.0.tar.gz.

File metadata

  • Download URL: virtux-0.1.0.tar.gz
  • Upload date:
  • Size: 62.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for virtux-0.1.0.tar.gz
Algorithm Hash digest
SHA256 071c606df4fefb5f11f4504407f3c7af936ca8aafdb6520146fe413bd3e024c7
MD5 407815699055dede66a21d5cf4b6c787
BLAKE2b-256 30b4b395341fe3bac69ecd568fae5fa5f2a61d9f07324d2f51dfa75ba7b91379

See more details on using hashes here.

File details

Details for the file virtux-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: virtux-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 60.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for virtux-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6a4b4bf9b0b84e50731122b5e1bd599d246999d82d8a4a771747a396e864dfca
MD5 6b3c80db466f1c8ce952428bfb3d8b73
BLAKE2b-256 99150168a9030c686615d02fcfdf00ef98a07f69a8f7bbb310d8e8638f4dcfe4

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