Design: Metatool

2025-11-15

So... When building stuff, I keep finding this pattern where I have a 'system' that actually has a number of executables and I would really prefer to have a front-end CLI. It turns out that it's not a terribly difficult problem to solve once and for all, you just have to know the trick.

It's looking at argv[0] to know how the program was invoked.

No, really, that's it.

Finding the binary

OK, so there are a few more wrinkles, but that's the tricky bit. For example, in order to fit the meta tool to existing projects that just happen to be structured appropriately, we should probably accept both file name extensions, and handle multiple hyphenated words. Oh, and an environment variable to an alternate PATH.

FOO_PATH=/usr/local/lib/foo:/home/user/.bin

foo bar baz would then match foo-bar-baz in either path in $FOO_PATH or any in $PATH. Or foo-bar-baz.exe. Underscore should probably be accepted as well as hyphen, so foo_bar.sh would be invoked with "baz" as its first argument.

At this point, it's easy to feel how it would grow. Configs are another hassle that could be dealt with once for most systems projects. It'd be nice to not have to deal with the hierarchy of configs, but still get that rich system, user, project, environment variable, options hierarchy, right?

Again, following in the footsteps of git, aliases would be next. Aliases work by defining a name and a replacement is used to abbreviate commands, and to set parameters.

I think the way I'd want this to happen, would be a refactoring of git, so that the main git binary looks at argv[0] and just uses that name throughout, and all the version control-specific things it does would be move out of it. It would be nice, because git is already widely installed, and it would make it even more useful. That's extremely unlikely to happen, not least of which is that it's a bit questionable to change the capabilities of an existing tool that way.

OK, but we can still build it, right?

Well, yes, but it turns out the devil is in the details, so it's not quite as simple as it looks.

Parameters

The hierarchy of parameters.

  1. System config
  2. User global config
  3. Project config
  4. Environment variables
  5. CLI args

Environment variables would be munged according to some system. Here's from Kafka:

  • . => _
  • - => ___
  • _ => __

The next problem is how to make these available in a more-or-less uniform way. We can probably munge something into env vars, but the weird corner cases keep on coming. For a simple example, what to do with repeated long-opts? --fnord can definitely be rendered as FOO_FNORD, but do you do if there are three of them? Perhaps the answer is to have sensible defaults, and to leave it to a top-level configuration to control this.

RSS
https://blog.eurenius.eu/posts/feed.xml