Thanks for wanting to contribute. Here's how to get going and what to expect.
git clone https://github.com/Bandwidth/cli.git
cd cli
make build # compile → ./band
make test # run tests
make lint # run golangci-lintRequires Go 1.22+ and golangci-lint.
CI runs automatically on every pull request. Your PR needs to pass all of these before it can merge:
| Check | What it does |
|---|---|
| Test | go test ./... on Ubuntu, macOS, and Windows |
| Lint | golangci-lint — catches style issues, dead code, common bugs |
| Security | govulncheck — flags known vulnerabilities in dependencies |
| Docs check | Warns if you changed commands/flags without updating README.md or AGENTS.md |
If lint or tests fail, fix them locally before pushing again. Don't open a "fix CI" follow-up PR.
- Bug fixes — always welcome. Include a test that would have caught the bug.
- New flags or options on existing commands — usually straightforward. Open an issue first if you're unsure.
- New commands for existing Bandwidth APIs — open an issue to discuss before writing code. We want to make sure the command design fits the CLI's patterns.
- Documentation improvements — typo fixes, clarifications, better examples. Ship it.
- Test coverage — more tests are always good.
- New commands without prior discussion. Don't spend hours on a PR we haven't agreed on. Open an issue first.
- Large refactors or architectural changes without a design discussion. File an issue, explain the problem, propose a solution.
- Dependencies for things the standard library handles. We keep the dependency tree small.
- Cosmetic-only changes (reformatting, renaming, reordering imports) that don't fix a bug or add a feature. These create noise in git blame and review queues.
This CLI is agent-native. If your change affects command output, flags, or exit codes, see the design principles at the top of AGENTS.md and update that file alongside README.md.
We accept AI-assisted contributions, but they must be reviewed and understood by a human before submission. If your PR was substantially generated by an AI tool, note that in the PR description. We'll hold AI-generated PRs to the same quality bar as any other — tests, lint, docs, and a clear explanation of what the change does and why.
Bulk AI-generated PRs (typo-fixing sweeps, mass refactors, etc.) tend to introduce subtle issues and create review burden disproportionate to their value. Discuss first in an issue.
- Run
make lintbefore pushing. If it passes, you're good. gofmtis non-negotiable. The linter enforces it.- Keep functions short. If a function needs a comment explaining what it does, it might need to be split.
- Error messages should be lowercase and start with the operation that failed:
"creating application: %w", not"Failed to create application". - Don't add comments that restate the code. Add comments that explain why something non-obvious is happening.
cmd/
band/ Entrypoint (main.go)
<command>/ One package per command group (auth, app, call, etc.)
internal/
api/ HTTP client — JSON and XML modes, Requester interface
auth/ OAuth2 token manager, OS keychain storage
config/ Config file management (~/.config/band/)
cmdutil/ Shared command helpers (output flags, client creation)
output/ JSON formatting and response flattening
ui/ Terminal UI helpers (colors, spinners, progress output)
Commands live in cmd/<name>/. Each command group gets its own package. Tests live next to the code they test (e.g., cmd/tendlc/tendlc_test.go, internal/api/client_test.go). The internal/ packages are shared infrastructure — touch these carefully.
Write clear commit messages. We're not prescriptive about format, but:
- First line: short summary of what changed (under 72 chars)
- Body (if needed): explain why, not what — the diff shows what changed
Open an issue. We're happy to help you figure out whether your idea fits before you invest time in code.