# βš”οΈ Falyx ![Python](https://img.shields.io/badge/Python-3.10+-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Async-Ready](https://img.shields.io/badge/asyncio-ready-purple) **Falyx** is a battle-ready, introspectable CLI framework for building resilient, asynchronous workflows with: - βœ… Modular action chaining and rollback - πŸ” Built-in retry handling - βš™οΈ Full lifecycle hooks (before, after, success, error, teardown) - πŸ“Š Execution tracing, logging, and introspection - πŸ§™β€β™‚οΈ Async-first design with Process support - 🧩 Extensible CLI menus and customizable output > Built for developers who value *clarity*, *resilience*, and *visibility* in their terminal workflows. --- ## ✨ Why Falyx? Modern CLI tools deserve the same resilience as production systems. Falyx makes it easy to: - Compose workflows using `Action`, `ChainedAction`, or `ActionGroup` - Inject the result of one step into the next (`last_result`) - Handle flaky operations with retries and exponential backoff - Roll back safely on failure with structured undo logic - Add observability with execution timing, result tracking, and hooks - Run in both interactive *and* headless (scriptable) modes - Customize output with Rich `Table`s (grouping, theming, etc.) --- ## πŸ”§ Installation ```bash pip install falyx ``` > Or install from source: ```bash git clone https://github.com/yourname/falyx.git cd falyx poetry install ``` --- ## ⚑ Quick Example ```python import asyncio import random from falyx import Falyx, Action, ChainedAction # A flaky async step that fails randomly async def flaky_step(): await asyncio.sleep(0.2) if random.random() < 0.5: raise RuntimeError("Random failure!") return "ok" # Create the actions step1 = Action(name="step_1", action=flaky_step, retry=True) step2 = Action(name="step_2", action=flaky_step, retry=True) # Chain the actions chain = ChainedAction(name="my_pipeline", actions=[step1, step2]) # Create the CLI menu falyx = Falyx("πŸš€ Falyx Demo") falyx.add_command( key="R", description="Run My Pipeline", action=chain, logging_hooks=True, preview_before_confirm=True, confirm=True, ) # Entry point if __name__ == "__main__": asyncio.run(falyx.run()) ``` ```bash ❯ python simple.py πŸš€ Falyx Demo [R] Run My Pipeline [Y] History [Q] Exit > ``` ```bash ❯ python simple.py run R Command: 'R' β€” Run My Pipeline └── β›“ ChainedAction 'my_pipeline' β”œβ”€β”€ βš™ Action 'step_1' β”‚ ↻ Retries: 3x, delay 1.0s, backoff 2.0x └── βš™ Action 'step_2' ↻ Retries: 3x, delay 1.0s, backoff 2.0x Confirm execution of R β€” Run My Pipeline (calls `my_pipeline`) [Y/n] y [2025-04-15 22:03:57] WARNING ⚠️ Retry attempt 1/3 failed due to 'Random failure!'. βœ… Result: ['ok', 'ok'] ``` --- ## πŸ“¦ Core Features - βœ… Async-native `Action`, `ChainedAction`, `ActionGroup` - πŸ” Retry policies + exponential backoff - β›“ Rollbacks on chained failures - πŸŽ›οΈ Headless or interactive CLI with argparse and prompt_toolkit - πŸ“Š Built-in execution registry, result tracking, and timing - 🧠 Supports `ProcessAction` for CPU-bound workloads - 🧩 Custom `Table` rendering for CLI menu views - πŸ” Hook lifecycle: `before`, `on_success`, `on_error`, `after`, `on_teardown` --- ## πŸ” Execution Trace ```bash [2025-04-14 10:33:22] DEBUG [Step 1] βš™ flaky_step() [2025-04-14 10:33:22] INFO [Step 1] πŸ” Retrying (1/3) in 1.0s... [2025-04-14 10:33:23] DEBUG [Step 1] βœ… Success | Result: ok [2025-04-14 10:33:23] DEBUG [My Pipeline] βœ… Result: ['ok', 'ok'] ``` --- ### 🧱 Core Building Blocks #### `Action` A single async unit of work. Painless retry support. #### `ChainedAction` Run tasks in sequence. Supports rollback on failure and context propagation. #### `ActionGroup` Run tasks in parallel. Useful for fan-out operations like batch API calls. #### `ProcessAction` Offload CPU-bound work to another process β€” no extra code needed. #### `Falyx` Your CLI controller β€” powers menus, subcommands, history, bottom bars, and more. #### `ExecutionContext` Tracks metadata, arguments, timing, and results for each action execution. #### `HookManager` Registers and triggers lifecycle hooks (`before`, `after`, `on_error`, etc.) for actions and commands. --- ## 🧠 Design Philosophy > β€œLike a phalanx: organized, resilient, and reliable.” Falyx is designed for developers who don’t just want CLI tools to run β€” they want them to **fail meaningfully**, **recover gracefully**, and **log clearly**. ---