rainbo 0.1.13 → 0.2.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 CHANGED
@@ -14,16 +14,55 @@ Those platform packages are published under the `@singdata` scope.
14
14
 
15
15
  ## Install
16
16
 
17
+ First-time install:
18
+
17
19
  ```bash
18
20
  npm install -g rainbo
19
21
  rainbo version
20
22
  ```
21
23
 
24
+ The npm package automatically attempts to sync the official Rainbo skills after
25
+ install. If the postinstall sync cannot reach GitLab or `npx skills`, it does
26
+ not fail the npm install; run the same sync manually:
27
+
28
+ ```bash
29
+ rainbo update --force
30
+ ```
31
+
32
+ Set `RAINBO_NPM_NO_SKILLS_SYNC=1` to skip the automatic postinstall sync in
33
+ scripted environments. If GitLab is unavailable, use the offline package from
34
+ 数据校验宝典:
35
+
36
+ ```bash
37
+ rainbo update --skills-package /path/to/rainbo-skills.zip
38
+ ```
39
+
40
+ Maintainers can regenerate the offline package from the repository root with:
41
+
42
+ ```bash
43
+ cd packages/rainbo
44
+ npm run pack:skills
45
+ ```
46
+
47
+ This writes `../../skills.zip`, a standard `npx skills` source archive that
48
+ contains `skills/index.json` plus all official Rainbo skill directories.
49
+
50
+ If `rainbo` is already installed, prefer the built-in upgrade flow instead of
51
+ running bare `npm install -g rainbo`:
52
+
53
+ ```bash
54
+ rainbo update
55
+ ```
56
+
57
+ `rainbo update` upgrades the npm package and syncs official Rainbo skills in
58
+ one step, which avoids `_notice.skills` drift.
59
+
22
60
  ## Development
23
61
 
24
62
  ```bash
25
63
  node packaging/npm/run.js version
26
64
  node packaging/npm/run.js help
65
+ npm run check:npm
27
66
  npm run check:skills
28
67
  npm run build:npm:local
29
68
  ```
@@ -55,6 +94,7 @@ Errors are written to stderr:
55
94
  rainbo update --check
56
95
  rainbo update
57
96
  rainbo update --force
97
+ rainbo update --skills-only
58
98
  rainbo update --skills-package /path/to/rainbo-skills.zip
59
99
  ```
60
100
 
@@ -64,12 +104,16 @@ and `_notice.skills` when locally synced skills are out of sync with the
64
104
  running binary. The update cache refreshes at most every 2 hours. Both notices
65
105
  recommend `rainbo update`.
66
106
 
107
+ `update --skills-only` syncs Rainbo skills without checking npm for newer
108
+ versions or attempting a self-update. It is intended for npm postinstall and
109
+ other bootstrap flows that only need skill synchronization.
110
+
67
111
  `update` detects npm installations, runs `npm install -g rainbo@<latest>`
68
112
  when auto-update is available, verifies the new binary, and syncs repository
69
113
  skills with:
70
114
 
71
115
  ```bash
72
- npx skills add git@gitlab.clickzetta-inc.com:ee/rainbo.git -y -g
116
+ npx skills add git@gitlab.clickzetta-inc.com:ee/rainbo.git -y -g --agent '*'
73
117
  ```
74
118
 
75
119
  Skill sync records detailed state in `skills-state.json` and updates installed
@@ -79,7 +123,10 @@ available, it falls back to a full install.
79
123
  When users cannot access the GitLab skills repository, they can use the offline
80
124
  skills package from 数据校验宝典 and run `rainbo update --skills-package
81
125
  /path/to/rainbo-skills.zip`. The CLI will update Rainbo as usual and sync skills
82
- from the local package path instead of the GitLab source.
126
+ from the local package path instead of the GitLab source. The offline package is
127
+ installed through the same `npx skills` protocol after Rainbo extracts the zip,
128
+ and `skills-state.json` records the package path for future `_notice.skills`
129
+ version drift checks.
83
130
 
84
131
  If automatic update is unavailable, the JSON action is `manual_required` and
85
132
  the response includes release and changelog URLs.
@@ -92,8 +139,8 @@ rainbo auth status
92
139
  rainbo auth logout
93
140
  ```
94
141
 
95
- Generate the connection URL from the logged-in Rainbo web UI user menu. `auth
96
- connect` exchanges the one-time connection code for a revocable CLI bearer token
142
+ Generate the Rainbo connection URL from the logged-in Rainbo web UI user menu. `auth
143
+ connect` exchanges the one-time connection code for a revocable bearer token
97
144
  and stores it under `~/.config/rainbo/auth.json` on Unix-like systems or
98
145
  `%APPDATA%\rainbo\auth.json` on Windows. Unix-like systems use `0600`
99
146
  permissions for this file.
@@ -102,10 +149,12 @@ permissions for this file.
102
149
 
103
150
  Authenticated API commands reuse the session created by `rainbo auth connect`.
104
151
  Complex request bodies can be passed with `--data-json`, `--data-file`, or
105
- `--data @payload.json`.
152
+ `--data @payload.json`. Add `--dry-run` to print the request method, path,
153
+ query, and body without reading auth state or calling Rainbo APIs.
106
154
 
107
155
  ```bash
108
156
  rainbo data-sync cmt-jobs --data-file cmt-jobs.json
157
+ rainbo data-sync cmt-jobs --data-file cmt-jobs.json --dry-run
109
158
  rainbo data-verify lineage-verify-table --data-file verify-table.json
110
159
  rainbo toolbox sql-debug --datasource-id 1 --sql "select 1"
111
160
  rainbo toolbox lineage-spark --data-file lineage-spark.json
@@ -145,8 +194,10 @@ npm run publish:npm:local
145
194
  ```
146
195
 
147
196
  The publish script refuses to continue if `package.json` and `rust/Cargo.toml`
148
- versions differ. After building the current-platform binary, it also runs the
149
- bundled binary and verifies `rainbo version` matches `package.json`.
197
+ versions differ. It also runs `npm run check:npm` to verify npm metadata,
198
+ generated meta-package contents, and platform optional dependencies before
199
+ publishing. After building the current-platform binary, it runs the bundled
200
+ binary and verifies `rainbo version` matches `package.json`.
150
201
  The publish script is cross-platform and can be run from macOS shells,
151
202
  Windows PowerShell, or Windows CMD.
152
203
 
@@ -167,7 +218,7 @@ To build multiple platforms from a machine with the required Rust
167
218
  targets/toolchains installed, set:
168
219
 
169
220
  ```bash
170
- RAINBO_NPM_BUILD_TARGETS=darwin-arm64,darwin-x64,win32-x64,win32-arm64 npm run publish:npm:local
221
+ RAINBO_NPM_BUILD_TARGETS=linux-x64,linux-arm64,darwin-arm64,darwin-x64,win32-x64,win32-arm64 npm run publish:npm:local
171
222
  ```
172
223
 
173
224
  The package source lives under the Rainbo GitLab repository as
@@ -181,18 +232,27 @@ top-level `rainbo` meta package that depends on those platform packages.
181
232
  Repository skills live in `skills/`. They can be installed from the repository:
182
233
 
183
234
  ```bash
184
- npx skills add git@gitlab.clickzetta-inc.com:ee/rainbo.git -y -g
235
+ npx skills add git@gitlab.clickzetta-inc.com:ee/rainbo.git -y -g --agent '*'
185
236
  ```
186
237
 
187
238
  `git@gitlab.clickzetta-inc.com:ee/rainbo.git` is the skills repository
188
239
  source used by `rainbo update`. The old aggregate `rainbo` skill has
189
- been removed; current Rainbo skills use focused names such as `rainbo-auth`.
240
+ been removed; current Rainbo skills use focused names such as
241
+ `rainbo-shared`, `rainbo-auth`, `rainbo-data-sync`, `rainbo-data-verify`,
242
+ `rainbo-studio`, `rainbo-lineage`, and `rainbo-toolbox`.
243
+
244
+ The repository root `skills/index.json` is the official skill list consumed by
245
+ the standard `npx skills` installer. Keep it in sync with `skills/*/SKILL.md`
246
+ and run `npm run check:skills` before publishing. Do not add agent-specific
247
+ install paths such as Claude or Codex directories to the Rainbo CLI; the
248
+ installer owns host compatibility.
190
249
 
191
250
  New Rainbo skills should follow the style in the repository-level
192
- `skill-template/`: the top-level
193
- `SKILL.md` acts as a routing and safety rulebook, while detailed command
194
- families live in `references/*.md`. Authenticated workflow skills should point
195
- to `rainbo-auth` first instead of duplicating session rules.
251
+ `skill-template/`: the top-level `SKILL.md` acts as a routing and safety
252
+ rulebook, while detailed command families live in `references/*.md`.
253
+ Business workflow skills should point to `rainbo-shared` first and then
254
+ `rainbo-auth` when they call authenticated APIs instead of duplicating shared
255
+ output, risk, dry-run, session, or secret-handling rules.
196
256
 
197
257
  ## Project layout
198
258
 
package/package.json CHANGED
@@ -1,7 +1,24 @@
1
1
  {
2
2
  "name": "rainbo",
3
- "version": "0.1.13",
3
+ "version": "0.2.1",
4
4
  "description": "Rainbo command line tools for data migration workflows",
5
+ "keywords": [
6
+ "rainbo",
7
+ "cli",
8
+ "data-migration",
9
+ "data-validation",
10
+ "lineage",
11
+ "ai-agent"
12
+ ],
13
+ "homepage": "https://gitlab.clickzetta-inc.com/ee/rainbo#readme",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+ssh://git@gitlab.clickzetta-inc.com/ee/rainbo.git",
17
+ "directory": "packages/rainbo"
18
+ },
19
+ "bugs": {
20
+ "url": "https://gitlab.clickzetta-inc.com/ee/rainbo/-/issues"
21
+ },
5
22
  "bin": {
6
23
  "rainbo": "packaging/npm/run.js"
7
24
  },
@@ -9,14 +26,20 @@
9
26
  "node": ">=16"
10
27
  },
11
28
  "optionalDependencies": {
12
- "@singdata/rainbo-cli-darwin-x64": "0.1.13",
13
- "@singdata/rainbo-cli-darwin-arm64": "0.1.13",
14
- "@singdata/rainbo-cli-win32-x64": "0.1.13",
15
- "@singdata/rainbo-cli-win32-arm64": "0.1.13"
29
+ "@singdata/rainbo-cli-linux-x64": "0.2.1",
30
+ "@singdata/rainbo-cli-linux-arm64": "0.2.1",
31
+ "@singdata/rainbo-cli-darwin-x64": "0.2.1",
32
+ "@singdata/rainbo-cli-darwin-arm64": "0.2.1",
33
+ "@singdata/rainbo-cli-win32-x64": "0.2.1",
34
+ "@singdata/rainbo-cli-win32-arm64": "0.2.1"
16
35
  },
17
36
  "license": "MIT",
37
+ "scripts": {
38
+ "postinstall": "node packaging/npm/postinstall.js"
39
+ },
18
40
  "files": [
19
41
  "packaging/npm/platform.js",
42
+ "packaging/npm/postinstall.js",
20
43
  "packaging/npm/run.js",
21
44
  "README.md",
22
45
  "LICENSE"
@@ -1,4 +1,20 @@
1
1
  const PLATFORM_PACKAGES = {
2
+ "linux-x64": {
3
+ packageName: "@singdata/rainbo-cli-linux-x64",
4
+ target: "x86_64-unknown-linux-gnu",
5
+ binary: "rainbo",
6
+ os: "linux",
7
+ cpu: "x64",
8
+ archiveExt: ".tar.xz",
9
+ },
10
+ "linux-arm64": {
11
+ packageName: "@singdata/rainbo-cli-linux-arm64",
12
+ target: "aarch64-unknown-linux-gnu",
13
+ binary: "rainbo",
14
+ os: "linux",
15
+ cpu: "arm64",
16
+ archiveExt: ".tar.xz",
17
+ },
2
18
  "darwin-x64": {
3
19
  packageName: "@singdata/rainbo-cli-darwin-x64",
4
20
  target: "x86_64-apple-darwin",
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require("child_process");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+
7
+ const isTruthy = (value) => value && value !== "0" && value.toLowerCase() !== "false";
8
+
9
+ const sourceManifest = path.join(__dirname, "..", "..", "rust", "Cargo.toml");
10
+ const launcher = path.join(__dirname, "run.js");
11
+
12
+ if (isTruthy(process.env.RAINBO_NPM_NO_INSTALL_HINT) || isTruthy(process.env.RAINBO_NPM_NO_SKILLS_SYNC)) {
13
+ process.exit(0);
14
+ }
15
+
16
+ function writeHint(reason) {
17
+ const reasonLine = reason ? [`Rainbo skills were not synced automatically: ${reason}`] : [];
18
+ const lines = [
19
+ "",
20
+ ...reasonLine,
21
+ "To sync the official Rainbo skills, run:",
22
+ " rainbo update --force",
23
+ "If GitLab is unavailable, use an offline skills package:",
24
+ " rainbo update --skills-package <path-to-rainbo-skills.zip>",
25
+ "Set RAINBO_NPM_NO_SKILLS_SYNC=1 to skip automatic postinstall sync.",
26
+ "",
27
+ ];
28
+ process.stderr.write(`${lines.join("\n")}\n`);
29
+ }
30
+
31
+ if (fs.existsSync(sourceManifest)) {
32
+ writeHint("source checkout detected");
33
+ process.exit(0);
34
+ }
35
+
36
+ if (!fs.existsSync(launcher)) {
37
+ writeHint("rainbo npm launcher is missing");
38
+ process.exit(0);
39
+ }
40
+
41
+ process.stderr.write("\nrainbo installed. Syncing official Rainbo skills...\n");
42
+ const child = spawn(
43
+ process.execPath,
44
+ [launcher, "update", "--skills-only", "--force", "--format", "json", "--progress", "pretty"],
45
+ {
46
+ stdio: ["ignore", "pipe", "pipe"],
47
+ encoding: "utf8",
48
+ env: {
49
+ ...process.env,
50
+ RAINBO_NPM_POSTINSTALL: "1",
51
+ RAINBO_CLI_NO_UPDATE_NOTIFIER: "1",
52
+ RAINBO_CLI_NO_SKILLS_NOTIFIER: "1",
53
+ },
54
+ },
55
+ );
56
+
57
+ let stdout = "";
58
+ let stderr = "";
59
+
60
+ child.stdout.setEncoding("utf8");
61
+ child.stdout.on("data", (chunk) => {
62
+ stdout += chunk;
63
+ });
64
+
65
+ child.stderr.setEncoding("utf8");
66
+ child.stderr.on("data", (chunk) => {
67
+ stderr += chunk;
68
+ process.stderr.write(chunk);
69
+ });
70
+
71
+ child.on("error", (err) => {
72
+ writeHint(err.message);
73
+ process.exit(0);
74
+ });
75
+
76
+ child.on("close", (status) => {
77
+ if (status !== 0) {
78
+ writeHint(`sync command exited with status ${status}`);
79
+ process.exit(0);
80
+ }
81
+
82
+ let output;
83
+ try {
84
+ output = JSON.parse(stdout.trim());
85
+ } catch (err) {
86
+ const trimmedStdout = stdout.trim();
87
+ const trimmedStderr = stderr.trim();
88
+ if (trimmedStdout) process.stderr.write(`${trimmedStdout}\n`);
89
+ if (trimmedStderr) process.stderr.write(`${trimmedStderr}\n`);
90
+ writeHint(`sync command returned non-JSON output: ${err.message}`);
91
+ process.exit(0);
92
+ }
93
+
94
+ const action = output && output.data && output.data.skills_action;
95
+ if (!action) {
96
+ writeHint("sync command did not report skills_action");
97
+ process.exit(0);
98
+ }
99
+ if (action === "failed" || action === "fallback_failed") {
100
+ const warning = output.data.skills_warning || output.data.skills_detail || action;
101
+ writeHint(warning);
102
+ process.exit(0);
103
+ }
104
+
105
+ const lines = [
106
+ "",
107
+ "Rainbo skills synced.",
108
+ "",
109
+ ];
110
+ process.stderr.write(`${lines.join("\n")}\n`);
111
+ });
@@ -9,6 +9,19 @@ const isWindows = process.platform === "win32";
9
9
  const repoRoot = path.join(__dirname, "..", "..");
10
10
  const sourceManifest = path.join(repoRoot, "rust", "Cargo.toml");
11
11
 
12
+ function writeError(type, subtype, message, hint) {
13
+ const error = {
14
+ ok: false,
15
+ error: {
16
+ type,
17
+ subtype,
18
+ message,
19
+ },
20
+ };
21
+ if (hint) error.error.hint = hint;
22
+ process.stderr.write(`${JSON.stringify(error)}\n`);
23
+ }
24
+
12
25
  function resolveBundledLauncher() {
13
26
  const platformPackage = currentPlatformPackage();
14
27
  if (!platformPackage) return null;
@@ -37,9 +50,12 @@ function installIfMissing() {
37
50
  const packageHint = platformPackage
38
51
  ? `${platformPackage.packageName} (${currentPlatformKey()})`
39
52
  : `unsupported platform ${currentPlatformKey()}`;
40
- console.error(`rainbo binary package is missing for ${currentPlatformKey()}.`);
41
- console.error(`Expected installed npm binary package: ${packageHint}`);
42
- console.error("Reinstall the rainbo npm package so the matching optional dependency is installed.");
53
+ writeError(
54
+ "internal",
55
+ platformPackage ? "binary_package_missing" : "unsupported_platform",
56
+ `rainbo binary package is missing for ${currentPlatformKey()}`,
57
+ `expected npm binary package: ${packageHint}; reinstall rainbo so npm installs the matching optional dependency`,
58
+ );
43
59
  process.exit(1);
44
60
  }
45
61
 
@@ -55,11 +71,24 @@ const command = useSource ? "cargo" : resolveLauncher();
55
71
  const args = useSource
56
72
  ? ["run", "--quiet", "--manifest-path", sourceManifest, "--", ...process.argv.slice(2)]
57
73
  : process.argv.slice(2);
58
- if (!command) process.exit(1);
74
+ if (!command) {
75
+ writeError(
76
+ "internal",
77
+ "launcher_missing",
78
+ "rainbo launcher could not resolve a source or bundled binary",
79
+ "reinstall the rainbo npm package",
80
+ );
81
+ process.exit(1);
82
+ }
59
83
  const result = spawnSync(command, args, { stdio: "inherit", shell: isWindows });
60
84
 
61
85
  if (result.error) {
62
- console.error(result.error.message);
86
+ writeError(
87
+ "internal",
88
+ "launcher_spawn_failed",
89
+ result.error.message,
90
+ `failed to execute ${command}`,
91
+ );
63
92
  process.exit(1);
64
93
  }
65
94
  process.exit(result.status || 0);