Add PyPI packaging and release workflow for smbcloud-cli
- Add pypi/pyproject.toml and pypi/README.md for PyPI builds - Add .github/workflows/release-pypi.yml for automated wheel/sdist build and publish - Update .gitignore for PyPI artifacts - Document pip install/uninstall in crates/cli/README.md - Expand SKILL.md to cover PyPI release flow and source of truth
Seto Elkahfi committed
Mar 28, 2026 at 22:37 UTC
5ca20781039d05a88052aaea824861d235eb1100
6 files changed
+367
-146
.agents/skills/smbcloud-cli-release/SKILL.md
+100
-146
@@ -1,6 +1,6 @@
1
---
2
name: smbcloud-cli-release
3
-description: Use when building, packaging, or releasing smbCloud CLI binaries through npm or GitHub Actions CI/CD. Covers the Rust binary packages under `npm/cli-*`, the `@smbcloud/cli` wrapper package, macOS arm64 vs x64 constraints, npm 2FA publishing, and fixes to `.github/workflows/release-npm.yml`.
3
+description: Use when building, packaging, or releasing smbCloud CLI binaries through npm, PyPI, or GitHub Actions CI/CD. Covers the Rust binary release source of truth, the npm wrapper and platform packages, the PyPI `maturin` package under `pypi/`, local publishing with `uv tool install maturin`, and fixes to `.github/workflows/release-npm.yml` or `.github/workflows/release-pypi.yml`.
4
---
5
6
# smbcloud CLI Release
@@ -8,17 +8,34 @@ description: Use when building, packaging, or releasing smbCloud CLI binaries th
8
Use this skill when work touches any part of the smbCloud CLI distribution flow:
9
10
- local npm release for `smbcloud-cli`
11
+- local PyPI release for `smbcloud-cli`
12
- GitHub Actions npm release automation
12
-- Rust binary packaging into scoped npm platform packages
13
-- release failures caused by macOS cross-compilation, missing package metadata, or npm 2FA
13
+- GitHub Actions PyPI release automation
14
+- Rust binary packaging into npm platform packages or PyPI wheels
15
+- release failures caused by macOS cross-compilation, missing package metadata, npm 2FA, or PyPI trusted publishing setup
16
+
17
+## Source of truth
18
+
19
+Use these files as the release source of truth:
20
+
21
+- Rust crate version and binary name: `crates/cli/Cargo.toml`
22
+- npm release workflow: `.github/workflows/release-npm.yml`
23
+- PyPI release workflow: `.github/workflows/release-pypi.yml`
24
+- npm platform package generator: `npm/scripts/render-platform-package.cjs`
25
+- npm wrapper package generator: `npm/scripts/render-main-package.cjs`
26
+- npm wrapper launcher: `npm/smbcloud-cli/src/index.ts`
27
+- PyPI package metadata: `pypi/pyproject.toml`
28
+- PyPI package README: `pypi/README.md`
29
30
## Release model
31
17
-There are two npm package layers. Publish them in order.
32
+There are two public distribution channels.
33
+
34
+### 1. npm
35
19
-### 1. Platform binary packages
36
+npm has two package layers. Publish them in order.
37
21
-These packages contain the compiled Rust binary only:
38
+Platform binary packages:
39
40
- `@smbcloud/cli-darwin-arm64`
41
- `@smbcloud/cli-darwin-x64`
@@ -26,31 +43,22 @@ These packages contain the compiled Rust binary only:
43
- `@smbcloud/cli-windows-arm64`
44
- `@smbcloud/cli-windows-x64`
45
29
-Their package directories are generated under `npm/cli-*/` and should be treated as release artifacts, not source.
30
-
31
-### 2. Wrapper package
32
-
33
-The public package is:
46
+Wrapper package:
47
48
- `@smbcloud/cli`
49
37
-It contains the Node launcher in `npm/smbcloud-cli/src/index.ts` and resolves the correct platform package with `require.resolve(...)`.
38
-
50
+The wrapper package resolves the right platform package with `require.resolve(...)`.
51
Do not publish `@smbcloud/cli` before the required platform packages for that version exist.
52
41
-## Source of truth
53
+### 2. PyPI
54
43
-Use these files as the release source of truth:
55
+PyPI uses one package:
56
45
-- Rust crate version: `crates/cli/Cargo.toml`
46
-- npm release workflow: `.github/workflows/release-npm.yml`
47
-- platform package generator: `npm/scripts/render-platform-package.cjs`
48
-- wrapper package generator: `npm/scripts/render-main-package.cjs`
49
-- wrapper launcher: `npm/smbcloud-cli/src/index.ts`
57
+- `smbcloud-cli`
58
51
-Do not hand-edit generated `npm/cli-*/package.json` files unless debugging a broken release artifact.
59
+It is built from `pypi/pyproject.toml` with `maturin` and `bindings = "bin"`, so the published wheel installs the native `smb` executable directly.
60
53
-## Local release workflow
61
+## Local npm release workflow
62
63
### Preflight
64
@@ -64,7 +72,7 @@ Build each target first:
72
73
- `cargo build --release --locked --target aarch64-apple-darwin`
74
- `cargo build --release --locked --target x86_64-apple-darwin`
67
-- or the matching Linux/Windows target in CI
75
+- or the matching Linux or Windows target in CI
76
77
### Generate platform package
78
@@ -87,187 +95,133 @@ Example:
95
4. Run `npm run build`
96
5. Publish `@smbcloud/cli`
97
90
-## npm 2FA
98
+## Local PyPI release workflow
99
92
-Publishing may fail with `EOTP`.
100
+### Tooling
101
94
-When that happens, retry the exact `npm publish` command with:
102
+Use `uv` for local `maturin` installation in this repo.
103
96
-- `--otp=<code>`
104
+Install:
105
98
-Do not assume the first publish failed before the package upload step. Check the exit result or npm registry state before retrying repeatedly.
106
+- `uv tool install maturin`
107
100
-## Trusted publishing
108
+Upgrade later if needed:
109
102
-Prefer npm trusted publishers for CI over `NPM_TOKEN`.
103
-
104
-Official references:
105
-
106
-- https://docs.npmjs.com/trusted-publishers/
107
-- https://docs.npmjs.com/cli/v11/commands/npm-trust/
108
-
109
-### npm-side constraints
110
-
111
-Trusted publishing can only be configured for packages that already exist on npm.
110
+- `uv tool upgrade maturin`
111
113
-That means:
112
+If the shell cannot find `maturin`, use:
113
115
-- publish a package once manually if it does not exist yet
116
-- then configure trust for that package
117
-- each package can have only one trusted publisher configuration at a time
114
+- `uv tool run maturin --version`
115
119
-For `smbcloud-cli`, configure trust per package, not only for `@smbcloud/cli`.
116
+### Preflight
117
121
-Example packages:
118
+1. Confirm the crate version in `crates/cli/Cargo.toml`.
119
+2. Make sure `.env` exists with `CLI_CLIENT_SECRET=...` because the Rust build reads it at compile time.
120
+3. If publishing from a local machine, use a PyPI API token. Trusted publishing is for CI.
121
123
-- `@smbcloud/cli`
124
-- `@smbcloud/cli-darwin-arm64`
125
-- later, each additional published `@smbcloud/cli-*` package
122
+### Build and upload
123
127
-### GitHub Actions setup
124
+From `pypi/`:
125
129
-The workflow must include:
126
+- `maturin build --release --locked --compatibility pypi --out dist`
127
+- `maturin upload dist/*`
128
131
-- `permissions:`
132
-- `id-token: write`
133
-- `contents: read`
129
+Or publish in one step:
130
135
-Do not pass `NODE_AUTH_TOKEN` to `npm publish` when using trusted publishing.
131
+- `maturin publish --release --locked --compatibility pypi`
132
137
-The npm CLI detects the GitHub OIDC environment automatically and exchanges it for a short-lived publish credential.
133
+For local uploads, export `MATURIN_PYPI_TOKEN` before running `maturin upload` or `maturin publish`.
134
139
-### Rust toolchain consistency
135
+### Local publishing constraint
136
141
-When cross-compiling in CI, the Rust toolchain used for `rustup target add` must match the toolchain used by `cargo build`.
137
+A local publish normally builds only for the current platform.
138
143
-For this repo, `rust-toolchain.toml` is the source of truth.
139
+Do not claim a full PyPI release is complete from one machine unless you intentionally published only one platform or separately produced all required wheels.
140
145
-Do not duplicate the Rust version in the matrix unless the workflow intentionally tests multiple toolchains.
141
+## npm 2FA
142
147
-If the workflow installs a target for one toolchain but Cargo builds with another, CI can fail with:
143
+Publishing may fail with `EOTP`.
144
149
-- `error[E0463]: can't find crate for core`
150
-- note that the target may not be installed
145
+When that happens, retry the exact `npm publish` command with:
146
152
-This can happen even when `rustup target add <target>` already ran successfully.
147
+- `--otp=<code>`
148
154
-### dtolnay action behavior
149
+Do not assume the first publish failed before the package upload step. Check the exit result or npm registry state before retrying repeatedly.
150
156
-For the pinned `dtolnay/rust-toolchain` revision used in this repo, do not assume the action will infer the toolchain from `rust-toolchain.toml` without input.
151
+## Trusted publishing
152
158
-A workflow can fail with:
153
+### npm
154
160
-- `'toolchain' is a required input`
155
+Prefer npm trusted publishers for CI over `NPM_TOKEN`.
156
162
-Preferred pattern in this repo:
157
+Official references:
158
164
-- read `channel = "..."` from `rust-toolchain.toml`
165
-- write it to `RUST_TOOLCHAIN` in `GITHUB_ENV`
166
-- pass `toolchain: ${{ env.RUST_TOOLCHAIN }}` to `dtolnay/rust-toolchain`
167
-- run `rustup target add <target> --toolchain ${{ env.RUST_TOOLCHAIN }}`
168
-- run `cargo build --target <target>` after the action sets that toolchain active
159
+- https://docs.npmjs.com/trusted-publishers/
160
+- https://docs.npmjs.com/cli/v11/commands/npm-trust/
161
170
-This keeps `rust-toolchain.toml` as the only Rust version source while avoiding implicit action behavior.
162
+Trusted publishing can only be configured for packages that already exist on npm.
163
+That means new package names still need one manual publish before trust can be configured.
164
172
-### Trusted publisher command
165
+### PyPI
166
174
-For this repo, the trust relationship should point at:
167
+Use trusted publishing in GitHub Actions through `pypa/gh-action-pypi-publish@release/v1`.
168
+Do not use trusted publishing as the default local-machine publish path.
169
176
-- repository: `smbcloudXYZ/smbcloud-cli`
177
-- workflow file: `release-npm.yml`
170
+## CI/CD workflow rules
171
179
-Example:
172
+### Shared rules
173
181
-- `npm trust github @smbcloud/cli --repo smbcloudXYZ/smbcloud-cli --file release-npm.yml --yes`
182
-- `npm trust github @smbcloud/cli-darwin-arm64 --repo smbcloudXYZ/smbcloud-cli --file release-npm.yml --yes`
174
+For both release workflows:
175
184
-These commands may require npm 2FA and support `--otp=<code>`.
176
+- `runs-on` must use `matrix.build.OS` when the matrix uses upper-case keys
177
+- derive `RELEASE_VERSION` from the git tag when `GITHUB_REF_TYPE=tag`
178
+- for `workflow_dispatch`, fall back to the version in `crates/cli/Cargo.toml`
179
+- read the Rust toolchain from `rust-toolchain.toml`
180
+- pass that exact toolchain into `dtolnay/rust-toolchain`
181
+- run `rustup target add <target> --toolchain ${{ env.RUST_TOOLCHAIN }}` before cross-target builds
182
186
-### Migration guidance
183
+### npm workflow
184
188
-Recommended order:
185
+The npm workflow lives in `.github/workflows/release-npm.yml`.
186
190
-1. enable trusted publishing for existing packages
191
-2. verify a CI publish works through OIDC
192
-3. then remove or stop using `NPM_TOKEN`
193
-4. after the migration is proven, tighten npm package publishing access if desired
187
+Important rules:
188
195
-Do not remove the manual publish path for brand-new package names, because npm trust cannot be configured before the first publish.
189
+- avoid `envsubst` for package generation across runners
190
+- use the Node generator scripts instead
191
+- use `npm install` and `npm run build` for the wrapper package job
192
197
-## CI/CD workflow rules
193
+### PyPI workflow
194
199
-The release workflow lives in `.github/workflows/release-npm.yml`.
195
+The PyPI workflow lives in `.github/workflows/release-pypi.yml`.
196
197
Important rules:
198
203
-- `runs-on` must use `matrix.build.OS`, not `matrix.build.os`
204
-- derive `RELEASE_VERSION` from the git tag when `GITHUB_REF_TYPE=tag`
205
-- for `workflow_dispatch`, fall back to the version in `crates/cli/Cargo.toml`
206
-- avoid `envsubst` for package generation across runners
207
-- use the Node generator scripts instead
208
-- use `npm install` and `npm run build` for the wrapper package job
199
+- build wheels with `PyO3/maturin-action@v1`
200
+- use `working-directory: pypi`
201
+- pass `target: ${{ matrix.build.TARGET }}`
202
+- use `manylinux: ${{ matrix.build.MANYLINUX || 'off' }}`
203
+- build the sdist in a separate job
204
+- publish only after wheel and sdist artifacts are downloaded into one directory
205
+
206
+## Rust toolchain consistency
207
210
-### Package generation
208
+When cross-compiling in CI, the Rust toolchain used for `rustup target add` must match the toolchain used by `cargo build` or `maturin`.
209
212
-Prefer deterministic Node scripts over shell templating.
210
+For this repo, `rust-toolchain.toml` is the only Rust version source of truth.
211
214
-Reasons:
212
+If the workflow installs a target for one toolchain but builds with another, CI can fail with:
213
216
-- `envsubst` is not guaranteed across macOS and Windows runners
217
-- package metadata must stay identical between local release and CI
218
-- the generated wrapper package must point optional dependencies at the exact release version
214
+- `error[E0463]: can't find crate for core`
215
216
## macOS cross-build constraint
217
218
On an Apple Silicon host, `x86_64-apple-darwin` may fail due to `openssl-sys` if only arm64 Homebrew OpenSSL exists under `/opt/homebrew`.
219
224
-Typical symptom:
225
-
226
-- `openssl-sys` cannot find an `x86_64-apple-darwin` OpenSSL
227
-
220
If that happens:
221
222
- do not claim the x64 package is releasable from that machine
223
- either build on an Intel Mac
232
-- or use a Rosetta/x86 Homebrew toolchain with Intel OpenSSL under `/usr/local/opt/openssl@3`
224
+- or use a Rosetta or x86 Homebrew toolchain with Intel OpenSSL under `/usr/local/opt/openssl@3`
225
- or publish only the arm64 platform package and explicitly avoid calling the release complete
226
227
Do not publish `@smbcloud/cli` for a version unless you accept that missing platform packages for that version can break installs on those platforms.
236
-
237
-## Generated artifacts
238
-
239
-Generated platform package directories should be git-ignored:
240
-
241
-- `/npm/cli-*/`
242
-
243
-These are build artifacts and should not be committed.
244
-
245
-## Validation
246
-
247
-Use the smallest checks that match the change.
248
-
249
-### Local
250
-
251
-- `npm whoami`
252
-- `cargo build --release --locked --target <target>`
253
-- `node npm/scripts/render-platform-package.cjs ...`
254
-- `node npm/scripts/render-main-package.cjs ...`
255
-- `npm install`
256
-- `npm run build`
257
-
258
-### CI/CD edits
259
-
260
-After changing the workflow:
261
-
262
-- inspect `.github/workflows/release-npm.yml`
263
-- verify the package generators still output the expected names and versions
264
-- confirm `@smbcloud/cli` optional dependencies match the platform package names exactly
265
-
266
-## Common mistakes
267
-
268
-- publishing `@smbcloud/cli` before the matching platform packages exist
269
-- assuming `workflow_dispatch` has a tag-derived version
270
-- relying on `envsubst` in a cross-platform GitHub Actions workflow
271
-- forgetting that Windows binaries need `.exe`
272
-- treating generated `npm/cli-*` directories as source files
273
-- trying to cross-build macOS x64 on Apple Silicon without an Intel OpenSSL toolchain
.github/workflows/release-pypi.yml
new
+194
@@ -0,0 +1,194 @@
1
+name: PyPI Release
2
+
3
+on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+
9
+permissions:
10
+ id-token: write
11
+ contents: read
12
+
13
+env:
14
+ CARGO_TERM_COLOR: always
15
+ SMB_CLIENT_ID: ${{ secrets.SMB_CLIENT_ID }}
16
+ SMB_CLIENT_SECRET: ${{ secrets.SMB_CLIENT_SECRET }}
17
+ SMB_API_HOST: ${{ secrets.SMB_API_HOST }}
18
+ SMB_API_PROTOCOL: ${{ secrets.SMB_API_PROTOCOL }}
19
+ GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
20
+ GH_OAUTH_CLIENT_SECRET: ${{ secrets.GH_OAUTH_CLIENT_SECRET }}
21
+ GH_OAUTH_REDIRECT_HOST: ${{ secrets.GH_OAUTH_REDIRECT_HOST }}
22
+ GH_OAUTH_REDIRECT_PORT: ${{ secrets.GH_OAUTH_REDIRECT_PORT }}
23
+
24
+jobs:
25
+ build-wheels:
26
+ name: Build PyPI wheels
27
+ runs-on: ${{ matrix.build.OS }}
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ build:
32
+ - {
33
+ NAME: linux-x64-glibc,
34
+ OS: ubuntu-latest,
35
+ TARGET: x86_64-unknown-linux-gnu,
36
+ MANYLINUX: "2014",
37
+ }
38
+ # Cannot cross-compile for now
39
+ #- {
40
+ # NAME: linux-arm64-glibc,
41
+ # OS: ubuntu-latest,
42
+ # TOOLCHAIN: stable,
43
+ # TARGET: aarch64-unknown-linux-gnu,
44
+ # }
45
+ - {
46
+ NAME: win32-x64-msvc,
47
+ OS: windows-2022,
48
+ TARGET: x86_64-pc-windows-msvc,
49
+ }
50
+ - {
51
+ NAME: win32-arm64-msvc,
52
+ OS: windows-2022,
53
+ TARGET: aarch64-pc-windows-msvc,
54
+ }
55
+ - {
56
+ NAME: darwin-x64,
57
+ OS: macos-latest,
58
+ TARGET: x86_64-apple-darwin,
59
+ }
60
+ - {
61
+ NAME: darwin-arm64,
62
+ OS: macos-latest,
63
+ TARGET: aarch64-apple-darwin,
64
+ }
65
+ steps:
66
+ - name: Checkout
67
+ uses: actions/checkout@v6
68
+
69
+ - name: Set the release version
70
+ shell: bash
71
+ run: |
72
+ if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
73
+ release_version="${GITHUB_REF_NAME#v}"
74
+ else
75
+ release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
76
+ fi
77
+
78
+ echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
79
+
80
+ - name: Read Rust toolchain
81
+ shell: bash
82
+ run: |
83
+ rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
84
+ if [ -z "$rust_toolchain" ]; then
85
+ echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
86
+ exit 1
87
+ fi
88
+
89
+ echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
90
+
91
+ - name: Install toolkit
92
+ uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
93
+ with:
94
+ toolchain: ${{ env.RUST_TOOLCHAIN }}
95
+
96
+ - name: Install Rust target
97
+ shell: bash
98
+ run: |
99
+ rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
100
+ rustup target list --installed
101
+
102
+ - name: Create .env file
103
+ run: |
104
+ touch .env
105
+ echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
106
+ cat .env
107
+
108
+ - name: Build wheel
109
+ uses: PyO3/maturin-action@v1
110
+ with:
111
+ target: ${{ matrix.build.TARGET }}
112
+ manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
113
+ working-directory: pypi
114
+ args: --release --locked --compatibility pypi --out dist
115
+
116
+ - name: Upload wheel artifact
117
+ uses: actions/upload-artifact@v4
118
+ with:
119
+ name: wheels-${{ matrix.build.NAME }}
120
+ path: pypi/dist/*
121
+
122
+ build-sdist:
123
+ name: Build source distribution
124
+ runs-on: ubuntu-latest
125
+ steps:
126
+ - name: Checkout
127
+ uses: actions/checkout@v6
128
+
129
+ - name: Set the release version
130
+ shell: bash
131
+ run: |
132
+ if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
133
+ release_version="${GITHUB_REF_NAME#v}"
134
+ else
135
+ release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
136
+ fi
137
+
138
+ echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
139
+
140
+ - name: Read Rust toolchain
141
+ shell: bash
142
+ run: |
143
+ rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
144
+ if [ -z "$rust_toolchain" ]; then
145
+ echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
146
+ exit 1
147
+ fi
148
+
149
+ echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
150
+
151
+ - name: Install toolkit
152
+ uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
153
+ with:
154
+ toolchain: ${{ env.RUST_TOOLCHAIN }}
155
+
156
+ - name: Create .env file
157
+ run: |
158
+ touch .env
159
+ echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
160
+ cat .env
161
+
162
+ - name: Build sdist
163
+ uses: PyO3/maturin-action@v1
164
+ with:
165
+ command: sdist
166
+ working-directory: pypi
167
+ args: --out dist
168
+
169
+ - name: Upload sdist artifact
170
+ uses: actions/upload-artifact@v4
171
+ with:
172
+ name: sdist
173
+ path: pypi/dist/*
174
+
175
+ publish-pypi:
176
+ name: Publish to PyPI
177
+ runs-on: ubuntu-latest
178
+ needs:
179
+ - build-wheels
180
+ - build-sdist
181
+
182
+ steps:
183
+ - name: Checkout
184
+ uses: actions/checkout@v6
185
+
186
+ - name: Download distribution artifacts
187
+ uses: actions/download-artifact@v4
188
+ with:
189
+ pattern: "*"
190
+ path: dist
191
+ merge-multiple: true
192
+
193
+ - name: Publish distribution
194
+ uses: pypa/gh-action-pypi-publish@release/v1
.gitignore
+3
@@ -9,3 +9,6 @@
9
.env
10
# Generated npm release artifacts
11
/npm/cli-*/
12
+# Generated PyPI release artifacts
13
+/pypi/dist/
14
+/pypi/.venv/
crates/cli/README.md
+9
@@ -25,6 +25,12 @@ brew install cli
25
npm i -g @smbcloud/cli
26
```
27
28
+### With PyPI
29
+
30
+```bash
31
+pip install smbcloud-cli
32
+```
33
+
34
## Update
35
36
Simply rerun the installation command.
@@ -42,6 +48,9 @@ npm uninstall -g @smbcloud/cli
48
# With Homebrew
49
brew untap smbcloud/tap
50
brew uninstall smbcloud/tap/cli
51
+
52
+# With pip
53
+pip uninstall smbcloud-cli
54
```
55
56
## Usage:
pypi/README.md
new
+23
@@ -0,0 +1,23 @@
1
+# smbcloud-cli
2
+
3
+Python distribution for the `smb` command line interface used to access
4
+[smbcloud](https://smbcloud.xyz/).
5
+
6
+## Installation
7
+
8
+```bash
9
+pip install smbcloud-cli
10
+```
11
+
12
+This package installs the native `smb` executable for the current platform.
13
+
14
+## Usage
15
+
16
+```bash
17
+smb --help
18
+```
19
+
20
+## Project
21
+
22
+- Repository: https://github.com/smbcloudXYZ/smbcloud-cli
23
+- Documentation: https://docs.smbcloud.xyz/cli
pypi/pyproject.toml
new
+38
@@ -0,0 +1,38 @@
1
+[build-system]
2
+requires = ["maturin>=1.7,<2.0"]
3
+build-backend = "maturin"
4
+
5
+[project]
6
+name = "smbcloud-cli"
7
+description = "smbCloud command line interface."
8
+readme = "README.md"
9
+requires-python = ">=3.8"
10
+dynamic = ["version"]
11
+license = { text = "Apache-2.0" }
12
+authors = [{ name = "Seto Elkahfi", email = "hej@setoelkahfi.se" }]
13
+keywords = ["cli", "cloud", "smbcloud", "web2", "web3"]
14
+classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Operating System :: MacOS",
20
+ "Operating System :: Microsoft :: Windows",
21
+ "Operating System :: POSIX :: Linux",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Rust",
24
+ "Topic :: Software Development :: Build Tools",
25
+ "Topic :: System :: Systems Administration",
26
+ "Topic :: Utilities",
27
+]
28
+
29
+[project.urls]
30
+Homepage = "https://smbcloud.xyz/"
31
+Documentation = "https://docs.smbcloud.xyz/cli"
32
+Repository = "https://github.com/smbcloudXYZ/smbcloud-cli"
33
+Issues = "https://github.com/smbcloudXYZ/smbcloud-cli/issues"
34
+
35
+[tool.maturin]
36
+manifest-path = "../crates/cli/Cargo.toml"
37
+bindings = "bin"
38
+strip = true