id: cli
title: Six binaries with six naming conventions, and no way for anyone else to add a seventh
status: open
crates: [didbot-setup, didbot-hookd, didbot-serve, didbot-swarm, didbot-mcp]
dependsOn: []
exitCriterion: >
A single didbot command dispatches every first-party surface as a
subcommand, and an unrecognised subcommand resolves to didbot-<name> on
PATH and runs with no credential inherited from the parent. #
cli #
There is no didbot command. There are didbot-hook, didbot-dev,
didbot-setup, didbot-swarm and vibescrobble-mcp, each its own binary
under crates/*/src/bin/, named by whoever added it. A person who has
installed this project has no single entry point to run, nothing to type to
find out what is available, and no way to discover a surface they did not
already know the name of.
More surfaces are coming — operator is being built now, moderator is
expected — and each one added the current way is another loose name on PATH.
This epic is about the entry point, not about what the surfaces do. Each of those has its own epic; this one says how a person reaches them.
Bake the first-party surfaces in; leave the door open #
Two shapes were considered. Cargo features on one binary select surfaces at
compile time, which means a surface can only be added by rebuilding and
reshipping this project's binary. External dispatch — didbot foo execs
didbot-foo from PATH, the shape git, cargo and kubectl all
converged on — lets someone add a subcommand in any language without
touching this repository.
The near-term decision is to bake the first-party surfaces in: one
didbot binary with hook, dev, setup, swarm and operator as real
clap subcommands, sharing argument conventions, help output and error
formatting. That is the whole of the immediate work.
External dispatch is the escape hatch, and the reason to decide its conventions now rather than when the first extension exists: a calling convention becomes load-bearing the moment anything depends on it, and the first extension written is the one every later extension is copied from.
Done #
Nothing closed yet.