@coderook/cli 0.33.1 → 0.34.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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "coderook",
3
3
  "displayName": "CodeRook",
4
- "description": "Save, browse and restore whole-snapshot versions of a project on CodeRook, from Claude Code.",
5
- "version": "0.33.1",
4
+ "description": "Save, browse and restore whole-snapshot versions of a project on CodeRook, with cbx or plain git, from Claude Code.",
5
+ "version": "0.34.1",
6
6
  "author": {
7
7
  "name": "ACCA Gaming Productions",
8
8
  "url": "https://coderook.com"
@@ -13,6 +13,7 @@
13
13
  "coderook",
14
14
  "versioning",
15
15
  "snapshots",
16
- "backup"
16
+ "backup",
17
+ "git"
17
18
  ]
18
19
  }
package/README.md CHANGED
@@ -32,7 +32,7 @@ project moved by one is understood by the other.
32
32
 
33
33
  ## Install
34
34
 
35
- Requires Node 20.11 or later, and nothing else.
35
+ Requires Node 22.15 or later (Node 24 is the safe choice), and nothing else. Older Node lacks the zstd support bundles use, and the CLI says so rather than failing later.
36
36
 
37
37
  ```
38
38
  npm install --global @coderook/cli
@@ -80,9 +80,20 @@ cbx clone my-project fetch a project into a new folder
80
80
  ```
81
81
 
82
82
  `status` and `submit` act on the current directory unless you name another.
83
- The first time either runs in a folder, it looks for a project on your account
84
- whose name matches and links the two, so a folder you already uploaded from
85
- the desktop is recognised rather than treated as new.
83
+
84
+ A folder is linked to its project by its first save, by `cbx clone`, or by
85
+ `cbx link <project>`, and the link travels with the folder (in
86
+ `.coderook/link.json`), so the same disk seen from another operating system is
87
+ still recognised. A folder that is not linked is never matched to a project by
88
+ name. Its first `submit` starts a new project, unless your account already has
89
+ one with a name like it; then you are asked which you mean. A script or an
90
+ assistant has to say:
91
+
92
+ ```
93
+ cbx submit --into my-project -m "…" this folder is that project
94
+ cbx submit --new -m "…" a separate project
95
+ cbx link my-project link it now, send nothing
96
+ ```
86
97
 
87
98
  `submit` sends only what changed. Files the service already holds are not
88
99
  uploaded again, and the version it records still names every file in the
@@ -302,14 +313,31 @@ Installing the CLI also installs `git-remote-coderook`, so git talks to
302
313
  CodeRook directly — both ways:
303
314
 
304
315
  ```
305
- git clone coderook://my-project
316
+ git clone coderook://my-project # the remote is called origin
317
+ git remote add coderook coderook://my-project # or add it to a repository you have
306
318
  git push coderook main
307
- git fetch
319
+ git fetch coderook
320
+ ```
321
+
322
+ If your folder is a git repository, use this rather than `cbx submit`: each
323
+ commit arrives with its own message, and every editor's built-in git panel
324
+ works with CodeRook without a plugin. `cbx submit` is the tool for folders
325
+ that are not git repositories. The helper is installed by
326
+ `npm install --global @coderook/cli`; the Claude Code plugin and `npx` do not
327
+ put it on your `PATH`.
328
+
329
+ **A project you started with `cbx submit`.** Its saves did not come from git,
330
+ so the first push from your repository is refused rather than replaying your
331
+ history on top of them. If the repository holds that project, adopt it once:
332
+
333
+ ```
334
+ git push -o adopt coderook main
308
335
  ```
309
336
 
310
- It exists so that every editor's built-in git panel works with CodeRook
311
- without a plugin. If you are not already living in git, `cbx submit` is
312
- the simpler tool and this is not an upgrade on it.
337
+ The project's saves stay as they are, your current commit is saved on top as
338
+ one save, and from then on every push sends one save per commit. Or start
339
+ from the project instead: `git clone coderook://my-project` and carry on in
340
+ the clone.
313
341
 
314
342
  **Pushing.** Each commit becomes a version, oldest first, with its message
315
343
  kept. Later pushes send only what is new, so the usual case — a few commits —
@@ -348,7 +376,7 @@ has two parents is rebuilt as a real git merge.
348
376
  Each version records the commit it came from, so a colleague pushing the same
349
377
  project does not republish history the project already holds. Pushing a git
350
378
  history into a project whose versions came from somewhere else is refused
351
- rather than interleaved.
379
+ rather than interleaved, unless you adopt it with `-o adopt` as above.
352
380
 
353
381
  ### The names are the same
354
382
 
@@ -408,6 +436,34 @@ artifacts or with `cbx attach <file>`, so a release made by pushing a tag
408
436
  simply has none until something adds them — which is what a release without a
409
437
  build has always looked like.
410
438
 
439
+ ## Building for every platform
440
+
441
+ ```
442
+ cbx build --plan how each target would be built on this machine
443
+ cbx build --target win,linux,mac build them
444
+ cbx build --target all --ship and attach them to the newest save
445
+ cbx build init describe the build in coderook.build.json
446
+ ```
447
+
448
+ `cbx build` makes the project's executables for Windows, Linux and macOS on
449
+ the machine you are using. Each target is built natively or cross-compiled,
450
+ chosen from what is installed; Docker and WSL are used when present and never
451
+ required for Linux. A target that cannot be built here is named, with what
452
+ would build it.
453
+
454
+ | Toolchain | From any machine | Needs its own system |
455
+ | --- | --- | --- |
456
+ | Go, Bun, Deno, .NET | Windows, Linux, macOS | — |
457
+ | Rust | all three, with cargo-zigbuild | macOS apps using system frameworks |
458
+ | Electron | Linux (tar.gz) straight from Windows; Windows and Linux elsewhere with Docker or wine | macOS; AppImage and deb need Linux |
459
+ | Python | Windows, Linux, macOS: the target's own CPython with its wheels, as a tar.gz with a launcher (PyInstaller where it runs) | a dependency with no wheel for that system |
460
+
461
+ The toolchain is recognised from the files present. `coderook.build.json`
462
+ settles it, and takes a command of your own (`{target}`, `{os}`, `{arch}` and
463
+ `{out}` are filled in, and a target can name a Docker image to run it in).
464
+ Output lands in `.coderook/build/<target>/`, which is never uploaded and which
465
+ git ignores — not `dist/`, which Electron apps commonly package.
466
+
411
467
  ## Bundles
412
468
 
413
469
  ```
@@ -31,6 +31,7 @@ const node_crypto_1 = require("node:crypto");
31
31
  const node_fs_1 = require("node:fs");
32
32
  const promises_1 = require("node:fs/promises");
33
33
  const node_path_1 = __importDefault(require("node:path"));
34
+ const node_process_1 = __importDefault(require("node:process"));
34
35
  const safe_path_js_1 = require("../shared/safe_path.js");
35
36
  const node_zlib_1 = require("node:zlib");
36
37
  const download_js_1 = require("./download.js");
@@ -411,6 +412,14 @@ async function unpackBundle(source, destination, report) {
411
412
  throw new Error(`${record.path} did not survive the bundle intact`);
412
413
  }
413
414
  await (0, promises_1.writeFile)(full, contents);
415
+ /*
416
+ The mode was recorded when the bundle was made and never put back, so
417
+ a script that went in executable came out needing chmod. Only the
418
+ permission bits, and only where the system has them.
419
+ */
420
+ if (node_process_1.default.platform !== "win32" && record.mode & 0o111) {
421
+ await (0, promises_1.chmod)(full, (record.mode & 0o777) | 0o400);
422
+ }
414
423
  written += 1;
415
424
  bytes += contents.length;
416
425
  }
@@ -730,6 +730,10 @@ class Uploader {
730
730
  const existing = await this.findBySlug(slug);
731
731
  if (!existing)
732
732
  throw error;
733
+ if (request.joinExisting === false) {
734
+ throw new Error(`Your account already has a project called ${slug}. Save into it on purpose, ` +
735
+ `or give this one another name.`);
736
+ }
733
737
  return existing;
734
738
  }
735
739
  }
@@ -217,6 +217,7 @@ async function push(repository, options) {
217
217
  message: shortMessage(save.message),
218
218
  projectName: options.projectName,
219
219
  repositoryId,
220
+ ...(options.joinExisting === false ? { joinExisting: false } : {}),
220
221
  baseVersionId,
221
222
  ...(baseVersionId ? { expectedHeadVersionId: baseVersionId } : {}),
222
223
  track: line,