Skip to main content

Python Library that builds a complete CLI given one or more functions using introspection

Project description

Freyja

Freyja ⚡

No-dependency, zero-configuration CLI tool to build command-line interfaces purely from your code.

Transform your Python functions and classes into powerful command-line applications in seconds! Freyja uses introspection and type annotations to automatically generate professional CLIs with zero configuration required.

Table of Contents

🚀 Why Freyja?

Build CLIs in under 5 minutes! No configuration files, no complex setup, no learning curve. Just add type annotations to your functions and Freyja does the rest.

pip install freyja
# That's it! No dependencies, no configuration needed.

Before Freyja:

python script.py --config-file /path/to/config --database-host localhost --database-port 5432 --username admin --password secret --table-name users --action create --data '{"name": "Alice", "email": "alice@example.com"}'

After Freyja:

python script.py database--create-user --name Alice --email alice@example.com
# Global config handled automatically, clean syntax, built-in help

⚡ Quick Start

Step 1: Install Freyja

pip install freyja

Step 2: Add type annotations to your functions

def greet(name: str = "World", excited: bool = False) -> None:
    """Greet someone by name."""
    greeting = f"Hello, {name}!"
    if excited:
        greeting += " 🎉"
    print(greeting)

Step 3: Add 3 lines of Freyja code

from freyja import CLI
import sys

if __name__ == '__main__':
    cli = CLI(sys.modules[__name__], title="My CLI")
    cli.display()

Step 4: Use your new CLI!

python script.py greet --name Alice --excited
# Output: Hello, Alice! 🎉

python script.py --help
# Automatic help generation with beautiful formatting

🗂️ Module-based CLI

Perfect for functional programming styles and simple utilities. Every function becomes a command:

# data_processor.py
from freyja import CLI
import sys


def process_csv(input_file: str, output_format: str = "json", verbose: bool = False) -> None:
    """Process CSV file and convert to specified format."""
    print(f"Processing {input_file} -> {output_format}")
    if verbose:
        print("Verbose mode enabled")


def analyze_logs(log_file: str, pattern: str, max_lines: int = 1000) -> None:
    """Analyze log files for specific patterns."""
    print(f"Analyzing {log_file} for pattern: {pattern} (max {max_lines} lines)")


if __name__ == '__main__':
    cli = CLI(sys.modules[__name__], title="Data Processing Tools")
    cli.display()

Usage:

python data_processor.py process-csv --input-file data.csv --output-format xml --verbose
python data_processor.py analyze-logs --log-file app.log --pattern "ERROR" --max-lines 500
python data_processor.py --help  # Beautiful auto-generated help

🏗️ Class-based CLI

Ideal for stateful applications and complex workflows. Supports two powerful patterns:

Direct Methods Pattern

Simple and clean - each method becomes a command:

# calculator.py
from freyja import CLI


class Calculator:
    """Advanced calculator with memory and history."""

    def __init__(self, precision: int = 2, memory_enabled: bool = True):
        """Initialize calculator with global settings."""
        self.precision = precision
        self.memory = 0 if memory_enabled else None

    def add(self, a: float, b: float, store_result: bool = False) -> None:
        """Add two numbers together."""
        result = round(a + b, self.precision)
        print(f"{a} + {b} = {result}")
        
        if store_result and self.memory is not None:
            self.memory = result
            print(f"Result stored in memory: {result}")

    def multiply(self, a: float, b: float) -> None:
        """Multiply two numbers."""
        result = round(a * b, self.precision)
        print(f"{a} × {b} = {result}")


if __name__ == '__main__':
    cli = CLI(Calculator, title="Advanced Calculator")
    cli.display()

Usage:

python calculator.py --precision 4 add --a 3.14159 --b 2.71828 --store-result
# Output: 3.14159 + 2.71828 = 5.8599
#         Result stored in memory: 5.8599

Inner Classes Pattern

Organize complex applications with flat double-dash commands:

# project_manager.py
from freyja import CLI
from pathlib import Path


class ProjectManager:
    """Complete project management suite with organized command structure."""

    def __init__(self, config_file: str = "config.json", debug: bool = False):
        """Initialize with global settings."""
        self.config_file = config_file
        self.debug = debug

    class Database:
        """Database operations and management."""

        def __init__(self, connection_string: str = "sqlite:///projects.db", timeout: int = 30):
            """Initialize database connection."""
            self.connection_string = connection_string
            self.timeout = timeout

        def migrate(self, version: str = "latest", dry_run: bool = False) -> None:
            """Run database migrations."""
            action = "Would run" if dry_run else "Running"
            print(f"{action} migration to version: {version}")
            print(f"Connection: {self.connection_string}")

        def backup(self, output_path: Path, compress: bool = True) -> None:
            """Create database backup."""
            compression = "compressed" if compress else "uncompressed"
            print(f"Creating {compression} backup at: {output_path}")

    class Projects:
        """Project creation and management operations."""

        def __init__(self, workspace: str = "./projects", auto_save: bool = True):
            """Initialize project operations."""
            self.workspace = workspace
            self.auto_save = auto_save

        def create(self, name: str, template: str = "basic", description: str = "") -> None:
            """Create a new project from template."""
            print(f"Creating project '{name}' using '{template}' template")
            print(f"Workspace: {self.workspace}")
            print(f"Description: {description}")
            print(f"Auto-save: {'enabled' if self.auto_save else 'disabled'}")

        def deploy(self, project_name: str, environment: str = "staging", force: bool = False) -> None:
            """Deploy project to specified environment."""
            action = "Force deploying" if force else "Deploying"
            print(f"{action} {project_name} to {environment}")


if __name__ == '__main__':
    cli = CLI(ProjectManager, title="Project Management Suite")
    cli.display()

Usage:

# Global + Sub-global + Command arguments (all flat)
python project_manager.py --config-file prod.json --debug \
  database--migrate --connection-string postgres://prod --version 2.1.0 --dry-run

# Create new project with custom workspace
python project_manager.py projects--create --workspace /prod/projects --auto-save \
  --name "web-app" --template "react" --description "Production web application"

# Deploy with force flag
python project_manager.py projects--deploy --project-name web-app --environment production --force

# Beautiful help shows all flat commands organized by group
python project_manager.py --help

✨ Key Features

🚀 Zero Configuration - Works out of the box with just type annotations
Lightning Fast - No runtime dependencies, minimal overhead
🎯 Type Safe - Automatic validation from your type hints
📚 Auto Documentation - Help text generated from your docstrings
🎨 Beautiful Output - Professional themes and formatting
🔧 Flexible Architecture - Module-based or class-based patterns
📦 No Dependencies - Uses only Python standard library
🌈 Shell Completion - Bash, Zsh, Fish, and PowerShell support
Production Ready - Battle-tested in enterprise applications

📚 Documentation

📖 Complete Documentation Hub - Everything you need to master Freyja

Quick Links

🛠️ Development

📖 Development Guide - Comprehensive guide for contributors

Quick Setup

# Clone and setup
git clone https://github.com/terracoil/freyja.git
cd freyja

# Install Poetry and setup environment  
curl -sSL https://install.python-poetry.org | python3 -
./bin/setup-dev.sh

# Run tests and examples
./bin/test.sh
poetry run python examples/mod_example.py --help
poetry run python examples/cls_example.py --help

Development Commands

poetry install              # Install dependencies
./bin/test.sh              # Run tests with coverage
./bin/lint.sh              # Run all linters and formatters
poetry build               # Build package
./bin/publish.sh           # Publish to PyPI (maintainers)

⚙️ Requirements

  • Python 3.13.5+ (recommended) or Python 3.8+
  • Zero runtime dependencies - uses only Python standard library
  • Type annotations required - for automatic CLI generation
  • Docstrings recommended - for automatic help text generation

Ready to transform your Python code into powerful CLIs?

pip install freyja
# Start building amazing command-line tools in minutes! ⚡

📚 Get Started Now →

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

freyja-1.0.1.tar.gz (102.1 kB view details)

Uploaded Source

Built Distribution

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

freyja-1.0.1-py3-none-any.whl (123.7 kB view details)

Uploaded Python 3

File details

Details for the file freyja-1.0.1.tar.gz.

File metadata

  • Download URL: freyja-1.0.1.tar.gz
  • Upload date:
  • Size: 102.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.4 Darwin/24.6.0

File hashes

Hashes for freyja-1.0.1.tar.gz
Algorithm Hash digest
SHA256 b1ff9b508eb0b416a946e642cc33f80f8124a715e7d6d503a131aa259b07f2e8
MD5 c7310649fea7bcf5fa9edc483a3d3c07
BLAKE2b-256 783f2ed9549afe6c49a69d00510ce6b03ca1288d791749e006b1a514cafd6ca2

See more details on using hashes here.

File details

Details for the file freyja-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: freyja-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 123.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.4 Darwin/24.6.0

File hashes

Hashes for freyja-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a3763d8c17af9a9143a22b7de7b6d75b9b2b022dc96bdc2eb5a9af493f13dd0f
MD5 4b5f3e2db7783e9d6bfb2110d647b4b4
BLAKE2b-256 ae5346cd64ee98fc49895c8ad6cef8230a388019098d1c144d175acfcbb38128

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