claude-code-reader 0.1.0-beta.4 → 1.0.0-rc.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/bin/ccr.js +100 -15
- package/package.json +9 -7
- package/scripts/postinstall.js +0 -135
package/bin/ccr.js
CHANGED
|
@@ -1,38 +1,123 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @file ccr.js - ClaudeCodeReader CLI 入口脚本
|
|
5
|
+
* @description 通过 `npm install -g claude-code-reader` 安装后,
|
|
6
|
+
* 用户可以在终端运行 `ccr` 命令来启动桌面应用。
|
|
7
|
+
*
|
|
8
|
+
* 此脚本采用平台专属包(optionalDependencies)架构:
|
|
9
|
+
* npm 在安装主包时会根据当前操作系统和 CPU 架构,自动安装对应的平台包
|
|
10
|
+
* (如 claude-code-reader-win32-x64),平台包中包含预编译的二进制文件。
|
|
11
|
+
* 本脚本通过 require.resolve() 定位已安装的平台包目录,
|
|
12
|
+
* 从中找到对应的可执行文件路径,然后以独立进程方式启动 GUI 应用程序。
|
|
13
|
+
*/
|
|
14
|
+
|
|
3
15
|
import { spawn } from 'child_process';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
16
|
import { dirname, join } from 'path';
|
|
6
17
|
import { existsSync } from 'fs';
|
|
18
|
+
import { createRequire } from 'module';
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
/*
|
|
21
|
+
* 创建 CommonJS 风格的 require 函数。
|
|
22
|
+
* 在 ES Module 中无法直接使用 require(),需要通过 createRequire() 创建一个
|
|
23
|
+
* 基于当前模块 URL 的 require 函数,用于调用 require.resolve() 定位平台包。
|
|
24
|
+
*/
|
|
25
|
+
const require = createRequire(import.meta.url);
|
|
10
26
|
|
|
11
|
-
|
|
27
|
+
/* ---------------------------------------------------------------------------
|
|
28
|
+
平台包映射表
|
|
29
|
+
键为 `${process.platform}-${process.arch}` 的组合,值为对应的 NPM 平台包名。
|
|
30
|
+
npm 安装主包时会根据平台包 package.json 中的 os/cpu 字段声明,
|
|
31
|
+
自动选择并安装与当前系统匹配的 optionalDependency。
|
|
32
|
+
--------------------------------------------------------------------------- */
|
|
33
|
+
const PLATFORM_PACKAGES = {
|
|
34
|
+
'win32-x64': 'claude-code-reader-win32-x64',
|
|
35
|
+
'darwin-arm64': 'claude-code-reader-darwin-arm64',
|
|
36
|
+
'darwin-x64': 'claude-code-reader-darwin-x64',
|
|
37
|
+
'linux-x64': 'claude-code-reader-linux-x64'
|
|
38
|
+
};
|
|
12
39
|
|
|
13
|
-
|
|
40
|
+
/* ---------------------------------------------------------------------------
|
|
41
|
+
二进制文件名映射表
|
|
42
|
+
每个平台包的 bin/ 目录下存放的可执行文件名称不同:
|
|
43
|
+
- Windows: 直接使用 .exe 可执行文件
|
|
44
|
+
- macOS: 使用 .app 应用束内部的实际可执行文件(Contents/MacOS/ 目录下)
|
|
45
|
+
- Linux: 使用 AppImage 格式的单文件可执行包
|
|
46
|
+
--------------------------------------------------------------------------- */
|
|
47
|
+
const BINARY_PATHS = {
|
|
48
|
+
'win32-x64': join('bin', 'ClaudeCodeReader.exe'),
|
|
49
|
+
'darwin-arm64': join('bin', 'ClaudeCodeReader.app', 'Contents', 'MacOS', 'ClaudeCodeReader'),
|
|
50
|
+
'darwin-x64': join('bin', 'ClaudeCodeReader.app', 'Contents', 'MacOS', 'ClaudeCodeReader'),
|
|
51
|
+
'linux-x64': join('bin', 'ClaudeCodeReader.AppImage')
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/* 检测当前运行的操作系统平台和 CPU 架构 */
|
|
55
|
+
const platformKey = `${process.platform}-${process.arch}`;
|
|
56
|
+
|
|
57
|
+
/* 检查当前平台是否在支持列表中 */
|
|
58
|
+
const packageName = PLATFORM_PACKAGES[platformKey];
|
|
59
|
+
if (!packageName) {
|
|
60
|
+
console.error(`Unsupported platform: ${process.platform} ${process.arch}`);
|
|
61
|
+
console.error('Supported platforms: win32-x64, darwin-arm64, darwin-x64, linux-x64');
|
|
62
|
+
console.error('Please download manually from: https://github.com/MoYeRanQianZhi/ClaudeCodeReader/releases');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
14
65
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
66
|
+
/*
|
|
67
|
+
* 通过 require.resolve() 定位已安装的平台包目录。
|
|
68
|
+
* require.resolve(`${packageName}/package.json`) 会返回平台包 package.json 的绝对路径,
|
|
69
|
+
* 对其取 dirname() 即可获得平台包的根目录,再拼接 bin/ 下的二进制文件相对路径。
|
|
70
|
+
*
|
|
71
|
+
* 如果平台包未安装(如网络问题导致 optionalDependency 安装失败),
|
|
72
|
+
* require.resolve() 会抛出 MODULE_NOT_FOUND 错误,在 catch 中给出友好提示。
|
|
73
|
+
*/
|
|
74
|
+
let binaryPath;
|
|
75
|
+
try {
|
|
76
|
+
const packageDir = dirname(require.resolve(`${packageName}/package.json`));
|
|
77
|
+
binaryPath = join(packageDir, BINARY_PATHS[platformKey]);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error(`Failed to locate platform package: ${packageName}`);
|
|
80
|
+
console.error('The platform-specific binary package may not have been installed correctly.');
|
|
81
|
+
console.error('');
|
|
82
|
+
console.error('Try reinstalling:');
|
|
83
|
+
console.error(' npm install -g claude-code-reader');
|
|
84
|
+
console.error('');
|
|
85
|
+
console.error('Or download manually from: https://github.com/MoYeRanQianZhi/ClaudeCodeReader/releases');
|
|
23
86
|
process.exit(1);
|
|
24
87
|
}
|
|
25
88
|
|
|
89
|
+
/*
|
|
90
|
+
* 检查二进制文件是否实际存在于平台包目录中。
|
|
91
|
+
* 虽然平台包已安装,但如果包内容不完整(如发布时遗漏文件),
|
|
92
|
+
* 二进制文件可能不存在,此时给出明确的错误提示。
|
|
93
|
+
*/
|
|
26
94
|
if (!existsSync(binaryPath)) {
|
|
27
|
-
console.error('Claude Code Reader binary not found.');
|
|
28
|
-
console.error(
|
|
95
|
+
console.error('Claude Code Reader binary not found in platform package.');
|
|
96
|
+
console.error(`Expected path: ${binaryPath}`);
|
|
97
|
+
console.error('');
|
|
98
|
+
console.error('Try reinstalling:');
|
|
99
|
+
console.error(' npm install -g claude-code-reader');
|
|
100
|
+
console.error('');
|
|
29
101
|
console.error('Or download manually from: https://github.com/MoYeRanQianZhi/ClaudeCodeReader/releases');
|
|
30
102
|
process.exit(1);
|
|
31
103
|
}
|
|
32
104
|
|
|
105
|
+
/*
|
|
106
|
+
* 使用 spawn 启动 GUI 应用程序:
|
|
107
|
+
* - process.argv.slice(2): 透传用户在 `ccr` 命令后附加的所有参数
|
|
108
|
+
* - detached: true — 让 GUI 应用作为独立进程运行,不与终端会话绑定,
|
|
109
|
+
* 关闭终端后应用仍可继续运行
|
|
110
|
+
* - stdio: 'ignore' — 不继承终端的标准输入/输出/错误流,
|
|
111
|
+
* 避免 GUI 应用的日志输出干扰终端
|
|
112
|
+
*/
|
|
33
113
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
34
114
|
detached: true,
|
|
35
115
|
stdio: 'ignore'
|
|
36
116
|
});
|
|
37
117
|
|
|
118
|
+
/*
|
|
119
|
+
* child.unref() — 从 Node.js 事件循环中解除对子进程的引用。
|
|
120
|
+
* 这使得 Node.js 主进程可以立即退出,无需等待 GUI 子进程结束。
|
|
121
|
+
* 配合 detached: true,实现"启动即退出"的 CLI 启动器行为。
|
|
122
|
+
*/
|
|
38
123
|
child.unref();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-reader",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A desktop application for viewing and managing Claude Code session records and settings",
|
|
6
6
|
"author": "墨叶染千枝",
|
|
@@ -25,12 +25,8 @@
|
|
|
25
25
|
"bin": {
|
|
26
26
|
"ccr": "bin/ccr.js"
|
|
27
27
|
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"postinstall": "node scripts/postinstall.js"
|
|
30
|
-
},
|
|
31
28
|
"files": [
|
|
32
|
-
"bin"
|
|
33
|
-
"scripts"
|
|
29
|
+
"bin"
|
|
34
30
|
],
|
|
35
31
|
"engines": {
|
|
36
32
|
"node": ">=16.0.0"
|
|
@@ -39,5 +35,11 @@
|
|
|
39
35
|
"win32",
|
|
40
36
|
"darwin",
|
|
41
37
|
"linux"
|
|
42
|
-
]
|
|
38
|
+
],
|
|
39
|
+
"optionalDependencies": {
|
|
40
|
+
"claude-code-reader-win32-x64": "1.0.0-rc.1",
|
|
41
|
+
"claude-code-reader-darwin-arm64": "1.0.0-rc.1",
|
|
42
|
+
"claude-code-reader-darwin-x64": "1.0.0-rc.1",
|
|
43
|
+
"claude-code-reader-linux-x64": "1.0.0-rc.1"
|
|
44
|
+
}
|
|
43
45
|
}
|
package/scripts/postinstall.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { createWriteStream, existsSync, mkdirSync, chmodSync, unlinkSync } from 'fs';
|
|
4
|
-
import { get } from 'https';
|
|
5
|
-
import { join, dirname } from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = dirname(__filename);
|
|
10
|
-
|
|
11
|
-
const VERSION = '0.1.0-beta.4';
|
|
12
|
-
const GITHUB_REPO = 'MoYeRanQianZhi/ClaudeCodeReader';
|
|
13
|
-
const BASE_URL = `https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}`;
|
|
14
|
-
|
|
15
|
-
const platform = process.platform;
|
|
16
|
-
const arch = process.arch;
|
|
17
|
-
|
|
18
|
-
function getDownloadInfo() {
|
|
19
|
-
if (platform === 'win32') {
|
|
20
|
-
return {
|
|
21
|
-
url: `${BASE_URL}/ClaudeCodeReader_${VERSION}_x64.exe`,
|
|
22
|
-
filename: 'ClaudeCodeReader.exe'
|
|
23
|
-
};
|
|
24
|
-
} else if (platform === 'darwin') {
|
|
25
|
-
const macArch = arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
|
|
26
|
-
return {
|
|
27
|
-
url: `${BASE_URL}/ClaudeCodeReader_${VERSION}_${macArch}.app.tar.gz`,
|
|
28
|
-
filename: `ClaudeCodeReader.app.tar.gz`,
|
|
29
|
-
extract: true
|
|
30
|
-
};
|
|
31
|
-
} else if (platform === 'linux') {
|
|
32
|
-
return {
|
|
33
|
-
url: `${BASE_URL}/ClaudeCodeReader_${VERSION}_amd64.AppImage`,
|
|
34
|
-
filename: 'ClaudeCodeReader.AppImage'
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function download(url, dest) {
|
|
41
|
-
return new Promise((resolve, reject) => {
|
|
42
|
-
const file = createWriteStream(dest);
|
|
43
|
-
|
|
44
|
-
const request = (url) => {
|
|
45
|
-
get(url, (response) => {
|
|
46
|
-
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
47
|
-
request(response.headers.location);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (response.statusCode !== 200) {
|
|
52
|
-
reject(new Error(`Download failed with status: ${response.statusCode}`));
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const totalSize = parseInt(response.headers['content-length'], 10);
|
|
57
|
-
let downloadedSize = 0;
|
|
58
|
-
|
|
59
|
-
response.on('data', (chunk) => {
|
|
60
|
-
downloadedSize += chunk.length;
|
|
61
|
-
if (totalSize) {
|
|
62
|
-
const percent = ((downloadedSize / totalSize) * 100).toFixed(1);
|
|
63
|
-
process.stdout.write(`\rDownloading... ${percent}%`);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
response.pipe(file);
|
|
68
|
-
|
|
69
|
-
file.on('finish', () => {
|
|
70
|
-
file.close();
|
|
71
|
-
console.log('\nDownload complete!');
|
|
72
|
-
resolve();
|
|
73
|
-
});
|
|
74
|
-
}).on('error', (err) => {
|
|
75
|
-
unlinkSync(dest);
|
|
76
|
-
reject(err);
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
request(url);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function main() {
|
|
85
|
-
const downloadInfo = getDownloadInfo();
|
|
86
|
-
|
|
87
|
-
if (!downloadInfo) {
|
|
88
|
-
console.error(`Unsupported platform: ${platform} ${arch}`);
|
|
89
|
-
console.error('Please download manually from: https://github.com/MoYeRanQianZhi/ClaudeCodeReader/releases');
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const binDir = join(__dirname, '..', 'bin');
|
|
94
|
-
|
|
95
|
-
if (!existsSync(binDir)) {
|
|
96
|
-
mkdirSync(binDir, { recursive: true });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const destPath = join(binDir, downloadInfo.filename);
|
|
100
|
-
|
|
101
|
-
// Check if already downloaded
|
|
102
|
-
if (existsSync(destPath) || (platform === 'darwin' && existsSync(join(binDir, 'ClaudeCodeReader.app')))) {
|
|
103
|
-
console.log('Claude Code Reader is already installed.');
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
console.log(`Downloading Claude Code Reader for ${platform} ${arch}...`);
|
|
108
|
-
console.log(`URL: ${downloadInfo.url}`);
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await download(downloadInfo.url, destPath);
|
|
112
|
-
|
|
113
|
-
// Extract tar.gz on macOS
|
|
114
|
-
if (downloadInfo.extract && platform === 'darwin') {
|
|
115
|
-
const { execSync } = await import('child_process');
|
|
116
|
-
console.log('Extracting...');
|
|
117
|
-
execSync(`tar -xzf "${destPath}" -C "${binDir}"`);
|
|
118
|
-
unlinkSync(destPath);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Make executable on Unix systems
|
|
122
|
-
if (platform !== 'win32' && !downloadInfo.extract) {
|
|
123
|
-
chmodSync(destPath, 0o755);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
console.log('Claude Code Reader installed successfully!');
|
|
127
|
-
console.log('Run "ccr" to start the application.');
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error('Failed to download Claude Code Reader:', error.message);
|
|
130
|
-
console.error('Please download manually from: https://github.com/MoYeRanQianZhi/ClaudeCodeReader/releases');
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
main();
|