guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Guix CLI, thoughts and suggestions


From: Ian Eure
Subject: Guix CLI, thoughts and suggestions
Date: Mon, 15 Jan 2024 11:24:29 -0800
User-agent: mu4e 1.10.8; emacs 29.1

Greetings,

As I’ve been learning Guix, one of the things I’ve found somewhat unpleasant is the lack of consistency within the guix CLI tool. It feels a bit Git-like, with not much consistency, commands that non-obvioulsy perform more than operation, related commands in different places in the tree, etc.

Just so you know where I’m coming from: I’ve found that compliex CLI tooling benefits from organization and consistency. The Linux ip(8) command is a good example of this kind of organization: to add an IP address, you use `ip address add'. To show address, `ip address show', and to remove one `ip address del'. When options are needed, they get added after the verb or branch in the verb tree; the final verb may take positional arguments as well as --long or -s (short)-form options.

Some examples of where I think Guix could do better. This is an illustrative list, not an exhaustive one.

Inconsistent organization
=========================

Most package-related commands are under `guix package', but many are sibling commands. Examples are `guix size', `guix lint', `guix hash', etc.


Inconsistency between verbs and options
=======================================

Some verbs are bare-word positional arguments, and others are flags to related verbs. IMO, this is the biggest problem, and makes it very difficult to find all the things the CLI can do. `guix package' is a major offender in this area, as it mixes verbs and verb-specific options into the same level. For example, installing a package is `guix package -i foo' rather than `guix package install foo', removing is `guix package -r foo' rather than `guix package remove foo', and listing installed packages is `guix package -I' rather than `guix package installed' (or similar).

This means that users can express commands which *seem* like they should work, but do not. For example `guix package -i emacs -r emacs-pgtk -I' represents a command to 1) install emacs 2) remove emacs-pgtk 3) list installed packages (which would verify the previous two operations occurred). This is a valid command within the accepted organization of `guix package', and doesn’t cause an error, but doesn’t work: the install and remove steps are ignored. A thing I’ve found throughout my career is that designing systems so it’s *impossible* to represent unsupported, nonsensical, or undefined things is an extremely valuable technique to avoid errors and pitfalls. I think Guix could get a lot of mileage out of adopting something similar.

This causes a related problem of making it impossible to know what options are valid for what verbs. Will `guix package --cores=8 -r emacs' remove the package while using eight cores of my system? Will `guix system -s i686 switch-generation 5' switch me to a 32-bit version of generation 5? If verbs are organized better, and have their own options, this ambiguity vanishes.


More inconsistency
==================

Other parts of guix have the opposite problem: `guix system docker-image' probably ought to be an option to `guix system image' rather than a separate verb.


Inconsistency between similar commands
======================================

There are generations of both the system (for GuixSD) and the user profile, however, they work differently. For the system, there’s `guix system list-generations' and `guix system switch-generation', but for the user profile, you need `guix package --list-generations' and `guix package --switch-generation=PATTERN'. Additionally, no help is available for either of the system commands: `guix system switch-generations --help' gives the same output as `guix system --help' -- no description of the supported ways of expressing a generation are available.


Flattened verbs
===============

Related, the generation-related commands under `guix system' ought to be one level deeper: `guix system generation list', `guix system generation switch' etc.


Repeated options
================

Many commands (`guix package', `guix system', `guix build', `guix shell') take -L options, to add Guile source to their load-path. This probably ought to be an option to guix itself, so you can do `guix -L~/src/my-channel build ...'.


Suggestions
===========

All commands should be organized into a tree of verbs.

Verbs should have common aliases (`rm' for `remove', etc).

Verbs should be selected by specifying the minimum unambiguous substring. For example `guix sys gen sw' could refer to `guix system generation switch'.

Options should be applicable to each level of the tree, ex `guix -L~/src/my-channel' would add that load-path, which would be visible to any command. Requesting help is a verb. Appending "help" to any level of the verb tree should show both options applicable to that verb, and its child verbs. `guix help' would show global options and all top-level verbs (package, system, generation, etc); `guix package help' would show package-specific options and package-specific verbs; and so on.


Conclusion
==========

I have no idea if anyone feels similarly about this, or whether there’s appetite to change the CLI, but I think it’d be time well-spent. Having some kind of agreed-upon standard for how the CLI stuff is organized seems like a good thing to me, even if it just stops or slows the addition of more commands with unique expressions.

It seems like a lot of work to change, and backwards compatibility also is an issue. One option I could see working is shoving the entire existing structure under a command in the new tool, so you could do `guix old package -I' or similar. An alternate approach would be using an environment variable to change behaviors.

What do you all think?

Thanks,

 — Ian



reply via email to

[Prev in Thread] Current Thread [Next in Thread]