Modern CLI tools with better UX
Pure Python package manager for the pynosaur ecosystem
pget is a minimalist package manager for lightweight Python CLI tools. It installs standalone executables to ~/.pget/bin, making it easy to distribute and install simple command-line utilities without pip or virtual environments.
pget install yday
pget is a package manager designed specifically for standalone Python CLI applications in the pynosaur ecosystem. Unlike pip which manages libraries and dependencies, pget focuses on distributing self-contained executable tools.
Why pget?
~/.pget/bin (including pget itself) - clean and isolatedUse Cases:
No build required - start using pget immediately:
git clone https://github.com/pynosaur/pget.git
cd pget
python app/main.py --help
With this option, use python app/main.py for all commands.
Build once, then use the pget command anywhere. Requires Bazel or Bazelisk:
git clone https://github.com/pynosaur/pget.git
cd pget
bazel build //:pget_bin
mkdir -p ~/.pget/bin
cp bazel-bin/pget ~/.pget/bin/
export PATH="$HOME/.pget/bin:$PATH" # Add to your shell rc file
Now you can use pget directly from anywhere (instead of python app/main.py).
Note: The ~/.pget/bin directory is where pget installs all apps, including itself. Make sure this directory is in your PATH.
If running from source, use python app/main.py. If you built the standalone binary, use pget directly.
# Search for available packages
pget search
# Install an app (e.g., yday - prints current day of year)
pget install yday
# List installed packages
pget list
# Use the installed app
yday
# Output: 360
# Update an app
pget update yday
# Remove an app
pget remove yday
Note: If running from source without building, replace pget with python app/main.py in all commands above.
~/.pget/bin (including pget itself), automatically added to your PATH/usr/local/bin) with sudo, falling back to user installs if not permittedNote: The examples below use pget (standalone binary). If running from source, use python app/main.py instead.
Install a package from the pynosaur organization:
pget install <app_name>
Example output:
Installing yday
Looking for binary: yday-darwin-arm64
Downloading yday (2.1 MB)
Installing yday to /Users/username/.pget/bin/yday
yday installed successfully
Uninstall a previously installed package:
pget remove <app_name>
Show all installed packages:
pget list
Example output:
Installed packages in /Users/username/.pget/bin:
pget 0.1.0
yday 0.1.0
Update a package to the latest version:
pget update <app_name>
Search for available packages in the pynosaur organization:
# List all packages
pget search
# Search with a query
pget search date
Example output:
Name Description
yday Prints the current day of the year (1-366)
pget Pure Python package manager for pynosaur ecosystem
-h, --help - Show help message-v, --version - Show version information--verbose - Enable verbose outputApps currently available in the pynosaur ecosystem:
To see all available apps, run:
pget search
Platform Support:
MIT License - See LICENSE file for details.
This section is for developers who want to create apps compatible with pget. Following these guidelines ensures your app can be easily installed and distributed through the pynosaur ecosystem.
pynosaur GitHub organizationyday, pget)<app_name>/
├── app/
│ ├── __init__.py
│ └── main.py # Main entry point
├── doc/
│ └── <app_name>.yaml # App metadata
├── test/
│ └── test_*.py # Test files
├── BUILD # Bazel build file (required for source builds)
├── MODULE.bazel # Bazel module file (required for source builds)
└── README.md # Documentation
app/main.py)#!/usr/bin/env python3--help or -h: Display help message--version or -v: Display version informationpython app/main.pypython -m app.main__version__ in app/__init__.py:
__version__ = "0.1.0"
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from app import __version__
def main():
args = sys.argv[1:]
if not args:
# Default behavior
return 0
if args[0] in ("-h", "--help"):
print("Usage: app_name [options]")
return 0
if args[0] in ("-v", "--version"):
print(__version__)
return 0
# Your app logic here
return 0
if __name__ == "__main__":
sys.exit(main())
module(
name = "<app_name>",
version = "0.1.0",
)
bazel_dep(name = "rules_python", version = "0.40.0")
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(python_version = "3.11")
genrule(
name = "<app_name>_bin",
srcs = glob(["app/**/*.py"]),
outs = ["<app_name>"],
cmd = """
/opt/homebrew/bin/nuitka \
--onefile \
--onefile-tempdir-spec=/tmp/nuitka-<app_name> \
--no-progressbar \
--assume-yes-for-downloads \
--output-dir=$$(dirname $(location <app_name>)) \
--output-filename=<app_name> \
$(location app/main.py)
""",
local = 1,
visibility = ["//visibility:public"],
)
//:<app_name>_bin<app_name>--onefile flag for standalone binariesFor faster installation, provide pre-compiled binaries in GitHub releases:
{app_name}-{platform}
yday-darwin-arm64, yday-linux-x86_64, yday-windows-x86_64darwin-arm64 (Apple Silicon macOS)darwin-x86_64 (Intel macOS)linux-x86_64 (Linux x86_64)linux-arm64 (Linux ARM64)windows-x86_64 (Windows x86_64)v0.1.0)<app_name>-source.tar.gz)If no release binary is available, pget will:
MODULE.bazel or BUILD file//:{app_name}_binNote: Users need Bazel (or bazelisk) installed for source builds.
Should include:
Metadata file for app information (ALL CAPS field names):
NAME: <app_name>
VERSION: "0.1.0"
DESCRIPTION: >
Brief description of the app
USAGE:
- "<app_name>"
- "<app_name> --help"
- "<app_name> --version"
OPTIONS:
- "-h, --help Show help message"
- "-v, --version Show version information"
OUTPUT: Description of output
AUTHOR: "@username"
DATE: "YYYY-MM-DD"
NOTES: []
test/ directorytest_*.pypget is designed for CLI (Command Line Interface) tools:
Not suitable for:
When a user runs pget install <app_name>:
pynosaur organization~/.pget/bin/doc/ to ~/.pget/helpers/<app_name>/doc/~/.pget/helpers/<app_name>/.pget-metadata.json~/.pget/bin is in user’s PATHApps installed by pget use a hybrid directory structure:
~/.pget/
├── bin/ # All executables (in PATH)
│ └── <app_name>
└── helpers/ # Per-app helper files and data
└── <app_name>/
├── .pget-metadata.json # Install metadata (created by pget)
├── doc/ # Documentation (created by pget)
│ └── <app_name>.yaml
├── data/ # Optional: create if needed
├── config/ # Optional: create if needed
└── cache/ # Optional: create if needed
bin/ - All executables, added to PATHhelpers/<name>/doc/ - App documentation (managed by pget)helpers/<name>/data/ - Persistent storage (databases, saved state)helpers/<name>/config/ - User configuration fileshelpers/<name>/cache/ - Temporary/cached data (can be deleted)Apps that need persistent storage should use the standard directories:
from pathlib import Path
APP_NAME = "myapp"
PGET_HELPERS = Path.home() / ".pget" / "helpers"
# App directories
APP_ROOT = PGET_HELPERS / APP_NAME
DATA_DIR = APP_ROOT / "data"
CONFIG_DIR = APP_ROOT / "config"
CACHE_DIR = APP_ROOT / "cache"
def ensure_dirs():
"""Create app directories as needed."""
DATA_DIR.mkdir(parents=True, exist_ok=True)
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
def save_database():
ensure_dirs()
db_path = DATA_DIR / "database.json"
# ... save to db_path
Important: Apps must create data/, config/, and cache/ directories themselves when needed. Only doc/ is created by pget during installation.
--help output0.1.0)Creating a new pget-compatible app:
mkdir myapp
cd myapp
mkdir -p app doc test
app/__init__.py
__version__ = "0.1.0"
app/main.py
#!/usr/bin/env python3
import sys
from app import __version__
def main():
args = sys.argv[1:]
if args and args[0] in ("-h", "--help"):
print("Usage: myapp [options]")
return 0
if args and args[0] in ("-v", "--version"):
print(__version__)
return 0
# Your app logic here
print("Hello, Friend?")
return 0
if __name__ == "__main__":
sys.exit(main())
Create MODULE.bazel (copy from yday example)
Create BUILD (copy from yday example, update app name)
python app/main.py
bazel build //:myapp_bin
For a complete working example, see the yday repository.
Ahoy there! Code, code:
pget is in active development. The core functionality is stable and ready for use, but APIs may change as the project evolves.