@cc-claw/code 0.6.12 → 0.6.14
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 +54 -54
- package/bin/cc-code +19 -19
- package/install.js +172 -172
- package/package.json +43 -43
package/README.md
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
# cc-code
|
|
2
|
-
|
|
3
|
-
**用开源模型跑 Agent Loop — Rust 写的终端编程助手,兼容 Claude Code 全家桶**
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@cc-claw/code)
|
|
6
|
-
[](LICENSE)
|
|
7
|
-
|
|
8
|
-
## 安装
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install -g @cc-claw/code
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## 升级
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm update -g @cc-claw/code
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## 快速开始
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# 启动交互式 TUI
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# 直接给任务
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# 指定模型
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## 支持的平台
|
|
34
|
-
|
|
35
|
-
| 平台 | 架构 |
|
|
36
|
-
|------|------|
|
|
37
|
-
| Linux | x86_64, aarch64, riscv64 |
|
|
38
|
-
| macOS | x86_64 (Intel), aarch64 (Apple Silicon) |
|
|
39
|
-
| Windows | x86_64 |
|
|
40
|
-
|
|
41
|
-
## 为什么选 cc-code?
|
|
42
|
-
|
|
43
|
-
| 对比项 | 其他终端 Agent | cc-code |
|
|
44
|
-
|--------|---------------|------|
|
|
45
|
-
| 运行时 | Node.js / Bun,动辄吃 1GB 内存 | Rust 原生,启动快,~50MB 内存 |
|
|
46
|
-
| 模型绑定 | 锁死一家 LLM | 随便换:Anthropic、OpenAI 兼容、DeepSeek、GLM |
|
|
47
|
-
| Prompt 缓存 | 每轮重算,token 白烧 | 冻结 system prompt,95-99% 缓存命中率 |
|
|
48
|
-
| Claude Code 生态 | 不兼容 | 直接用 `.claude/` 配置、agents、skills、hooks、MCP |
|
|
49
|
-
|
|
50
|
-
## 链接
|
|
51
|
-
|
|
52
|
-
- [GitHub](https://github.com/cc-claws/cc-code)
|
|
53
|
-
- [Issues](https://github.com/cc-claws/cc-code/issues)
|
|
54
|
-
- [English README](https://github.com/cc-claws/cc-code#readme)
|
|
1
|
+
# cc-code
|
|
2
|
+
|
|
3
|
+
**用开源模型跑 Agent Loop — Rust 写的终端编程助手,兼容 Claude Code 全家桶**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@cc-claw/code)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## 安装
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -g @cc-claw/code
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## 升级
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm update -g @cc-claw/code
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 启动交互式 TUI
|
|
24
|
+
cc-code
|
|
25
|
+
|
|
26
|
+
# 直接给任务
|
|
27
|
+
cc-code "解释这个项目的目录结构"
|
|
28
|
+
|
|
29
|
+
# 指定模型
|
|
30
|
+
cc-code --model deepseek/deepseek-chat "重构这个函数"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 支持的平台
|
|
34
|
+
|
|
35
|
+
| 平台 | 架构 |
|
|
36
|
+
|------|------|
|
|
37
|
+
| Linux | x86_64, aarch64, riscv64 |
|
|
38
|
+
| macOS | x86_64 (Intel), aarch64 (Apple Silicon) |
|
|
39
|
+
| Windows | x86_64 |
|
|
40
|
+
|
|
41
|
+
## 为什么选 cc-code?
|
|
42
|
+
|
|
43
|
+
| 对比项 | 其他终端 Agent | cc-code |
|
|
44
|
+
|--------|---------------|------|
|
|
45
|
+
| 运行时 | Node.js / Bun,动辄吃 1GB 内存 | Rust 原生,启动快,~50MB 内存 |
|
|
46
|
+
| 模型绑定 | 锁死一家 LLM | 随便换:Anthropic、OpenAI 兼容、DeepSeek、GLM |
|
|
47
|
+
| Prompt 缓存 | 每轮重算,token 白烧 | 冻结 system prompt,95-99% 缓存命中率 |
|
|
48
|
+
| Claude Code 生态 | 不兼容 | 直接用 `.claude/` 配置、agents、skills、hooks、MCP |
|
|
49
|
+
|
|
50
|
+
## 链接
|
|
51
|
+
|
|
52
|
+
- [GitHub](https://github.com/cc-claws/cc-code)
|
|
53
|
+
- [Issues](https://github.com/cc-claws/cc-code/issues)
|
|
54
|
+
- [English README](https://github.com/cc-claws/cc-code#readme)
|
package/bin/cc-code
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { existsSync } = require("fs");
|
|
4
|
-
const { join, dirname } = require("path");
|
|
5
|
-
const { execFileSync } = require("child_process");
|
|
6
|
-
|
|
7
|
-
const dir = dirname(__filename);
|
|
8
|
-
const binPath = existsSync(join(dir, "
|
|
9
|
-
? join(dir, "
|
|
10
|
-
: join(dir, "
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
14
|
-
} catch (err) {
|
|
15
|
-
if (err.status !== null) {
|
|
16
|
-
process.exit(err.status);
|
|
17
|
-
}
|
|
18
|
-
throw err;
|
|
19
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { existsSync } = require("fs");
|
|
4
|
+
const { join, dirname } = require("path");
|
|
5
|
+
const { execFileSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
const dir = dirname(__filename);
|
|
8
|
+
const binPath = existsSync(join(dir, "cc-code-bin"))
|
|
9
|
+
? join(dir, "cc-code-bin")
|
|
10
|
+
: join(dir, "cc-code.exe");
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
14
|
+
} catch (err) {
|
|
15
|
+
if (err.status !== null) {
|
|
16
|
+
process.exit(err.status);
|
|
17
|
+
}
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
package/install.js
CHANGED
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { createWriteStream, mkdirSync, chmodSync, existsSync, renameSync, unlinkSync, writeFileSync } = require("fs");
|
|
4
|
-
const { join } = require("path");
|
|
5
|
-
const { execSync } = require("child_process");
|
|
6
|
-
|
|
7
|
-
const VERSION = require("./package.json").version;
|
|
8
|
-
const REPO = "cc-claws/cc-code";
|
|
9
|
-
const BASE_URL = `https://github.com/${REPO}/releases/download/npm-v${VERSION}`;
|
|
10
|
-
|
|
11
|
-
const PLATFORMS = {
|
|
12
|
-
"linux-x64": { os: "linux", arch: "x64", suffix: "linux-x86_64", ext: "tar.gz" },
|
|
13
|
-
"linux-arm64": { os: "linux", arch: "arm64", suffix: "linux-aarch64", ext: "tar.gz" },
|
|
14
|
-
"darwin-x64": { os: "darwin", arch: "x64", suffix: "macos-x86_64", ext: "tar.gz" },
|
|
15
|
-
"darwin-arm64": { os: "darwin", arch: "arm64", suffix: "macos-aarch64", ext: "tar.gz" },
|
|
16
|
-
"win32-x64": { os: "win32", arch: "x64", suffix: "windows-x86_64", ext: "zip" },
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function getPlatformKey() {
|
|
20
|
-
const key = `${process.platform}-${process.arch}`;
|
|
21
|
-
if (!PLATFORMS[key]) {
|
|
22
|
-
throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORMS).join(", ")}`);
|
|
23
|
-
}
|
|
24
|
-
return key;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function getProxyUrl() {
|
|
28
|
-
// Check common proxy environment variables
|
|
29
|
-
const proxy = process.env.HTTPS_PROXY || process.env.https_proxy
|
|
30
|
-
|| process.env.HTTP_PROXY || process.env.http_proxy
|
|
31
|
-
|| process.env.ALL_PROXY || process.env.all_proxy;
|
|
32
|
-
return proxy || null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function download(url) {
|
|
36
|
-
const proxyUrl = getProxyUrl();
|
|
37
|
-
|
|
38
|
-
if (proxyUrl) {
|
|
39
|
-
return downloadViaProxy(url, proxyUrl);
|
|
40
|
-
}
|
|
41
|
-
return downloadDirect(url);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function downloadDirect(url) {
|
|
45
|
-
const { get } = require("https");
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
get(url, (res) => {
|
|
48
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
49
|
-
downloadDirect(res.headers.location).then(resolve, reject);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (res.statusCode !== 200) {
|
|
53
|
-
reject(new Error(`Download failed: HTTP ${res.statusCode} for ${url}`));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const chunks = [];
|
|
57
|
-
res.on("data", (chunk) => chunks.push(chunk));
|
|
58
|
-
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
59
|
-
res.on("error", reject);
|
|
60
|
-
}).on("error", reject);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function downloadViaProxy(url, proxyUrl) {
|
|
65
|
-
const { URL } = require("url");
|
|
66
|
-
const target = new URL(url);
|
|
67
|
-
const proxy = new URL(proxyUrl);
|
|
68
|
-
|
|
69
|
-
const isHttps = proxy.protocol === "https:" || proxy.protocol === "HTTPS:";
|
|
70
|
-
const proxyModule = isHttps ? require("https") : require("http");
|
|
71
|
-
|
|
72
|
-
const proxyOpts = {
|
|
73
|
-
hostname: proxy.hostname,
|
|
74
|
-
port: proxy.port || (isHttps ? 443 : 80),
|
|
75
|
-
path: url,
|
|
76
|
-
method: "GET",
|
|
77
|
-
headers: { "Host": target.hostname, "User-Agent": "
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// Support proxy auth
|
|
81
|
-
if (proxy.username) {
|
|
82
|
-
const auth = decodeURIComponent(`${proxy.username}:${proxy.password || ""}`);
|
|
83
|
-
proxyOpts.headers["Proxy-Authorization"] = `Basic ${Buffer.from(auth).toString("base64")}`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
console.log(` Using proxy: ${proxy.hostname}:${proxy.port || (isHttps ? 443 : 80)}`);
|
|
87
|
-
|
|
88
|
-
return new Promise((resolve, reject) => {
|
|
89
|
-
const req = proxyModule.request(proxyOpts, (res) => {
|
|
90
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
91
|
-
download(res.headers.location).then(resolve, reject);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
if (res.statusCode !== 200) {
|
|
95
|
-
reject(new Error(`Download failed: HTTP ${res.statusCode} for ${url}`));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const chunks = [];
|
|
99
|
-
res.on("data", (chunk) => chunks.push(chunk));
|
|
100
|
-
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
101
|
-
res.on("error", reject);
|
|
102
|
-
});
|
|
103
|
-
req.on("error", reject);
|
|
104
|
-
req.end();
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function extractTarGz(buffer, dest) {
|
|
109
|
-
const tmpFile = join(dest, "
|
|
110
|
-
writeFileSync(tmpFile, buffer);
|
|
111
|
-
execSync(`tar -xzf "${tmpFile}" -C "${dest}"`, { stdio: "ignore" });
|
|
112
|
-
unlinkSync(tmpFile);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function extractZip(buffer, dest) {
|
|
116
|
-
const AdmZip = require("adm-zip");
|
|
117
|
-
const zip = new AdmZip(buffer);
|
|
118
|
-
zip.extractAllTo(dest, true);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
async function main() {
|
|
122
|
-
const key = getPlatformKey();
|
|
123
|
-
const platform = PLATFORMS[key];
|
|
124
|
-
const fileName = `
|
|
125
|
-
const url = `${BASE_URL}/${fileName}`;
|
|
126
|
-
const binDir = join(__dirname, "bin");
|
|
127
|
-
|
|
128
|
-
if (!existsSync(binDir)) {
|
|
129
|
-
mkdirSync(binDir, { recursive: true });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
console.log(`Downloading
|
|
133
|
-
console.log(` URL: ${url}`);
|
|
134
|
-
|
|
135
|
-
const buffer = await download(url);
|
|
136
|
-
|
|
137
|
-
if (platform.ext === "tar.gz") {
|
|
138
|
-
extractTarGz(buffer, binDir);
|
|
139
|
-
} else {
|
|
140
|
-
extractZip(buffer, binDir);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const extractedName = platform.os === "win32"
|
|
144
|
-
? `
|
|
145
|
-
: `
|
|
146
|
-
const finalName = platform.os === "win32" ? "
|
|
147
|
-
const extractedPath = join(binDir, extractedName);
|
|
148
|
-
const finalPath = join(binDir, finalName);
|
|
149
|
-
|
|
150
|
-
if (existsSync(extractedPath)) {
|
|
151
|
-
if (existsSync(finalPath)) unlinkSync(finalPath);
|
|
152
|
-
renameSync(extractedPath, finalPath);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (platform.os !== "win32") {
|
|
156
|
-
chmodSync(finalPath, 0o755);
|
|
157
|
-
const wrapperPath = join(__dirname, "bin", "
|
|
158
|
-
if (existsSync(wrapperPath)) chmodSync(wrapperPath, 0o755);
|
|
159
|
-
} else {
|
|
160
|
-
// Generate Windows batch wrapper so npm's
|
|
161
|
-
const binDirPath = join(__dirname, "bin");
|
|
162
|
-
writeFileSync(join(binDirPath, "
|
|
163
|
-
writeFileSync(join(binDirPath, "
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
console.log(`
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
main().catch((err) => {
|
|
170
|
-
console.error("Failed to install
|
|
171
|
-
process.exit(1);
|
|
172
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { createWriteStream, mkdirSync, chmodSync, existsSync, renameSync, unlinkSync, writeFileSync } = require("fs");
|
|
4
|
+
const { join } = require("path");
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
const VERSION = require("./package.json").version;
|
|
8
|
+
const REPO = "cc-claws/cc-code";
|
|
9
|
+
const BASE_URL = `https://github.com/${REPO}/releases/download/npm-v${VERSION}`;
|
|
10
|
+
|
|
11
|
+
const PLATFORMS = {
|
|
12
|
+
"linux-x64": { os: "linux", arch: "x64", suffix: "linux-x86_64", ext: "tar.gz" },
|
|
13
|
+
"linux-arm64": { os: "linux", arch: "arm64", suffix: "linux-aarch64", ext: "tar.gz" },
|
|
14
|
+
"darwin-x64": { os: "darwin", arch: "x64", suffix: "macos-x86_64", ext: "tar.gz" },
|
|
15
|
+
"darwin-arm64": { os: "darwin", arch: "arm64", suffix: "macos-aarch64", ext: "tar.gz" },
|
|
16
|
+
"win32-x64": { os: "win32", arch: "x64", suffix: "windows-x86_64", ext: "zip" },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function getPlatformKey() {
|
|
20
|
+
const key = `${process.platform}-${process.arch}`;
|
|
21
|
+
if (!PLATFORMS[key]) {
|
|
22
|
+
throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORMS).join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
return key;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getProxyUrl() {
|
|
28
|
+
// Check common proxy environment variables
|
|
29
|
+
const proxy = process.env.HTTPS_PROXY || process.env.https_proxy
|
|
30
|
+
|| process.env.HTTP_PROXY || process.env.http_proxy
|
|
31
|
+
|| process.env.ALL_PROXY || process.env.all_proxy;
|
|
32
|
+
return proxy || null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function download(url) {
|
|
36
|
+
const proxyUrl = getProxyUrl();
|
|
37
|
+
|
|
38
|
+
if (proxyUrl) {
|
|
39
|
+
return downloadViaProxy(url, proxyUrl);
|
|
40
|
+
}
|
|
41
|
+
return downloadDirect(url);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function downloadDirect(url) {
|
|
45
|
+
const { get } = require("https");
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
get(url, (res) => {
|
|
48
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
49
|
+
downloadDirect(res.headers.location).then(resolve, reject);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (res.statusCode !== 200) {
|
|
53
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode} for ${url}`));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const chunks = [];
|
|
57
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
58
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
59
|
+
res.on("error", reject);
|
|
60
|
+
}).on("error", reject);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function downloadViaProxy(url, proxyUrl) {
|
|
65
|
+
const { URL } = require("url");
|
|
66
|
+
const target = new URL(url);
|
|
67
|
+
const proxy = new URL(proxyUrl);
|
|
68
|
+
|
|
69
|
+
const isHttps = proxy.protocol === "https:" || proxy.protocol === "HTTPS:";
|
|
70
|
+
const proxyModule = isHttps ? require("https") : require("http");
|
|
71
|
+
|
|
72
|
+
const proxyOpts = {
|
|
73
|
+
hostname: proxy.hostname,
|
|
74
|
+
port: proxy.port || (isHttps ? 443 : 80),
|
|
75
|
+
path: url,
|
|
76
|
+
method: "GET",
|
|
77
|
+
headers: { "Host": target.hostname, "User-Agent": "cc-code-installer" },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Support proxy auth
|
|
81
|
+
if (proxy.username) {
|
|
82
|
+
const auth = decodeURIComponent(`${proxy.username}:${proxy.password || ""}`);
|
|
83
|
+
proxyOpts.headers["Proxy-Authorization"] = `Basic ${Buffer.from(auth).toString("base64")}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.log(` Using proxy: ${proxy.hostname}:${proxy.port || (isHttps ? 443 : 80)}`);
|
|
87
|
+
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
const req = proxyModule.request(proxyOpts, (res) => {
|
|
90
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
91
|
+
download(res.headers.location).then(resolve, reject);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (res.statusCode !== 200) {
|
|
95
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode} for ${url}`));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const chunks = [];
|
|
99
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
100
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
101
|
+
res.on("error", reject);
|
|
102
|
+
});
|
|
103
|
+
req.on("error", reject);
|
|
104
|
+
req.end();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function extractTarGz(buffer, dest) {
|
|
109
|
+
const tmpFile = join(dest, "cc-code.tar.gz");
|
|
110
|
+
writeFileSync(tmpFile, buffer);
|
|
111
|
+
execSync(`tar -xzf "${tmpFile}" -C "${dest}"`, { stdio: "ignore" });
|
|
112
|
+
unlinkSync(tmpFile);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function extractZip(buffer, dest) {
|
|
116
|
+
const AdmZip = require("adm-zip");
|
|
117
|
+
const zip = new AdmZip(buffer);
|
|
118
|
+
zip.extractAllTo(dest, true);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function main() {
|
|
122
|
+
const key = getPlatformKey();
|
|
123
|
+
const platform = PLATFORMS[key];
|
|
124
|
+
const fileName = `cc-code-${platform.suffix}.${platform.ext}`;
|
|
125
|
+
const url = `${BASE_URL}/${fileName}`;
|
|
126
|
+
const binDir = join(__dirname, "bin");
|
|
127
|
+
|
|
128
|
+
if (!existsSync(binDir)) {
|
|
129
|
+
mkdirSync(binDir, { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log(`Downloading cc-code ${VERSION} for ${platform.os}-${platform.arch}...`);
|
|
133
|
+
console.log(` URL: ${url}`);
|
|
134
|
+
|
|
135
|
+
const buffer = await download(url);
|
|
136
|
+
|
|
137
|
+
if (platform.ext === "tar.gz") {
|
|
138
|
+
extractTarGz(buffer, binDir);
|
|
139
|
+
} else {
|
|
140
|
+
extractZip(buffer, binDir);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const extractedName = platform.os === "win32"
|
|
144
|
+
? `cc-code-${platform.suffix}.exe`
|
|
145
|
+
: `cc-code-${platform.suffix}`;
|
|
146
|
+
const finalName = platform.os === "win32" ? "cc-code.exe" : "cc-code-bin";
|
|
147
|
+
const extractedPath = join(binDir, extractedName);
|
|
148
|
+
const finalPath = join(binDir, finalName);
|
|
149
|
+
|
|
150
|
+
if (existsSync(extractedPath)) {
|
|
151
|
+
if (existsSync(finalPath)) unlinkSync(finalPath);
|
|
152
|
+
renameSync(extractedPath, finalPath);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (platform.os !== "win32") {
|
|
156
|
+
chmodSync(finalPath, 0o755);
|
|
157
|
+
const wrapperPath = join(__dirname, "bin", "cc-code");
|
|
158
|
+
if (existsSync(wrapperPath)) chmodSync(wrapperPath, 0o755);
|
|
159
|
+
} else {
|
|
160
|
+
// Generate Windows batch wrapper so npm's cc-code.cmd/ps1 can invoke it
|
|
161
|
+
const binDirPath = join(__dirname, "bin");
|
|
162
|
+
writeFileSync(join(binDirPath, "cc-code.cmd"), `@echo off\r\n"%~dp0cc-code.exe" %*\r\n`);
|
|
163
|
+
writeFileSync(join(binDirPath, "cc-code.ps1"), `$basedir = Split-Path $MyInvocation.MyCommand.Definition -Parent\r\n& "$basedir\\cc-code.exe" @args\r\nexit $LASTEXITCODE\r\n`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log(`cc-code ${VERSION} installed successfully.`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
main().catch((err) => {
|
|
170
|
+
console.error("Failed to install cc-code:", err.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
package/package.json
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@cc-claw/code",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "cc-code — Terminal coding agent powered by open-source models — Rust-built, Claude Code compatible",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"agent",
|
|
7
|
-
"coding",
|
|
8
|
-
"terminal",
|
|
9
|
-
"rust",
|
|
10
|
-
"llm",
|
|
11
|
-
"claude-code"
|
|
12
|
-
],
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/cc-claws/cc-code.git"
|
|
16
|
-
},
|
|
17
|
-
"homepage": "https://github.com/cc-claws/cc-code",
|
|
18
|
-
"bugs": {
|
|
19
|
-
"url": "https://github.com/cc-claws/cc-code/issues"
|
|
20
|
-
},
|
|
21
|
-
"license": "Apache-2.0",
|
|
22
|
-
"bin": {
|
|
23
|
-
"cc-code": "bin/cc-code"
|
|
24
|
-
},
|
|
25
|
-
"scripts": {
|
|
26
|
-
"postinstall": "node install.js"
|
|
27
|
-
},
|
|
28
|
-
"os": [
|
|
29
|
-
"linux",
|
|
30
|
-
"darwin",
|
|
31
|
-
"win32"
|
|
32
|
-
],
|
|
33
|
-
"cpu": [
|
|
34
|
-
"x64",
|
|
35
|
-
"arm64"
|
|
36
|
-
],
|
|
37
|
-
"engines": {
|
|
38
|
-
"node": ">=16"
|
|
39
|
-
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"adm-zip": "^0.5.16"
|
|
42
|
-
}
|
|
43
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@cc-claw/code",
|
|
3
|
+
"version": "0.6.14",
|
|
4
|
+
"description": "cc-code — Terminal coding agent powered by open-source models — Rust-built, Claude Code compatible",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent",
|
|
7
|
+
"coding",
|
|
8
|
+
"terminal",
|
|
9
|
+
"rust",
|
|
10
|
+
"llm",
|
|
11
|
+
"claude-code"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/cc-claws/cc-code.git"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/cc-claws/cc-code",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/cc-claws/cc-code/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"bin": {
|
|
23
|
+
"cc-code": "bin/cc-code"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"postinstall": "node install.js"
|
|
27
|
+
},
|
|
28
|
+
"os": [
|
|
29
|
+
"linux",
|
|
30
|
+
"darwin",
|
|
31
|
+
"win32"
|
|
32
|
+
],
|
|
33
|
+
"cpu": [
|
|
34
|
+
"x64",
|
|
35
|
+
"arm64"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"adm-zip": "^0.5.16"
|
|
42
|
+
}
|
|
43
|
+
}
|