Skip to main content

Python-first interactive shell for Debian and Unix-like systems

Project description

PySH

Python-first interactive shell for Debian and Unix-like systems.

PySH is a small, dependency-free interactive shell written in pure Python. It is packaged as a regular PyPI distribution (pysh-shell), installs a single console command (pysh), and is designed to feel familiar to anyone used to a Bourne-style shell while remaining hackable from Python.

The 0.1.1 release targets Python 3.13+ and is validated on Debian 13.


Features

  • Interactive REPL with command history (~/.pysh_history).
  • Welcome banner, configurable prompt with user and CWD (~ collapsed).
  • Robust quote-aware parser:
    • Splits chains on ;, &&, || only outside of quotes.
    • Splits pipelines on | only outside of quotes.
  • Pipelines with correctly managed file-descriptor handover.
  • Redirection: <, >, >>, 2>, 2>>, &>, &>>.
  • Local variables (NAME=value) and exported environment variables (export NAME=value) with $NAME / ${NAME} expansion.
  • Aliases with sane defaults and user overrides via alias.
  • Startup file ~/.pyshrc (and the source builtin) for persistent customisation.
  • Basic tab completion for aliases, builtins, files and directories.
  • Clean Ctrl+C (cancels current line, keeps the shell alive) and Ctrl+D (exits the shell).

Installation

From PyPI

pip install pysh-shell

Then start the shell with:

pysh

Development install

python3.13 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

Running

pysh           # console entry point installed by the wheel
python -m pysh # equivalent module entry point

Builtins

Implemented directly inside the shell (no subprocess spawned):

Builtin Description
cd Change the current working directory.
pwd Print the current working directory.
alias Define or display aliases.
export Define or display exported environment vars.
source Execute commands from a file (also .).
exit Exit the shell with an optional status code.
quit Same as exit.

Operators

Operator Meaning
cmd1 ; cmd2 Run cmd1, then unconditionally run cmd2.
cmd1 && cmd2 Run cmd2 only if cmd1 exits with status 0.
cmd1 || cmd2 Run cmd2 only if cmd1 exits with non-zero status.
cmd1 | cmd2 Pipe cmd1's stdout into cmd2's stdin.

Operators inside single or double quotes are treated as literal text.

echo "🐍 PySH v1.0 | Python 3.13.5"
python3.13 -c "import subprocess; print('ok')"

Redirection

Syntax Effect
< file Read stdin from file.
> file Write stdout to file (truncate).
>> file Write stdout to file (append).
2> file Write stderr to file (truncate).
2>> file Write stderr to file (append).
&> file Write stdout + stderr to file.
&>> file Append stdout + stderr to file.
ls -la 2>/dev/null | head -3
python3.13 -c "import sys; print('err', file=sys.stderr)" 2> err.log
echo "hello" > out.txt
echo "again" >> out.txt

Redirection operators inside quotes are kept as literal characters.


Pipelines

PySH connects each stage with a real OS pipe and closes the parent's duplicate handles after the child is spawned, so neither side deadlocks.

ls -la | head -3
apt list --upgradable 2>/dev/null | grep -c "/"

Variables

NAME=world           # local shell variable
export GREETING=hi   # exported environment variable
echo "$GREETING, $NAME"

Local variables shadow environment variables when expanded. Single quotes suppress expansion; double quotes do not.


~/.pyshrc

If ~/.pyshrc exists at startup, PySH executes it line by line through the normal command path. Blank lines and lines starting with # are ignored. You can also re-source it at any time:

source ~/.pyshrc

Example ~/.pyshrc

export EDITOR="nano"
export PAGER="less"
export LANG="pl_PL.UTF-8"
export PYTHONDONTWRITEBYTECODE="1"

alias ll="ls -la --color=auto -F"
alias ls="ls --color=auto -F"
alias grep="grep --color=auto"
alias rm="rm -i"
alias cp="cp -i"
alias mv="mv -i"
alias df="df -h"
alias free="free -h"
alias python="python3.13"
alias pip="pip3.13"

echo "🐍 PySH 0.1.1 | Python 3.13+"
echo "🐧 Debian ready"
echo "💡 Supported: && || ; | > >> < 2> 2>> &> &>> source alias export cd"

A failing line is reported on stderr and the next line is still executed.


Tab completion

Tab completes aliases and builtins for the first word, and filesystem paths for any word. Inaccessible directories are silently skipped.


Testing and quality gates

pytest -q
ruff check src tests
python -m build
twine check dist/*

The project ships with unit tests for the parser, the redirection module, the rc loader and the shell itself.


Publishing

This repository is configured for PyPI Trusted Publishing via GitHub Actions. See .github/workflows/publish.yml — it uses pypa/gh-action-pypi-publish@release/v1 with id-token: write and the pypi environment. Tagging a release on GitHub publishes the build.

Do not publish from a developer machine; let the workflow do it.


Target platform

  • Primary target: Debian 13 with Python 3.13+.
  • Should work on any POSIX system with a working subprocess and readline, but only Debian 13 is regularly validated.

License

PySH is distributed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). See LICENSE for the full text.

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

pysh_shell-0.1.1.tar.gz (28.5 kB view details)

Uploaded Source

Built Distribution

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

pysh_shell-0.1.1-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file pysh_shell-0.1.1.tar.gz.

File metadata

  • Download URL: pysh_shell-0.1.1.tar.gz
  • Upload date:
  • Size: 28.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysh_shell-0.1.1.tar.gz
Algorithm Hash digest
SHA256 30a5c321b688340d909d0e937b2d38d5e2114b1d9a0df37468d2f469f6c4e1de
MD5 2242c27feb08eed535c7e7ba98dae3b6
BLAKE2b-256 d5197391ea4350d6ebb7f62096868090cebe0062336841e33293d3ce34b136de

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysh_shell-0.1.1.tar.gz:

Publisher: publish.yml on SSobol77/pysh

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pysh_shell-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pysh_shell-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 29.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysh_shell-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e9f535f32d40b19ee1de1d5e5d30728f22fef3fa4cf777a704470757f2c233cd
MD5 4ffca7cfca7bb9f0bd830927cb447eb1
BLAKE2b-256 06fecc21351c805c6dd8c96f20e76cada3676063e880a37df2595af5acb089f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysh_shell-0.1.1-py3-none-any.whl:

Publisher: publish.yml on SSobol77/pysh

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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