A dog is a Beagle tool with a fixed shape: a static library plus an executable, each owning one purview of the repo's data. The goal is uniform composition — be dispatches HTTP-like verbs to dogs by spawning processes, and dogs coordinate through keeper's read APIs rather than pushing into each other. The method: a name struct with three entry points (DOGOpen/DOGExec/DOGClose), a shared dog [verb] [--flags] URI* CLI, sibling discovery via dog/HOME, and pull-based indexing from Keeper.
Every dog's static lib exposes a name control struct and three uniform calls; the first DOGOpen across all dogs in a process decides whether the session is writable.
DOGOpen(branch, rw) opens the dog's shards for branch in the home singleton; repeated calls compose a multi-branch view.rw.DOGExec(state, cli) runs a parsed CLI (verb + flags + URIs) against open state; DOGClose closes every shard it opened.
Dogs layer over a foundation — beagle → spot,graf,sniff,… → keeper → libdog — so the dispatcher sits on top and the object store at the bottom.
HOMEResolveSibling), so graf can fork a sibling like Bro.
Every dog speaks dog [verb] [--flags] URI*; no verb means a read-only view or search, a verb means an action with a direction of data flow.
get repo→wt, post wt→repo, patch transform in place, put/delete reflog edits; no verb = view/search.[scheme:][//authority][path][?ref][#fragment], canonicalized via DOGCanonURI; see URI for the slots.timestamp verb uri rows (see Sniff for the wtlog).There is no push path into a dog's index: after a write each indexing dog runs its own pass driven by the invoking URI, pulling object data from Keeper.