freyja


Namefreyja JSON
Version 1.0.4 PyPI version JSON
download
home_pagehttps://pypi.org/project/freyja/
SummaryPython Library that builds a complete CLI given one or more functions using introspection
upload_time2025-09-03 16:33:29
maintainerNone
docs_urlNone
authorSteven Miers
requires_python<4.0.0,>=3.13.7
licenseMIT
keywords cli auto introspection argparse command-line
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ![Freyja](https://github.com/terracoil/freyja/blob/f7f3411a3ea7346d9294e394629e78f078352579/freyja.png)

# 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?](#-why-freyja)
* [⚡ Quick Start](#-quick-start)
* [🗂️ Module-based CLI](#️-module-based-cli)
* [🏗️ Class-based CLI](#️-class-based-cli)
  * [Direct Methods Pattern](#direct-methods-pattern)
  * [Inner Classes Pattern](#inner-classes-pattern)
* [✨ Key Features](#-key-features)
* [📚 Documentation](#-documentation)
* [🛠️ Development](#️-development)
* [⚙️ Requirements](#️-requirements)

## 🚀 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.

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

**Before Freyja:**
```bash
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:**
```bash
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
```bash
pip install freyja
```

**Step 2:** Add type annotations to your functions
```python
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
```python
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!
```bash
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:

```python
# 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:**
```bash
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:

```python
# 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:**
```bash
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:

```python
# 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:**
```bash
# 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](docs/README.md)** - Everything you need to master Freyja

### Quick Links
* **[🚀 Getting Started](docs/getting-started/README.md)** - Installation and first steps
* **[👤 User Guide](docs/user-guide/README.md)** - Comprehensive guides for both CLI modes  
* **[⚙️ Features](docs/features/README.md)** - Type annotations, themes, completion, and more
* **[📋 Examples & Best Practices](docs/guides/README.md)** - Real-world examples and patterns
* **[❓ FAQ](docs/faq.md)** - Frequently asked questions
* **[🔧 API Reference](docs/reference/README.md)** - Complete API documentation

## 🛠️ Development

**[📖 Development Guide](CLAUDE.md)** - Comprehensive guide for contributors

### Quick Setup

```bash
# 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

```bash
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?**

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

**[📚 Get Started Now →](docs/getting-started/README.md)**
            

Raw data

            {
    "_id": null,
    "home_page": "https://pypi.org/project/freyja/",
    "name": "freyja",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0.0,>=3.13.7",
    "maintainer_email": null,
    "keywords": "cli, auto, introspection, argparse, command-line",
    "author": "Steven Miers",
    "author_email": "steven.miers@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/ca/62/22e5123871133d3f31aebdba2953abb60b9408e8733ab19d4b4b7e720e32/freyja-1.0.4.tar.gz",
    "platform": null,
    "description": "![Freyja](https://github.com/terracoil/freyja/blob/f7f3411a3ea7346d9294e394629e78f078352579/freyja.png)\n\n# Freyja \u26a1\n**No-dependency, zero-configuration CLI tool to build command-line interfaces purely from your code.**\n\nTransform 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.\n\n## Table of Contents\n* [\ud83d\ude80 Why Freyja?](#-why-freyja)\n* [\u26a1 Quick Start](#-quick-start)\n* [\ud83d\uddc2\ufe0f Module-based CLI](#\ufe0f-module-based-cli)\n* [\ud83c\udfd7\ufe0f Class-based CLI](#\ufe0f-class-based-cli)\n  * [Direct Methods Pattern](#direct-methods-pattern)\n  * [Inner Classes Pattern](#inner-classes-pattern)\n* [\u2728 Key Features](#-key-features)\n* [\ud83d\udcda Documentation](#-documentation)\n* [\ud83d\udee0\ufe0f Development](#\ufe0f-development)\n* [\u2699\ufe0f Requirements](#\ufe0f-requirements)\n\n## \ud83d\ude80 Why Freyja?\n\n**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.\n\n```bash\npip install freyja\n# That's it! No dependencies, no configuration needed.\n```\n\n**Before Freyja:**\n```bash\npython 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\"}'\n```\n\n**After Freyja:**\n```bash\npython script.py database--create-user --name Alice --email alice@example.com\n# Global config handled automatically, clean syntax, built-in help\n```\n\n## \u26a1 Quick Start\n\n**Step 1:** Install Freyja\n```bash\npip install freyja\n```\n\n**Step 2:** Add type annotations to your functions\n```python\ndef greet(name: str = \"World\", excited: bool = False) -> None:\n    \"\"\"Greet someone by name.\"\"\"\n    greeting = f\"Hello, {name}!\"\n    if excited:\n        greeting += \" \ud83c\udf89\"\n    print(greeting)\n```\n\n**Step 3:** Add 3 lines of Freyja code\n```python\nfrom freyja import CLI\nimport sys\n\nif __name__ == '__main__':\n    cli = CLI(sys.modules[__name__], title=\"My CLI\")\n    cli.display()\n```\n\n**Step 4:** Use your new CLI!\n```bash\npython script.py greet --name Alice --excited\n# Output: Hello, Alice! \ud83c\udf89\n\npython script.py --help\n# Automatic help generation with beautiful formatting\n```\n\n## \ud83d\uddc2\ufe0f Module-based CLI\n\nPerfect for functional programming styles and simple utilities. Every function becomes a command:\n\n```python\n# data_processor.py\nfrom freyja import CLI\nimport sys\n\n\ndef process_csv(input_file: str, output_format: str = \"json\", verbose: bool = False) -> None:\n    \"\"\"Process CSV file and convert to specified format.\"\"\"\n    print(f\"Processing {input_file} -> {output_format}\")\n    if verbose:\n        print(\"Verbose mode enabled\")\n\n\ndef analyze_logs(log_file: str, pattern: str, max_lines: int = 1000) -> None:\n    \"\"\"Analyze log files for specific patterns.\"\"\"\n    print(f\"Analyzing {log_file} for pattern: {pattern} (max {max_lines} lines)\")\n\n\nif __name__ == '__main__':\n    cli = CLI(sys.modules[__name__], title=\"Data Processing Tools\")\n    cli.display()\n```\n\n**Usage:**\n```bash\npython data_processor.py process-csv --input-file data.csv --output-format xml --verbose\npython data_processor.py analyze-logs --log-file app.log --pattern \"ERROR\" --max-lines 500\npython data_processor.py --help  # Beautiful auto-generated help\n```\n\n## \ud83c\udfd7\ufe0f Class-based CLI\n\nIdeal for stateful applications and complex workflows. Supports two powerful patterns:\n\n### Direct Methods Pattern\n\nSimple and clean - each method becomes a command:\n\n```python\n# calculator.py\nfrom freyja import CLI\n\n\nclass Calculator:\n    \"\"\"Advanced calculator with memory and history.\"\"\"\n\n    def __init__(self, precision: int = 2, memory_enabled: bool = True):\n        \"\"\"Initialize calculator with global settings.\"\"\"\n        self.precision = precision\n        self.memory = 0 if memory_enabled else None\n\n    def add(self, a: float, b: float, store_result: bool = False) -> None:\n        \"\"\"Add two numbers together.\"\"\"\n        result = round(a + b, self.precision)\n        print(f\"{a} + {b} = {result}\")\n        \n        if store_result and self.memory is not None:\n            self.memory = result\n            print(f\"Result stored in memory: {result}\")\n\n    def multiply(self, a: float, b: float) -> None:\n        \"\"\"Multiply two numbers.\"\"\"\n        result = round(a * b, self.precision)\n        print(f\"{a} \u00d7 {b} = {result}\")\n\n\nif __name__ == '__main__':\n    cli = CLI(Calculator, title=\"Advanced Calculator\")\n    cli.display()\n```\n\n**Usage:**\n```bash\npython calculator.py --precision 4 add --a 3.14159 --b 2.71828 --store-result\n# Output: 3.14159 + 2.71828 = 5.8599\n#         Result stored in memory: 5.8599\n```\n\n### Inner Classes Pattern\n\nOrganize complex applications with flat double-dash commands:\n\n```python\n# project_manager.py\nfrom freyja import CLI\nfrom pathlib import Path\n\n\nclass ProjectManager:\n    \"\"\"Complete project management suite with organized command structure.\"\"\"\n\n    def __init__(self, config_file: str = \"config.json\", debug: bool = False):\n        \"\"\"Initialize with global settings.\"\"\"\n        self.config_file = config_file\n        self.debug = debug\n\n    class Database:\n        \"\"\"Database operations and management.\"\"\"\n\n        def __init__(self, connection_string: str = \"sqlite:///projects.db\", timeout: int = 30):\n            \"\"\"Initialize database connection.\"\"\"\n            self.connection_string = connection_string\n            self.timeout = timeout\n\n        def migrate(self, version: str = \"latest\", dry_run: bool = False) -> None:\n            \"\"\"Run database migrations.\"\"\"\n            action = \"Would run\" if dry_run else \"Running\"\n            print(f\"{action} migration to version: {version}\")\n            print(f\"Connection: {self.connection_string}\")\n\n        def backup(self, output_path: Path, compress: bool = True) -> None:\n            \"\"\"Create database backup.\"\"\"\n            compression = \"compressed\" if compress else \"uncompressed\"\n            print(f\"Creating {compression} backup at: {output_path}\")\n\n    class Projects:\n        \"\"\"Project creation and management operations.\"\"\"\n\n        def __init__(self, workspace: str = \"./projects\", auto_save: bool = True):\n            \"\"\"Initialize project operations.\"\"\"\n            self.workspace = workspace\n            self.auto_save = auto_save\n\n        def create(self, name: str, template: str = \"basic\", description: str = \"\") -> None:\n            \"\"\"Create a new project from template.\"\"\"\n            print(f\"Creating project '{name}' using '{template}' template\")\n            print(f\"Workspace: {self.workspace}\")\n            print(f\"Description: {description}\")\n            print(f\"Auto-save: {'enabled' if self.auto_save else 'disabled'}\")\n\n        def deploy(self, project_name: str, environment: str = \"staging\", force: bool = False) -> None:\n            \"\"\"Deploy project to specified environment.\"\"\"\n            action = \"Force deploying\" if force else \"Deploying\"\n            print(f\"{action} {project_name} to {environment}\")\n\n\nif __name__ == '__main__':\n    cli = CLI(ProjectManager, title=\"Project Management Suite\")\n    cli.display()\n```\n\n**Usage:**\n```bash\n# Global + Sub-global + Command arguments (all flat)\npython project_manager.py --config-file prod.json --debug \\\n  database--migrate --connection-string postgres://prod --version 2.1.0 --dry-run\n\n# Create new project with custom workspace\npython project_manager.py projects--create --workspace /prod/projects --auto-save \\\n  --name \"web-app\" --template \"react\" --description \"Production web application\"\n\n# Deploy with force flag\npython project_manager.py projects--deploy --project-name web-app --environment production --force\n\n# Beautiful help shows all flat commands organized by group\npython project_manager.py --help\n```\n\n## \u2728 Key Features\n\n\ud83d\ude80 **Zero Configuration** - Works out of the box with just type annotations  \n\u26a1 **Lightning Fast** - No runtime dependencies, minimal overhead  \n\ud83c\udfaf **Type Safe** - Automatic validation from your type hints  \n\ud83d\udcda **Auto Documentation** - Help text generated from your docstrings  \n\ud83c\udfa8 **Beautiful Output** - Professional themes and formatting  \n\ud83d\udd27 **Flexible Architecture** - Module-based or class-based patterns  \n\ud83d\udce6 **No Dependencies** - Uses only Python standard library  \n\ud83c\udf08 **Shell Completion** - Bash, Zsh, Fish, and PowerShell support  \n\u2705 **Production Ready** - Battle-tested in enterprise applications  \n\n## \ud83d\udcda Documentation\n\n**[\ud83d\udcd6 Complete Documentation Hub](docs/README.md)** - Everything you need to master Freyja\n\n### Quick Links\n* **[\ud83d\ude80 Getting Started](docs/getting-started/README.md)** - Installation and first steps\n* **[\ud83d\udc64 User Guide](docs/user-guide/README.md)** - Comprehensive guides for both CLI modes  \n* **[\u2699\ufe0f Features](docs/features/README.md)** - Type annotations, themes, completion, and more\n* **[\ud83d\udccb Examples & Best Practices](docs/guides/README.md)** - Real-world examples and patterns\n* **[\u2753 FAQ](docs/faq.md)** - Frequently asked questions\n* **[\ud83d\udd27 API Reference](docs/reference/README.md)** - Complete API documentation\n\n## \ud83d\udee0\ufe0f Development\n\n**[\ud83d\udcd6 Development Guide](CLAUDE.md)** - Comprehensive guide for contributors\n\n### Quick Setup\n\n```bash\n# Clone and setup\ngit clone https://github.com/terracoil/freyja.git\ncd freyja\n\n# Install Poetry and setup environment  \ncurl -sSL https://install.python-poetry.org | python3 -\n./bin/setup-dev.sh\n\n# Run tests and examples\n./bin/test.sh\npoetry run python examples/mod_example.py --help\npoetry run python examples/cls_example.py --help\n```\n\n### Development Commands\n\n```bash\npoetry install              # Install dependencies\n./bin/test.sh              # Run tests with coverage\n./bin/lint.sh              # Run all linters and formatters\npoetry build               # Build package\n./bin/publish.sh           # Publish to PyPI (maintainers)\n```\n\n## \u2699\ufe0f Requirements\n\n* **Python 3.13.5+** (recommended) or Python 3.8+\n* **Zero runtime dependencies** - uses only Python standard library\n* **Type annotations required** - for automatic CLI generation\n* **Docstrings recommended** - for automatic help text generation\n\n---\n\n**Ready to transform your Python code into powerful CLIs?**\n\n```bash\npip install freyja\n# Start building amazing command-line tools in minutes! \u26a1\n```\n\n**[\ud83d\udcda Get Started Now \u2192](docs/getting-started/README.md)**",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python Library that builds a complete CLI given one or more functions using introspection",
    "version": "1.0.4",
    "project_urls": {
        "Documentation": "https://github.com/tangledpath/freyja/docs",
        "Homepage": "https://pypi.org/project/freyja/",
        "Repository": "https://github.com/tangledpath/freyja"
    },
    "split_keywords": [
        "cli",
        " auto",
        " introspection",
        " argparse",
        " command-line"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "75d3033306f94abbaf555b156220c2468aebdde37733ab4620b2d16421baac02",
                "md5": "7f976c626316f91ea534f020b64c9286",
                "sha256": "268770ad85f1101afa0df4debcdc18529412ed2cac6b91029eeaff2ebf97d111"
            },
            "downloads": -1,
            "filename": "freyja-1.0.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7f976c626316f91ea534f020b64c9286",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0.0,>=3.13.7",
            "size": 124324,
            "upload_time": "2025-09-03T16:33:28",
            "upload_time_iso_8601": "2025-09-03T16:33:28.474110Z",
            "url": "https://files.pythonhosted.org/packages/75/d3/033306f94abbaf555b156220c2468aebdde37733ab4620b2d16421baac02/freyja-1.0.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ca6222e5123871133d3f31aebdba2953abb60b9408e8733ab19d4b4b7e720e32",
                "md5": "fedff4d9cbebcccc8ba817814deb1943",
                "sha256": "f710cd1d87117873a7fc6e3902138f0602439be042a0294d6781507741e8a013"
            },
            "downloads": -1,
            "filename": "freyja-1.0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "fedff4d9cbebcccc8ba817814deb1943",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0.0,>=3.13.7",
            "size": 102698,
            "upload_time": "2025-09-03T16:33:29",
            "upload_time_iso_8601": "2025-09-03T16:33:29.543805Z",
            "url": "https://files.pythonhosted.org/packages/ca/62/22e5123871133d3f31aebdba2953abb60b9408e8733ab19d4b4b7e720e32/freyja-1.0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-03 16:33:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tangledpath",
    "github_project": "freyja",
    "github_not_found": true,
    "lcname": "freyja"
}
        
Elapsed time: 0.57320s