Moulti

repository·master·Indexed 41 days ago

https://github.com/xavierog/moulti

A terminal tool that transforms standard shell script and Ansible output into organized, visual, and collapsible steps. It features interactive questions, progress bars, and custom styling via Textual CSS (TCSS). Moulti includes a specialized stdout callback plugin for Ansible to display tasks in separate steps and provides helper tools like moulti-askpass for handling sensitive input for SSH, Git, and sudo.

Tokens
32.2K
Snippets
116
Records
172
Agent score
51%

What's inside Moulti

  1. Overview of Moulti tools and extensions

    master

    Moulti is a general-purpose CLI-driven TUI (Terminal User Interface). Beyond the core engine, several practical tools and extensions are available to extend its functionality:

    • Ansible plugin: An extension that integrates with Ansible playbooks, allowing you to monitor playbook execution within the Moulti interface.
    • diff subcommand: A specialized subcommand that converts unified diff chunks into discrete Moulti steps.
    • moulti-man wrapper: A utility that allows you to read system man pages directly within the Moulti TUI.
    • Community Tools: Additional community-driven tools can be found in the Show and tell discussions on GitHub.
  2. Overview of Moulti features

    master

    Moulti provides several interactive and visual features for terminal output management:

    • Interactive Questions: Supports text input questions and button-based questions.
    • Text Search: Search through output similar to less.
    • Step Management: Ability to maximize a single step log (similar to tmux zoom).
    • Progress Bars: Visual indicators for long-running tasks.
    • Programmatic Scrolling: Control how the terminal scrolls through steps.
    • SSH/Askpass Support: Includes moulti-askpass for handling sensitive input.
    • Specialized Formats: Built-in support for Ansible playbooks, man pages, and unified diffs.
  3. Explore Moulti example scripts

    master

    The examples/ directory contains various scripts demonstrating Moulti's capabilities, ranging from system administration tasks to complex UI layouts. Use these scripts to understand how to implement specific features like progress bars, concurrency, and custom styling.

    Available Examples:

    • debian-upgrade: Demonstrates upgrading a Debian-based host using apt.
    • many-buttons: Shows a two-step workflow with numerous buttons.
    • pass-concurrency: Demonstrates running multiple steps concurrently (e.g., running ping localhost 8 times simultaneously). The number of steps is controlled by the $MOULTI_PASS_CONCURRENCY environment variable.
    • progressbar: Shows how to track the generation of multiple items (e.g., 10 SSH keys) using a progress bar.
    • python-checks: A script to run linters on Moulti code (must be executed from the parent directory).
    • scoreboard: Demonstrates an unusual layout (team scores next to a central timer) achieved via the MOULTI_CUSTOM_CSS environment variable.
    • social-preview: Uses toilet, ping, and bat to generate a social preview image.
  4. Understand the Moulti progress bar abstraction

    master

    The progress bar is a Textual widget (since Moulti is built on the Textual framework), but it is not a standard Moulti widget.

    Unlike standard Moulti widgets, which can be added, updated, or deleted in multiple instances within the scrolling area, the progress bar is a single, global UI element controlled strictly via CLI commands. It is not managed as a collection of items in the main view, but rather as a persistent status indicator at the bottom of the screen.

  5. How moulti manpage works under the hood

    master

    The moulti-man wrapper is a convenience layer that executes the following command structure:

    moulti run -- moulti manpage run -- man <command>

    This process starts a new Moulti instance, executes the specified man command, captures the output, and transforms it into a sequence of divider and step widgets.

    moulti run -- moulti manpage run -- man bash
  6. Understand the Moulti write-only security model

    master

    Moulti employs a write-only model for socket operations to minimize the impact of unauthorized connections.

    What an unauthorized user CAN do via the socket:

    • Send ping commands.
    • Change the displayed title.
    • Add new steps with arbitrary content.
    • Alter or erase existing steps (if the name is known).
    • Read answers to questions (potential sensitive information leak).

    What an unauthorized user CANNOT do:

    • List existing steps.
    • Read properties or contents of existing steps.
    • Dump all current steps to disk.
    • Copy any step to the clipboard.
    • Change appearance settings (TCSS, ANSI theme, dark/light mode).
    • Execute any command.
  7. How Moulti's architecture works

    master

    Moulti is a CLI-driven TUI (Terminal User Interface). It operates using a long-running process that maintains and updates the TUI, while short-running CLI processes send instructions to update the interface.

    The architecture consists of five core components:

    • moulti.cli: The CLI part used to drive the instance and initialize it (via moulti init and moulti run).
    • moulti.client: The client part used to send instructions.
    • moulti.protocol: The communication protocol.
    • moulti.server: The server part that manages the instance.
    • moulti.app: The TUI part that renders the interface.
  8. Use default classes to style widgets

    master

    Moulti provides five built-in classes that can be applied to widgets (such as steps, questions, or dividers) to change their appearance, primarily their background color. These classes are synonyms for styles or colors and correspond to CSS classes.

    Available default classes:

    • standard (blue)
    • success (green)
    • warning (orange)
    • error (red)
    • inactive (gray)
  9. Understand Moulti's threading model

    master

    Moulti utilizes multiple threads to manage the TUI, network communication, command execution, and data processing. Understanding these threads helps in debugging performance or inspecting the process via system tools.

    Core Threads

    • moulti:main: Runs the Textual asyncio event loop and manages the TUI.
    • network-loop: Handles non-blocking Unix socket network events (connections, messages). It analyzes incoming messages but delegates TUI updates to the main thread.
    • exec-command: Spawns when using moulti run to execute and monitor the target command.

    Textual Internal Threads

    Every Textual application (including Moulti) spawns two unnamed threads:

    1. Renders the UI to stderr.
    2. Reads events (keystrokes/mouse) from stdin.
  10. Use Rich markup in Moulti

    master

    Moulti supports "Rich markup" (BBcode-like syntax) for styling text in the top-text and bottom-text fields of a step.

    Warning: Rich markup cannot be used in the log part of a step.

    Supported Styles

    Commonly supported styles in modern terminal emulators include:

    • blink, bold, conceal, italic, overline, reverse, strike, underline, underline2.
    • Colors: [red]text[/], [blue]text[/], etc.
    • Combined styles: [blue on yellow1]text[/].

    Example Usage

    moulti step update my_step --bottom-text '[blink]blink[/] [bold]bold[/] [blue]blue[/]'
    moulti step update my_step --bottom-text '[blink]blink[/] [bold]bold[/] [blue]blue[/]'
  11. Handling input transformations in Moulti

    master

    Moulti is designed to display arbitrary output without reformatting it. It does not perform the following tasks:

    • Line numbering (use nl or cat -n)
    • Timestamping (use ts from moreutils)
    • Syntax highlighting (use bat or rich)
    • Line wrapping (use fold)
    • Distinguishing stdout from stderr (use stderred)
    • Stripping colors (use ansi2txt or --color=never)

    Buffering and PTY issues: If your command's output is not appearing in Moulti as expected due to buffering, you should use upstream tools to force line-buffering or allocate a pseudo-terminal (PTY). Examples include:

    • Using stdbuf (from coreutils)
    • Using script or faketty to allocate a PTY.

    Example using script to pipe output to a Moulti step:

    script --quiet --return --command 'your command here' /dev/null | moulti pass your_step