@bitpub/cli 2.0.0 → 2.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpub/cli",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "BitPub CLI — local-first shared memory for AI agents. Six daily verbs (save/load/list/find/sync/delete), zero-config private namespace, encrypted client-side.",
5
5
  "bin": {
6
6
  "bitpub": "./bin/bitpub.js"
@@ -1,103 +1,102 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * `bitpub update` — pull the latest CLI tarball from your tenant and
4
+ * `bitpub update` — pull the latest CLI from the npm registry and
5
5
  * reinstall globally.
6
6
  *
7
- * Resolution order for the tenant URL (first match wins):
8
- * 1. --url flag
9
- * 2. BITPUB_CLOUD_URL env var
10
- * 3. api_url from ~/.bitpub/config.json (set by `bitpub init` / `auth login`)
11
- * 4. https://bitpub.io
7
+ * Source of truth is the public npm package at
8
+ * https://www.npmjs.com/package/@bitpub/cli
9
+ * which is published from cli/package.json. We read the latest version
10
+ * via the registry API (https://registry.npmjs.org/@bitpub/cli/latest)
11
+ * and then delegate the actual install to `npm install -g @bitpub/cli@<version>`.
12
12
  *
13
- * The tarball lives at `${url}/cli/latest.tgz` same path the one-liner
14
- * installer uses. We download to a temp file, peek at its package.json
15
- * for a version diff, then run `npm install -g <tarball>`.
13
+ * Anyone with the CLI on PATH can also self-update without this command —
14
+ * `npm install -g @bitpub/cli@latest` is equivalent. `bitpub update` exists
15
+ * to add (1) a one-line version diff before installing, (2) automatic
16
+ * refresh of installed skill files after the install, and (3) a `--check`
17
+ * mode for CI / agent flows that want to know "is there a newer version"
18
+ * without actually upgrading.
19
+ *
20
+ * `--registry <url>` overrides the registry, for teams publishing to a
21
+ * private npm registry (Verdaccio, GitHub Packages, AWS CodeArtifact, etc.).
16
22
  */
17
23
 
18
- const path = require('path');
19
- const fs = require('fs');
20
- const os = require('os');
21
24
  const { spawnSync } = require('child_process');
22
25
  const axios = require('axios');
23
- const { readConfig } = require('../config');
24
26
  const { refreshExistingSkills } = require('./skills');
25
27
 
28
+ const PACKAGE_NAME = '@bitpub/cli';
29
+ const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
30
+ const NPM_WEB_URL = `https://www.npmjs.com/package/${PACKAGE_NAME}`;
31
+
26
32
  module.exports = function registerUpdate(program) {
27
33
  program
28
34
  .command('update')
29
- .description('Update the BitPub CLI (and any installed skill files) to the latest tarball published by your tenant')
30
- .option('--url <string>', 'Override the tenant URL to fetch the tarball from')
35
+ .description('Update the BitPub CLI (and any installed skill files) to the latest version on npm')
36
+ .option('--registry <url>', 'Override the npm registry (for private npm mirrors)')
31
37
  .option('--check', 'Only check the remote version; do not install')
32
38
  .option('--skip-skills', 'Do not refresh installed skill files after the update')
33
39
  .action(async (opts) => {
34
- const config = readConfig();
35
- const cloudUrl = (
36
- opts.url ||
37
- process.env.BITPUB_CLOUD_URL ||
38
- config?.api_url ||
39
- 'https://bitpub.io'
40
- ).replace(/\/$/, '');
41
-
42
- const tarballUrl = `${cloudUrl}/cli/latest.tgz`;
40
+ const registry = (opts.registry || DEFAULT_REGISTRY).replace(/\/$/, '');
41
+ const versionUrl = `${registry}/${encodeURIComponent(PACKAGE_NAME)}/latest`;
43
42
  const localVersion = require('../../package.json').version;
44
43
 
45
44
  console.log(`Current : v${localVersion}`);
46
- console.log(`Tarball : ${tarballUrl}`);
47
-
48
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bitpub-update-'));
49
- const tarballPath = path.join(tmpDir, 'bitpub-cli.tgz');
45
+ console.log(`Source : ${NPM_WEB_URL}`);
46
+ if (opts.registry) console.log(`Registry: ${registry}`);
50
47
 
48
+ let remoteVersion;
51
49
  try {
52
- const resp = await axios.get(tarballUrl, {
53
- responseType: 'arraybuffer',
54
- timeout: 30_000,
55
- maxRedirects: 5,
50
+ const resp = await axios.get(versionUrl, {
51
+ timeout: 15_000,
56
52
  validateStatus: (s) => s === 200,
53
+ headers: { accept: 'application/json' },
57
54
  });
58
- fs.writeFileSync(tarballPath, Buffer.from(resp.data));
55
+ remoteVersion = resp.data?.version;
59
56
  } catch (err) {
60
- cleanup(tmpDir);
61
57
  const status = err.response?.status;
62
- if (status) {
63
- console.error(`\n✗ Failed to download tarball: HTTP ${status} from ${tarballUrl}`);
64
- if (status === 404) {
65
- console.error(' This tenant does not appear to publish a CLI tarball.');
66
- console.error(' Try --url https://bitpub.io for the public tenant.');
67
- }
58
+ if (status === 404) {
59
+ console.error(`\n✗ ${PACKAGE_NAME} not found on ${registry}.`);
60
+ console.error(' If you publish to a private registry, pass --registry <url>.');
61
+ } else if (status) {
62
+ console.error(`\n✗ Registry query failed: HTTP ${status} from ${versionUrl}`);
68
63
  } else {
69
- console.error(`\n✗ Failed to download tarball: ${err.message}`);
64
+ console.error(`\n✗ Registry query failed: ${err.message}`);
70
65
  }
71
66
  process.exit(1);
72
67
  }
73
68
 
74
- const remoteVersion = readVersionFromTarball(tarballPath) || 'unknown';
69
+ if (!remoteVersion) {
70
+ console.error(`\n✗ Registry response did not include a version. URL: ${versionUrl}`);
71
+ process.exit(1);
72
+ }
73
+
75
74
  console.log(`Remote : v${remoteVersion}`);
76
75
 
77
76
  if (opts.check) {
78
- cleanup(tmpDir);
79
77
  if (remoteVersion === localVersion) {
80
78
  console.log('\n✓ Already up to date.');
81
79
  } else {
82
- console.log('\nRun `bitpub update` to install v' + remoteVersion + '.');
80
+ console.log(`\nRun \`bitpub update\` to install v${remoteVersion}.`);
83
81
  }
84
82
  return;
85
83
  }
86
84
 
87
85
  if (remoteVersion === localVersion) {
88
- console.log('\nAlready on v' + localVersion + ' — reinstalling anyway to refresh files.');
86
+ console.log(`\nAlready on v${localVersion} — reinstalling anyway to refresh files.`);
89
87
  }
90
88
 
91
- console.log('\nInstalling globally with npm...');
92
- const result = spawnSync('npm', ['install', '-g', tarballPath], {
93
- stdio: 'inherit',
94
- });
89
+ const installSpec = `${PACKAGE_NAME}@${remoteVersion}`;
90
+ const npmArgs = ['install', '-g', installSpec];
91
+ if (opts.registry) npmArgs.push('--registry', registry);
95
92
 
96
- cleanup(tmpDir);
93
+ console.log(`\nInstalling: npm ${npmArgs.join(' ')}`);
94
+ const result = spawnSync('npm', npmArgs, { stdio: 'inherit' });
97
95
 
98
96
  if (result.status !== 0) {
99
97
  console.error('\n✗ npm install -g failed.');
100
98
  console.error(' Try running the command with sudo, or set npm prefix to a writable dir.');
99
+ console.error(` Or manually: npm install -g ${installSpec}`);
101
100
  process.exit(result.status || 1);
102
101
  }
103
102
 
@@ -112,7 +111,7 @@ module.exports = function registerUpdate(program) {
112
111
  return;
113
112
  }
114
113
  if (updates.length === 0) {
115
- console.log(' (no skill installs found — run `bitpub skills install` to set them up)');
114
+ console.log(' (no skill installs found — run `bitpub setup skill install` to set them up)');
116
115
  return;
117
116
  }
118
117
  for (const u of updates) {
@@ -127,29 +126,3 @@ module.exports = function registerUpdate(program) {
127
126
  }
128
127
  });
129
128
  };
130
-
131
- function cleanup(tmpDir) {
132
- try {
133
- fs.rmSync(tmpDir, { recursive: true, force: true });
134
- } catch {
135
- // best-effort
136
- }
137
- }
138
-
139
- /**
140
- * Peek at `package/package.json` inside an npm tarball using the system
141
- * `tar`. Both BSD tar (macOS default) and GNU tar (Linux) support
142
- * `-xzOf <file> <member>` to extract a single entry to stdout. Returns
143
- * null on any error; callers treat that as "version unknown" and proceed.
144
- */
145
- function readVersionFromTarball(tarballPath) {
146
- const out = spawnSync('tar', ['-xzOf', tarballPath, 'package/package.json'], {
147
- encoding: 'utf-8',
148
- });
149
- if (out.status !== 0 || !out.stdout) return null;
150
- try {
151
- return JSON.parse(out.stdout).version || null;
152
- } catch {
153
- return null;
154
- }
155
- }