release/v0.7.4
claude/smbcloud-github-app-k9641p
development
feature/apps
feature/build-release
feature/ci-docs
feature/ci-ruby-gems
feature/cicd
feature/completion
feature/dist-nuget
feature/fix-ci-sdk-pypi-rubygem
feature/fix-clippy-on-stable-channel
feature/fix-deployment-script
feature/github-email
feature/gresiq-v1
feature/project-new-structure
feature/rsync-deploy
feature/ruby-runner
feature/sdk-npm
feature/sdk-workflows
feature/smbcloud-cli-release-npm
feature/smbcloud-deploy
feature/wasm
main
release/v0.7.4
| 1 | # GitHub Copilot Instructions — smbcloud-cli |
| 2 | |
| 3 | ## Project Overview |
| 4 | |
| 5 | `smbcloud-cli` is a Rust CLI tool that ships as the `smb` binary. It lets users authenticate, manage projects, and trigger deployments on the smbCloud platform. The workspace targets Rust 1.93 (edition 2021) and is built as a Cargo workspace with multiple focused crates. |
| 6 | |
| 7 | ## Workspace Structure |
| 8 | |
| 9 | | Crate | Role | |
| 10 | |---|---| |
| 11 | | `crates/cli` | Main binary (`smb`) — all commands, entrypoint | |
| 12 | | `crates/smbcloud-model` | Shared `serde` data models (source of truth for API shapes) | |
| 13 | | `crates/smbcloud-network` | Network config, environment resolution, connectivity check | |
| 14 | | `crates/smbcloud-networking` | Core HTTP client (`SmbClient`) | |
| 15 | | `crates/smbcloud-auth` | Auth SDK API calls — login, logout, me | |
| 16 | | `crates/smbcloud-networking-project` | Project API calls | |
| 17 | | `crates/smbcloud-utils` | Shared utility helpers | |
| 18 | | `crates/gresiq` | Internal tooling | |
| 19 | |
| 20 | ### CLI Source Layout (`crates/cli/src/`) |
| 21 | |
| 22 | ``` |
| 23 | main.rs — tokio entrypoint, logging setup, command dispatch |
| 24 | lib.rs — crate root, SmbClient accessor |
| 25 | cli/ — Cli struct, Commands enum, CommandResult |
| 26 | account/ — login, logout, me handlers |
| 27 | deploy/ — deploy command handler |
| 28 | project/ — project init, crud, process handlers |
| 29 | token/ — token storage/retrieval |
| 30 | ui/ — terminal output helpers (spinners, styles) |
| 31 | ``` |
| 32 | |
| 33 | ## Dependency Graph |
| 34 | |
| 35 | ``` |
| 36 | crates/cli |
| 37 | └── smbcloud-auth |
| 38 | └── smbcloud-networking-project |
| 39 | └── smbcloud-networking (SmbClient) |
| 40 | └── smbcloud-model (API types) |
| 41 | └── smbcloud-network (Environment, connectivity) |
| 42 | └── smbcloud-utils |
| 43 | ``` |
| 44 | |
| 45 | All workspace-level dependencies are declared **once** in the root `Cargo.toml` under `[workspace.dependencies]`. Crate-level `Cargo.toml` files must inherit from workspace with `{ workspace = true }`. |
| 46 | |
| 47 | ## Coding Guidelines |
| 48 | |
| 49 | ### Correctness & Clarity |
| 50 | |
| 51 | - Prioritize correctness and clarity. Performance is a secondary concern unless explicitly stated. |
| 52 | - Comments explain **why**, never **what**. Do not write comments that summarize or re-describe the code. |
| 53 | - Implement new functionality in existing files when it fits logically. Avoid creating many small, single-purpose files. |
| 54 | |
| 55 | ### Error Handling |
| 56 | |
| 57 | - Use `?` to propagate errors. Never call `.unwrap()` or `.expect()` outside of test code. |
| 58 | - Never silently discard errors with `let _ =` on fallible operations: |
| 59 | - Propagate with `?` when the caller should handle it |
| 60 | - Use explicit `match` or `if let Err(e) = ...` when custom recovery logic is needed |
| 61 | - Log and ignore only when truly intentional and visibility is preserved |
| 62 | - All command handlers return `anyhow::Result<CommandResult>`. Surface user-facing errors with `anyhow!("descriptive message")`. |
| 63 | - Ensure async errors propagate to the top level so the user sees meaningful terminal output. |
| 64 | |
| 65 | ### Naming & Style |
| 66 | |
| 67 | - Use full words for all variable and parameter names — no single-letter names, no abbreviations (e.g. `environment` not `env`, `client` not `c`). |
| 68 | - Use variable shadowing to scope `.clone()` calls inside async closures, minimizing borrow lifetimes: |
| 69 | ```rust |
| 70 | cx.spawn({ |
| 71 | let handle = handle.clone(); |
| 72 | async move { |
| 73 | handle.do_work().await; |
| 74 | } |
| 75 | }); |
| 76 | ``` |
| 77 | |
| 78 | ### Module Structure |
| 79 | |
| 80 | - **Never create `mod.rs` files.** Use `src/some_module.rs` instead of `src/some_module/mod.rs`. |
| 81 | - When creating new crates, set `[lib] path = "src/<crate_name>.rs"` in `Cargo.toml` instead of relying on the default `lib.rs`. |
| 82 | |
| 83 | ### Panics & Bounds |
| 84 | |
| 85 | - Avoid any operation that can panic at runtime: no `.unwrap()`, no unchecked indexing, no `.expect()` in production code. |
| 86 | - When iterating or slicing, always validate bounds or use safe alternatives like `.get()`. |
| 87 | |
| 88 | ## Architecture Patterns |
| 89 | |
| 90 | ### Adding a New Command |
| 91 | |
| 92 | 1. Add a variant to the `Commands` enum in `crates/cli/src/cli/` |
| 93 | 2. Create a handler function in `crates/cli/src/<domain>/` |
| 94 | 3. Wire it in the `match cli.command { ... }` block in `main.rs` |
| 95 | 4. Mark commands that require internet access in the `needs_internet` match block |
| 96 | |
| 97 | ### Adding a New API Call |
| 98 | |
| 99 | 1. Add or update the request/response types in `crates/smbcloud-model/src/` |
| 100 | 2. Implement the call in the relevant `crates/smbcloud-networking-*/src/` crate using `SmbClient` |
| 101 | 3. Call the networking function from the CLI command handler |
| 102 | |
| 103 | ### Environment & Auth |
| 104 | |
| 105 | - The `Environment` type (from `smbcloud-network`) is threaded through all command handlers — always accept it as the first parameter. |
| 106 | - Auth tokens are managed through the `token` module — never hardcode credentials. |
| 107 | - The `CLI_CLIENT_SECRET` comes from the `.env` file via `dotenv_codegen` at compile time. |
| 108 | |
| 109 | ### Terminal Output |
| 110 | |
| 111 | - Use the `ui` module helpers for consistent spinner, progress, and styled output. |
| 112 | - Use `console::style(...)` for coloured terminal text. |
| 113 | - Errors are printed in red with a `✘` prefix (handled in `main.rs`). |
| 114 | |
| 115 | ## Build & Test Commands |
| 116 | |
| 117 | ```bash |
| 118 | # Verify compilation across the whole workspace |
| 119 | cargo check --workspace |
| 120 | |
| 121 | # Build release binary |
| 122 | cargo build --release |
| 123 | |
| 124 | # Run all tests |
| 125 | cargo test --all-features |
| 126 | |
| 127 | # Lint — treat warnings as errors |
| 128 | cargo clippy --workspace --tests -- -D warnings |
| 129 | |
| 130 | # Format |
| 131 | cargo fmt --all |
| 132 | |
| 133 | # Check formatting without modifying files |
| 134 | cargo fmt --all -- --check |
| 135 | |
| 136 | # Publish all workspace crates (requires cargo-workspaces) |
| 137 | cargo workspaces publish --publish-as-is |
| 138 | ``` |
| 139 | |
| 140 | ## Common Pitfalls |
| 141 | |
| 142 | 1. **`.env` must exist** with `CLI_CLIENT_SECRET` before building. CI generates it from secrets; locally you must create it manually. |
| 143 | 2. **No `mod.rs`** — always use named files for submodules. |
| 144 | 3. **All new dependencies go in the root `Cargo.toml`** under `[workspace.dependencies]`, then inherit them in each crate with `{ workspace = true }`. |
| 145 | 4. **`#[tokio::main]` lives only in `main.rs`** — all other async entry points are plain `async fn`. |
| 146 | 5. **The binary is named `smb`**, not `smbcloud-cli` — it comes from `[[bin]] name = "smb"` in `crates/cli/Cargo.toml`. |
| 147 | 6. **`SmbClient` is a zero-cost static reference** — obtain it with the `client()` helper in `lib.rs`, don't construct it ad-hoc. |
| 148 | 7. **Do not add crate-local dependencies** without first checking the workspace root — duplicate version declarations break the workspace resolver. |
| 149 | |
| 150 | ## Pull Request Conventions |
| 151 | |
| 152 | - Use a clear, imperative PR title: `Fix crash when project name is empty`, not `fixed stuff`. |
| 153 | - No conventional-commit prefixes (`feat:`, `fix:`, etc.) in the PR title. |
| 154 | - Include a `Release Notes:` section at the end of the PR body: |
| 155 | ``` |
| 156 | Release Notes: |
| 157 | |
| 158 | - Fixed ... |
| 159 | ``` |
| 160 | Use `- N/A` for non-user-facing changes. |