@renxqoo/renx-code-linux-x64 0.0.61
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 +108 -0
- package/bin/renx +0 -0
- package/bin/rg +79 -0
- package/package.json +27 -0
- package/scripts/install-ripgrep.mjs +195 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @renxqoo/renx-code
|
|
2
|
+
|
|
3
|
+
Renx Code terminal AI coding assistant for the command line.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @renxqoo/renx-code
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
renx
|
|
15
|
+
renx --help
|
|
16
|
+
renx --version
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Supported Platforms
|
|
20
|
+
|
|
21
|
+
- macOS arm64
|
|
22
|
+
- macOS x64
|
|
23
|
+
- Linux arm64
|
|
24
|
+
- Linux x64
|
|
25
|
+
- Windows x64
|
|
26
|
+
|
|
27
|
+
Windows arm64 is not bundled yet because the current Bun compiler target matrix does not provide a native `bun-windows-arm64` executable target.
|
|
28
|
+
|
|
29
|
+
## Runtime Cache
|
|
30
|
+
|
|
31
|
+
The launcher copies installed native binaries into a user-scoped cache before execution. This keeps active Windows processes from locking files inside `node_modules` during upgrades.
|
|
32
|
+
|
|
33
|
+
- Default cache path on Windows: `%LOCALAPPDATA%\Renx\binary-cache`
|
|
34
|
+
- Override cache path: `RENX_BINARY_CACHE_DIR`
|
|
35
|
+
- Disable the cache for debugging: `RENX_DISABLE_BINARY_CACHE=1`
|
|
36
|
+
|
|
37
|
+
## Release
|
|
38
|
+
|
|
39
|
+
### GitHub Actions workflow
|
|
40
|
+
|
|
41
|
+
Use the manual GitHub Actions workflow at `.github/workflows/cli-release.yml`.
|
|
42
|
+
|
|
43
|
+
- Workflow name: `CLI Release`
|
|
44
|
+
- Trigger: `workflow_dispatch`
|
|
45
|
+
- Inputs:
|
|
46
|
+
- `npm_tag`: optional npm dist-tag. Leave empty to publish with the default npm tag.
|
|
47
|
+
- `otp`: optional one-time password for npm publish when your npm setup requires it.
|
|
48
|
+
|
|
49
|
+
The workflow publishes platform packages first, then publishes the main package only after all platform publishes succeed.
|
|
50
|
+
|
|
51
|
+
### Required secrets and permissions
|
|
52
|
+
|
|
53
|
+
Configure these before running the workflow:
|
|
54
|
+
|
|
55
|
+
- `NPM_TOKEN`: required. The workflow exposes it as `NODE_AUTH_TOKEN` for npm publish.
|
|
56
|
+
- npm package publish permission for `@renxqoo/renx-code` and the platform packages under the same scope.
|
|
57
|
+
- If your npm publish flow requires OTP, provide it through the `otp` workflow input when triggering the run.
|
|
58
|
+
|
|
59
|
+
### First release recommendation
|
|
60
|
+
|
|
61
|
+
For the first public release of a new version, prefer this sequence:
|
|
62
|
+
|
|
63
|
+
1. Run the workflow with `npm_tag=next`.
|
|
64
|
+
2. Verify install and execution from the published `next` tag on the platforms you care about.
|
|
65
|
+
3. Run the workflow again with an empty `npm_tag` value to publish to the default tag, or set `npm_tag=latest` explicitly if you want to be explicit.
|
|
66
|
+
|
|
67
|
+
This reduces the chance of breaking users on `latest` before the new platform packages are validated.
|
|
68
|
+
|
|
69
|
+
### Dist-tag usage
|
|
70
|
+
|
|
71
|
+
- Stable release: leave `npm_tag` empty, or set `npm_tag=latest`.
|
|
72
|
+
- Preview / canary release: set `npm_tag=next`.
|
|
73
|
+
|
|
74
|
+
Example installs:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install -g @renxqoo/renx-code@latest
|
|
78
|
+
npm install -g @renxqoo/renx-code@next
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Local verification commands
|
|
82
|
+
|
|
83
|
+
Before triggering the publish workflow, these local commands are useful:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --single --dry-run
|
|
87
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --target darwin-arm64 --dry-run
|
|
88
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --target darwin-x64 --dry-run
|
|
89
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --target linux-arm64 --dry-run
|
|
90
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --target linux-x64 --dry-run
|
|
91
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --target win32-x64 --dry-run
|
|
92
|
+
pnpm --filter @renxqoo/renx-code release:pack -- --all --dry-run
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For local npm authentication checks, run:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pnpm --filter @renxqoo/renx-code release:preflight
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Local manual publish
|
|
102
|
+
|
|
103
|
+
If you need to publish outside GitHub Actions, use the same unified script entrypoints:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pnpm --filter @renxqoo/renx-code release:publish -- --target darwin-arm64 --tag next
|
|
107
|
+
pnpm --filter @renxqoo/renx-code release:publish -- --single --tag next
|
|
108
|
+
```
|
package/bin/renx
ADDED
|
Binary file
|
package/bin/rg
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env dotslash
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
"name": "rg",
|
|
5
|
+
"platforms": {
|
|
6
|
+
"macos-aarch64": {
|
|
7
|
+
"size": 1777930,
|
|
8
|
+
"hash": "sha256",
|
|
9
|
+
"digest": "378e973289176ca0c6054054ee7f631a065874a352bf43f0fa60ef079b6ba715",
|
|
10
|
+
"format": "tar.gz",
|
|
11
|
+
"path": "ripgrep-15.1.0-aarch64-apple-darwin/rg",
|
|
12
|
+
"providers": [
|
|
13
|
+
{
|
|
14
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-aarch64-apple-darwin.tar.gz"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"linux-aarch64": {
|
|
19
|
+
"size": 1869959,
|
|
20
|
+
"hash": "sha256",
|
|
21
|
+
"digest": "2b661c6ef508e902f388e9098d9c4c5aca72c87b55922d94abdba830b4dc885e",
|
|
22
|
+
"format": "tar.gz",
|
|
23
|
+
"path": "ripgrep-15.1.0-aarch64-unknown-linux-gnu/rg",
|
|
24
|
+
"providers": [
|
|
25
|
+
{
|
|
26
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-aarch64-unknown-linux-gnu.tar.gz"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"macos-x86_64": {
|
|
31
|
+
"size": 1894127,
|
|
32
|
+
"hash": "sha256",
|
|
33
|
+
"digest": "64811cb24e77cac3057d6c40b63ac9becf9082eedd54ca411b475b755d334882",
|
|
34
|
+
"format": "tar.gz",
|
|
35
|
+
"path": "ripgrep-15.1.0-x86_64-apple-darwin/rg",
|
|
36
|
+
"providers": [
|
|
37
|
+
{
|
|
38
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-apple-darwin.tar.gz"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"linux-x86_64": {
|
|
43
|
+
"size": 2263077,
|
|
44
|
+
"hash": "sha256",
|
|
45
|
+
"digest": "1c9297be4a084eea7ecaedf93eb03d058d6faae29bbc57ecdaf5063921491599",
|
|
46
|
+
"format": "tar.gz",
|
|
47
|
+
"path": "ripgrep-15.1.0-x86_64-unknown-linux-musl/rg",
|
|
48
|
+
"providers": [
|
|
49
|
+
{
|
|
50
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-unknown-linux-musl.tar.gz"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"windows-x86_64": {
|
|
55
|
+
"size": 1810687,
|
|
56
|
+
"hash": "sha256",
|
|
57
|
+
"digest": "124510b94b6baa3380d051fdf4650eaa80a302c876d611e9dba0b2e18d87493a",
|
|
58
|
+
"format": "zip",
|
|
59
|
+
"path": "ripgrep-15.1.0-x86_64-pc-windows-msvc/rg.exe",
|
|
60
|
+
"providers": [
|
|
61
|
+
{
|
|
62
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-pc-windows-msvc.zip"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"windows-aarch64": {
|
|
67
|
+
"size": 1675460,
|
|
68
|
+
"hash": "sha256",
|
|
69
|
+
"digest": "00d931fb5237c9696ca49308818edb76d8eb6fc132761cb2a1bd616b2df02f8e",
|
|
70
|
+
"format": "zip",
|
|
71
|
+
"path": "ripgrep-15.1.0-aarch64-pc-windows-msvc/rg.exe",
|
|
72
|
+
"providers": [
|
|
73
|
+
{
|
|
74
|
+
"url": "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-aarch64-pc-windows-msvc.zip"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@renxqoo/renx-code-linux-x64",
|
|
3
|
+
"version": "0.0.61",
|
|
4
|
+
"description": "Renx Code terminal AI coding assistant (linux-x64)",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"private": false,
|
|
7
|
+
"os": [
|
|
8
|
+
"linux"
|
|
9
|
+
],
|
|
10
|
+
"cpu": [
|
|
11
|
+
"x64"
|
|
12
|
+
],
|
|
13
|
+
"bin": {
|
|
14
|
+
"renx": "./bin/renx"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin",
|
|
18
|
+
"scripts",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"postinstall": "node ./scripts/install-ripgrep.mjs"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { createWriteStream } from 'node:fs';
|
|
6
|
+
import fs from 'node:fs/promises';
|
|
7
|
+
import https from 'node:https';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
15
|
+
const manifestPath = path.join(packageRoot, 'bin', 'rg');
|
|
16
|
+
|
|
17
|
+
const TARGETS = {
|
|
18
|
+
'darwin:arm64': { target: 'aarch64-apple-darwin', platformKey: 'macos-aarch64' },
|
|
19
|
+
'darwin:x64': { target: 'x86_64-apple-darwin', platformKey: 'macos-x86_64' },
|
|
20
|
+
'linux:arm64': { target: 'aarch64-unknown-linux-musl', platformKey: 'linux-aarch64' },
|
|
21
|
+
'linux:x64': { target: 'x86_64-unknown-linux-musl', platformKey: 'linux-x86_64' },
|
|
22
|
+
'win32:arm64': { target: 'aarch64-pc-windows-msvc', platformKey: 'windows-aarch64' },
|
|
23
|
+
'win32:x64': { target: 'x86_64-pc-windows-msvc', platformKey: 'windows-x86_64' },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
if (process.env.RENX_SKIP_RIPGREP_INSTALL === '1') {
|
|
28
|
+
console.log('[renx] skipping bundled ripgrep install (RENX_SKIP_RIPGREP_INSTALL=1)');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const targetInfo = TARGETS[`${process.platform}:${process.arch}`];
|
|
33
|
+
if (!targetInfo) {
|
|
34
|
+
console.warn(
|
|
35
|
+
`[renx] no bundled ripgrep target for ${process.platform}/${process.arch}; falling back to system rg if available`
|
|
36
|
+
);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const manifest = await loadManifest(manifestPath);
|
|
41
|
+
const platformInfo = manifest.platforms?.[targetInfo.platformKey];
|
|
42
|
+
if (!platformInfo) {
|
|
43
|
+
throw new Error(`ripgrep manifest is missing platform ${targetInfo.platformKey}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const binaryName = process.platform === 'win32' ? 'rg.exe' : 'rg';
|
|
47
|
+
const installDir = path.join(packageRoot, 'vendor', 'ripgrep', targetInfo.target, 'path');
|
|
48
|
+
const binaryPath = path.join(installDir, binaryName);
|
|
49
|
+
if (await fileExists(binaryPath)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await fs.mkdir(installDir, { recursive: true });
|
|
54
|
+
|
|
55
|
+
const provider = platformInfo.providers?.[0];
|
|
56
|
+
const url = provider?.url;
|
|
57
|
+
if (!url) {
|
|
58
|
+
throw new Error(`ripgrep manifest has no provider URL for ${targetInfo.platformKey}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'renx-ripgrep-'));
|
|
62
|
+
try {
|
|
63
|
+
const archivePath = path.join(tempDir, path.basename(new URL(url).pathname));
|
|
64
|
+
console.log(`[renx] downloading ripgrep for ${targetInfo.target}`);
|
|
65
|
+
await downloadFile(url, archivePath);
|
|
66
|
+
await verifyArchive(archivePath, platformInfo);
|
|
67
|
+
|
|
68
|
+
const extractDir = path.join(tempDir, 'extract');
|
|
69
|
+
await fs.mkdir(extractDir, { recursive: true });
|
|
70
|
+
await extractArchive(archivePath, platformInfo.format, extractDir);
|
|
71
|
+
|
|
72
|
+
const memberPath = path.join(extractDir, platformInfo.path);
|
|
73
|
+
await fs.copyFile(memberPath, binaryPath);
|
|
74
|
+
if (process.platform !== 'win32') {
|
|
75
|
+
await fs.chmod(binaryPath, 0o755);
|
|
76
|
+
}
|
|
77
|
+
console.log(`[renx] installed bundled ripgrep to ${binaryPath}`);
|
|
78
|
+
} finally {
|
|
79
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function loadManifest(filePath) {
|
|
84
|
+
const raw = await fs.readFile(filePath, 'utf8');
|
|
85
|
+
const json = raw.startsWith('#!') ? raw.split('\n').slice(1).join('\n') : raw;
|
|
86
|
+
return JSON.parse(json);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function fileExists(filePath) {
|
|
90
|
+
try {
|
|
91
|
+
await fs.access(filePath);
|
|
92
|
+
return true;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function downloadFile(url, destination) {
|
|
99
|
+
await new Promise((resolve, reject) => {
|
|
100
|
+
const request = https.get(url, (response) => {
|
|
101
|
+
if (
|
|
102
|
+
response.statusCode &&
|
|
103
|
+
response.statusCode >= 300 &&
|
|
104
|
+
response.statusCode < 400 &&
|
|
105
|
+
response.headers.location
|
|
106
|
+
) {
|
|
107
|
+
response.resume();
|
|
108
|
+
downloadFile(response.headers.location, destination).then(resolve, reject);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (response.statusCode !== 200) {
|
|
113
|
+
reject(new Error(`download failed with status ${response.statusCode ?? 'unknown'}`));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const output = createWriteStream(destination);
|
|
118
|
+
response.pipe(output);
|
|
119
|
+
output.on('finish', () => {
|
|
120
|
+
output.close();
|
|
121
|
+
resolve(undefined);
|
|
122
|
+
});
|
|
123
|
+
output.on('error', reject);
|
|
124
|
+
});
|
|
125
|
+
request.on('error', reject);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function verifyArchive(archivePath, platformInfo) {
|
|
130
|
+
const stats = await fs.stat(archivePath);
|
|
131
|
+
if (typeof platformInfo.size === 'number' && stats.size !== platformInfo.size) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`unexpected ripgrep archive size: expected ${platformInfo.size}, got ${stats.size}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (platformInfo.hash === 'sha256' && platformInfo.digest) {
|
|
138
|
+
const file = await fs.readFile(archivePath);
|
|
139
|
+
const digest = createHash('sha256').update(file).digest('hex');
|
|
140
|
+
if (digest !== platformInfo.digest) {
|
|
141
|
+
throw new Error('ripgrep archive sha256 digest mismatch');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function extractArchive(archivePath, format, destination) {
|
|
147
|
+
if (format === 'zip') {
|
|
148
|
+
const command = resolvePowerShellExecutable();
|
|
149
|
+
const result = spawnSync(
|
|
150
|
+
command,
|
|
151
|
+
[
|
|
152
|
+
'-NoProfile',
|
|
153
|
+
'-Command',
|
|
154
|
+
`Expand-Archive -LiteralPath '${escapePowerShell(archivePath)}' -DestinationPath '${escapePowerShell(destination)}' -Force`,
|
|
155
|
+
],
|
|
156
|
+
{
|
|
157
|
+
stdio: 'inherit',
|
|
158
|
+
windowsHide: true,
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
if (result.error || result.status !== 0) {
|
|
162
|
+
throw new Error('failed to extract ripgrep zip archive');
|
|
163
|
+
}
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (format === 'tar.gz') {
|
|
168
|
+
const result = spawnSync('tar', ['-xzf', archivePath, '-C', destination], {
|
|
169
|
+
stdio: 'inherit',
|
|
170
|
+
windowsHide: true,
|
|
171
|
+
});
|
|
172
|
+
if (result.error || result.status !== 0) {
|
|
173
|
+
throw new Error('failed to extract ripgrep tar.gz archive');
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
throw new Error(`unsupported ripgrep archive format: ${format}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function resolvePowerShellExecutable() {
|
|
182
|
+
return process.env.SystemRoot
|
|
183
|
+
? path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')
|
|
184
|
+
: 'powershell.exe';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function escapePowerShell(value) {
|
|
188
|
+
return value.replace(/'/g, "''");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
main().catch((error) => {
|
|
192
|
+
console.warn(
|
|
193
|
+
`[renx] bundled ripgrep install skipped: ${error instanceof Error ? error.message : String(error)}`
|
|
194
|
+
);
|
|
195
|
+
});
|