Command Structure¶
This document explains the design decisions behind how commands are organised in the CLI.
Decision¶
We prefer top-level commands (dbx clone, dbx sync) over nested command groups (dbx repo clone, dbx repo sync), but command groups and even two-level nesting are used when the domain is rich enough to warrant it.
Rationale¶
Simplicity and Discoverability¶
Top-level commands are more discoverable and easier to use:
Shorter commands:
dbx clone -g pymongovsdbx repo clone -g pymongoFewer concepts: Users don’t need to understand command groups
Better help output: Commands appear directly in
dbx --help
Common Usage Patterns¶
The most frequently used commands should be at the top level:
dbx clone— Clone repositories from a groupdbx sync— Sync repositories with upstreamdbx install— Install packagesdbx test— Run testsdbx list— List cloned repositories
These are the primary workflows, so they should be as accessible as possible.
Consistency with Git¶
Git uses top-level commands (git clone, git pull, git push) rather than nested groups (git repo clone). This pattern is familiar to developers.
Current Command Inventory¶
Top-Level Commands¶
Single-action commands that are frequently used or domain-agnostic:
dbx branch Git branch operations across repositories
dbx clone Clone a repository group
dbx edit Open a repository in an editor
dbx install Install package dependencies
dbx just Run just commands in a repository
dbx list List cloned repositories
dbx log Git log across repositories
dbx open Open a repository in the browser
dbx patch Create Evergreen CI patches
dbx remove Remove a cloned repository
dbx status Git status across repositories
dbx swap Swap between repository versions
dbx switch Switch git branches across repositories
dbx sync Sync repositories with upstream
dbx test Run tests in a repository
Command Groups (One Level)¶
Related subcommands that share a common domain:
# Configuration management
dbx config init
dbx config show
dbx config edit
# Documentation operations
dbx docs build
dbx docs list
dbx docs open
# Virtual environment management
dbx env init
dbx env list
dbx env remove
# Django project management
dbx project add myproject
dbx project install
dbx project migrate
dbx project run
dbx project su
dbx project list
dbx project remove
Command Groups (Two Levels)¶
When a domain has enough distinct sub-domains, two levels of nesting are acceptable. The only current example is dbx spec, where spec-level operations (sync, list, status) are clearly separate from patch lifecycle operations:
# Spec-level operations
dbx spec sync crud sessions
dbx spec list
dbx spec status
# Patch lifecycle (sub-group)
dbx spec patch apply
dbx spec patch create PYTHON-1234
dbx spec patch list
dbx spec patch remove PYTHON-1234
dbx spec patch verify
Two-level nesting should remain rare. The bar for adding a third level is very high — if you find yourself wanting dbx foo bar baz, consider whether foo and bar should be merged or whether baz belongs at a higher level.
When to Use Command Groups¶
Command groups are appropriate when:
Multiple related subcommands share a common domain (e.g., environment management, spec sync)
Namespacing prevents collisions —
dbx spec listanddbx listdo different thingsThe group has 3+ subcommands — a group with only one subcommand adds friction without benefit
Top-level placement is preferred when:
The command is used frequently in isolation
It has no natural siblings that share state or configuration
Adding it to a group would make it harder to discover
Migration Notes¶
This design was established when clone and sync were promoted from the repo command group to the top level.
Before:
dbx repo clone -g pymongo
dbx repo sync mongo-python-driver
dbx repo -l
After:
dbx clone -g pymongo
dbx sync mongo-python-driver
dbx list
The repo.py module was converted from a command module to a utility functions module containing helpers like get_config(), get_base_dir(), and get_repo_groups().
Smart Defaults for Convenience¶
To further improve usability, commands should provide smart defaults when possible.
Project Commands Default to Newest¶
Most dbx project commands default to the newest project when no project name is specified:
dbx project run # Run newest project
dbx project manage shell # Open shell on newest project
dbx project su # Create superuser on newest project
dbx project migrate # Run migrations on newest project
dbx project remove # Remove newest project
The “newest” project is determined by filesystem modification time. When a command defaults to the newest project, it displays an informative message:
ℹ️ No project specified, using newest: 'myproject'
This follows the principle of optimizing for the common case: developers typically work on one project at a time, so requiring the project name for every command adds unnecessary friction.
Future Considerations¶
As the CLI grows, continue to evaluate whether commands belong at the top level or in a group:
Top level: Frequently used, standalone operations
Command groups: Related operations that share context or configuration
Two-level groups: Only when a domain is large enough to have distinct sub-domains
When adding smart defaults:
Sensible defaults: Commands should work with minimal arguments for common use cases
Clear feedback: When defaults are applied, inform the user what was chosen
Easy override: Defaults should be easy to override when needed