Skip to main content

A TUI command runner based on git changes

Project description

Fnug

[!WARNING] The main branch is currently undergoing a refactor to Rust. If you're looking for the latest Python version, see the python branch.

CI Crates.io image

Fnug is a TUI command runner that automatically selects and executes lint and test commands based on git changes or file watching. Think of it as a terminal multiplexer (like tmux), but purpose-built for running your dev commands side by side.

Fnug demo

Features

  • Git integration — automatically select commands based on uncommitted file changes
  • File watching — monitor the file system and re-select commands when files change
  • Terminal emulation with scrollback — full PTY support for interactive commands and long output
  • Headless mode (fnug check) — run selected commands without the TUI, useful for CI
  • Git hook integration (fnug init-hooks) — install a pre-commit hook that runs fnug check
  • Command dependencies — define depends_on to control execution order
  • Environment variables — set per-command or per-group env vars
  • Nested command groups — organize commands into a hierarchical tree with inherited settings
  • Workspace support — discover and merge .fnug.yaml files from subdirectories in mono-repos

Installation

From crates.io

cargo install fnug

From PyPI

# With uv
uv tool install fnug

# With pipx
pipx install fnug

From GitHub Releases

Download a prebuilt binary from GitHub Releases.

With Nix

# Run directly
nix run github:nickolaj-jepsen/fnug

# Or install to profile
nix profile install github:nickolaj-jepsen/fnug

From source

git clone https://github.com/nickolaj-jepsen/fnug.git
cd fnug
cargo install --path .

Usage

Run fnug in a directory with a .fnug.yaml configuration file (or pass -c path/to/config.yaml).

Subcommands

Command Description
fnug Launch the TUI
fnug check Run selected commands headlessly (exit code reflects pass/fail)
fnug init-hooks Install a git pre-commit hook that runs fnug check

Flags

Flag Description
-c <path> Path to config file
--no-workspace Disable workspace resolution (don't search for a parent root)
--log-file Write logs to a file
--log-level Log level: off, error, warn, info, debug, trace (default: info)
--fail-fast Stop on first failure (check only)
--no-tui Never prompt to open TUI on failure (check only)
--mute-success Suppress output for passing commands (check only)
--all Include commands with auto.check: false (check only)
--force Overwrite existing hook (init-hooks only)

Configuration

Fnug searches for .fnug.yaml, .fnug.yml, or .fnug.json from the current directory upward.

Minimal example

fnug_version: 0.1.0
name: my-project
commands:
  - name: hello
    cmd: echo world

Git auto-selection

Select commands based on uncommitted changes. Re-trigger with g in the TUI.

fnug_version: 0.1.0
name: my-project
commands:
  - name: lint
    cmd: cargo clippy
    auto:
      git: true
      path:
        - "./src"
      regex:
        - "\\.rs$"

File watching

Monitor the file system and select commands when matching files change. Can be combined with git auto.

fnug_version: 0.1.0
name: my-project
commands:
  - name: test
    cmd: cargo test
    auto:
      watch: true
      path:
        - "./src"
      regex:
        - "\\.rs$"

Always auto-selection

Mark commands that should always be selected, regardless of git changes or file watching.

fnug_version: 0.1.0
name: my-project
commands:
  - name: typecheck
    cmd: cargo check
    auto:
      always: true

Excluding commands from check mode

Commands with auto.check: false are skipped during fnug check (and git hooks) but remain auto-selected in the TUI. Use fnug check --all to include them.

Useful for commands that are too slow or noisy for pre-commit checks but you still want to run them automatically in the TUI.

fnug_version: 0.1.0
name: my-project
commands:
  - name: unit tests
    cmd: cargo test
    auto:
      git: true
  - name: integration tests
    cmd: cargo test --release
    auto:
      git: true
      check: false   # skip in `fnug check`, still auto-selected in TUI

Nested groups with inheritance

Groups inherit cwd, auto, and env settings from their parent.

fnug_version: 0.1.0
name: my-project
children:
  - name: backend
    auto:
      git: true
      watch: true
      path:
        - "./src"
      regex:
        - "\\.rs$"
    commands:
      - name: fmt
        cmd: cargo fmt
      - name: test
        cmd: cargo test
      - name: clippy
        cmd: cargo clippy

Workspace

Workspace mode discovers .fnug.yaml files in subdirectories and merges them as child groups. This is useful for mono-repos where each package has its own config.

When workspace: true, fnug walks the filesystem (skipping .gitignore'd and hidden directories) to find sub-configs. Files do not need to be git-tracked to be discovered.

# Auto-discover sub-configs (walks up to 5 levels deep)
fnug_version: 0.1.0
name: my-monorepo
workspace: true
commands:
  - name: root-lint
    cmd: echo "root"
# Custom max scan depth
workspace:
  max_depth: 2
# Explicit glob patterns
workspace:
  paths:
    - "./packages/*/"
    - "./apps/*/"

When run from a subdirectory that contains a .fnug.yaml, fnug automatically resolves upward to the nearest workspace root. Use --no-workspace to disable this behavior.

Advanced example

See this project's .fnug.yaml for a full example.

Configuration reference

Root fields

Field Type Description
fnug_version string Expected fnug version — warns on mismatch
name string Display name for the root group
workspace bool / object Enable workspace mode (see Workspace)
commands list Top-level commands
children list Nested command groups
cwd string Working directory (inherited by children)
env map Environment variables (inherited by children)
auto object Default auto rules (inherited by children)

Command fields

Field Type Description
name string Display name (required)
cmd string Shell command to run (required)
id string Custom identifier — defaults to the command name
cwd string Working directory override
env map Extra environment variables
auto object Auto-selection rules (see below)
depends_on list of strings Command IDs that must finish before this one runs
scrollback integer PTY scrollback buffer size (number of lines)

Group fields

Field Type Description
name string Display name (required)
id string Custom identifier — defaults to the group name
cwd string Working directory (inherited by children)
env map Environment variables (inherited by children)
auto object Default auto rules (inherited by children)
commands list Commands in this group
children list Nested child groups

Auto fields

Field Type Description
git bool Select when git-changed files match path/regex
watch bool Select when watched files match path/regex
always bool Always selected regardless of changes
path list of strings Path prefixes to match against (e.g. "./src")
regex list of strings Regex patterns to match against file paths (e.g. "\\.rs$")
check bool Include in fnug check — set false to skip (default true)

Keyboard Shortcuts

Key Context Action
j / Tree Move down
k / Tree Move up
h / Tree Collapse group / Deselect command
l / Tree Expand group / Select command
Space Tree Toggle expand/select
Enter Tree Run all selected commands
r Tree Run current command
s Tree Stop current command
c Tree Clear current command
g Tree Git auto-select
/ Tree Search/filter commands
Esc Search Clear search
L Tree Toggle log panel
Tab Tree Focus terminal
Esc Terminal Back to tree
Ctrl+R Global Toggle fullscreen
Ctrl+C Global Quit
q Tree Quit

Mouse

  • Click a tree item to select it
  • Double-click a command to run it, or a group to expand/collapse
  • Click the selection orb (●/○) or arrow (▼/▶) to toggle
  • Drag the separator between tree and terminal to resize
  • Scroll wheel in the terminal panel to scroll output
  • Right-click a command for a context menu with run/stop/clear options

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

fnug-0.1.0a10.tar.gz (750.8 kB view details)

Uploaded Source

Built Distributions

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

fnug-0.1.0a10-py3-none-win_amd64.whl (3.6 MB view details)

Uploaded Python 3Windows x86-64

fnug-0.1.0a10-py3-none-manylinux_2_28_x86_64.whl (3.4 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

fnug-0.1.0a10-py3-none-manylinux_2_28_aarch64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

fnug-0.1.0a10-py3-none-macosx_11_0_arm64.whl (3.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

fnug-0.1.0a10-py3-none-macosx_10_12_x86_64.whl (3.2 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file fnug-0.1.0a10.tar.gz.

File metadata

  • Download URL: fnug-0.1.0a10.tar.gz
  • Upload date:
  • Size: 750.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.12.6

File hashes

Hashes for fnug-0.1.0a10.tar.gz
Algorithm Hash digest
SHA256 25f93da2b01b9ce01034c4498496c332bff370c829be5305d3a9d8d3aac6fc77
MD5 e8b2a6959407474fce3c3979d0cb143d
BLAKE2b-256 47cb50e002af295ec3cfc15eed7d5fe00588367f0a82385650321d38f376bc53

See more details on using hashes here.

File details

Details for the file fnug-0.1.0a10-py3-none-win_amd64.whl.

File metadata

  • Download URL: fnug-0.1.0a10-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.6 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.12.6

File hashes

Hashes for fnug-0.1.0a10-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 84f2b956cfb2d87e173b0285e7dd8bbb72be67ac3b984b130864372121309eb3
MD5 5c484e0b8ff49c0ef5e25f9e1a6a3df4
BLAKE2b-256 1ce9d441601f503b4e1c675d65b9034394483e4a024b36a0a089ff7c5e1aa5c8

See more details on using hashes here.

File details

Details for the file fnug-0.1.0a10-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for fnug-0.1.0a10-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 873d2b85bd4a478497245da8fb2c868d069aa47e3e3630afe47549fd1bda3863
MD5 be0696cc2cb2c225150d7a708499c27d
BLAKE2b-256 9472776f40a5c0192a9c1fdd99866bc6524169e29d68712076fe54b43c2ea1bd

See more details on using hashes here.

File details

Details for the file fnug-0.1.0a10-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for fnug-0.1.0a10-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a126500d49a3693769c3bce00e05a1ca23b3f818db9e1034c9940ef4950256ff
MD5 8dc8cfdc725155df04a806147dd72a17
BLAKE2b-256 a31a545f67b4235ab060ef28eb5083304159e8a0b3ef7748437307216904767e

See more details on using hashes here.

File details

Details for the file fnug-0.1.0a10-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fnug-0.1.0a10-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b94a200ea1b80192aa7b4f14943b9973cfbbb4c6cea6d7ad003256a137180dfb
MD5 8131f929697d201bc9716a1e2280c3f7
BLAKE2b-256 2bcd9d93fce41ab1ef73149c7a48e1933563f7d06611415d2c58de15927f95bb

See more details on using hashes here.

File details

Details for the file fnug-0.1.0a10-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for fnug-0.1.0a10-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 101f1fe63248fd0a7bb35a5b2422601f620f7d0f429a5b38d02754ce80bd9017
MD5 c706699b610458dacf780e2796d81eaa
BLAKE2b-256 403b9c65b81e86a81516d1be0c1a6be6bdb55971b7bf114df01d1d700f64b725

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