sxcli.devSimple Extensible CLI

What it checks

Two analyzers, both on by default; -sxreg and -sxserved select one explicitly.

These are the shapes of mistake the tool looks for, described so you know what it is for. The tool is early and due a redesign — for the exact diagnostics your version emits, run it.

sxreg — registrations and compositions#

Service ids. An id should be an exported package constant, path-shaped, and rooted in the registering package's import path. That rooting rule is the point: ids are unique by construction when they start with the package that declares them, and it is precisely the guarantee the runtime cannot check — at run time there is no such thing as "the package this registration is written in".

go
go
const ID = "example.com/box/serve" // in package example.com/box/serve

Registration chains. Every chain must reach a terminal — .Register() or fw.Solo — and must declare an alias. A chain that is built and then dropped compiles perfectly and registers nothing; that is a mistake with no runtime symptom at all, because the service simply isn't there. Alias grammar is validated too.

Config struct tags. The engine's rules, mirrored:

  • conf: / env: / pos: grammar, and the mandatory json: name
  • the dead arg: tag
  • the Version mandate
  • positional shape — contiguity, at most one rest, no required index after an optional one
  • positionals declared on non-applet services
  • separator runs (a--b) that would forge a boundary in a derived environment name

Migration chains. From-versions contiguous, each step's input type matching the previous step's output, and the final step's output equal to the current config type. A chain that stops one version short is a startup error you would otherwise meet on a machine with an old config file — which is to say, in production.

Compositions. Accept and Order must name registrations that are actually catalogued, Order must be a subset of Accept, and duplicates are reported. Ambiguous dependencies — two unranked candidates for one slot — are caught here rather than at startup.

sxserved — the two-phase front door#

conf.New and conf.NewLoader(...).Load() return a served boolean. When it is true, the run was already answered — --help printed the schema, --write-config wrote the file, --upgrade-config migrated it, --validate-config found nothing wrong — and the program should return. See the conf front door for the exact set, including which failures are deliberately not served.

Discard that value and --help prints the help and then the program runs anyway. Nothing errors; the tool just does its job when the user asked a question. The analyzer flags the discard.

Where this fits#

These checks exist because the framework already enforces the same rules at startup. What the analyzer changes is when you find out — in an editor or in CI, rather than the first time someone runs the binary with a real config file.

Both back-ends are documented from the other side too: fw for the framework's runtime checks, and conf for the standalone engine's.