MANI(1)

NAME
mani - repositories manager and task runner

SYNOPSIS
mani [command] [flags]

DESCRIPTION
manage multiple repositories and run commands across them

OPTIONS

--color[=true]
    enable color

-c, --config=""
    specify config

-h, --help[=false]
    help for mani

-u, --user-config=""
    specify user config

COMMANDS

run <task>
    Run tasks. The tasks are specified in a mani.yaml file along with the projects you can target. Available Options:

        -a, --all[=false]
            select all projects

        -k, --cwd[=false]
            select current working directory

        --describe[=false]
            display task information

        --dry-run[=false]
            display the task without execution

        -e, --edit[=false]
            edit task

        -f, --forks=4
            maximum number of concurrent processes

        --ignore-errors[=false]
            continue execution despite errors

        --ignore-non-existing[=false]
            skip non-existing projects

        --omit-empty-columns[=false]
            hide empty columns in table output

        --omit-empty-rows[=false]
            hide empty rows in table output

        -o, --output=""
            set output format [stream|table|markdown|html]

        --parallel[=false]
            execute tasks in parallel across projects

        -d, --paths=[]
            select projects by path

        -p, --projects=[]
            select projects by name

        -s, --silent[=false]
            hide progress output during task execution

        -J, --spec=""
            set spec

        -t, --tags=[]
            select projects by tag

        -E, --tags-expr=""
            select projects by tags expression

        -T, --target=""
            select projects by target name

        --theme=""
            set theme

        --tty[=false]
            replace current process

exec <command> [flags]
    Execute arbitrary commands. Use single quotes around your command to prevent file globbing and environment variable expansion from occurring before the command is executed in each directory. Available Options:

        -a, --all[=false]
            target all projects

        -k, --cwd[=false]
            use current working directory

        --dry-run[=false]
            print commands without executing them

        -f, --forks=4
            maximum number of concurrent processes

        --ignore-errors[=false]
            ignore errors

        --ignore-non-existing[=false]
            ignore non-existing projects

        --omit-empty-columns[=false]
            omit empty columns in table output

        --omit-empty-rows[=false]
            omit empty rows in table output

        -o, --output=""
            set output format [stream|table|markdown|html]

        --parallel[=false]
            run tasks in parallel across projects

        -d, --paths=[]
            select projects by path

        -p, --projects=[]
            select projects by name

        -s, --silent[=false]
            hide progress when running tasks

        -J, --spec=""
            set spec

        -t, --tags=[]
            select projects by tag

        -E, --tags-expr=""
            select projects by tags expression

        -T, --target=""
            target projects by target name

        --theme=""
            set theme

        --tty[=false]
            replace current process

init [flags]
    Initialize a mani repository. Creates a new mani repository by generating a mani.yaml configuration file and a .gitignore file in the current directory. Available Options:

        --auto-discovery[=true]
            automatically discover and add Git repositories to mani.yaml

        -g, --sync-gitignore[=true]
            synchronize .gitignore file

sync [flags]
    Clone repositories and update .gitignore file. For repositories requiring authentication, disable parallel cloning to enter credentials for each repository individually. Available Options:

        -f, --forks=4
            maximum number of concurrent processes

        --ignore-sync-state[=false]
            sync project even if the project's sync field is set to false

        -p, --parallel[=false]
            clone projects in parallel

        -d, --paths=[]
            clone projects by path

        -w, --remove-orphaned-worktrees[=false]
            remove git worktrees not in config

        -s, --status[=false]
            display status only

        -g, --sync-gitignore[=true]
            sync gitignore

        -r, --sync-remotes[=false]
            update git remote state

        -t, --tags=[]
            clone projects by tags

        -E, --tags-expr=""
            clone projects by tag expression

edit
    Open up mani config file in $EDITOR.

edit project [project]
    Edit mani project in $EDITOR.

edit task [task]
    Edit mani task in $EDITOR.

list projects [projects] [flags]
    List projects. Available Options:

        -a, --all[=true]
            select all projects

        -k, --cwd[=false]
            select current working directory

        --headers=[project,tag,description]
            specify columns to display [project, path, relpath, description, url, tag, worktree]

        -d, --paths=[]
            select projects by paths

        -t, --tags=[]
            select projects by tags

        -E, --tags-expr=""
            select projects by tags expression

        -T, --target=""
            select projects by target name

        --tree[=false]
            display output in tree format

        -o, --output="table"
            set output format [table|markdown|html]

        --theme="default"
            set theme

list tags [tags] [flags]
    List tags. Available Options:

        --headers=[tag,project]
            specify columns to display [project, tag]

        -o, --output="table"
            set output format [table|markdown|html]

        --theme="default"
            set theme

list tasks [tasks] [flags]
    List tasks. Available Options:

        --headers=[task,description]
            specify columns to display [task, description, target, spec]

        -o, --output="table"
            set output format [table|markdown|html]

        --theme="default"
            set theme

describe projects [projects] [flags]
    Describe projects. Available Options:

        -a, --all[=true]
            select all projects

        -k, --cwd[=false]
            select current working directory

        -e, --edit[=false]
            edit project

        -d, --paths=[]
            filter projects by paths

        -t, --tags=[]
            filter projects by tags

        -E, --tags-expr=""
            target projects by tags expression

        -T, --target=""
            target projects by target name

        --theme="default"
            set theme

describe tasks [tasks] [flags]
    Describe tasks. Available Options:

        -e, --edit[=false]
            edit task

        --theme="default"
            set theme

tui [flags]
    Run TUI Available Options:

        -r, --reload-on-change[=false]
            reload mani on config change

        --theme="default"
            set theme

check
    Validate config.

gen Available Options:

        -d, --dir="./"
            directory to save manpage to

CONFIG
The mani.yaml config is based on the following concepts:

    •   projects are directories, which may be git repositories, in which case they have an URL attribute
    •   tasks are shell commands that you write and then run for selected projects
    •   specs are configs that alter task execution and output
    •   targets are configs that provide shorthand filtering of projects when executing tasks
    •   env are environment variables that can be defined globally, per project and per task
Specs, targets and themes use a default object by default that the user can override to modify execution of mani commands. Check the files and environment section to see how the config file is loaded. Below is a config file detailing all of the available options and their defaults.
     # Import projects/tasks/env/specs/themes/targets from other configs
     import:
       - ./some-dir/mani.yaml
     # Shell used for commands
     # If you use any other program than bash, zsh, sh, node, and python
     # then you have to provide the command flag if you want the command-line string evaluted
     # For instance: bash -c
     shell: bash
     # If set to true, mani will override the URL of any existing remote
     # and remove remotes not found in the config
     sync_remotes: false
     # Determines whether the .gitignore should be updated when syncing projects
     sync_gitignore: true
     # When running the TUI, specifies whether it should reload when the mani config is changed
     reload_tui_on_change: false
     # List of Projects
     projects:
       # Project name [required]
       pinto:
         # Determines if the project should be synchronized during 'mani sync'
         sync: true
         # Project path relative to the config file
         # Defaults to project name if not specified
         path: frontend/pinto
         # Repository URL
         url: git@github.com:alajmo/pinto
         # Project description
         desc: A vim theme editor
         # Custom clone command
         # Defaults to "git clone URL PATH"
         clone: git clone git@github.com:alajmo/pinto --branch main
         # Branch to use as primary HEAD when cloning
         # Defaults to repository's primary HEAD
         branch:
         # When true, clones only the specified branch or primary HEAD
         single_branch: false
         # Project tags
         tags: [dev]
         # Remote repositories
         # Key is the remote name, value is the URL
         remotes:
           foo: https://github.com/bar
         # Project-specific environment variables
         env:
           # Simple string value
           branch: main
           # Shell command substitution
           date: $(date -u +"%Y-%m-%dT%H:%M:%S%Z")
     # List of Specs
     specs:
       default:
         # Output format for task results
         # Options: stream, table, html, markdown
         output: stream
         # Enable parallel task execution
         parallel: false
         # Maximum number of concurrent tasks when running in parallel
         forks: 4
         # When true, continues execution if a command fails in a multi-command task
         ignore_errors: false
         # When true, skips project entries in the config that don't exist
         # on the filesystem without throwing an error
         ignore_non_existing: false
         # Hide projects with no command output
         omit_empty_rows: false
         # Hide columns with no data
         omit_empty_columns: false
         # Clear screen before task execution (TUI only)
         clear_output: true
     # List of targets
     targets:
       default:
         # Select all projects
         all: false
         # Select project in current working directory
         cwd: false
         # Select projects by name
         projects: []
         # Select projects by path
         paths: []
         # Select projects by tag
         tags: []
         # Select projects by tag expression
         tags_expr: ""
     # Environment variables available to all tasks
     env:
       # Simple string value
       AUTHOR: "alajmo"
       # Shell command substitution
       DATE: $(date -u +"%Y-%m-%dT%H:%M:%S%Z")
     # List of tasks
     tasks:
       # Command name [required]
       simple-2: echo "hello world"
       # Command name [required]
       simple-1:
         cmd: |
           echo "hello world"
         desc: simple command 1
       # Command name [required]
       advanced-command:
         # Task description
         desc: complex task
         # Task theme
         theme: default
         # Shell interpreter
         shell: bash
         # Task-specific environment variables
         env:
           # Static value
           branch: main
           # Dynamic shell command output
           num_lines: $(ls -1 | wc -l)
         # Can reference predefined spec:
         # spec: custom_spec
         # or define inline:
         spec:
           output: table
           parallel: true
           forks: 4
           ignore_errors: false
           ignore_non_existing: true
           omit_empty_rows: true
           omit_empty_columns: true
         # Can reference predefined target:
         # target: custom_target
         # or define inline:
         target:
           all: true
           cwd: false
           projects: [pinto]
           paths: [frontend]
           tags: [dev]
           tags_expr: (prod || dev) && !test
         # Single multi-line command
         cmd: |
           echo complex
           echo command
         # Multiple commands
         commands:
           # Node.js command example
           - name: node-example
                shell: node
             cmd: console.log("hello world from node.js");
           # Reference to another task
           - task: simple-1
     # List of themes
     # Styling Options:
     # Fg (foreground color): Empty string (""), hex color, or named color from W3C standard
     # Bg (background color): Empty string (""), hex color, or named color from W3C standard
     # Format: Empty string (""), "lower", "title", "upper"
     # Attribute: Empty string (""), "bold", "italic", "underline"
     # Alignment: Empty string (""), "left", "center", "right"
     themes:
       # Theme name [required]
       default:
         # Stream Output Configuration
         stream:
           # Include project name prefix for each line
           prefix: true
           # Colors to alternate between for each project prefix
           prefix_colors: ["#d787ff", "#00af5f", "#d75f5f", "#5f87d7", "#00af87", "#5f00ff"]
           # Add a header before each project
           header: true
           # String value that appears before the project name in the header
           header_prefix: "TASK"
           # Fill remaining spaces with a character after the prefix
           header_char: "*"
         # Table Output Configuration
         table:
           # Table style
           # Available options: ascii, light, bold, double, rounded
           style: ascii
           # Border options for table output
           border:
             around: false # Border around the table
             columns: true # Vertical border between columns
             header: true # Horizontal border between headers and rows
             rows: false # Horizontal border between rows
           header:
             fg: "#d787ff"
             attr: bold
             format: ""
           title_column:
             fg: "#5f87d7"
             attr: bold
             format: ""
         # Tree View Configuration
         tree:
           # Tree style
           # Available options: ascii, light, bold, double, rounded, bullet-square, bullet-circle, bullet-star
           style: ascii
         # Block Display Configuration
         block:
           key:
             fg: "#5f87d7"
           separator:
             fg: "#5f87d7"
           value:
             fg:
           value_true:
             fg: "#00af5f"
           value_false:
             fg: "#d75f5f"
          # TUI Configuration
          tui:
            default:
              fg:
              bg:
              attr:
            border:
              fg:
            border_focus:
              fg: "#d787ff"
            title:
              fg:
              bg:
              attr:
              align: center
            title_active:
              fg: "#000000"
              bg: "#d787ff"
              attr:
              align: center
            button:
              fg:
              bg:
              attr:
              format:
            button_active:
              fg: "#080808"
              bg: "#d787ff"
              attr:
              format:
            table_header:
              fg: "#d787ff"
              bg:
              attr: bold
              align: left
              format:
            item:
              fg:
              bg:
              attr:
            item_focused:
              fg: "#ffffff"
              bg: "#262626"
              attr:
            item_selected:
              fg: "#5f87d7"
              bg:
              attr:
            item_dir:
              fg: "#d787ff"
              bg:
              attr:
            item_ref:
              fg: "#d787ff"
              bg:
              attr:
            search_label:
              fg: "#d7d75f"
              bg:
              attr: bold
            search_text:
              fg:
              bg:
              attr:
            filter_label:
              fg: "#d7d75f"
              bg:
              attr: bold
            filter_text:
              fg:
              bg:
              attr:
            shortcut_label:
              fg: "#00af5f"
              bg:
              attr:
            shortcut_text:
              fg:
              bg:
              attr:

EXAMPLES
Initialize mani
    samir@hal-9000 ~ $ mani init
    Initialized mani repository in /tmp
    - Created mani.yaml
    - Created .gitignore
    Following projects were added to mani.yaml
     Project  | Path
    ----------+------------
     test     | .
     pinto    | dev/pinto
Clone projects
    samir@hal-9000 ~ $ mani sync --parallel --forks 8
    pinto | Cloning into '/tmp/dev/pinto'...
     Project  | Synced
    ----------+--------
     test     | ✓
     pinto    | ✓
List all projects
    samir@hal-9000 ~ $ mani list projects
     Project
    ---------
     test
     pinto
List all projects with output set to tree
    samir@hal-9000 ~ $ mani list projects --tree
        ── dev
           └─ pinto
List all tags
    samir@hal-9000 ~ $ mani list tags
     Tag | Project
    -----+---------
     dev | pinto
List all tasks
    samir@hal-9000 ~ $ mani list tasks
     Task             | Description
    ------------------+------------------
     simple-1         | simple command 1
     simple-2         |
     advanced-command | complex task
Describe a task
    samir@hal-9000 ~ $ mani describe tasks advanced-command
    Name: advanced-command
    Description: complex task
    Theme: default
    Target:
        All: true
        Cwd: false
        Projects: pinto
        Paths: frontend
        Tags: dev
        TagsExpr: ""
    Spec:
        Output: table
        Parallel: true
        Forks: 4
        IgnoreErrors: false
        IgnoreNonExisting: false
        OmitEmptyRows: false
        OmitEmptyColumns: false
    Env:
        branch: dev
        num_lines: 2
    Cmd:
        echo advanced
        echo command
    Commands:
         - simple-1
         - simple-2
         - cmd
Run a task for all projects with tag 'dev'
    samir@hal-9000 ~ $ mani run simple-1 --tags dev
     Project | Simple-1
    ---------+-------------
     pinto   | hello world
Run a task for all projects matching tags expression 'dev && !prod'
    samir@hal-9000 ~ $ mani run simple-1 --tags-expr '(dev && !prod)'
     Project | Simple-1
    ---------+-------------
     pinto   | hello world
Run ad-hoc command for all projects
    samir@hal-9000 ~ $ mani exec 'echo 123' --all
     Project | Output
    ---------+--------
     archive | 123
     pinto   | 123

FILTERING PROJECTS
Projects can be filtered when managing projects (sync, list, describe) or running tasks. Filters can be specified through CLI flags or target configurations. The filtering is inclusive, meaning projects must satisfy all specified filters to be included in the results.
Available options:
    •   cwd: include only the project under the current working directory, ignoring all other filters
    •   all: include all projects
    •   projects: Filter by project names
    •   paths: Filter by project paths
    •   tags: Filter by project tags
    •   tags_expr: Filter using tag logic expressions
    •   target: Filter using target
For mani sync/list/describe:
    •   No filters: Targets all projects
    •   Multiple filters: Select intersection of projects/paths/tags/tags_expr/target filters
For mani run/exec:
    1.  Runtime flags (highest priority)
    2.  Target flag configuration (--target)
    3.  Task's default target data (lowest priority)
The default target is named `default` and can be overridden by defining a target named `default` in the config. This only applies for sub-commands `run` and `exec`.

TAGS EXPRESSION
Tag expressions allow filtering projects using boolean operations on their tags. The expression is evaluated for each project's tags to determine if the project should be included.
Operators (in precedence order):
    •   (): Parentheses for grouping
    •   !: NOT operator (logical negation)
    •   &&: AND operator (logical conjunction)
    •   ||: OR operator (logical disjunction)
For example, the expression:
  (main && (dev || prod)) && !test
requires the projects to pass these conditions:
    •   Must have "main" tag
    •   Must have either "dev" OR "prod" tag
    •   Must NOT have "test" tag

FILES
When running a command, mani will check the current directory and all parent directories for the following files: mani.yaml, mani.yml, .mani.yaml, .mani.yml. Additionally, it will import (if found) a config file from:
    •   Linux: $XDG_CONFIG_HOME/mani/config.yaml or $HOME/.config/mani/config.yaml if $XDG_CONFIG_HOME is not set.
    •   Darwin: $HOME/Library/Application Support/mani/config.yaml
    •   Windows: %AppData%ni
Both the config and user config can be specified via flags or environments variables.

ENVIRONMENT
MANI_CONFIG
    Override config file path
MANI_USER_CONFIG
    Override user config file path
NO_COLOR
    If this env variable is set (regardless of value) then all colors will be disabled

BUGS
See GitHub Issues: https://github.com/alajmo/mani/issues.

AUTHOR
mani was written by Samir Alajmovic alajmovic.samir@gmail.com. For updates and more information go to manicli.com (https://www.manicli.com).