@smbcloud / cli / commits / ef7a7d4

chore(docs): local docs generation + keep deploy config out of repo

Wire the docs site (now `website/` in this monorepo) to the local `docs/` tree, and stop tracking the smbCloud deploy config so this public repo carries no workspace/app IDs. Docs generation: - add scripts/generate-developer-docs.mjs — reads the sibling ../docs in place (no GitHub clone); docs/ is the single source of truth - remove scripts/sync-developer-docs.mjs (cloned smbcloud-cli) - run it on predev/prebuild via the docs:generate script - gitignore the generated content/developer pages + _meta.js (regenerated each build; hand-written index.mdx stays tracked) Deploy config: - gitignore /.smb/ and untrack .smb/config.toml — it holds project/app IDs and is operator-local by design (deploys run from a workstation that already has it; see CLAUDE.md open-source boundary) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

keypair34 committed Jun 27, 2026 at 23:28 UTC ef7a7d4459b41742a8a06189bbe5289338e25fa7
15 files changed +49 -432
.gitignore
+3
@@ -25,3 +25,6 @@
25 /nuget/**/bin/
26 /nuget/**/obj/
27 /nuget/smbcloud-cli/native/
28 +
29 +# smbCloud deploy config — carries workspace/app IDs; keep out of this public repo
30 +/.smb/
.smb/config.toml deleted
-11
@@ -1,11 +0,0 @@
1 -name = 'smbCloud CLI'
2 -description = 'smbCloud CLI monorepo'
3 -
4 -[project]
5 -id = 28
6 -name = "smbcloud-cli"
7 -repository = "smbcloud-cli"
8 -runner = 255
9 -description = "smbcloud cli monorepo"
10 -created_at = "2025-05-29T16:41:20.350Z"
11 -updated_at = "2025-05-29T16:41:20.350Z"
website/.gitignore
+13
@@ -33,3 +33,16 @@ yarn-error.log*
33
34 # vercel
35 .vercel
36 +
37 +# Developer docs generated from ../docs by scripts/generate-developer-docs.mjs
38 +# (run on predev/prebuild). ../docs is the source of truth; index.mdx is hand-written.
39 +/content/developer/_meta.js
40 +/content/developer/cli/_meta.js
41 +/content/developer/cli/native.mdx
42 +/content/developer/cli/homebrew.mdx
43 +/content/developer/cli/npm.mdx
44 +/content/developer/cli/pypi.mdx
45 +/content/developer/contributing/_meta.js
46 +/content/developer/contributing/debugging.mdx
47 +/content/developer/contributing/development.mdx
48 +/content/developer/contributing/gems.mdx
website/content/developer/_meta.js deleted
-4
@@ -1,4 +0,0 @@
1 -export default {
2 - cli: "CLI",
3 - contributing: "Contributing",
4 -}
website/content/developer/cli/_meta.js deleted
-6
@@ -1,6 +0,0 @@
1 -export default {
2 - native: "Native (Cargo)",
3 - homebrew: "Homebrew",
4 - npm: "npm",
5 - pypi: "PyPI",
6 -}
website/content/developer/cli/homebrew.mdx deleted
-44
@@ -1,44 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/cli-install-homebrew.md (smbcloud-cli, main). */}
2 -
3 -# Homebrew Installation
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/cli-install-homebrew.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/cli-install-homebrew.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -## Install
13 -
14 -```bash
15 -brew tap smbcloudXYZ/tap
16 -brew install cli
17 -```
18 -
19 -## Verify
20 -
21 -```bash
22 -smb --version
23 -```
24 -
25 -## Upgrade
26 -
27 -```bash
28 -brew upgrade cli
29 -```
30 -
31 -## Uninstall
32 -
33 -```bash
34 -brew uninstall cli
35 -brew untap smbcloudXYZ/tap
36 -```
37 -
38 -## Pre-built binaries
39 -
40 -Homebrew installs a pre-built binary for your platform — no compiler required.
41 -
42 -You can also download any release directly from GitHub:
43 -
44 -https://github.com/smbcloudXYZ/smbcloud-cli/releases
website/content/developer/cli/native.mdx deleted
-61
@@ -1,61 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/cli-install.md (smbcloud-cli, main). */}
2 -
3 -# Native Installation
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/cli-install.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/cli-install.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -Install directly from [crates.io](https://crates.io/crates/smbcloud-cli) using Cargo.
13 -
14 -## Prerequisites
15 -
16 -- [Rust](https://rustup.rs) (stable toolchain)
17 -- `CLI_CLIENT_SECRET` — required at compile time
18 -
19 -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.
20 -
21 -## Install
22 -
23 -Export the secret, then install:
24 -
25 -```bash
26 -export CLI_CLIENT_SECRET=your_secret_here
27 -cargo install smbcloud-cli
28 -```
29 -
30 -## Verify
31 -
32 -```bash
33 -smb --version
34 -```
35 -
36 -## Upgrade
37 -
38 -```bash
39 -export CLI_CLIENT_SECRET=your_secret_here
40 -cargo install smbcloud-cli --force
41 -```
42 -
43 -## Uninstall
44 -
45 -```bash
46 -cargo uninstall smbcloud-cli
47 -```
48 -
49 -## Troubleshooting
50 -
51 -**`error: proc-macro derive panicked … Error loading .env file`**
52 -
53 -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.
54 -
55 -**`error[E0463]: can't find crate for std`**
56 -
57 -Your Rust toolchain is missing the target. Run:
58 -
59 -```bash
60 -rustup target add <target>
61 -```
website/content/developer/cli/npm.mdx deleted
-46
@@ -1,46 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/cli-install-npm.md (smbcloud-cli, main). */}
2 -
3 -# npm Installation
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/cli-install-npm.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/cli-install-npm.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -## Install
13 -
14 -```bash
15 -npm install -g @smbcloud/cli
16 -```
17 -
18 -Also works with pnpm, bun, and yarn:
19 -
20 -```bash
21 -pnpm add -g @smbcloud/cli
22 -bun add -g @smbcloud/cli
23 -yarn global add @smbcloud/cli
24 -```
25 -
26 -## Verify
27 -
28 -```bash
29 -smb --version
30 -```
31 -
32 -## Upgrade
33 -
34 -```bash
35 -npm update -g @smbcloud/cli
36 -```
37 -
38 -## Uninstall
39 -
40 -```bash
41 -npm uninstall -g @smbcloud/cli
42 -```
43 -
44 -## Pre-built binaries
45 -
46 -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.
website/content/developer/cli/pypi.mdx deleted
-58
@@ -1,58 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/cli-install-pypi.md (smbcloud-cli, main). */}
2 -
3 -# PyPI Installation
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/cli-install-pypi.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/cli-install-pypi.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -## Install
13 -
14 -Run once without a persistent install:
15 -
16 -```bash
17 -uvx --from smbcloud-cli smb
18 -```
19 -
20 -Install as a persistent tool:
21 -
22 -```bash
23 -uv tool install smbcloud-cli
24 -```
25 -
26 -Or with pip:
27 -
28 -```bash
29 -pip install smbcloud-cli
30 -```
31 -
32 -## Upgrade
33 -
34 -```bash
35 -uv tool upgrade smbcloud-cli
36 -```
37 -
38 -Or with pip:
39 -
40 -```bash
41 -pip install --upgrade smbcloud-cli
42 -```
43 -
44 -## Uninstall
45 -
46 -```bash
47 -uv tool uninstall smbcloud-cli
48 -```
49 -
50 -Or with pip:
51 -
52 -```bash
53 -pip uninstall smbcloud-cli
54 -```
55 -
56 ----
57 -
58 -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).
website/content/developer/contributing/_meta.js deleted
-5
@@ -1,5 +0,0 @@
1 -export default {
2 - debugging: "VSCode Debugging",
3 - development: "Releasing & ADRs",
4 - gems: "Publishing the gem",
5 -}
website/content/developer/contributing/debugging.mdx deleted
-38
@@ -1,38 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/debugging.md (smbcloud-cli, main). */}
2 -
3 -# VSCode Debugging
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/debugging.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/debugging.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -To debug the app on VSCode, use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) and [cargo debugger](https://github.com/jkelleyrtp/cargo-debugger).
13 -
14 -```bash
15 -$ cargo debugger --package smbcloud-cli -- account signup
16 -```
17 -
18 -## Environment
19 -
20 -Default environment is production. To run against dev environemt:
21 -
22 -```bash
23 -$ cargo run -p smbcloud-cli -- -e dev account login
24 -```
25 -
26 -Example debug the dev environment:
27 -
28 -```bash
29 -$ cargo debugger --package smbcloud-cli -- -e dev account login
30 -```
31 -
32 -## Run from different directory
33 -
34 -To run from a different directory, use the `--manifest-path` flag and `--package` flag. :
35 -
36 -```bash
37 -$ cargo debugger --manifest-path .../path/to/smbcloud-cli/Cargo.toml --package smbcloud-cli -- -e dev account login
38 -```
website/content/developer/contributing/development.mdx deleted
-30
@@ -1,30 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/development.md (smbcloud-cli, main). */}
2 -
3 -# ADR
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/development.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/development.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -This repo uses [Architecture Decision Record](https://github.com/joelparkerhenderson/architecture-decision-record) in the `adr` folder.
13 -
14 -# Publish Update
15 -
16 -There's no GitHub action to automatically publish the package for now. Publishing task can also be done locally.
17 -
18 -To update the crate in the [crate.io](https://crate.io), use [cargo workspaces](https://github.com/pksunkara/cargo-workspaces) subcommand.
19 -
20 -Steps to publish new package:
21 -
22 -```bash
23 -$ cargo workspaces publish --publish-as-is
24 -```
25 -
26 -It will ask whether should bump the vesions of the packages or not. To update version separately:
27 -
28 -```bash
29 -$ cargo workspaces version
30 -```
website/content/developer/contributing/gems.mdx deleted
-85
@@ -1,85 +0,0 @@
1 -{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from docs/gems.md (smbcloud-cli, main). */}
2 -
3 -# Publishing the `smbcloud-model` gem
4 -
5 -import { Callout } from 'nextra/components'
6 -
7 -<Callout type="info">
8 - Synced from [`docs/gems.md`](https://github.com/smbcloudXYZ/smbcloud-cli/blob/main/docs/gems.md) on the `main` branch of
9 - [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.
10 -</Callout>
11 -
12 -The gem wraps the `smbcloud-model` Rust crate via a native extension. Publishing requires coordinating the Rust crate release and the gem release in order.
13 -
14 -## Prerequisites
15 -
16 -- [Rust toolchain](https://rustup.rs) installed
17 -- `bundler` and `gem` CLI available
18 -- RubyGems account with push access to `smbcloud-model`
19 -
20 ----
21 -
22 -## Steps
23 -
24 -### 1. Publish the Rust crate
25 -
26 -Publish `smbcloud-model` to crates.io first. The gem's native extension depends on it.
27 -
28 -```sh
29 -cargo publish -p smbcloud-model
30 -```
31 -
32 -### 2. Update the Cargo dependency
33 -
34 -Switch `gems/model/ext/model/Cargo.toml` from the local path to the published version:
35 -
36 -```toml
37 -# Before (development)
38 -smbcloud-model = { path = "./../../../../crates/smbcloud-model" }
39 -
40 -# After (release) — match the version just published
41 -smbcloud-model = "0.3"
42 -```
43 -
44 -### 3. Sync the gem version
45 -
46 -Set `gems/model/lib/model/version.rb` to match the `smbcloud-model` crate version:
47 -
48 -```ruby
49 -module Model
50 - VERSION = '0.3.31'
51 -end
52 -```
53 -
54 -### 4. Compile the native extension
55 -
56 -```sh
57 -cd gems/model
58 -bundle exec rake compile
59 -```
60 -
61 -### 5. Build the gem
62 -
63 -```sh
64 -bundle exec rake build
65 -```
66 -
67 -This produces `pkg/smbcloud-model-<version>.gem`.
68 -
69 -### 6. Publish the gem
70 -
71 -```sh
72 -gem push pkg/smbcloud-model-<version>.gem
73 -```
74 -
75 ----
76 -
77 -## Development workflow
78 -
79 -To work against the local crate instead of the published one, use the path dependency:
80 -
81 -```toml
82 -smbcloud-model = { path = "./../../../../crates/smbcloud-model" }
83 -```
84 -
85 -Remember to revert this before publishing.
website/package.json
+3 -1
@@ -1,7 +1,9 @@
1 {
2 "scripts": {
3 + "docs:generate": "node scripts/generate-developer-docs.mjs",
4 + "predev": "pnpm docs:generate",
5 "dev": "next",
4 - "sync:developer": "node scripts/sync-developer-docs.mjs",
6 + "prebuild": "pnpm docs:generate",
7 "build": "next build",
8 "postbuild": "pagefind --site .next/server/app --output-path public/_pagefind",
9 "start": "next start",
website/scripts/generate-developer-docs.mjs renamed
+30 -43
@@ -1,28 +1,27 @@
1 #!/usr/bin/env node
2 /**
3 - * Sync the /developer docs from the smbcloud-cli repository.
3 + * Generate the /developer docs from the sibling `docs/` tree.
4 *
5 - * The CLI / tooling documentation lives in `docs/` of smbcloud-cli and is the
6 - * source of truth. This script pulls those files into content/developer/ so the
7 - * docs site tracks the tool. Synced files are committed (vendored) so the site
8 - * builds on CI without network access — re-run this script to refresh them.
5 + * The CLI / tooling documentation lives in `docs/` at the smbcloud-cli repo root
6 + * (this site is `website/` in the same repo), so it is read in place — no clone,
7 + * no network. This runs automatically on `predev`/`prebuild`; the generated
8 + * pages are gitignored, leaving `docs/` as the single source of truth.
9 *
10 - * pnpm sync:developer
10 + * pnpm docs:generate
11 *
12 * Hand-written index pages (content/developer/**\/index.mdx) are NOT touched.
13 * Only the files listed in MANIFEST and the generated _meta.js are written.
14 */
15 -import { execSync } from 'node:child_process'
16 -import { mkdtempSync, rmSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'
17 -import { tmpdir } from 'node:os'
15 +import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
16 import { join, dirname } from 'node:path'
17 import { fileURLToPath } from 'node:url'
18
21 -const REPO = 'https://github.com/smbcloudXYZ/smbcloud-cli.git'
19 const BRANCH = 'main'
20 const SRC_DIR = 'docs'
21
22 const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
23 +// `docs/` sits next to `website/` at the smbcloud-cli repo root.
24 +const SRC = join(ROOT, '..', SRC_DIR)
25 const DEST = join(ROOT, 'content', 'developer')
26
27 // Source file -> where it lands and how it's labelled in the sidebar.
@@ -51,14 +50,14 @@ const MANIFEST = {
50 const blobUrl = src =>
51 `https://github.com/smbcloudXYZ/smbcloud-cli/blob/${BRANCH}/${SRC_DIR}/${src}`
52
54 -/** Wrap synced markdown: header note + a source callout after the first H1. */
53 +/** Wrap generated markdown: header note + a source callout after the first H1. */
54 function decorate(markdown, src) {
56 - const note = `{/* AUTO-GENERATED — do not edit. Synced by scripts/sync-developer-docs.mjs from ${SRC_DIR}/${src} (smbcloud-cli, ${BRANCH}). */}`
55 + const note = `{/* AUTO-GENERATED — do not edit. Generated by scripts/generate-developer-docs.mjs from ../${SRC_DIR}/${src}. */}`
56 const callout = [
57 "import { Callout } from 'nextra/components'",
58 '',
59 '<Callout type="info">',
61 - ` Synced from [\`${SRC_DIR}/${src}\`](${blobUrl(src)}) on the \`${BRANCH}\` branch of`,
60 + ` Generated from [\`${SRC_DIR}/${src}\`](${blobUrl(src)}) in`,
61 ' [smbcloud-cli](https://github.com/smbcloudXYZ/smbcloud-cli). Edit it there.',
62 '</Callout>'
63 ].join('\n')
@@ -81,39 +80,27 @@ function metaFile(pages) {
80 }
81
82 function main() {
84 - const tmp = mkdtempSync(join(tmpdir(), 'smb-cli-docs-'))
85 - try {
86 - console.log(`Cloning ${REPO} (${BRANCH}, sparse: ${SRC_DIR})…`)
87 - execSync(
88 - `git clone --depth 1 --branch ${BRANCH} --filter=blob:none --sparse ${REPO} "${tmp}"`,
89 - { stdio: 'inherit' }
90 - )
91 - execSync(`git -C "${tmp}" sparse-checkout set ${SRC_DIR}`, { stdio: 'inherit' })
92 -
93 - let count = 0
94 - for (const [section, { title, pages }] of Object.entries(MANIFEST)) {
95 - const dir = join(DEST, section)
96 - mkdirSync(dir, { recursive: true })
97 - for (const page of pages) {
98 - const raw = readFileSync(join(tmp, SRC_DIR, page.src), 'utf8')
99 - writeFileSync(join(dir, `${page.slug}.mdx`), decorate(raw, page.src))
100 - count++
101 - }
102 - writeFileSync(join(dir, '_meta.js'), metaFile(pages))
103 - console.log(` ${section}: ${pages.length} pages (${title})`)
104 - }
105 -
106 - // Top-level developer nav: each section (the overview is asIndexPage).
107 - const top = []
108 - for (const [section, { title }] of Object.entries(MANIFEST)) {
109 - top.push(` ${section}: ${JSON.stringify(title)},`)
83 + let count = 0
84 + for (const [section, { title, pages }] of Object.entries(MANIFEST)) {
85 + const dir = join(DEST, section)
86 + mkdirSync(dir, { recursive: true })
87 + for (const page of pages) {
88 + const raw = readFileSync(join(SRC, page.src), 'utf8')
89 + writeFileSync(join(dir, `${page.slug}.mdx`), decorate(raw, page.src))
90 + count++
91 }
111 - writeFileSync(join(DEST, '_meta.js'), `export default {\n${top.join('\n')}\n}\n`)
92 + writeFileSync(join(dir, '_meta.js'), metaFile(pages))
93 + console.log(` ${section}: ${pages.length} pages (${title})`)
94 + }
95
113 - console.log(`\nSynced ${count} pages into content/developer/.`)
114 - } finally {
115 - rmSync(tmp, { recursive: true, force: true })
96 + // Top-level developer nav: each section (the overview is asIndexPage).
97 + const top = []
98 + for (const [section, { title }] of Object.entries(MANIFEST)) {
99 + top.push(` ${section}: ${JSON.stringify(title)},`)
100 }
101 + writeFileSync(join(DEST, '_meta.js'), `export default {\n${top.join('\n')}\n}\n`)
102 +
103 + console.log(`\nGenerated ${count} pages into content/developer/ from ${SRC}.`)
104 }
105
106 main()