Add distribution skill doc and update README title
keypair34 committed
May 3, 2026 at 11:18 UTC
c5d3fe726056e1bd73b9898ea2baadc03a137262
2 files changed
+219
-1
.agents/skills/distribution/SKILL.md
+218
@@ -0,0 +1,218 @@
1
+---
2
+name: distribution
3
+description: Use when adding, fixing, or documenting package distribution for Onde CLI. Covers wrapper-package design across npm, PyPI, NuGet, pub.dev, GitHub Releases, and Homebrew, plus version alignment, artifact staging, README surfaces, and smoke-test strategy.
4
+---
5
+
6
+# Onde CLI distribution
7
+
8
+This skill captures how `onde-cli` is distributed today and what to watch when adding new channels.
9
+
10
+## Distribution model
11
+
12
+`onde-cli` is a native Rust CLI first.
13
+
14
+Everything else is packaging.
15
+
16
+That means:
17
+
18
+- build the Rust binary once per target
19
+- publish thin wrappers that install or launch that binary
20
+- keep channel-specific logic small and predictable
21
+
22
+This design keeps behavior consistent across ecosystems and avoids re-implementing CLI logic in each language.
23
+
24
+## Channel map
25
+
26
+### Native source of truth
27
+
28
+- Rust crate: `onde-cli`
29
+- binary name: `onde`
30
+- root manifest: `Cargo.toml`
31
+
32
+### Wrapper channels
33
+
34
+- npm: JavaScript launcher + optional platform packages
35
+- PyPI: `maturin` binary wheels
36
+- NuGet: .NET global tool launcher
37
+- pub.dev: Dart launcher package
38
+
39
+### Native artifact channels
40
+
41
+- crates.io
42
+- GitHub Releases
43
+- Homebrew
44
+
45
+## Wrapper design patterns
46
+
47
+### npm
48
+
49
+Use a very small Node launcher that:
50
+
51
+- detects OS and architecture
52
+- resolves the installed platform package
53
+- spawns the binary with inherited stdio
54
+
55
+Good fit for users who already live in npm tooling.
56
+
57
+### PyPI
58
+
59
+Use `maturin` with `bindings = "bin"` so the native executable is what gets installed.
60
+
61
+Good fit for Python users who want the CLI but not a Python reimplementation.
62
+
63
+### NuGet
64
+
65
+Use a `.NET global tool` wrapper.
66
+
67
+Important details:
68
+
69
+- keep the package as a launcher, not a managed rewrite
70
+- place native binaries under the tool payload
71
+- resolve the runtime identifier at startup
72
+- set Unix execute bits before launch
73
+
74
+Good fit for .NET developers and CI environments that already use `dotnet tool install`.
75
+
76
+### pub.dev
77
+
78
+Use a Dart package with a command entrypoint and a library that launches the bundled native binary.
79
+
80
+Important details:
81
+
82
+- executable command should stay `onde`
83
+- use `Isolate.resolvePackageUri` to find the installed package path
84
+- keep the runtime-id mapping explicit
85
+- do not overcomplicate the wrapper with platform-specific Dart APIs unless necessary
86
+
87
+Good fit for Dart and Flutter developers who want the same CLI through familiar tooling.
88
+
89
+## Runtime identifier mapping
90
+
91
+Keep these names aligned anywhere wrappers or workflows refer to native assets:
92
+
93
+- `darwin-x64`
94
+- `darwin-arm64`
95
+- `linux-x64`
96
+- `linux-arm64`
97
+- `windows-x64`
98
+- `windows-arm64`
99
+
100
+If a wrapper uses one naming scheme and a workflow uploads another, the installed package will pass packaging but fail at runtime.
101
+
102
+## Release workflow principles
103
+
104
+### Build first, package second
105
+
106
+Always build native binaries in a target matrix first.
107
+
108
+Then let the wrapper channel jobs package those artifacts.
109
+
110
+This avoids rebuilding the product multiple times and makes failures easier to reason about.
111
+
112
+### Idempotency
113
+
114
+Every publish workflow should check whether the target version already exists before publishing.
115
+
116
+Examples:
117
+
118
+- npm: `npm view`
119
+- PyPI: package JSON endpoint
120
+- NuGet: flat container index
121
+- pub.dev: package API endpoint
122
+
123
+### Smoke tests should match the product shape
124
+
125
+Because `onde` is TUI-first, avoid smoke tests that assume a traditional CLI help flow unless you know that code path is stable and non-interactive.
126
+
127
+Safer checks:
128
+
129
+- install succeeds
130
+- bundled native binary exists where expected
131
+- package manager validation passes
132
+
133
+## pub.dev-specific notes
134
+
135
+pub.dev behaves differently from npm and NuGet in one important way:
136
+
137
+- files ignored by git are generally excluded from publish input
138
+
139
+That means staged native binaries for `pub/onde_cli/native/` must be available to the package at publish time.
140
+
141
+Two practical consequences:
142
+
143
+- do not ignore `pub/onde_cli/native/` in the root `.gitignore` if CI stages binaries there
144
+- a `.pubignore` can hide local tool noise, but do not hide the native payload you intend to publish
145
+
146
+Run these during verification:
147
+
148
+- `dart pub get --directory pub/onde_cli`
149
+- `dart analyze pub/onde_cli`
150
+- `dart pub publish --dry-run --directory pub/onde_cli`
151
+
152
+## NuGet-specific notes
153
+
154
+NuGet packaging is sensitive to path layout.
155
+
156
+The safest pattern is:
157
+
158
+- copy native files into the publish output
159
+- let the .NET tool pack process carry them into the final package
160
+
161
+Avoid custom `PackagePath` patterns that can duplicate path segments or create nested native folders by accident.
162
+
163
+If the tool installs but cannot find the native binary, inspect the `.nupkg` contents before debugging the launcher.
164
+
165
+## README surfaces
166
+
167
+Every user-facing channel should document the same product with channel-specific installation instructions.
168
+
169
+Main files:
170
+
171
+- `README.md`
172
+- `npm/onde-cli/README.md`
173
+- `pypi/README.md`
174
+- `nuget/onde-cli/README.md`
175
+- `pub/onde_cli/README.md`
176
+
177
+Keep these aligned on:
178
+
179
+- product description
180
+- supported platforms
181
+- install method
182
+- license and copyright
183
+- relevant supporting links like the forward-pass explainer
184
+
185
+Do not let one channel sound like a different product.
186
+
187
+## Version alignment
188
+
189
+When cutting a release, update every user-facing distribution version that should move with the CLI.
190
+
191
+At minimum, check:
192
+
193
+- Rust crate version
194
+- npm package version
195
+- npm lockfile version if committed
196
+- PyPI release version source
197
+- NuGet package version at pack time
198
+- pub.dev package version in `pubspec.yaml`
199
+- workflow example tags and docs that mention concrete versions
200
+
201
+## Common failure modes
202
+
203
+- wrapper version does not match the Rust release version
204
+- staged native binaries land in the wrong directory before packaging
205
+- package builds successfully but installs without the native binary
206
+- pub.dev package omits staged assets because gitignore excludes them
207
+- smoke test invokes a TUI-first binary in a way that does not make sense for CI
208
+- README badges and install commands drift out of sync with real package names
209
+
210
+## Rule of thumb
211
+
212
+If the native binary works and the wrappers are boring, distribution stays manageable.
213
+
214
+If a wrapper starts acting like its own product, complexity grows fast.
215
+
216
+Keep it thin.
217
+Keep it aligned.
218
+Keep the Rust binary as the source of truth.
README.md
+1
-1
@@ -2,7 +2,7 @@
2
<img src="https://raw.githubusercontent.com/ondeinference/onde/main/assets/onde-inference-logo.svg" alt="Onde Inference" width="96">
3
</p>
4
5
-<h1 align="center">onde</h1>
5
+<h1 align="center">Onde Inference CLI</h1>
6
7
<p align="center">
8
Command-line interface for <a href="https://ondeinference.com">Onde Inference</a>.