wyvrnpm 2.3.2 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +465 -19
- package/bin/wyvrn.js +175 -9
- package/claude/skills/wyvrnpm.skill +0 -0
- package/cmake/macros.cmake +51 -0
- package/cmake/variables.cmake +13 -3
- package/package.json +1 -1
- package/src/auth.js +66 -0
- package/src/build/cache.js +196 -0
- package/src/build/index.js +23 -2
- package/src/build/msvc-env.js +50 -7
- package/src/build/recipe.js +36 -3
- package/src/commands/add.js +140 -0
- package/src/commands/build.js +111 -7
- package/src/commands/cache.js +189 -0
- package/src/commands/configure.js +15 -4
- package/src/commands/init.js +36 -0
- package/src/commands/install-skill.js +8 -0
- package/src/commands/install.js +271 -5
- package/src/commands/profile.js +70 -7
- package/src/commands/publish.js +41 -4
- package/src/commands/show.js +14 -4
- package/src/compat.js +21 -9
- package/src/conf/index.js +391 -0
- package/src/conf/namespaces.js +94 -0
- package/src/download.js +136 -148
- package/src/logger.js +30 -2
- package/src/manifest.js +34 -7
- package/src/profile.js +148 -12
- package/src/resolve.js +47 -7
- package/src/settings-overrides.js +152 -0
- package/src/toolchain/index.js +71 -0
- package/src/toolchain/presets.js +108 -31
- package/src/toolchain/template.cmake +11 -0
- package/src/upload-built.js +11 -2
- package/src/zip-safe.js +52 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A simple, private C++ package manager that works with any static file hosting pr
|
|
|
4
4
|
|
|
5
5
|
There is no central registry. You control where packages are hosted.
|
|
6
6
|
|
|
7
|
-
> **README version: 2.1
|
|
7
|
+
> **README version: 2.8.1** — Highlights since 2.4.0: non-ABI build-time `conf` block (CMake cache variables via recipe / team profile / `wyvrn.local.json` / CLI `--conf`), per-package `source` pin for multi-source defense, profile inheritance via `extends`, pattern-based `settingsOverrides` (`boost*: {...}`), `wyvrnpm cache list` / `cache prune` for selective source-build-cache cleanup, `install --dry-run` (JSON plan without side effects), `install --build=always` to force source-rebuild, `--token-env` for CI credentials, and a raft of security hardening (Zip Slip, MSVC arch allow-list). Full list in `claude/EVALUATION.md`.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -37,16 +37,19 @@ wyvrnpm configure add-source --kind publish --name default --url s3://my-bucket
|
|
|
37
37
|
# 3. Detect and save your build environment as the default profile
|
|
38
38
|
wyvrnpm configure profile detect
|
|
39
39
|
|
|
40
|
-
# 4.
|
|
40
|
+
# 4. Add dependencies (resolves latest from your configured sources)
|
|
41
|
+
wyvrnpm add zlib fmt@^10.0.0
|
|
42
|
+
|
|
43
|
+
# 5. Install dependencies (resolved against your build profile)
|
|
41
44
|
wyvrnpm install
|
|
42
45
|
|
|
43
|
-
#
|
|
46
|
+
# 6. Configure and build via the generated CMake preset
|
|
44
47
|
wyvrnpm build
|
|
45
48
|
|
|
46
|
-
#
|
|
49
|
+
# 7. Publish your package (uses the active profile automatically)
|
|
47
50
|
wyvrnpm publish
|
|
48
51
|
|
|
49
|
-
#
|
|
52
|
+
# 8. (Optional) Link local packages for development
|
|
50
53
|
cd ../my-local-lib && wyvrnpm link
|
|
51
54
|
cd ../my-app && wyvrnpm link my-local-lib
|
|
52
55
|
```
|
|
@@ -94,6 +97,37 @@ wyvrnpm configure profile set-default release
|
|
|
94
97
|
|
|
95
98
|
Once a default profile is saved, `install` and `publish` use it automatically — no flags required.
|
|
96
99
|
|
|
100
|
+
### Profile inheritance — `extends` (2.8.0+)
|
|
101
|
+
|
|
102
|
+
Teams often end up with a small fleet of near-duplicate profiles (`windows-msvc-debug`, `windows-msvc-release`, `windows-msvc-x86`, …) that drift over time. A profile can inherit from another via `extends`:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"extends": "windows-msvc-base",
|
|
107
|
+
"compiler.cppstd": "23"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Or from multiple parents (later entries override earlier):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"extends": ["windows-base", "team-defaults"],
|
|
116
|
+
"compiler.runtime": "static"
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Rules:
|
|
121
|
+
|
|
122
|
+
- `[settings]` fields merge per-key — child wins.
|
|
123
|
+
- The `conf` block (if present) merges per-leaf — child overrides single keys without dropping siblings.
|
|
124
|
+
- Overlay value `null` explicitly unsets a parent field (Conan's `None` semantics).
|
|
125
|
+
- Inheritance cycles are detected and fail with the full trail (`alpha → beta → alpha`).
|
|
126
|
+
- Missing parent names fail fast — no silent drop.
|
|
127
|
+
- `extends` itself is stripped from the resolved profile and is **not** folded into `profileHash`, so `{ "extends": "base" }` with no overrides hashes byte-identically to `base`.
|
|
128
|
+
|
|
129
|
+
`wyvrnpm configure profile show <name>` prints the raw `extends:` chain alongside the resolved `[settings]` so you can inspect inheritance without grepping JSON.
|
|
130
|
+
|
|
97
131
|
---
|
|
98
132
|
|
|
99
133
|
## Commands
|
|
@@ -109,6 +143,42 @@ wyvrnpm init --root ./my-project
|
|
|
109
143
|
|
|
110
144
|
---
|
|
111
145
|
|
|
146
|
+
### `wyvrnpm add`
|
|
147
|
+
|
|
148
|
+
Adds one or more dependencies to `wyvrn.json` without downloading them. Useful when you know the package name but not the latest version.
|
|
149
|
+
|
|
150
|
+
- **Bare name** — resolves `latest.json` from your configured install sources and writes `"^<latest>"` (caret range, major-pinned).
|
|
151
|
+
- **`name@<version>`** — writes the given string verbatim. Accepts exact pins (`1.2.3.4`), caret/tilde ranges (`^1.2.3.4`, `~1.2.3.4`), and explicit comparators (`>=1.80.0 <2.0.0`).
|
|
152
|
+
|
|
153
|
+
If the dependency is already listed, it is replaced. When the prior entry was an object (`{ version, settings, options }`), the `settings` and `options` are preserved — only the version field is updated.
|
|
154
|
+
|
|
155
|
+
`add` does **not** run install. Chain `wyvrnpm install` afterwards to download.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Resolve latest, write "^<latest>"
|
|
159
|
+
wyvrnpm add zlib
|
|
160
|
+
|
|
161
|
+
# Pin exactly
|
|
162
|
+
wyvrnpm add zlib@1.3.0.0
|
|
163
|
+
|
|
164
|
+
# Use a caret / tilde / comparator range
|
|
165
|
+
wyvrnpm add fmt@^10.0.0
|
|
166
|
+
wyvrnpm add boost@">=1.80.0 <2.0.0"
|
|
167
|
+
|
|
168
|
+
# Multiple in one call
|
|
169
|
+
wyvrnpm add zlib fmt@10.2.0.0 spdlog
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Options**
|
|
173
|
+
|
|
174
|
+
| Option | Default | Description |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| `--source` / `-s` | *(config)* | Base URL used for the `latest` lookup. Repeat for multiple. |
|
|
177
|
+
| `--platform` | `win_x64` | v1 legacy platform sub-path (used as a fallback during `latest` lookup). |
|
|
178
|
+
| `--manifest` | `./wyvrn.json` | Path to the manifest file. |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
112
182
|
### `wyvrnpm install`
|
|
113
183
|
|
|
114
184
|
Resolves the full dependency graph and downloads all packages.
|
|
@@ -122,7 +192,7 @@ Resolves the full dependency graph and downloads all packages.
|
|
|
122
192
|
3. **Source build** (with `--build=missing`) — clones the package's source at the published `gitSha`, resolves its own dependencies, invokes CMake through the shared toolchain generator, and caches the result under `%LOCALAPPDATA%\wyvrnpm\bc\`. On Windows/MSVC with a Ninja or Make generator, `vcvarsall.bat` is auto-activated.
|
|
123
193
|
4. **v1 legacy path** — only when no v2 entry exists for the package at all.
|
|
124
194
|
|
|
125
|
-
The pre-2.1 "same OS + arch, any compiler" loose fallback is
|
|
195
|
+
The pre-2.1 "same OS + arch, any compiler" loose fallback is no longer available. Publish a build for your profile, add a declarative `compatibility` block to the recipe, or rerun with `--build=missing` to source-build.
|
|
126
196
|
|
|
127
197
|
```bash
|
|
128
198
|
# Use configured sources and the default build profile
|
|
@@ -141,6 +211,13 @@ wyvrnpm install \
|
|
|
141
211
|
|
|
142
212
|
# Build any missing binary from source
|
|
143
213
|
wyvrnpm install --build=missing
|
|
214
|
+
|
|
215
|
+
# Force every dep to be rebuilt from source (debugging / reproducibility check)
|
|
216
|
+
wyvrnpm install --build=always
|
|
217
|
+
|
|
218
|
+
# Print the resolved install plan WITHOUT downloading (CI-friendly with --format=json)
|
|
219
|
+
wyvrnpm install --dry-run
|
|
220
|
+
wyvrnpm install --dry-run --format=json
|
|
144
221
|
```
|
|
145
222
|
|
|
146
223
|
**Options**
|
|
@@ -154,6 +231,8 @@ wyvrnpm install --build=missing
|
|
|
154
231
|
| `--timeout` | `300` | HTTP request timeout in seconds. |
|
|
155
232
|
| `--manifest` | `./wyvrn.json` | Path to the manifest file. |
|
|
156
233
|
| `--root` | `./` | Project root (packages extracted to `{root}/wyvrn_internal/`). |
|
|
234
|
+
| `--dry-run` | `false` | Run the resolver + profile/options math, print the install plan, and exit. No download, no `wyvrn.lock`, no `wyvrn_internal/`, no toolchain. Combine with `--format=json` for CI ingestion (payload carries `command: "install-dry-run"`). |
|
|
235
|
+
| `--conf` | — | Non-ABI build-time override. Repeatable. Format: `<namespace.leaf>=<value>` — e.g. `--conf cmake.cache.CHROMA_ENABLE_TEST=ON`. Layered: CLI > `wyvrn.local.json` > named-profile `conf` > recipe. Does **not** fold into `profileHash`. See [Build-time configuration (`conf`)](#build-time-configuration-conf). |
|
|
157
236
|
|
|
158
237
|
Packages are extracted to `wyvrn_internal/{name}/`. A `wyvrn.lock` file is written alongside the manifest recording the exact resolved versions, profile, and per-package SHA256. On subsequent installs the lock file pins all previously resolved versions — only newly added dependencies are resolved fresh.
|
|
159
238
|
|
|
@@ -164,6 +243,35 @@ After download, `install` also generates:
|
|
|
164
243
|
- `wyvrn_internal/wyvrn_profile.json` — snapshot of the active build profile.
|
|
165
244
|
- `CMakePresets.json` (or `CMakeUserPresets.json` if the project root file is user-owned) with a `wyvrn-<profile>` configure preset. Presets for other profiles are preserved so multiple profiles coexist.
|
|
166
245
|
|
|
246
|
+
**Toolchain variables exposed to your `CMakeLists.txt` (valid BEFORE `project()`)**:
|
|
247
|
+
|
|
248
|
+
| Variable | Value |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `WYVRN_PROFILE_NAME` / `WYVRN_PROFILE_HASH` | Active profile name + 16-char hash |
|
|
251
|
+
| `WYVRN_PROFILE_OS` / `WYVRN_PROFILE_ARCH` | OS + architecture from the profile |
|
|
252
|
+
| `WYVRN_PROFILE_COMPILER` / `WYVRN_PROFILE_COMPILER_VERSION` | Compiler identity |
|
|
253
|
+
| `WYVRN_PROFILE_CPPSTD` / `WYVRN_PROFILE_RUNTIME` | C++ standard + MSVC runtime linkage |
|
|
254
|
+
| `WYVRN_ARCH_SUFFIX` | `"64"` for 64-bit arches, `"32"` for 32-bit, empty for unmapped. Derived at toolchain-generation time so it's usable before `project()` — unlike `CMAKE_SIZEOF_VOID_P`. |
|
|
255
|
+
|
|
256
|
+
The optional helper `WYVRN_APPLY_ARCH_SUFFIX(<target> [BASE_NAME <name>])` from the bundled `macros.cmake` applies the suffix to a target's `OUTPUT_NAME` so x64 and x86 builds of the same library coexist on disk without overwriting each other. Target linkage (`target_link_libraries`) is unaffected — only the produced filename changes.
|
|
257
|
+
|
|
258
|
+
The bundled `variables.cmake` also suffixes the consumer's own output directories with `WYVRN_ARCH_SUFFIX` so multi-arch builds from one source tree don't clobber each other:
|
|
259
|
+
|
|
260
|
+
| Profile arch | Archive/library dir | Runtime (DLL/EXE) dir |
|
|
261
|
+
|---|---|---|
|
|
262
|
+
| `x86_64` / `armv8` | `output/lib64/` | `output/bin64/<CONFIG>/` |
|
|
263
|
+
| `x86` / `armv7` | `output/lib/` | `output/bin/<CONFIG>/` |
|
|
264
|
+
| unmapped | `output/lib/` | `output/bin/<CONFIG>/` |
|
|
265
|
+
|
|
266
|
+
Prior to `2.5.0` the runtime directory was always `output/bin/<CONFIG>/` regardless of arch — a multi-arch consumer building x64 then x86 would silently overwrite the first arch's DLLs. Scripts that hard-code `output/bin/…` expecting x64 payloads need to switch to `output/bin64/…` after upgrading.
|
|
267
|
+
|
|
268
|
+
```cmake
|
|
269
|
+
project(String CXX)
|
|
270
|
+
add_library(String STATIC ...)
|
|
271
|
+
WYVRN_APPLY_ARCH_SUFFIX(String) # → String64.lib / String32.lib
|
|
272
|
+
WYVRN_APPLY_ARCH_SUFFIX(String BASE_NAME my-str) # → my-str64.lib / my-str32.lib
|
|
273
|
+
```
|
|
274
|
+
|
|
167
275
|
---
|
|
168
276
|
|
|
169
277
|
### `wyvrnpm build`
|
|
@@ -189,6 +297,10 @@ wyvrnpm build --target my-lib
|
|
|
189
297
|
# Wipe the build directory first
|
|
190
298
|
wyvrnpm build --clean
|
|
191
299
|
|
|
300
|
+
# Override the preset's generator (pair with --clean when switching generators)
|
|
301
|
+
wyvrnpm build --clean --generator "Visual Studio 17 2022"
|
|
302
|
+
wyvrnpm build --clean -G "Ninja Multi-Config"
|
|
303
|
+
|
|
192
304
|
# Build, then install to the CMake install prefix
|
|
193
305
|
wyvrnpm build --install
|
|
194
306
|
wyvrnpm build --install --install-prefix C:\out\stage
|
|
@@ -210,6 +322,7 @@ wyvrnpm build -- -j 8
|
|
|
210
322
|
| `--target` / `-t` | *(all)* | Specific CMake target to build. |
|
|
211
323
|
| `--verbose` / `-v` | `false` | Pass `--verbose` to `cmake --build`. |
|
|
212
324
|
| `--clean` | `false` | Remove the build directory before configuring. |
|
|
325
|
+
| `--generator` / `-G` | *(from preset)* | Override the CMake generator used at configure time (e.g. `"Visual Studio 17 2022"`, `"Ninja"`, `"Ninja Multi-Config"`). CMake bakes the generator into the cache, so pair with `--clean` when switching. When the effective generator is Visual Studio, `-A <platform>` is auto-derived from the profile's arch (`x86→Win32`, `x86_64→x64`, `armv8→ARM64`, `armv7→ARM`) so VS doesn't silently default to x64 on 32-bit profiles. |
|
|
213
326
|
| `--install` | `false` | Run `cmake --install` after a successful build. |
|
|
214
327
|
| `--install-prefix` | *(baked in)* | Override `CMAKE_INSTALL_PREFIX` for `--install` without reconfiguring. |
|
|
215
328
|
| `--auto-install` | `true` | Auto-run `wyvrnpm install` when the toolchain is stale. Disable with `--no-auto-install`. |
|
|
@@ -240,7 +353,9 @@ wyvrnpm publish --source default
|
|
|
240
353
|
# Explicit destination URL
|
|
241
354
|
wyvrnpm publish --source s3://my-bucket/packages --aws-profile my-sso
|
|
242
355
|
|
|
243
|
-
# HTTP server with token auth
|
|
356
|
+
# HTTP server with token auth (CI-preferred: --token-env avoids argv leakage)
|
|
357
|
+
wyvrnpm publish --source https://pkg.corp.com --token-env WYVRN_HTTP_TOKEN
|
|
358
|
+
# Equivalent for interactive use; --token lands in shell history / ps output
|
|
244
359
|
wyvrnpm publish --source https://pkg.corp.com --token mytoken
|
|
245
360
|
|
|
246
361
|
# Local directory or SMB share
|
|
@@ -262,6 +377,7 @@ wyvrnpm publish --force
|
|
|
262
377
|
| `--profile` / `-p` | *(config / "default")* | Named build profile to publish under. |
|
|
263
378
|
| `--aws-profile` | *(config)* | AWS SSO profile for S3 authentication. |
|
|
264
379
|
| `--token` | *(config)* | Bearer token for HTTP server authentication. |
|
|
380
|
+
| `--token-env` | *(config)* | Name of an env var holding the bearer token. Preferred for CI — the literal value never lands in `argv` or shell history. |
|
|
265
381
|
| `--path` | `.` | Directory to zip and publish. |
|
|
266
382
|
| `--manifest` | `./wyvrn.json` | Path to the manifest file. |
|
|
267
383
|
| `--force` / `-f` | `false` | Overwrite an existing published version (same version + profile hash). |
|
|
@@ -307,6 +423,130 @@ wyvrnpm clean --build-cache
|
|
|
307
423
|
| Option | Default | Description |
|
|
308
424
|
|---|---|---|
|
|
309
425
|
| `--build-cache` | `false` | Also remove the source-build cache under `%LOCALAPPDATA%\wyvrnpm\bc\` (Unix: `~/.cache/wyvrnpm/bc/`). |
|
|
426
|
+
| `--uploaded-built` | `false` | Wipe only the local record of what this machine has uploaded via `--upload-built` (the `.uploaded-to.json` sidecars). Does **not** touch the registry, the artefacts, or `wyvrn_internal/`. |
|
|
427
|
+
|
|
428
|
+
For selective cache pruning (keep last N variants, drop entries older than N days), use `wyvrnpm cache prune` instead — see below.
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### `wyvrnpm cache` (2.8.0+)
|
|
433
|
+
|
|
434
|
+
Inspect and selectively prune the machine-wide source-build cache at `%LOCALAPPDATA%\wyvrnpm\bc\` (Unix: `~/.cache/wyvrnpm/bc/`). Useful once `--upload-built` adoption balloons cache size on dev rigs — `clean --build-cache` is the blunt alternative that wipes everything.
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
# List every cached entry as a table
|
|
438
|
+
wyvrnpm cache list
|
|
439
|
+
|
|
440
|
+
# Filter by package name (glob)
|
|
441
|
+
wyvrnpm cache list "boost*"
|
|
442
|
+
|
|
443
|
+
# Machine-readable output for CI
|
|
444
|
+
wyvrnpm cache list --format json
|
|
445
|
+
|
|
446
|
+
# Keep the 2 most-recently-touched variants per (name, version)
|
|
447
|
+
wyvrnpm cache prune --keep-last 2
|
|
448
|
+
|
|
449
|
+
# Drop entries older than 30 days
|
|
450
|
+
wyvrnpm cache prune --older-than 30d
|
|
451
|
+
|
|
452
|
+
# Combine: keep 1 recent per version AND drop anything stale
|
|
453
|
+
wyvrnpm cache prune --keep-last 1 --older-than 30d
|
|
454
|
+
|
|
455
|
+
# Preview — print what would be removed, delete nothing
|
|
456
|
+
wyvrnpm cache prune --keep-last 2 --dry-run
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**`cache list` options**
|
|
460
|
+
|
|
461
|
+
| Option | Default | Description |
|
|
462
|
+
|---|---|---|
|
|
463
|
+
| `[pattern]` / `--pattern` | *(none)* | Glob over package names (`*` for any chars, `?` for one). |
|
|
464
|
+
| `--format` | `text` | `text` (table) or `json` (structured payload for CI). |
|
|
465
|
+
|
|
466
|
+
**`cache prune` options**
|
|
467
|
+
|
|
468
|
+
| Option | Default | Description |
|
|
469
|
+
|---|---|---|
|
|
470
|
+
| `--keep-last <N>` | *(none)* | Retain the N most-recently-touched entries **per (name, version) group**. A four-profile rig keeping-last-2 still retains the two newest profile variants of each version. |
|
|
471
|
+
| `--older-than <dur>` | *(none)* | Remove entries whose mtime is older than the threshold. Format: `<number><unit>`, unit ∈ `s` / `m` / `h` / `d` (e.g. `30d`, `72h`). |
|
|
472
|
+
| `--pattern <glob>` | *(none)* | Restrict scope to package names matching the glob. |
|
|
473
|
+
| `--dry-run` | `false` | Print what would be removed without deleting. |
|
|
474
|
+
|
|
475
|
+
At least one of `--keep-last` / `--older-than` is required — calling `prune` bare errors out with a pointer to `clean --build-cache` (the nuke-everything path).
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### `wyvrnpm show`
|
|
480
|
+
|
|
481
|
+
Read-only registry-metadata inspector. Given `<name>[@<version>[@<profileHash>]]`, queries the first configured install source that knows the package (override with `--source`) and prints what's published.
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
# Index of every published version (one HTTP round trip per source)
|
|
485
|
+
wyvrnpm show zlib
|
|
486
|
+
|
|
487
|
+
# Narrow to one version — fans out a per-profile query so uploadedBy,
|
|
488
|
+
# compatibility, and declared options show up per build
|
|
489
|
+
wyvrnpm show zlib@1.3.0.0
|
|
490
|
+
|
|
491
|
+
# Narrow to one specific build
|
|
492
|
+
wyvrnpm show zlib@1.3.0.0@a1b2c3d4e5f60718
|
|
493
|
+
|
|
494
|
+
# Pick the source explicitly (skips install-source lookup order)
|
|
495
|
+
wyvrnpm show zlib@1.3.0.0 --source s3://team-pkgs
|
|
496
|
+
|
|
497
|
+
# Machine-readable for CI ingestion
|
|
498
|
+
wyvrnpm show zlib@1.3.0.0 --format json
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
What gets surfaced per profile:
|
|
502
|
+
|
|
503
|
+
- **origin** — `author-publish` vs `consumer-upload` (derived from whether the manifest carries an `uploadedBy` block).
|
|
504
|
+
- **uploadedBy** — when set, the consumer-upload provenance (`kind`, `builtFromGit`, `builtFromSha`, `uploadedAt`, `wyvrnpmVersion`).
|
|
505
|
+
- **compatibility** — the recipe's declarative compat block, if any.
|
|
506
|
+
- **declaredOptions** — the author-declared `options` map from the recipe.
|
|
507
|
+
- **resolvedOptions** — the resolved option values that produced this profile's `profileHash`.
|
|
508
|
+
- **publishedConf** — recipe + CLI `--conf` the publisher captured (informational; doesn't affect resolution).
|
|
509
|
+
- **signature** — when PLAN-SIGNING phase 1 ships, signer identity; absent today.
|
|
510
|
+
|
|
511
|
+
Useful for: auditing consumer uploads (who pushed this artefact, from which commit), spotting profile drift between two consumers, verifying a package's declared options before adding it to a recipe.
|
|
512
|
+
|
|
513
|
+
**Options**
|
|
514
|
+
|
|
515
|
+
| Option | Default | Description |
|
|
516
|
+
|---|---|---|
|
|
517
|
+
| `pkg` *(positional)* | *(required)* | `<name>[@<version>[@<profileHash>]]` |
|
|
518
|
+
| `--source` / `-s` | *(first configured install source)* | URL or configured source name. Repeatable. |
|
|
519
|
+
| `--format` | `text` | `text` or `json` (see [Shape — `show`](#shape--show) below). |
|
|
520
|
+
| `--token` / `--token-env` / `--aws-profile` | | Auth forwarded to the provider the same way `install` does. |
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
### `wyvrnpm install-skill`
|
|
525
|
+
|
|
526
|
+
Installs the bundled wyvrnpm Agent Skill — the authoring guide Claude Code uses when it sees a `wyvrn.json` in the workspace. Ships as a `.skill` zip inside the npm package (`claude/skills/wyvrnpm.skill`) and is extracted into `~/.claude/skills/wyvrnpm/` on demand.
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
# One-shot: install the bundled skill for Claude Code
|
|
530
|
+
wyvrnpm install-skill --claude
|
|
531
|
+
|
|
532
|
+
# Overwrite an existing installation (e.g. after upgrading wyvrnpm)
|
|
533
|
+
wyvrnpm install-skill --claude --force
|
|
534
|
+
|
|
535
|
+
# Preview without writing
|
|
536
|
+
wyvrnpm install-skill --claude --dry-run
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
You only need this if you want Claude Code to pick up the skill. The CLI itself works without it.
|
|
540
|
+
|
|
541
|
+
**Options**
|
|
542
|
+
|
|
543
|
+
| Option | Default | Description |
|
|
544
|
+
|---|---|---|
|
|
545
|
+
| `--claude` | `false` | Install for Claude Code (extracts to `~/.claude/skills/wyvrnpm/` + writes the `.skill` zip alongside). Required — present so a future `--cursor` / `--vscode` target can slot in without CLI churn. |
|
|
546
|
+
| `--force` | `false` | Overwrite an existing skill install. Without it, the command refuses to clobber. |
|
|
547
|
+
| `--dry-run` | `false` | Print the destination paths and intended actions without writing. |
|
|
548
|
+
|
|
549
|
+
**CLAUDE.md §9 note for contributors:** the tested path for deploying a locally-edited skill is `node scripts/repack-skill.js && node bin/wyvrn.js install-skill --claude --force` — never `rm -rf` + `cp -r`.
|
|
310
550
|
|
|
311
551
|
---
|
|
312
552
|
|
|
@@ -460,7 +700,8 @@ wyvrnpm configure add-source \
|
|
|
460
700
|
| `--name` | Yes | Unique name for this source. |
|
|
461
701
|
| `--url` | Yes | Destination URL, URI, or file path. |
|
|
462
702
|
| `--profile` | No | AWS SSO profile (S3 sources). |
|
|
463
|
-
| `--token` | No | Bearer token (HTTP sources). |
|
|
703
|
+
| `--token` | No | Bearer token (HTTP sources). Persisted in plaintext in `config.json` — prefer `--token-env` for CI and shared setups. |
|
|
704
|
+
| `--token-env` | No | Name of an env var whose value is the bearer token. Only the **name** lands in `config.json`; the value is resolved fresh on every `wyvrnpm` call. |
|
|
464
705
|
|
|
465
706
|
#### `wyvrnpm configure remove-source`
|
|
466
707
|
|
|
@@ -862,6 +1103,56 @@ Example:
|
|
|
862
1103
|
}
|
|
863
1104
|
```
|
|
864
1105
|
|
|
1106
|
+
### Per-dependency source pin (2.8.0+)
|
|
1107
|
+
|
|
1108
|
+
When you have more than one configured install source (e.g. a primary S3 bucket plus a mirror), you can pin a security-sensitive dep to its canonical source by name:
|
|
1109
|
+
|
|
1110
|
+
```json
|
|
1111
|
+
{
|
|
1112
|
+
"dependencies": {
|
|
1113
|
+
"OpenSSL": {
|
|
1114
|
+
"version": "3.0.0.0",
|
|
1115
|
+
"source": "primary-s3"
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
`"primary-s3"` must match a `name` from `wyvrnpm configure list`; an unknown name fails install with exit code 1 rather than silently fanning out. The pin closes two common multi-source holes:
|
|
1122
|
+
|
|
1123
|
+
- **Mirror shadowing.** A package accidentally published to the mirror can't substitute for the primary's copy.
|
|
1124
|
+
- **Dependency confusion.** A squatter on a secondary source can't poison the build.
|
|
1125
|
+
|
|
1126
|
+
Pins are direct-only — they don't cascade to the pinned package's own transitive deps. CLI `--source` overrides config entirely, so on a run with `--source`, any manifest pin is ignored with a warning rather than an error. The lockfile records `source: "<name>"` on pinned entries so reviewers can spot at a glance that the artefact came from the declared source; absent on non-pinned entries so pre-2.8.0 locks remain byte-identical.
|
|
1127
|
+
|
|
1128
|
+
### Pattern-based `settingsOverrides` (2.8.0+)
|
|
1129
|
+
|
|
1130
|
+
When many deps need the same settings override — every `boost-*` family member needing `compiler.cppstd: "17"`, or every `*-debug` variant needing `compiler.runtime: "static"` — declare the pattern at the top level of the manifest instead of copy-pasting per dep:
|
|
1131
|
+
|
|
1132
|
+
```json
|
|
1133
|
+
{
|
|
1134
|
+
"dependencies": {
|
|
1135
|
+
"boost-filesystem": "1.80.0.0",
|
|
1136
|
+
"boost-system": "1.80.0.0",
|
|
1137
|
+
"boost-thread": "1.80.0.0",
|
|
1138
|
+
"zlib": "1.3.0.0"
|
|
1139
|
+
},
|
|
1140
|
+
"settingsOverrides": {
|
|
1141
|
+
"boost*": { "compiler.cppstd": "17" },
|
|
1142
|
+
"*-debug": { "compiler.runtime": "static" }
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
Rules:
|
|
1148
|
+
|
|
1149
|
+
- Keys are globs — `*` matches any chars, `?` matches exactly one, literal names work too. Both ends are anchored (no substring match unless you add `*` on either side).
|
|
1150
|
+
- Values accept the same keys as profile overrides: `os`, `arch`, `compiler`, `compiler.version`, `compiler.cppstd`, `compiler.runtime`. Unknown keys fail install with a clear error.
|
|
1151
|
+
- More-specific patterns win: literal `"boost-filesystem"` beats `"boost*"`, which beats `"*"`.
|
|
1152
|
+
- A literal per-dep `settings` block inside `dependencies` still wins over any pattern. Use that for the one dep that deviates from the family rule.
|
|
1153
|
+
|
|
1154
|
+
Each matching pattern shifts that dep's `profileHash`, so different settings produce distinct registry artefacts — identical semantics to literal per-dep `settings`.
|
|
1155
|
+
|
|
865
1156
|
### Package options (`options`)
|
|
866
1157
|
|
|
867
1158
|
A library author can declare **options** — compile-time feature toggles that change the produced binary's ABI. Examples: `shared` (shared vs static library), `minizip` (zlib's minizip support), `fips` (OpenSSL's FIPS mode). Each option produces a distinct `profileHash`, so every option combination gets its own artefact on the registry.
|
|
@@ -956,6 +1247,169 @@ On Windows with MSVC and a non-Visual-Studio generator (Ninja, Make), `vcvarsall
|
|
|
956
1247
|
|
|
957
1248
|
---
|
|
958
1249
|
|
|
1250
|
+
## Build-time configuration (`conf`)
|
|
1251
|
+
|
|
1252
|
+
`conf` is wyvrnpm's channel for **non-ABI** build-time knobs — CMake cache variables, feature toggles that change `add_subdirectory()` but not the public binary, and (in future phases) other build-tool settings. It is a deliberate sibling of `options`, with the opposite hashing property:
|
|
1253
|
+
|
|
1254
|
+
| | `options` (F1) | `conf` (this section) |
|
|
1255
|
+
|---|---|---|
|
|
1256
|
+
| Folds into `profileHash`? | Yes — every combination is a distinct registry artefact. | **No.** Informational only; two builds with different `conf` still share the same `profileHash`. |
|
|
1257
|
+
| Typical use | `shared`/`minizip`/`fips` — things that genuinely change the binary. | `CHROMA_ENABLE_TEST`, `BUILD_DOCS`, `CMAKE_EXPORT_COMPILE_COMMANDS` — things that don't. |
|
|
1258
|
+
| Consumer can override? | Yes (per-dep `options` in `wyvrn.json` or `-o pkg:name=val` on CLI). | Yes (recipe → named-profile `conf` → `wyvrn.local.json` → `--conf`, in that precedence). |
|
|
1259
|
+
|
|
1260
|
+
Phase 1 (2.6.0+) supports a single namespace: `cmake.cache.<VAR>`. It flows into the generated `CMakePresets.json`'s `cacheVariables`.
|
|
1261
|
+
|
|
1262
|
+
### The four layers
|
|
1263
|
+
|
|
1264
|
+
```
|
|
1265
|
+
highest CLI --conf cmake.cache.X=ON
|
|
1266
|
+
│ ─────
|
|
1267
|
+
│ local wyvrn.local.json (per-developer, gitignored)
|
|
1268
|
+
│ ─────
|
|
1269
|
+
│ profile named-profile JSON.conf (team-shared, checked-in)
|
|
1270
|
+
│ ─────
|
|
1271
|
+
│ recipe wyvrn.json.conf (author defaults)
|
|
1272
|
+
▼ ─────
|
|
1273
|
+
lowest (nothing — key absent)
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
**Per-leaf override, not per-branch replace.** A CLI `--conf cmake.cache.FOO=ON` on top of a recipe setting `BAR=OFF` yields both keys — it does not discard `BAR`. Any omitted layer is equivalent to an empty map at that position — a project with no `wyvrn.local.json` and no profile `conf` merges recipe + CLI exactly as phase 1.
|
|
1277
|
+
|
|
1278
|
+
### Recipe-level defaults
|
|
1279
|
+
|
|
1280
|
+
Authors can declare defaults on their package:
|
|
1281
|
+
|
|
1282
|
+
```json
|
|
1283
|
+
{
|
|
1284
|
+
"name": "ChromaSDK",
|
|
1285
|
+
"version": "2.5.0.0",
|
|
1286
|
+
"conf": {
|
|
1287
|
+
"cmake": {
|
|
1288
|
+
"cache": {
|
|
1289
|
+
"CHROMA_ENABLE_TEST": "OFF",
|
|
1290
|
+
"CHROMA_ENABLE_EXAMPLES": "OFF",
|
|
1291
|
+
"CHROMA_LOG_LEVEL": "WARNING"
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
`true`/`false` in the JSON are normalised to CMake `"ON"`/`"OFF"`; numbers are stringified; strings pass through.
|
|
1299
|
+
|
|
1300
|
+
### Per-developer overlay — `wyvrn.local.json`
|
|
1301
|
+
|
|
1302
|
+
Drop a `wyvrn.local.json` next to `wyvrn.json` for per-machine overrides. `wyvrnpm init` scaffolds a `.gitignore` entry for new projects; existing projects get a one-line nudge on `wyvrnpm install` when the file is present but not ignored.
|
|
1303
|
+
|
|
1304
|
+
```json
|
|
1305
|
+
{
|
|
1306
|
+
"conf": {
|
|
1307
|
+
"cmake": {
|
|
1308
|
+
"cache": {
|
|
1309
|
+
"CHROMA_ENABLE_TEST": "ON",
|
|
1310
|
+
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
Phase 1 accepts **only** the top-level key `conf` in this file — `dependencies` / `options` / anything else is a hard error, forecloseing the silent-inert footgun where a user writes `{ "dependencies": {...} }` expecting local dep overrides. Phase 2 will widen the allow-list.
|
|
1318
|
+
|
|
1319
|
+
### Team-shared overlay — named-profile `conf` (phase 2, 2.7.0+)
|
|
1320
|
+
|
|
1321
|
+
When every developer on a team would end up with the same `wyvrn.local.json`, check that shared policy into the named profile instead. A saved profile (e.g. `%LOCALAPPDATA%\wyvrnpm\profiles\team-default.json`) may carry an optional top-level `conf` block alongside its `[settings]`:
|
|
1322
|
+
|
|
1323
|
+
```json
|
|
1324
|
+
{
|
|
1325
|
+
"os": "Windows",
|
|
1326
|
+
"arch": "x86_64",
|
|
1327
|
+
"compiler": "msvc",
|
|
1328
|
+
"compiler.version": "193",
|
|
1329
|
+
"compiler.cppstd": "20",
|
|
1330
|
+
"compiler.runtime": "dynamic",
|
|
1331
|
+
"conf": {
|
|
1332
|
+
"cmake": {
|
|
1333
|
+
"cache": {
|
|
1334
|
+
"CHROMA_ENABLE_SANITIZERS": "OFF",
|
|
1335
|
+
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
Edit via the `configure profile set` convenience (repeatable, same `KEY=VAL` / bare-`KEY` / `KEY=` syntax as the other CLI sinks):
|
|
1343
|
+
|
|
1344
|
+
```bash
|
|
1345
|
+
wyvrnpm configure profile set --name team-default --conf cmake.cache.CMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
1346
|
+
wyvrnpm configure profile set --name team-default --conf cmake.cache.LEGACY_FLAG= # clears it
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
Profile `conf` layers **between recipe and local**: a project's `wyvrn.local.json` (the individual override) still wins over team defaults, and CLI `--conf` still wins over everything. The distinction Conan makes between the `[conf]` block in a profile and the `-c` CLI flag maps directly onto this precedence.
|
|
1350
|
+
|
|
1351
|
+
Profile `conf` is **non-ABI**: adding or changing keys inside it does NOT shift `profileHash`, so switching a team policy between `ENABLE_SANITIZERS=ON` and `=OFF` does not invalidate already-downloaded artefacts. The invariant is locked in by `tests/profile-hash.test.js`.
|
|
1352
|
+
|
|
1353
|
+
Auto-detected profiles (when no on-disk profile file exists) never inject a `conf` layer — detection is about `[settings]` only.
|
|
1354
|
+
|
|
1355
|
+
### CLI — ad-hoc, one invocation
|
|
1356
|
+
|
|
1357
|
+
```bash
|
|
1358
|
+
# Single toggle
|
|
1359
|
+
wyvrnpm build --conf cmake.cache.CHROMA_ENABLE_TEST=ON
|
|
1360
|
+
|
|
1361
|
+
# Repeatable
|
|
1362
|
+
wyvrnpm build \
|
|
1363
|
+
--conf cmake.cache.CHROMA_ENABLE_TEST=ON \
|
|
1364
|
+
--conf cmake.cache.BUILD_DOCS=OFF
|
|
1365
|
+
|
|
1366
|
+
# Bare KEY is sugar for KEY=ON (CMake -D convention)
|
|
1367
|
+
wyvrnpm build --conf cmake.cache.CHROMA_ENABLE_TEST
|
|
1368
|
+
|
|
1369
|
+
# KEY= (empty RHS) clears a value inherited from a lower layer
|
|
1370
|
+
wyvrnpm build --conf cmake.cache.CHROMA_ENABLE_TEST=
|
|
1371
|
+
|
|
1372
|
+
# Also honoured on install and publish (publish records it as
|
|
1373
|
+
# `publishedConf` on the uploaded manifest — informational metadata
|
|
1374
|
+
# that `wyvrnpm show` surfaces).
|
|
1375
|
+
wyvrnpm install --conf cmake.cache.CHROMA_ENABLE_TEST=ON
|
|
1376
|
+
wyvrnpm publish --conf cmake.cache.BUILD_DOCS=OFF
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
`--conf` on `wyvrnpm build` passes through to `cmake --preset` as `-D` / `-U` overrides **for that invocation only** — it does not regenerate `CMakePresets.json`. Persistent per-machine overrides belong in `wyvrn.local.json`; `wyvrnpm install` regenerates the preset deterministically with the overlay applied.
|
|
1380
|
+
|
|
1381
|
+
### Lockfile semantics
|
|
1382
|
+
|
|
1383
|
+
`wyvrn.lock` gains an informational `effectiveConf` block after each install:
|
|
1384
|
+
|
|
1385
|
+
```json
|
|
1386
|
+
{
|
|
1387
|
+
"wyvrnVersion": 2,
|
|
1388
|
+
"profileHash": "a1b2c3d4e5f60718",
|
|
1389
|
+
"effectiveConf": {
|
|
1390
|
+
"cmake": { "cache": { "CHROMA_ENABLE_TEST": "ON" } }
|
|
1391
|
+
},
|
|
1392
|
+
"packages": { ... }
|
|
1393
|
+
}
|
|
1394
|
+
```
|
|
1395
|
+
|
|
1396
|
+
This is diagnostic only — changing `conf` between installs shows up as a lockfile diff but never causes a relock or version change. Conf drift is a legitimate review signal, not an error.
|
|
1397
|
+
|
|
1398
|
+
### Source-build boundary
|
|
1399
|
+
|
|
1400
|
+
When `--build=missing` or `--build=always` source-builds a dependency, **only that dep's own recipe `conf`** flows into its CMake invocation. The root project's merged conf (including `wyvrn.local.json`, named-profile `conf`, and CLI `--conf`) never reaches a dep's source-build. This preserves cross-consumer reproducibility — two developers source-building the same `(name, version, profileHash)` produce the same binary regardless of their local overlays or team profile, which is load-bearing for `--upload-built`.
|
|
1401
|
+
|
|
1402
|
+
### Why this isn't `build.configure`
|
|
1403
|
+
|
|
1404
|
+
Existing authors using `build.configure: ["-DFOO=ON", "-DBAR=OFF"]` keep working unchanged. But `build.configure` has two weaknesses `conf` fixes:
|
|
1405
|
+
|
|
1406
|
+
1. **All-or-nothing.** A consumer can't disable one flag without overriding the whole array.
|
|
1407
|
+
2. **Opaque strings.** `"-DFOO=ON"` is parsed at configure time, not at manifest load.
|
|
1408
|
+
|
|
1409
|
+
Recipe authors writing new packages should prefer `conf.cmake.cache.FOO=ON` for cache variables and keep `build.configure` for non-cache args like `-G`, `-T`, or `-A`. Setting the same KEY in both `build.configure` (`-DKEY=...`) AND `conf.cmake.cache.KEY` is a recipe-normalise error — pick one route.
|
|
1410
|
+
|
|
1411
|
+
---
|
|
1412
|
+
|
|
959
1413
|
## Compatibility Rules
|
|
960
1414
|
|
|
961
1415
|
Publishers declare an optional `compatibility` block in a package's `wyvrn.json`. It tells wyvrnpm which profile fields must match the consumer's profile exactly, and which may legitimately differ without breaking ABI. When no exact `profileHash` match exists on the registry, `install` evaluates this block against every published build for the requested `(name, version)` and picks the best compatible candidate.
|
|
@@ -1010,16 +1464,6 @@ When multiple published builds satisfy the consumer's profile, the winner is pic
|
|
|
1010
1464
|
|
|
1011
1465
|
The chosen candidate is logged along with a per-field summary (e.g. `compiler.cppstd 20→23 (lte), compiler.runtime=dynamic`).
|
|
1012
1466
|
|
|
1013
|
-
### Legacy loose fallback
|
|
1014
|
-
|
|
1015
|
-
The pre-2.1 "same OS + arch, any compiler" fallback is removed from the default resolution path. For one release cycle it remains reachable via an env var:
|
|
1016
|
-
|
|
1017
|
-
```bash
|
|
1018
|
-
WYVRNPM_ALLOW_LOOSE_COMPAT=1 wyvrnpm install
|
|
1019
|
-
```
|
|
1020
|
-
|
|
1021
|
-
This prints a deprecation warning every time it fires and will be removed in the next minor release. Prefer adding a real `compatibility` block to affected packages, or rebuilding with `--build=missing`.
|
|
1022
|
-
|
|
1023
1467
|
---
|
|
1024
1468
|
|
|
1025
1469
|
## Source Builds
|
|
@@ -1081,6 +1525,8 @@ Source builds are cached machine-wide, keyed by `(name, version, profileHash)`:
|
|
|
1081
1525
|
|
|
1082
1526
|
Re-running `install --build=missing` with the same inputs short-circuits to the cached artefact. The cache root is deliberately shallow (`bc/`, not `build-cache/`) to keep nested CMake paths under Windows' 260-char limit.
|
|
1083
1527
|
|
|
1528
|
+
`--build=always` (2.5.0+) ignores every registry-binary path — exact-match, compat-match, and any already-extracted `wyvrn_internal/{name}/` — and forces a source-build for every dep. Useful for debugging whether a registry binary differs from what the current source tree would produce, or for reproducibility verification. The build-cache short-circuit still applies: re-running `--build=always` with unchanged inputs completes in seconds.
|
|
1529
|
+
|
|
1084
1530
|
Clone behaviour is tri-tier:
|
|
1085
1531
|
|
|
1086
1532
|
1. **Shallow-SHA fetch** (`git fetch origin <sha> --depth=1`) — fastest; works when the git server allows it.
|
|
@@ -1130,7 +1576,7 @@ wyvrnpm install --build=missing --upload-built --upload-source team-s3
|
|
|
1130
1576
|
|
|
1131
1577
|
# Upload auth is resolved in order: CLI flag → named-source config → first configured publish source.
|
|
1132
1578
|
wyvrnpm install --build=missing --upload-built --aws-profile my-sso
|
|
1133
|
-
wyvrnpm install --build=missing --upload-built --token
|
|
1579
|
+
wyvrnpm install --build=missing --upload-built --token-env WYVRN_HTTP_TOKEN
|
|
1134
1580
|
```
|
|
1135
1581
|
|
|
1136
1582
|
Semantics:
|