ghul.cli 0.3.3

Prefix Reserved
dotnet tool install --global ghul.cli --version 0.3.3
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local ghul.cli --version 0.3.3
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=ghul.cli&version=0.3.3
                    
nuke :add-package ghul.cli --version 0.3.3
                    

ghūl CLI

Run a ghūl script directly, without a project file — on Linux, including via a #! shebang line.

#!/usr/bin/env ghul

entry(args: string[]) is
    IO.Std.write_line("hello, {if args.count > 0 then args[0] else "world" fi}");
si
chmod +x greet.ghul
./greet.ghul world
# hello, world

Or run it directly without the shebang:

ghul greet.ghul world

Commands

ghul [--no-cache] [--] <script> [args...]   # run, if it looks runnable (see below)
ghul run [--no-cache] <script> [args...]    # run unconditionally
ghul compile [--no-cache] <script.ghul>     # compile and print the path to the result
ghul install-compiler [version]             # install (or update) ghul.compiler
ghul cache clear                            # empty the compiled-script cache
ghul version                                # print ghul's and ghul.compiler's versions

With no verb, ghul only runs a file that looks like a script: one whose name ends in .ghul, or one that is executable and starts with #! — the same file a shell would already agree to run directly. Anything else is refused, naming ghul run as the way to force it. ghul run runs the given file regardless, which is also what a #!/usr/bin/env ghul shebang line invokes. A file that happens to be named run, compile, cache, install-compiler or version is reached with ghul -- <name>, the same -- convention every other CLI uses to end option/verb parsing.

ghul compile compiles the script (installing the compiler first if needed) and prints the path to the compiled binary on stdout, with nothing else — install and compiler diagnostics stay on stderr, so the path is safe to capture with $(...). It never runs the result.

ghul install-compiler installs ghul.compiler into ghul's own private tool directory ahead of time, optionally pinned to a given version, so the first real script run doesn't pay for it. Given no version it installs (or updates to) the latest; given one already installed, it's a no-op.

A - in place of <script> reads the source from standard input instead of a file, for both running and compiling:

echo 'entry() is IO.Std.write_line("hi"); si' | ghul -
curl -fsSL https://example.com/greet.ghul | ghul -

--no-cache, given before the script (or before the verb, for run and compile), forces a fresh compile even if a matching cache entry already exists — useful if a cached result ever looks wrong and a rebuild is wanted without reaching for ghul cache clear first. ghul cache clear empties the whole compiled-script cache outright.

Installing

dotnet tool install -g ghul.cli

On first use, ghul installs its own private copy of ghul.compiler (into ~/.local/share/ghul-cli/tools) if one isn't already there — nothing else to set up first.

How it works

Each script is compiled once per script-content-and-compiler-version pair and the result cached under ~/.cache/ghul-cli/scripts; a later run of an unchanged script skips straight to running the cached build. Everything after the script path is passed through unchanged as the running program's own command-line arguments, and its exit code becomes ghul's own.

Installing the compiler and compiling a given script are each protected by a file lock, so running several scripts (or the same new one) at once doesn't race two installs or two compiles of the same content against each other — one does the work and the rest wait for it, rather than one of them losing a half-written result to the other.

There are no reference-assembly options: ghul relies entirely on what ghul.compiler resolves on its own, and doesn't try to add anything it wouldn't already find.

Building from source

dotnet tool restore
dotnet build
dotnet test unit-tests
./tests/smoke.sh
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.3.3 90 9/11/2026
0.3.2 86 9/11/2026
0.3.1 104 9/10/2026
0.3.0 82 9/10/2026
0.2.0 79 9/10/2026
0.1.0 87 9/10/2026