Polycmd
Polycmd is a shared multi platform syntax, zero dependency python based, terminal that runs a practical subset of POSIX, Windows CMD, and PowerShell commands through one safe, portable Python execution model.
current_version = "v0.17.0"
Commands are compiled into canonical operations before execution. Supported commands are not forwarded to a native shell, keeping behavior consistent across Windows, macOS, and Linux.
Quick start
Install
pip install polycmd
Polycmd supports Python 3.11, 3.12, and 3.13.
Open the lightweight terminal
polycmd terminal
The standard-library Tkinter terminal accepts commands without a polycmd
prefix:
ls -la
dir /s /b *.py
Get-ChildItem . -Force
cat app.log | grep error > errors.txt
It keeps one Polycmd session alive, including its virtual working directory and command history. The dialect selector appears on the left of the command path and offers Auto, POSIX, CMD, and PowerShell; Auto is selected by default. Enter runs a command, Up and Down navigate history, Ctrl+L clears the display, and Ctrl+Q exits.
Wildcard directory listings are expanded inside Polycmd rather than by the host shell, so they behave consistently in the terminal on every platform:
ls *.md*
dir /s /b *.py
Get-ChildItem docs/*.md
Tkinter is included with standard CPython installers for Windows and macOS. Some minimal Linux distributions package Tk separately.
Get help
Display catalog-backed help from the command line:
polycmd --help
polycmd help ls
polycmd ls --help
polycmd help fs.copy
Use the same forms inside the lightweight terminal without a polycmd prefix:
help
help ls
ls --help
help dir
help Get-ChildItem
help fs.copy
Help is generated from the live command and operation catalogs. It includes plugin commands, resolves aliases, and shows every dialect when a name has more than one meaning. Command providers can supply a description, usage syntax, and examples; otherwise Polycmd uses the compiler function's docstring.
Why Polycmd?
Applications frequently need command-like behavior without depending on the host operating system's shell syntax, quoting rules, or installed utilities. Polycmd separates command syntax from execution:
POSIX / CMD / PowerShell command
↓
Dialect strategy
↓
Canonical Polycmd IR
↓
Registered operation
↓
Portable Python service
This provides:
- one API for POSIX, CMD, and PowerShell input;
- conservative automatic dialect detection;
- portable filesystem, text, and environment operations;
- composable pipelines, redirects, conditionals, and sequences;
- filesystem confinement and explicit destructive-operation metadata;
- disabled-by-default external process execution;
- open registries for third-party dialects, commands, and operations;
- catalog-driven serialization and capability discovery.
Polycmd is a compatibility runtime, not a complete Bash, CMD, or PowerShell emulator. Unsupported syntax fails explicitly.
Command-line usage
Run a command using automatic dialect detection:
polycmd "ls -la ./data"
polycmd "dir /s /b *.py"
polycmd "Get-ChildItem ./data -Force"
Compile a command into canonical JSON without executing it:
polycmd compile --dialect posix "cat app.log | grep error > errors.txt"
Execute a previously serialized program:
polycmd execute program.json
Inspect installed capabilities:
polycmd capabilities
Python API
from pathlib import Path
from polycmd import Shell, ShellConfig
shell = Shell(
ShellConfig(
root=Path("./workspace"),
discover_plugins=False,
)
)
result = shell.run("Get-ChildItem . -Force")
print(result.stdout)
Select a dialect explicitly when required:
program = shell.compile(
"cat app.log | grep error > errors.txt",
dialect="posix",
)
result = shell.execute(program)
Serialize and replay the same canonical program:
payload = shell.serialization.dumps(program)
restored = shell.serialization.loads(payload)
assert restored == program
shell.execute(restored)
Supported command surface
| Capability | Examples |
|---|---|
| Filesystem | list, current directory, change directory, create, copy, move, delete, touch, find |
| Text | read, write, search, head, tail, sort, unique, count |
| Environment | list and retrieve variables |
| Composition | pipelines, >, >>, ;, &&, ` |
| Program data | canonical JSON serialization and replay |
| Dialects | POSIX, CMD, PowerShell, and registered third-party dialects |
For example, these commands compile to equivalent canonical operations:
cat app.log
type app.log
Get-Content app.log
Shell integration
Polycmd can expose registered operation and dialect command names through the normal system PATH:
polycmd shell install
polycmd shell status
polycmd shell uninstall
Restart the terminal after installation. On Zsh, Polycmd installs managed
noglob aliases so foreign-dialect wildcard syntax reaches Polycmd unchanged:
dir /s /b *.py
Commands without a registered Polycmd shim continue through the native PATH.
When an entire compound expression must be compiled by Polycmd, use the Tkinter
terminal or the explicit polycmd "..." form. Otherwise, operators such as |
and > remain owned by the active host shell.
Configuration and security
Relative paths are confined beneath ShellConfig.root. Polycmd maintains a
virtual current directory and never changes the host process directory with
os.chdir().
External process execution is disabled by default. Enabling it requires both
allow_external=True and an exact executable name in external_allowlist:
from pathlib import Path
from polycmd import Shell, ShellConfig
shell = Shell(
ShellConfig(
root=Path("./workspace"),
allow_external=True,
external_allowlist=("python",),
)
)
External arguments are passed as an array with shell=False. Polycmd does not
fall back to executing unsupported input through a native shell.
Extending Polycmd
Add or replace a dialect command
from polycmd import CommandDefinition
from polycmd.ir import WriteText
def compile_hello(invocation):
return WriteText(text=" ".join(invocation.argv))
shell.register_command(
"posix",
CommandDefinition("hello", compile_hello),
)
Existing names are protected unless replace=True is explicitly supplied.
Add an operation
from dataclasses import dataclass
from polycmd.ir import Operation
from polycmd.registries import OperationDefinition
@dataclass(frozen=True, kw_only=True)
class CompressArchive(Operation):
source: str
destination: str
context.operations.register(
OperationDefinition(
operation_id="archive.compress",
operation_type=CompressArchive,
handler=compress_archive,
shell_aliases=("compress",),
)
)
The operation catalog owns execution, serialization identity, destructive
metadata, capabilities, and shell names. Plugins can register through the
polycmd.plugins entry-point group without changing Polycmd core.
More detail is available in:
Development
Clone the repository and install the development environment:
git clone https://github.com/systemizing-solutions/polycmd.git
cd polycmd
poetry install
Run the quality gates:
poetry run pytest
poetry run ruff check src/polycmd tests
poetry run ruff format --check src/polycmd tests
poetry run mypy
BumpVer
Preview a version change before applying it:
poetry run bumpver update --patch --dry
poetry run bumpver update --minor --dry
poetry run bumpver update --major --dry
Apply a release bump:
poetry run bumpver update --patch
BumpVer updates pyproject.toml, src/polycmd/__init__.py, and this README,
creates the version commit and tag, and pushes them. Pushing a semantic version
tag starts the PyPI publication workflow.
Build locally
poetry check
poetry build
The build produces a source distribution and a universal Python wheel in
dist/.
Automated PyPI publishing
The publish.yml workflow publishes semantic version tags through PyPI trusted
publishing. No PyPI API token is stored in GitHub.
One-time repository setup:
- Create the
polycmdproject or a pending trusted publisher on PyPI. - Set the GitHub owner to
systemizing-solutions. - Set the repository to
polycmd. - Set the workflow filename to
publish.yml. - Set the environment name to
pypi. - Create a matching GitHub environment named
pypi.
For every tagged release, GitHub Actions verifies that the tag equals the Poetry version, validates package metadata, runs linting, typing, and tests, builds both distribution formats, and publishes them using OpenID Connect.
License
Polycmd is released under the MIT License. See LICENSE.
Credits
Author: Ryan Julyan
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polycmd-0.17.0.tar.gz.
File metadata
- Download URL: polycmd-0.17.0.tar.gz
- Upload date:
- Size: 45.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.4.2 CPython/3.12.2 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6c5d8b97e80262503d111d4a41d6f4ecac4ed1656157db0c1b34de897873940
|
|
| MD5 |
637ae56ab1de03c71ea4c6fb10533286
|
|
| BLAKE2b-256 |
39b445725da2917395bdabe766a38048fa5eefe7e45e9671893a5d70729524b1
|
File details
Details for the file polycmd-0.17.0-py3-none-any.whl.
File metadata
- Download URL: polycmd-0.17.0-py3-none-any.whl
- Upload date:
- Size: 68.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
poetry/2.4.2 CPython/3.12.2 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
188ad6abf9483ca4706277750bbfdfc25fd0d4ddf6931156f7e381f58bb71174
|
|
| MD5 |
6f7335807cebbf4c9c7275e5cb724578
|
|
| BLAKE2b-256 |
9e606e06e267ddaa5705904cf3f1aacf743fd331b216b2dadfbc176c134438b6
|