PsychoLlama / clapfile

Turn config files into command line apps

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clapfile

Turn config files into command line apps

Project Status

🧑‍🔬 Experimental

I wrote this for my home lab (a managed NixOS cluster). It works, it's useful, but I'm still playing with the concept. I might abandon it later.

Documentation is kind of thrown together.

Purpose

Managed systems usually have maintenance scripts that run manually, like initializing a ZFS pool or unlocking a Vault server. These scripts are written in Python, Bash, Perl, or whatever language was convenient at the time.

Over time scripts become less discoverable. They are scattered across the filesystem, have different interfaces, and different levels of --help.

Clapfile unifies scripts into one interface. You define subcommands, the script to execute, the options it accepts, and clapfile wraps them into in a single CLI.

This gets you some advantages:

  • Discoverability: All management scripts are in one place and discoverable through --help.
  • Shell completions: Generated completions are available for popular shells.
  • Argument validation: Required arguments are checked before running the script.

Usage

Create a clapfile.toml in your project. This defines the available scripts.

Tip

The config file mirrors the clap library. If clap::Command has a method .about(h: String), then the TOML key is about = "string". However, not all options are supported.

name = "system"
about = "System administration tasks"

[subcommands.greet]
about = "Says hello"
run = 'echo "Hello, $name"'

args = [
  { id = "name", required = true }
]

Then run it with clapfile:

clapfile run --config clapfile.toml -- greet world
# => "Hello, world"

The run key is a shell command to execute. Any arguments defined are passed through as environment variables.

This is just to get started quickly. The Nix wrapper has all the bells and whistles. It's the recommended way to use clapfile.

Installation

This package is only available as a Nix flake. To quickly try it, run:

nix run 'github:PsychoLlama/clapfile'

Or programmatically by adding it to your flake.nix:

{
  inputs.clapfile.url = "github:PsychoLlama/clapfile";

  outputs = { self, clapfile }: {
    devShell = eachSystem (system: pkgs: pkgs.mkShell {
      packages = [
        (clapfile.packages.${system}.clapfile.command {
          args.shell = "${pkgs.bash}/bin/bash";
          command = {
            name = "example";
            run = "echo 'Hello, world!'";
          };
        })
      ];
    });
  };
}

Usage with Nix

The project flake exports a clapfile derivation. You can add this to a dev shell, or use the clapfile.command {...} builder to construct a wrapper program:

project = clapfile.command {
  args = {
    # Optional: extra options passed to `clapfile run`
  };

  command = {
    name = "project";
    about = "Project task runner";
    subcommands = {
      lint = {
        about = "Lint the project";
        run = pkgs.writers.writeBash "lint-project" ''
          echo "Linting..."
        '';
      };

      test = {
        about = "Run the test suite";
        run = pkgs.writers.writePython3 "run-tests" { } ''
          print("Running tests...")
        '';
      };
    };
  };
}

The result is a project command you can add to your dev shell or environment.systemPackages.

project --help
Project task runner

Usage: project [COMMAND]

Commands:
  test  Run the test suite
  lint  Lint the project
  help  Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print help

Usage with NixOS

There is a NixOS module that works similar to the Nix example above.

{
  # Provides `config.clapfile`.
  imports = [ flake-inputs.clapfile.nixosModules.nixos ];

  # Ensures `pkgs.clapfile` is available.
  nixpkgs.overlays = [ flake-inputs.clapfile.overlays.programs ];

  clapfile = {
    enable = true; # Add the generated program to `environment.systemPackages`.
    args = {
      # Optional command line args passed to `clapfile run`
    };

    command = {
      name = "greet";
      about = "Says hello";
      run = "echo 'Hello, world!'";
    };
  };
}
greet
# => "Hello, world!"

About

Turn config files into command line apps

License:MIT License


Languages

Language:Rust 70.1%Language:Nix 29.9%