Thank you for considering contributing to smbcloud-cli! This document covers everything you need to get up and running.
By participating in this project you agree to abide by our Code of Conduct. Please be respectful and considerate of others.
- Rust — toolchain version is pinned in
rust-toolchain.toml(currently 1.93) - cargo-workspaces — for publishing (
cargo install cargo-workspaces) - A
.envfile in the repo root containingCLI_CLIENT_SECRET=<value>— required at compile time bydotenv_codegen
- Fork the repository on GitHub
- Clone your fork:
git clone https://github.com/your-username/smbcloud-cli.git cd smbcloud-cli - Create the
.envfile (ask a maintainer for the value, or use a local stub for offline work):echo "CLI_CLIENT_SECRET=your_secret_here" > .env
- Verify everything compiles:
cargo check --workspace
- Create a branch for your work:
git checkout -b your-feature-or-fix
# Debug build
cargo build
# Release build
cargo build --releaseThe compiled binary is at target/release/smb.
cargo test --all-featurescargo clippy --workspace --tests -- -D warningsFix any warnings before opening a PR — CI treats warnings as errors.
# Apply formatting
cargo fmt --all
# Check only (what CI runs)
cargo fmt --all -- --checkThis is a Cargo workspace. Each crate has a focused responsibility:
| Crate | Purpose |
|---|---|
crates/cli |
Main binary (smb) — commands, entrypoint |
crates/smbcloud-model |
Shared API data types (serde structs) |
crates/smbcloud-network |
Network config and environment resolution |
crates/smbcloud-networking |
Core HTTP client (SmbClient) |
crates/smbcloud-networking-account |
Account API calls |
crates/smbcloud-networking-project |
Project API calls |
crates/smbcloud-utils |
Shared utilities |
All workspace-level dependencies are declared once in the root Cargo.toml under [workspace.dependencies]. When adding a dependency to a crate, add it to the root table first, then inherit it with { workspace = true } in the crate's own Cargo.toml.
These rules are enforced in code review and by CI:
- Use
?to propagate errors — never.unwrap()or.expect()in production code. - Never silently discard errors with
let _ =on fallible operations. - Do not create
mod.rsfiles — usesrc/some_module.rsinstead ofsrc/some_module/mod.rs. - Use full words for variable names — no abbreviations.
- Comments explain why, not what. Do not write comments that summarize code.
- Prefer adding to existing files over creating many small new files.
The full guidelines are in AGENTS.md.
- Ensure all of the following pass locally before pushing:
cargo check --workspace cargo test --all-features cargo clippy --workspace --tests -- -D warnings cargo fmt --all -- --check - Push your branch and open a PR against
main. - Fill out the pull request template — in particular the Release Notes section.
- A maintainer will review your changes and may request modifications.
- Once approved, your PR will be merged.
Use a clear, imperative title that describes the change:
- ✅
Fix crash when project name contains spaces - ✅
Add logout command - ❌
feat: add logout(no conventional-commit prefixes) - ❌
Fixed some stuff.(no past tense, no trailing punctuation)
Use the GitHub issue tracker and fill out the bug report template. Please include:
- A clear description of the problem
- Steps to reproduce
- Expected vs. actual behaviour
- Your OS and the output of
smb --version
Use the GitHub issue tracker and fill out the feature request template. Describe the use case clearly — what problem does the feature solve?
Releases are handled by maintainers using cargo-workspaces:
# Bump versions interactively
cargo workspaces version
# Publish all crates
cargo workspaces publish --publish-as-isGitHub Actions workflows handle the GitHub release and npm wrapper publish automatically on tag push.
Open a GitHub issue or reach out to the maintainers. We're happy to help.