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- What is pget?
- Installation
- Quick Start
- Features
- Commands
- Example Apps
- Requirements
- License
- App Development Guidelines
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?
- No dependency conflicts - each app is a standalone binary compiled with Nuitka
- Works without pip, virtualenv, or conda
- Perfect for simple CLI utilities that do one thing well
- Automatically downloads pre-built binaries for your platform
- Falls back to building from source when needed
- Everything lives in
~/.pget/bin(including pget itself) - clean and isolated
Use Cases:
- System utilities and CLI tools
- Developer productivity tools
- Simple data processing scripts
- Cross-platform command-line applications
No build required - start using pget immediately:
git clone https://github.com/pynosaur/pget.git
cd pget
python app/main.py --helpWith 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 fileNow 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 ydayNote: If running from source without building, replace pget with python app/main.py in all commands above.
- Pure Python - No external dependencies, uses only standard library
- Cross-platform - Works on macOS, Linux, and Windows
- Smart Installation - Downloads pre-built binaries when available, builds from source as fallback
- Simple CLI - Familiar package manager commands (install, remove, list, update, search)
- Self-contained - Everything lives in
~/.pget/bin(including pget itself), automatically added to your PATH - Standalone Binaries - Apps compiled with Nuitka for fast startup and no runtime dependencies
- System-aware installs - Attempts system-wide install (
/usr/local/bin) with sudo, falling back to user installs if not permitted
Note: 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 listExample 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 dateExample 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 output
Apps currently available in the pynosaur ecosystem:
- yday - Display current day of year (1-366). Simple utility for date calculations.
- pget - The package manager itself. Demonstrates self-hosting capability.
To see all available apps, run:
pget search- Python 3.6 or higher
- Internet connection (for downloading packages)
- Bazel or Bazelisk (optional, only needed for building from source when no binary is available)
Platform Support:
- macOS (ARM64 and x86_64)
- Linux (x86_64 and ARM64)
- Windows (x86_64)
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.
- GitHub Organization: Apps must be in the
pynosaurGitHub organization - Repository Name: Should match the app name (e.g.,
yday,pget) - Standard Structure: Must follow the directory structure:
<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
- Shebang: Must start with
#!/usr/bin/env python3 - Executable: Should be directly runnable as a CLI tool
- Standard Flags: Should support:
--helpor-h: Display help message--versionor-v: Display version information
- Exit Codes: Return proper exit codes (0 for success, non-zero for errors)
- Module Support: Should work both as:
- Direct script:
python app/main.py - Module:
python -m app.main
- Direct script:
- Define
__version__inapp/__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.bazel: Bazel module configuration
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")
-
BUILD: Bazel build rules
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"], )
- Target Name: Must be
//:<app_name>_bin - Output: Should produce a single executable binary named
<app_name> - Compilation: Uses Nuitka with
--onefileflag for standalone binaries
For faster installation, provide pre-compiled binaries in GitHub releases:
-
Naming Convention:
{app_name}-{platform}- Examples:
yday-darwin-arm64,yday-linux-x86_64,yday-windows-x86_64
- Examples:
-
Supported Platforms:
darwin-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)
-
Release Process:
- Create a GitHub release with tag (e.g.,
v0.1.0) - Upload binary assets with the correct naming convention
- Upload a source tarball (e.g.,
<app_name>-source.tar.gz)
- Create a GitHub release with tag (e.g.,
If no release binary is available, pget will:
- Download the source code from the repository
- Look for
MODULE.bazelorBUILDfile - Build using Bazel with the target
//:{app_name}_bin - Install the resulting binary
Note: Users need Bazel (or bazelisk) installed for source builds.
Should include:
- Description of what the app does
- Usage examples
- Installation instructions
- Requirements
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: []- Place test files in
test/directory - Use standard Python testing (unittest, pytest, etc.)
- Test files should be named
test_*.py
pget is designed for CLI (Command Line Interface) tools:
- CLI utilities: Command-line tools that perform specific tasks
- Single-purpose tools: Focused tools that do one thing well
- Cross-platform tools: Should work on macOS, Linux, and Windows
- Standalone executables: Self-contained binaries (via Nuitka)
Not suitable for:
- GUI applications (unless they also have CLI interface)
- Web servers or long-running services
- Libraries or packages meant for import only
- Tools requiring complex runtime dependencies
When a user runs pget install <app_name>:
- Check Repository: Verifies app exists in
pynosaurorganization - Try Binary Download: Looks for release binary matching user's platform
- Fallback to Source: If no binary, downloads source and builds with Bazel
- Install Binary: Copies binary to
~/.pget/bin/ - Install Documentation: Copies
doc/to~/.pget/helpers/<app_name>/doc/ - Create Metadata: Saves install info to
~/.pget/helpers/<app_name>/.pget-metadata.json - Make Executable: Sets executable permissions
- Update PATH: Ensures
~/.pget/binis in user's PATH
Apps 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_pathImportant: Apps must create data/, config/, and cache/ directories themselves when needed. Only doc/ is created by pget during installation.
- Keep it simple: Focus on doing one thing well
- Pure Python: Prefer standard library, minimize external dependencies
- Error handling: Provide clear error messages
- Documentation: Include helpful
--helpoutput - Testing: Write tests for core functionality
- Versioning: Use semantic versioning (e.g.,
0.1.0) - Releases: Tag releases and provide binaries for common platforms
Creating a new pget-compatible app:
-
Create repository structure
mkdir myapp cd myapp mkdir -p app doc test
-
Create
app/__init__.py__version__ = "0.1.0"
-
Create
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) -
Test locally
python app/main.py
-
Build with Bazel
bazel build //:myapp_bin
-
Create GitHub release with binary assets
For a complete working example, see the yday repository.
Ahoy there! Code, code:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
- Report issues on GitHub Issues
- For app development questions, refer to the App Development Guidelines above
pget is in active development. The core functionality is stable and ready for use, but APIs may change as the project evolves.