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.27.3+ and golangci-lint.
Go 1.27.3 includes the crypto/x509 fix rejecting the compromised eMudhra
intermediate certificates. CI and release builds select the toolchain from
go.mod; keep the Docker builder's version aligned with that minimum. Existing
CLI binaries and container images must be rebuilt to pick up the fix; updating
the host's Go installation does not patch an already compiled binary.
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.