16 files changed
+214
-129
.agents/skills/ci-cd/SKILL.md
+3
@@ -622,6 +622,9 @@ When the main `README.MD` changes its tagline, logo URL, quick start commands, o
622
**Platform support table missing new targets**
623
When a new platform is added to any release matrix (e.g. `linux-arm64`), update the platform support table in `npm/smbcloud-cli/README.md` and `pypi/README.md` in the same PR.
624
625
+**PyPI blocks short and protocol-reserved package names**
626
+PyPI maintains a blocklist of names that are too generic or conflict with well-known protocols and tools. `smb` is blocked because it is the name of the Windows SMB/CIFS file sharing protocol. Attempting to publish a package named `smb` returns `400 The name 'smb' isn't allowed`. There is no workaround — the name cannot be registered regardless of who owns it. If you need `uvx <name>` to work without `--from`, the package name and binary name must match AND the package name must not be on the blocklist. For this repo, `uvx --from smbcloud-cli smb` is the correct form.
627
+
628
**`on: release: types: [published]` does not fire when the release is created by automation**
629
When `softprops/action-gh-release` (or any action) creates a GitHub Release using the implicit `GITHUB_TOKEN`, GitHub does not dispatch the `release` event to other workflows. The downstream workflow simply never runs — no error, no log entry. Use `workflow_dispatch` via `actions/github-script@v7` to chain workflows explicitly, and add `actions: write` to the upstream workflow's `permissions`.
630
.agents/skills/smbcloud-cli-release/SKILL.md
+23
@@ -132,6 +132,29 @@ Or publish in one step:
132
133
For local uploads, export `MATURIN_PYPI_TOKEN` before running `maturin upload` or `maturin publish`.
134
135
+### Publishing the smb stub (one-time)
136
+
137
+The stub lives in `pypi/smb-stub/` and is built with `hatchling`, not `maturin`. It only needs to be published once — it never changes.
138
+
139
+```sh
140
+cd pypi/smb-stub
141
+pip install hatchling build twine
142
+python -m build
143
+twine upload dist/*
144
+```
145
+
146
+Or with uv:
147
+
148
+```sh
149
+cd pypi/smb-stub
150
+uv run --with build python -m build
151
+uv run --with twine twine upload dist/*
152
+```
153
+
154
+Use a PyPI API token with upload scope for `smb`. Trusted publishing is not required for a static stub.
155
+
156
+Do not republish the stub on every CLI release. It permanently depends on the unpinned `smbcloud-cli`, so uv always resolves the latest version when the tool environment is created or upgraded.
157
+
158
### Local publishing constraint
159
160
A local publish normally builds only for the current platform.
.github/workflows/ci.yml
+2
-5
@@ -21,10 +21,7 @@ jobs:
21
- uses: actions/checkout@v6
22
- uses: dtolnay/rust-toolchain@stable
23
24
- - name: Create .env file
25
- run: |
26
- touch .env
27
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
28
- cat .env
24
+ - name: Export build secret
25
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
26
27
- run: cargo test --all-features
.github/workflows/release-crate.yml
+2
-5
@@ -68,11 +68,8 @@ jobs:
68
with:
69
key: publish
70
71
- - name: Create .env file
72
- run: |
73
- touch .env
74
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
75
- cat .env
71
+ - name: Export build secret
72
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
73
74
- name: Verify Cargo.toml version matches tag
75
shell: bash
.github/workflows/release-github.yml
+2
-5
@@ -86,11 +86,8 @@ jobs:
86
with:
87
key: github-${{ matrix.target }}
88
89
- - name: Create .env file
90
- run: |
91
- touch .env
92
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
93
- cat .env
89
+ - name: Export build secrets
90
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
91
92
- name: Build binary
93
shell: bash
.github/workflows/release-npm.yml
+2
-5
@@ -102,11 +102,8 @@ jobs:
102
rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
103
rustup target list --installed
104
105
- - name: Create .env file
106
- run: |
107
- touch .env
108
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
109
- cat .env
105
+ - name: Export build secret
106
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
107
108
- name: Build
109
env:
.github/workflows/release-pypi.yml
+4
-10
@@ -97,11 +97,8 @@ jobs:
97
rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
98
rustup target list --installed
99
100
- - name: Create .env file
101
- run: |
102
- touch .env
103
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
104
- cat .env
100
+ - name: Export build secret
101
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
102
103
- name: Build wheel
104
uses: PyO3/maturin-action@v1
@@ -155,11 +152,8 @@ jobs:
152
with:
153
toolchain: ${{ env.RUST_TOOLCHAIN }}
154
158
- - name: Create .env file
159
- run: |
160
- touch .env
161
- echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
162
- cat .env
155
+ - name: Export build secret
156
+ run: echo "CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }}" >> "$GITHUB_ENV"
157
158
- name: Build sdist
159
uses: PyO3/maturin-action@v1
Cargo.lock
-36
@@ -427,35 +427,6 @@ dependencies = [
427
"syn 2.0.114",
428
]
429
430
-[[package]]
431
-name = "dotenv"
432
-version = "0.15.0"
433
-source = "registry+https://github.com/rust-lang/crates.io-index"
434
-checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
435
-
436
-[[package]]
437
-name = "dotenv_codegen"
438
-version = "0.15.0"
439
-source = "registry+https://github.com/rust-lang/crates.io-index"
440
-checksum = "56966279c10e4f8ee8c22123a15ed74e7c8150b658b26c619c53f4a56eb4a8aa"
441
-dependencies = [
442
- "dotenv_codegen_implementation",
443
- "proc-macro-hack",
444
-]
445
-
446
-[[package]]
447
-name = "dotenv_codegen_implementation"
448
-version = "0.15.0"
449
-source = "registry+https://github.com/rust-lang/crates.io-index"
450
-checksum = "53e737a3522cd45f6adc19b644ce43ef53e1e9045f2d2de425c1f468abd4cf33"
451
-dependencies = [
452
- "dotenv",
453
- "proc-macro-hack",
454
- "proc-macro2",
455
- "quote",
456
- "syn 1.0.109",
457
-]
458
-
430
[[package]]
431
name = "encode_unicode"
432
version = "1.0.0"
@@ -1509,12 +1480,6 @@ dependencies = [
1480
"syn 2.0.114",
1481
]
1482
1512
-[[package]]
1513
-name = "proc-macro-hack"
1514
-version = "0.5.20+deprecated"
1515
-source = "registry+https://github.com/rust-lang/crates.io-index"
1516
-checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
1517
-
1483
[[package]]
1484
name = "proc-macro2"
1485
version = "1.0.106"
@@ -2138,7 +2103,6 @@ dependencies = [
2103
"console 0.16.2",
2104
"dialoguer",
2105
"dirs",
2141
- "dotenv_codegen",
2106
"git2",
2107
"home",
2108
"indicatif",
Cargo.toml
+1
-1
@@ -12,7 +12,7 @@ console = "0.16"
12
dialoguer = "0.11.0"
13
dirs = "6.0"
14
15
-dotenv_codegen = "0.15"
15
+
16
git2 = "0.20.1"
17
home = "0.5.4"
18
indicatif = "0.17.11"
crates/cli/Cargo.toml
+1
-1
@@ -30,7 +30,7 @@ console = { workspace = true }
30
dialoguer = { workspace = true }
31
dirs = { workspace = true }
32
33
-dotenv_codegen = { workspace = true }
33
+
34
git2 = { workspace = true }
35
36
home = { workspace = true }
crates/cli/src/lib.rs
+1
-4
@@ -7,10 +7,7 @@ pub mod project;
7
mod token;
8
mod ui;
9
10
-#[macro_use]
11
-extern crate dotenv_codegen;
12
-
10
pub(crate) fn client() -> (&'static SmbClient, &'static str) {
14
- let secret = dotenv!("CLI_CLIENT_SECRET");
11
+ let secret = env!("CLI_CLIENT_SECRET");
12
(&SmbClient::Cli, secret)
13
}
docs/cli-install-homebrew.md
new
+35
@@ -0,0 +1,35 @@
1
+# Homebrew Installation
2
+
3
+## Install
4
+
5
+```bash
6
+brew tap smbcloudXYZ/tap
7
+brew install cli
8
+```
9
+
10
+## Verify
11
+
12
+```bash
13
+smb --version
14
+```
15
+
16
+## Upgrade
17
+
18
+```bash
19
+brew upgrade cli
20
+```
21
+
22
+## Uninstall
23
+
24
+```bash
25
+brew uninstall cli
26
+brew untap smbcloudXYZ/tap
27
+```
28
+
29
+## Pre-built binaries
30
+
31
+Homebrew installs a pre-built binary for your platform — no compiler required.
32
+
33
+You can also download any release directly from GitHub:
34
+
35
+https://github.com/smbcloudXYZ/smbcloud-cli/releases
docs/cli-install-npm.md
new
+37
@@ -0,0 +1,37 @@
1
+# npm Installation
2
+
3
+## Install
4
+
5
+```bash
6
+npm install -g @smbcloud/cli
7
+```
8
+
9
+Also works with pnpm, bun, and yarn:
10
+
11
+```bash
12
+pnpm add -g @smbcloud/cli
13
+bun add -g @smbcloud/cli
14
+yarn global add @smbcloud/cli
15
+```
16
+
17
+## Verify
18
+
19
+```bash
20
+smb --version
21
+```
22
+
23
+## Upgrade
24
+
25
+```bash
26
+npm update -g @smbcloud/cli
27
+```
28
+
29
+## Uninstall
30
+
31
+```bash
32
+npm uninstall -g @smbcloud/cli
33
+```
34
+
35
+## Pre-built binaries
36
+
37
+All installation methods above use pre-built binaries. You can also download them directly from the [GitHub releases page](https://github.com/smbcloudXYZ/smbcloud-cli/releases) — useful for air-gapped environments, custom install scripts, or pinning to a specific version.
docs/cli-install-pypi.md
new
+49
@@ -0,0 +1,49 @@
1
+# PyPI Installation
2
+
3
+## Install
4
+
5
+Run once without a persistent install:
6
+
7
+```bash
8
+uvx --from smbcloud-cli smb
9
+```
10
+
11
+Install as a persistent tool:
12
+
13
+```bash
14
+uv tool install smbcloud-cli
15
+```
16
+
17
+Or with pip:
18
+
19
+```bash
20
+pip install smbcloud-cli
21
+```
22
+
23
+## Upgrade
24
+
25
+```bash
26
+uv tool upgrade smbcloud-cli
27
+```
28
+
29
+Or with pip:
30
+
31
+```bash
32
+pip install --upgrade smbcloud-cli
33
+```
34
+
35
+## Uninstall
36
+
37
+```bash
38
+uv tool uninstall smbcloud-cli
39
+```
40
+
41
+Or with pip:
42
+
43
+```bash
44
+pip uninstall smbcloud-cli
45
+```
46
+
47
+---
48
+
49
+All installation methods above use pre-built binaries — no Rust toolchain required. You can also download the binary directly from [GitHub Releases](https://github.com/smbcloudXYZ/smbcloud-cli/releases).
docs/cli-install.md
new
+52
@@ -0,0 +1,52 @@
1
+# Native Installation
2
+
3
+Install directly from [crates.io](https://crates.io/crates/smbcloud-cli) using Cargo.
4
+
5
+## Prerequisites
6
+
7
+- [Rust](https://rustup.rs) (stable toolchain)
8
+- `CLI_CLIENT_SECRET` — required at compile time
9
+
10
+The `CLI_CLIENT_SECRET` value is baked into the binary at compile time. Contact [hej@setoelkahfi.se](mailto:hej@setoelkahfi.se) or check your smbCloud account dashboard to obtain it.
11
+
12
+## Install
13
+
14
+Export the secret, then install:
15
+
16
+```bash
17
+export CLI_CLIENT_SECRET=your_secret_here
18
+cargo install smbcloud-cli
19
+```
20
+
21
+## Verify
22
+
23
+```bash
24
+smb --version
25
+```
26
+
27
+## Upgrade
28
+
29
+```bash
30
+export CLI_CLIENT_SECRET=your_secret_here
31
+cargo install smbcloud-cli --force
32
+```
33
+
34
+## Uninstall
35
+
36
+```bash
37
+cargo uninstall smbcloud-cli
38
+```
39
+
40
+## Troubleshooting
41
+
42
+**`error: proc-macro derive panicked … Error loading .env file`**
43
+
44
+This error appears on older versions of `smbcloud-cli` (before `0.3.37`). Upgrade to the latest version — it reads `CLI_CLIENT_SECRET` directly from the environment at compile time and no longer requires a `.env` file.
45
+
46
+**`error[E0463]: can't find crate for std`**
47
+
48
+Your Rust toolchain is missing the target. Run:
49
+
50
+```bash
51
+rustup target add <target>
52
+```
docs/install.md
deleted
-57
@@ -1,57 +0,0 @@
1
-# Installation
2
-
3
-Deploying to the cloud should be absolutely frictionless. We provide pre-built binaries and seamless installation across all major platforms. Choose the method that best fits your workflow.
4
-
5
-### Homebrew (macOS & Linux)
6
-
7
-The fastest way to get started on Apple Silicon, Intel Macs, and Linux. We maintain an official tap with highly optimized, pre-built binaries so you can install `smb` in seconds.
8
-
9
-```bash
10
-brew tap smbcloudXYZ/tap
11
-brew install cli
12
-```
13
-
14
-### Node Package Managers (npm / pnpm / bun / yarn)
15
-
16
-Perfect for JavaScript and TypeScript developers. The CLI is distributed as a lightweight, native binary wrapper.
17
-
18
-```bash
19
-npm install -g @smbcloud/cli
20
-```
21
-
22
-## Updating
23
-
24
-To get the latest features, speed improvements, and security patches:
25
-
26
-```bash
27
-# Homebrew
28
-brew upgrade cli
29
-
30
-# NPM
31
-npm update -g @smbcloud/cli
32
-
33
-
34
-```
35
-
36
-## Uninstallation
37
-
38
-Remove the CLI using your preferred package manager:
39
-
40
-```bash
41
-# Homebrew
42
-brew uninstall cli
43
-brew untap smbcloudXYZ/tap
44
-
45
-# NPM
46
-npm uninstall -g @smbcloud/cli
47
-
48
-
49
-```
50
-
51
-## Getting Started
52
-
53
-Explore the available commands and deploy your first app:
54
-
55
-```bash
56
-smb --help
57
-```