@go-hare/claude-code 2.6.33 → 2.6.34
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 +57 -18
- package/install.cjs +224 -224
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -16,16 +16,20 @@
|
|
|
16
16
|
| **Claude 群控技术** | Pipe IPC 多实例协作:同机 main/sub 自动编排 + LAN 跨机器零配置发现与通讯,`/pipes` 选择面板 + `Shift+↓` 交互 + 消息广播路由 |
|
|
17
17
|
| **ACP 协议一等一支持** | 支持接入 Zed、Cursor 等 IDE,支持会话恢复、Skills、权限桥接 |
|
|
18
18
|
| **Remote Control 私有部署** | Docker 自托管远程界面, 可以手机上看 CC |
|
|
19
|
+
| **Agents / BG 后台会话** | `claude agents` 全屏 dashboard、daemon job dispatch、`/exit` 后台移交(resume/fork)、WMI 自启与 Windows 终端稳固 |
|
|
20
|
+
| **Fullscreen densable** | 对齐官方 2.1.210:fullscreen 默认开、滚轮/Jump-to-bottom、spinner 可见性恢复、alt-screen 退出序列防闪窗 |
|
|
19
21
|
| **Langfuse 监控** | 企业级 Agent 监控, 可以清晰看到每次 agent loop 细节, 可以一键转化为数据集 |
|
|
20
22
|
| **Web Search** | 内置网页搜索工具, 支持 bing 和 brave 搜索 |
|
|
21
23
|
| **Poor Mode** | 穷鬼模式,关闭记忆提取和键入建议,大幅度减少并发请求,`/poor` 可以开关 |
|
|
22
24
|
| **KAIROS 常驻助手** | 持久化 AI 助手模式,支持 brief 输出、后台等待、频道消息、每日记忆日志、PR 订阅与推送通知等主动 Agent 能力 |
|
|
23
25
|
| **Buddy Agent 宠物** | 终端里的 AI 伙伴/宠物系统,支持 `/buddy` 唤出、陪伴展示、互动摸摸、上下文反应与提示输入联动 |
|
|
24
26
|
| **Channels 频道通知** | MCP 服务器推送外部消息到会话(飞书/Slack/Discord/微信等),`--channels plugin:name@marketplace` 启用 |
|
|
25
|
-
| **自定义模型供应商** | OpenAI/Anthropic/Gemini/Grok 兼容(`/login
|
|
27
|
+
| **自定义模型供应商** | OpenAI/Anthropic/Gemini/Grok 兼容(`/login`);含 Sonnet 5 / Org default 映射 |
|
|
28
|
+
| **Gateway / IdP 会话** | 过期 session 优先 tryRestore、secure-storage 负缓存、refreshable 会话恢复,避免静默回落 Bedrock |
|
|
26
29
|
| Voice Mode | 语音输入,支持豆包语言输入(`/voice doubao`) |
|
|
27
30
|
| Computer Use | 屏幕截图、键鼠控制 |
|
|
28
31
|
| Chrome Use | 浏览器自动化、表单填写、数据抓取 |
|
|
32
|
+
| Artifacts | HTML/Markdown 上传托管、代码高亮与 mermaid |
|
|
29
33
|
| Sentry | 企业级错误追踪 |
|
|
30
34
|
| GrowthBook | 企业级特性开关 |
|
|
31
35
|
| /dream 记忆整理 | 自动整理和优化记忆文件 |
|
|
@@ -57,17 +61,34 @@
|
|
|
57
61
|
|
|
58
62
|
## 当前能力
|
|
59
63
|
|
|
60
|
-
- 交互式 CLI / REPL
|
|
64
|
+
- 交互式 CLI / REPL(fullscreen 默认开,对齐官方 2.1.210 滚轮 / sticky / Jump-to-bottom)
|
|
61
65
|
- headless runtime session
|
|
62
66
|
- direct-connect / server
|
|
63
67
|
- ACP agent 模式
|
|
64
|
-
- bridge / remote-control / daemon host
|
|
68
|
+
- bridge / remote-control / daemon host(含 Windows WMI 自启与 exit 后台移交)
|
|
69
|
+
- `claude agents` 后台会话 dashboard(分组 / PR 列 / needs-input nudge / token footer)
|
|
65
70
|
- MCP、channels、plugins
|
|
66
|
-
- OpenAI / Anthropic / Gemini / Grok
|
|
71
|
+
- OpenAI / Anthropic / Gemini / Grok 兼容模型接入(含 Sonnet 5 / Org default)
|
|
67
72
|
- Buddy agent 宠物、KAIROS 常驻助手、Coordinator、task、subagent、team 主链
|
|
68
|
-
- computer-use / chrome bridge / remote-control 相关能力
|
|
73
|
+
- computer-use / chrome bridge / remote-control / artifacts 相关能力
|
|
69
74
|
- Langfuse、Sentry、GrowthBook 等可观测性与企业集成能力
|
|
70
75
|
|
|
76
|
+
## 近期更新(2.6.x)
|
|
77
|
+
|
|
78
|
+
对照近期 git 主线,已合入并发布到 npm 的方向包括:
|
|
79
|
+
|
|
80
|
+
| 版本区间 | 要点 |
|
|
81
|
+
| -------- | ---- |
|
|
82
|
+
| **2.6.34** | Jump-to-bottom 后立即恢复 spinner 动画(viewport 可见性 notify) |
|
|
83
|
+
| **2.6.32–2.6.30** | alt-screen 双次 EXIT 防 Windows Terminal 多层闪窗;fullscreen / 滚轮 densable 对齐官方 2.1.210 |
|
|
84
|
+
| **2.6.29** | modal 双线、滚轮残片与折叠空白修复;残差端口对齐 |
|
|
85
|
+
| **2.6.x agents** | agents view 分组顺序 / review 列表 / done fold / PR 列 / fleet token / fleet needs-input / token footer |
|
|
86
|
+
| **Gateway** | 过期 session tryRestore、IdP transient 重读、secure-storage 负缓存、显式 Gateway env 与 refreshable 恢复 |
|
|
87
|
+
| **Daemon / exit** | `/exit` 走 daemon `submitDispatch(resume/fork)`;`cliLaunch` 优先稳定 user-bin;Windows WMI `Win32_Process.Create` densable |
|
|
88
|
+
| **2.6.27 及前** | vendor 可执行权限 postinstall、Windows Bash/ripgrep、swarm banner 宽度、macOS 粘贴图片等 |
|
|
89
|
+
|
|
90
|
+
当前发布包版本见 `package.json`(`@go-hare/claude-code`)。
|
|
91
|
+
|
|
71
92
|
## 使用 Agent Core
|
|
72
93
|
|
|
73
94
|
当前包级 core 入口已经通过 `package.json` 的 `./core` 子路径暴露:
|
|
@@ -120,22 +141,28 @@ import { createAgent } from 'claude/core'
|
|
|
120
141
|
|
|
121
142
|
## ⚡ 快速开始(安装版)
|
|
122
143
|
|
|
123
|
-
不用克隆仓库, 从 NPM 下载后,
|
|
144
|
+
不用克隆仓库, 从 NPM 下载后, 直接使用。本仓库发布的 scoped 包名为 **`@go-hare/claude-code`**(平台二进制在 `@go-hare/claude-code-<os>-<arch>` optionalDependencies)。
|
|
124
145
|
|
|
125
146
|
```sh
|
|
126
|
-
npm i -g claude-code
|
|
147
|
+
npm i -g @go-hare/claude-code
|
|
148
|
+
|
|
149
|
+
# Windows 若 claude.exe 被占用导致 EBUSY,先结束占用进程再装
|
|
150
|
+
# taskkill /F /IM claude.exe
|
|
127
151
|
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
#
|
|
152
|
+
claude # 启动(postinstall 会把对应平台 native 二进制落到 bin/)
|
|
153
|
+
claude --version
|
|
154
|
+
claude agents # 后台会话 dashboard(需 daemon)
|
|
155
|
+
claude update # 更新到最新版本
|
|
131
156
|
|
|
132
|
-
|
|
133
|
-
claude-
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
# 自托管 Remote Control 示例
|
|
158
|
+
CLAUDE_BRIDGE_BASE_URL=https://remote-control.claude-code.win/ \
|
|
159
|
+
CLAUDE_BRIDGE_OAUTH_TOKEN=test-my-key \
|
|
160
|
+
claude --remote-control
|
|
136
161
|
```
|
|
137
162
|
|
|
138
|
-
> **安装/更新失败?** 先 `npm rm -g claude-code` 清理旧版本,再 `npm i -g claude-code@latest
|
|
163
|
+
> **安装/更新失败?** 先 `npm rm -g @go-hare/claude-code` 清理旧版本,再 `npm i -g @go-hare/claude-code@latest`。仍失败可钉版本:`npm i -g @go-hare/claude-code@2.6.34`。
|
|
164
|
+
>
|
|
165
|
+
> 旧文档里的全局包名 `claude-code` 已不再对应本仓库发布流;请使用 `@go-hare/claude-code`。
|
|
139
166
|
|
|
140
167
|
## ⚡ 快速开始(源码版)
|
|
141
168
|
|
|
@@ -217,11 +244,23 @@ bun run dev
|
|
|
217
244
|
bun run build
|
|
218
245
|
```
|
|
219
246
|
|
|
220
|
-
构建采用 code splitting 多文件打包(`build.ts`),产物输出到 `dist/` 目录(入口 `dist/cli.js` +
|
|
247
|
+
构建采用 code splitting 多文件打包(`build.ts`),产物输出到 `dist/` 目录(入口 `dist/cli.js` + 多 chunk)。
|
|
248
|
+
|
|
249
|
+
跨平台原生包与主包发布:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
bun run build:compile # 仅编译各平台二进制到 packages/@go-hare/*
|
|
253
|
+
bun run scripts/publish.ts # 构建并 publish 平台包
|
|
254
|
+
bun run scripts/publish.ts --with-main # 同时 publish 主包 @go-hare/claude-code
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
构建出的版本 bun 和 node 都可以启动;若你 fork 后 publish 到私有源,可直接按上面的全局安装方式使用。
|
|
221
258
|
|
|
222
|
-
|
|
259
|
+
如果遇到 bug 请直接提 issues, 我们优先解决。提交前建议:
|
|
223
260
|
|
|
224
|
-
|
|
261
|
+
```bash
|
|
262
|
+
bun run precheck # typecheck + biome fix + test
|
|
263
|
+
```
|
|
225
264
|
|
|
226
265
|
### 👤 新人配置 /login
|
|
227
266
|
|
package/install.cjs
CHANGED
|
@@ -1,224 +1,224 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Postinstall for the claude wrapper package.
|
|
3
|
-
//
|
|
4
|
-
// In development (monorepo with .git), delegates to the dev postinstall scripts.
|
|
5
|
-
// In production (npm install from registry), copies the native binary from the
|
|
6
|
-
// platform-specific optionalDependency into bin/claude.exe.
|
|
7
|
-
//
|
|
8
|
-
// Platform detection + PLATFORMS map is duplicated in cli-wrapper.cjs — keep in sync.
|
|
9
|
-
|
|
10
|
-
const { spawnSync } = require('child_process')
|
|
11
|
-
const {
|
|
12
|
-
copyFileSync,
|
|
13
|
-
existsSync,
|
|
14
|
-
linkSync,
|
|
15
|
-
unlinkSync,
|
|
16
|
-
chmodSync,
|
|
17
|
-
readFileSync,
|
|
18
|
-
writeFileSync,
|
|
19
|
-
statSync,
|
|
20
|
-
readdirSync,
|
|
21
|
-
} = require('fs')
|
|
22
|
-
const { arch } = require('os')
|
|
23
|
-
const path = require('path')
|
|
24
|
-
|
|
25
|
-
// Dev environment detection: if .git exists at package root, we're in the monorepo
|
|
26
|
-
if (existsSync(path.join(__dirname, '.git'))) {
|
|
27
|
-
const r = spawnSync(
|
|
28
|
-
'node',
|
|
29
|
-
[
|
|
30
|
-
'scripts/run-parallel.mjs',
|
|
31
|
-
'scripts/postinstall.cjs',
|
|
32
|
-
'scripts/setup-chrome-mcp.mjs',
|
|
33
|
-
],
|
|
34
|
-
{ cwd: __dirname, stdio: 'inherit' },
|
|
35
|
-
)
|
|
36
|
-
process.exit(r.status ?? 0)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const PACKAGE_PREFIX = '@go-hare/claude-code'
|
|
40
|
-
const BINARY_NAME = 'claude'
|
|
41
|
-
const WRAPPER_NAME = require('./package.json').name
|
|
42
|
-
|
|
43
|
-
const PLATFORMS = {
|
|
44
|
-
'darwin-arm64': { pkg: PACKAGE_PREFIX + '-darwin-arm64', bin: BINARY_NAME },
|
|
45
|
-
'darwin-x64': { pkg: PACKAGE_PREFIX + '-darwin-x64', bin: BINARY_NAME },
|
|
46
|
-
'linux-x64': { pkg: PACKAGE_PREFIX + '-linux-x64', bin: BINARY_NAME },
|
|
47
|
-
'linux-arm64': { pkg: PACKAGE_PREFIX + '-linux-arm64', bin: BINARY_NAME },
|
|
48
|
-
'linux-x64-musl': {
|
|
49
|
-
pkg: PACKAGE_PREFIX + '-linux-x64-musl',
|
|
50
|
-
bin: BINARY_NAME,
|
|
51
|
-
},
|
|
52
|
-
'linux-arm64-musl': {
|
|
53
|
-
pkg: PACKAGE_PREFIX + '-linux-arm64-musl',
|
|
54
|
-
bin: BINARY_NAME,
|
|
55
|
-
},
|
|
56
|
-
'linux-arm64-android': {
|
|
57
|
-
pkg: PACKAGE_PREFIX + '-linux-arm64-android',
|
|
58
|
-
bin: BINARY_NAME,
|
|
59
|
-
},
|
|
60
|
-
'linux-x64-android': {
|
|
61
|
-
pkg: PACKAGE_PREFIX + '-linux-x64-android',
|
|
62
|
-
bin: BINARY_NAME,
|
|
63
|
-
},
|
|
64
|
-
'freebsd-x64': { pkg: PACKAGE_PREFIX + '-freebsd-x64', bin: BINARY_NAME },
|
|
65
|
-
'freebsd-arm64': {
|
|
66
|
-
pkg: PACKAGE_PREFIX + '-freebsd-arm64',
|
|
67
|
-
bin: BINARY_NAME,
|
|
68
|
-
},
|
|
69
|
-
'win32-x64': {
|
|
70
|
-
pkg: PACKAGE_PREFIX + '-win32-x64',
|
|
71
|
-
bin: BINARY_NAME + '.exe',
|
|
72
|
-
},
|
|
73
|
-
'win32-arm64': {
|
|
74
|
-
pkg: PACKAGE_PREFIX + '-win32-arm64',
|
|
75
|
-
bin: BINARY_NAME + '.exe',
|
|
76
|
-
},
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function detectMusl() {
|
|
80
|
-
if (process.platform !== 'linux') return false
|
|
81
|
-
const report =
|
|
82
|
-
typeof process.report?.getReport === 'function'
|
|
83
|
-
? process.report.getReport()
|
|
84
|
-
: null
|
|
85
|
-
return report != null && report.header?.glibcVersionRuntime === undefined
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function getPlatformKey() {
|
|
89
|
-
const platform = process.platform
|
|
90
|
-
let cpu = arch()
|
|
91
|
-
if (platform === 'android') return 'linux-' + cpu + '-android'
|
|
92
|
-
if (platform === 'linux')
|
|
93
|
-
return 'linux-' + cpu + (detectMusl() ? '-musl' : '')
|
|
94
|
-
if (platform === 'darwin' && cpu === 'x64') {
|
|
95
|
-
const r = spawnSync('sysctl', ['-n', 'sysctl.proc_translated'], {
|
|
96
|
-
encoding: 'utf8',
|
|
97
|
-
})
|
|
98
|
-
if (r.stdout?.trim() === '1') cpu = 'arm64'
|
|
99
|
-
}
|
|
100
|
-
return platform + '-' + cpu
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function placeBinary(src, dest) {
|
|
104
|
-
try {
|
|
105
|
-
linkSync(src, dest)
|
|
106
|
-
} catch (err) {
|
|
107
|
-
if (err.code === 'EEXIST') {
|
|
108
|
-
const stub = statSync(dest).size < 4096 ? readFileSync(dest) : null
|
|
109
|
-
unlinkSync(dest)
|
|
110
|
-
try {
|
|
111
|
-
linkSync(src, dest)
|
|
112
|
-
} catch {
|
|
113
|
-
try {
|
|
114
|
-
copyFileSync(src, dest)
|
|
115
|
-
} catch (copyErr) {
|
|
116
|
-
if (stub) {
|
|
117
|
-
try {
|
|
118
|
-
writeFileSync(dest, stub, { mode: 0o755 })
|
|
119
|
-
} catch {}
|
|
120
|
-
}
|
|
121
|
-
throw copyErr
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
} else if (err.code === 'EXDEV' || err.code === 'EPERM') {
|
|
125
|
-
copyFileSync(src, dest)
|
|
126
|
-
} else {
|
|
127
|
-
throw err
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (process.platform !== 'win32') chmodSync(dest, 0o755)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// npm install may drop the executable bit on vendored helpers (clipboard-image,
|
|
134
|
-
// ripgrep). Only the main binary was chmod'd before — restore +x under vendor/.
|
|
135
|
-
function ensureVendorBinariesExecutable(pkgDir) {
|
|
136
|
-
if (process.platform === 'win32') return
|
|
137
|
-
|
|
138
|
-
const vendorDir = path.join(pkgDir, 'vendor')
|
|
139
|
-
if (!existsSync(vendorDir)) return
|
|
140
|
-
|
|
141
|
-
const stack = [vendorDir]
|
|
142
|
-
while (stack.length > 0) {
|
|
143
|
-
const dir = stack.pop()
|
|
144
|
-
let entries
|
|
145
|
-
try {
|
|
146
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
147
|
-
} catch {
|
|
148
|
-
continue
|
|
149
|
-
}
|
|
150
|
-
for (const entry of entries) {
|
|
151
|
-
const full = path.join(dir, entry.name)
|
|
152
|
-
if (entry.isDirectory()) {
|
|
153
|
-
stack.push(full)
|
|
154
|
-
continue
|
|
155
|
-
}
|
|
156
|
-
if (!entry.isFile()) continue
|
|
157
|
-
try {
|
|
158
|
-
chmodSync(full, 0o755)
|
|
159
|
-
} catch {
|
|
160
|
-
// Best-effort: missing write permission shouldn't fail install.
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function main() {
|
|
167
|
-
const platformKey = getPlatformKey()
|
|
168
|
-
const info = PLATFORMS[platformKey]
|
|
169
|
-
|
|
170
|
-
if (!info) {
|
|
171
|
-
console.error(
|
|
172
|
-
`[${WRAPPER_NAME} postinstall] Unsupported platform: ${process.platform} ${arch()}`,
|
|
173
|
-
)
|
|
174
|
-
console.error(` Supported: ${Object.keys(PLATFORMS).join(', ')}`)
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const optionalDeps = require('./package.json').optionalDependencies || {}
|
|
179
|
-
if (!optionalDeps[info.pkg]) {
|
|
180
|
-
console.error(
|
|
181
|
-
`[${WRAPPER_NAME} postinstall] Native binaries for ${platformKey} are not available on this release channel.`,
|
|
182
|
-
)
|
|
183
|
-
console.error(
|
|
184
|
-
` Available: ${Object.keys(optionalDeps)
|
|
185
|
-
.map(p => p.replace(PACKAGE_PREFIX + '-', ''))
|
|
186
|
-
.join(', ')}`,
|
|
187
|
-
)
|
|
188
|
-
return
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
let pkgDir
|
|
192
|
-
let src
|
|
193
|
-
try {
|
|
194
|
-
pkgDir = path.dirname(require.resolve(info.pkg + '/package.json'))
|
|
195
|
-
src = path.join(pkgDir, info.bin)
|
|
196
|
-
} catch {
|
|
197
|
-
console.error(
|
|
198
|
-
`[${WRAPPER_NAME} postinstall] Native package "${info.pkg}" not found.`,
|
|
199
|
-
)
|
|
200
|
-
console.error(
|
|
201
|
-
' This happens with --omit=optional or when the download failed.',
|
|
202
|
-
)
|
|
203
|
-
console.error(
|
|
204
|
-
' The `claude` command will print instructions when invoked.',
|
|
205
|
-
)
|
|
206
|
-
console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
|
|
207
|
-
return
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const dest = path.join(__dirname, 'bin', 'claude.exe')
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
placeBinary(src, dest)
|
|
214
|
-
ensureVendorBinariesExecutable(pkgDir)
|
|
215
|
-
} catch (err) {
|
|
216
|
-
console.error(
|
|
217
|
-
`[${WRAPPER_NAME} postinstall] Failed to place binary: ${err.message}`,
|
|
218
|
-
)
|
|
219
|
-
console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
|
|
220
|
-
process.exitCode = 1
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
main()
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall for the claude wrapper package.
|
|
3
|
+
//
|
|
4
|
+
// In development (monorepo with .git), delegates to the dev postinstall scripts.
|
|
5
|
+
// In production (npm install from registry), copies the native binary from the
|
|
6
|
+
// platform-specific optionalDependency into bin/claude.exe.
|
|
7
|
+
//
|
|
8
|
+
// Platform detection + PLATFORMS map is duplicated in cli-wrapper.cjs — keep in sync.
|
|
9
|
+
|
|
10
|
+
const { spawnSync } = require('child_process')
|
|
11
|
+
const {
|
|
12
|
+
copyFileSync,
|
|
13
|
+
existsSync,
|
|
14
|
+
linkSync,
|
|
15
|
+
unlinkSync,
|
|
16
|
+
chmodSync,
|
|
17
|
+
readFileSync,
|
|
18
|
+
writeFileSync,
|
|
19
|
+
statSync,
|
|
20
|
+
readdirSync,
|
|
21
|
+
} = require('fs')
|
|
22
|
+
const { arch } = require('os')
|
|
23
|
+
const path = require('path')
|
|
24
|
+
|
|
25
|
+
// Dev environment detection: if .git exists at package root, we're in the monorepo
|
|
26
|
+
if (existsSync(path.join(__dirname, '.git'))) {
|
|
27
|
+
const r = spawnSync(
|
|
28
|
+
'node',
|
|
29
|
+
[
|
|
30
|
+
'scripts/run-parallel.mjs',
|
|
31
|
+
'scripts/postinstall.cjs',
|
|
32
|
+
'scripts/setup-chrome-mcp.mjs',
|
|
33
|
+
],
|
|
34
|
+
{ cwd: __dirname, stdio: 'inherit' },
|
|
35
|
+
)
|
|
36
|
+
process.exit(r.status ?? 0)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const PACKAGE_PREFIX = '@go-hare/claude-code'
|
|
40
|
+
const BINARY_NAME = 'claude'
|
|
41
|
+
const WRAPPER_NAME = require('./package.json').name
|
|
42
|
+
|
|
43
|
+
const PLATFORMS = {
|
|
44
|
+
'darwin-arm64': { pkg: PACKAGE_PREFIX + '-darwin-arm64', bin: BINARY_NAME },
|
|
45
|
+
'darwin-x64': { pkg: PACKAGE_PREFIX + '-darwin-x64', bin: BINARY_NAME },
|
|
46
|
+
'linux-x64': { pkg: PACKAGE_PREFIX + '-linux-x64', bin: BINARY_NAME },
|
|
47
|
+
'linux-arm64': { pkg: PACKAGE_PREFIX + '-linux-arm64', bin: BINARY_NAME },
|
|
48
|
+
'linux-x64-musl': {
|
|
49
|
+
pkg: PACKAGE_PREFIX + '-linux-x64-musl',
|
|
50
|
+
bin: BINARY_NAME,
|
|
51
|
+
},
|
|
52
|
+
'linux-arm64-musl': {
|
|
53
|
+
pkg: PACKAGE_PREFIX + '-linux-arm64-musl',
|
|
54
|
+
bin: BINARY_NAME,
|
|
55
|
+
},
|
|
56
|
+
'linux-arm64-android': {
|
|
57
|
+
pkg: PACKAGE_PREFIX + '-linux-arm64-android',
|
|
58
|
+
bin: BINARY_NAME,
|
|
59
|
+
},
|
|
60
|
+
'linux-x64-android': {
|
|
61
|
+
pkg: PACKAGE_PREFIX + '-linux-x64-android',
|
|
62
|
+
bin: BINARY_NAME,
|
|
63
|
+
},
|
|
64
|
+
'freebsd-x64': { pkg: PACKAGE_PREFIX + '-freebsd-x64', bin: BINARY_NAME },
|
|
65
|
+
'freebsd-arm64': {
|
|
66
|
+
pkg: PACKAGE_PREFIX + '-freebsd-arm64',
|
|
67
|
+
bin: BINARY_NAME,
|
|
68
|
+
},
|
|
69
|
+
'win32-x64': {
|
|
70
|
+
pkg: PACKAGE_PREFIX + '-win32-x64',
|
|
71
|
+
bin: BINARY_NAME + '.exe',
|
|
72
|
+
},
|
|
73
|
+
'win32-arm64': {
|
|
74
|
+
pkg: PACKAGE_PREFIX + '-win32-arm64',
|
|
75
|
+
bin: BINARY_NAME + '.exe',
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function detectMusl() {
|
|
80
|
+
if (process.platform !== 'linux') return false
|
|
81
|
+
const report =
|
|
82
|
+
typeof process.report?.getReport === 'function'
|
|
83
|
+
? process.report.getReport()
|
|
84
|
+
: null
|
|
85
|
+
return report != null && report.header?.glibcVersionRuntime === undefined
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getPlatformKey() {
|
|
89
|
+
const platform = process.platform
|
|
90
|
+
let cpu = arch()
|
|
91
|
+
if (platform === 'android') return 'linux-' + cpu + '-android'
|
|
92
|
+
if (platform === 'linux')
|
|
93
|
+
return 'linux-' + cpu + (detectMusl() ? '-musl' : '')
|
|
94
|
+
if (platform === 'darwin' && cpu === 'x64') {
|
|
95
|
+
const r = spawnSync('sysctl', ['-n', 'sysctl.proc_translated'], {
|
|
96
|
+
encoding: 'utf8',
|
|
97
|
+
})
|
|
98
|
+
if (r.stdout?.trim() === '1') cpu = 'arm64'
|
|
99
|
+
}
|
|
100
|
+
return platform + '-' + cpu
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function placeBinary(src, dest) {
|
|
104
|
+
try {
|
|
105
|
+
linkSync(src, dest)
|
|
106
|
+
} catch (err) {
|
|
107
|
+
if (err.code === 'EEXIST') {
|
|
108
|
+
const stub = statSync(dest).size < 4096 ? readFileSync(dest) : null
|
|
109
|
+
unlinkSync(dest)
|
|
110
|
+
try {
|
|
111
|
+
linkSync(src, dest)
|
|
112
|
+
} catch {
|
|
113
|
+
try {
|
|
114
|
+
copyFileSync(src, dest)
|
|
115
|
+
} catch (copyErr) {
|
|
116
|
+
if (stub) {
|
|
117
|
+
try {
|
|
118
|
+
writeFileSync(dest, stub, { mode: 0o755 })
|
|
119
|
+
} catch {}
|
|
120
|
+
}
|
|
121
|
+
throw copyErr
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
} else if (err.code === 'EXDEV' || err.code === 'EPERM') {
|
|
125
|
+
copyFileSync(src, dest)
|
|
126
|
+
} else {
|
|
127
|
+
throw err
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (process.platform !== 'win32') chmodSync(dest, 0o755)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// npm install may drop the executable bit on vendored helpers (clipboard-image,
|
|
134
|
+
// ripgrep). Only the main binary was chmod'd before — restore +x under vendor/.
|
|
135
|
+
function ensureVendorBinariesExecutable(pkgDir) {
|
|
136
|
+
if (process.platform === 'win32') return
|
|
137
|
+
|
|
138
|
+
const vendorDir = path.join(pkgDir, 'vendor')
|
|
139
|
+
if (!existsSync(vendorDir)) return
|
|
140
|
+
|
|
141
|
+
const stack = [vendorDir]
|
|
142
|
+
while (stack.length > 0) {
|
|
143
|
+
const dir = stack.pop()
|
|
144
|
+
let entries
|
|
145
|
+
try {
|
|
146
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
147
|
+
} catch {
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
for (const entry of entries) {
|
|
151
|
+
const full = path.join(dir, entry.name)
|
|
152
|
+
if (entry.isDirectory()) {
|
|
153
|
+
stack.push(full)
|
|
154
|
+
continue
|
|
155
|
+
}
|
|
156
|
+
if (!entry.isFile()) continue
|
|
157
|
+
try {
|
|
158
|
+
chmodSync(full, 0o755)
|
|
159
|
+
} catch {
|
|
160
|
+
// Best-effort: missing write permission shouldn't fail install.
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function main() {
|
|
167
|
+
const platformKey = getPlatformKey()
|
|
168
|
+
const info = PLATFORMS[platformKey]
|
|
169
|
+
|
|
170
|
+
if (!info) {
|
|
171
|
+
console.error(
|
|
172
|
+
`[${WRAPPER_NAME} postinstall] Unsupported platform: ${process.platform} ${arch()}`,
|
|
173
|
+
)
|
|
174
|
+
console.error(` Supported: ${Object.keys(PLATFORMS).join(', ')}`)
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const optionalDeps = require('./package.json').optionalDependencies || {}
|
|
179
|
+
if (!optionalDeps[info.pkg]) {
|
|
180
|
+
console.error(
|
|
181
|
+
`[${WRAPPER_NAME} postinstall] Native binaries for ${platformKey} are not available on this release channel.`,
|
|
182
|
+
)
|
|
183
|
+
console.error(
|
|
184
|
+
` Available: ${Object.keys(optionalDeps)
|
|
185
|
+
.map(p => p.replace(PACKAGE_PREFIX + '-', ''))
|
|
186
|
+
.join(', ')}`,
|
|
187
|
+
)
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let pkgDir
|
|
192
|
+
let src
|
|
193
|
+
try {
|
|
194
|
+
pkgDir = path.dirname(require.resolve(info.pkg + '/package.json'))
|
|
195
|
+
src = path.join(pkgDir, info.bin)
|
|
196
|
+
} catch {
|
|
197
|
+
console.error(
|
|
198
|
+
`[${WRAPPER_NAME} postinstall] Native package "${info.pkg}" not found.`,
|
|
199
|
+
)
|
|
200
|
+
console.error(
|
|
201
|
+
' This happens with --omit=optional or when the download failed.',
|
|
202
|
+
)
|
|
203
|
+
console.error(
|
|
204
|
+
' The `claude` command will print instructions when invoked.',
|
|
205
|
+
)
|
|
206
|
+
console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const dest = path.join(__dirname, 'bin', 'claude.exe')
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
placeBinary(src, dest)
|
|
214
|
+
ensureVendorBinariesExecutable(pkgDir)
|
|
215
|
+
} catch (err) {
|
|
216
|
+
console.error(
|
|
217
|
+
`[${WRAPPER_NAME} postinstall] Failed to place binary: ${err.message}`,
|
|
218
|
+
)
|
|
219
|
+
console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
|
|
220
|
+
process.exitCode = 1
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
main()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@go-hare/claude-code",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.34",
|
|
4
4
|
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "DeQiang",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"cli-wrapper.cjs"
|
|
40
40
|
],
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@go-hare/claude-code-darwin-arm64": ">=2.6.
|
|
43
|
-
"@go-hare/claude-code-darwin-x64": ">=2.6.
|
|
44
|
-
"@go-hare/claude-code-linux-x64": ">=2.6.
|
|
45
|
-
"@go-hare/claude-code-linux-arm64": ">=2.6.
|
|
46
|
-
"@go-hare/claude-code-linux-x64-musl": ">=2.6.
|
|
47
|
-
"@go-hare/claude-code-linux-arm64-musl": ">=2.6.
|
|
48
|
-
"@go-hare/claude-code-win32-x64": ">=2.6.
|
|
49
|
-
"@go-hare/claude-code-win32-arm64": ">=2.6.
|
|
42
|
+
"@go-hare/claude-code-darwin-arm64": ">=2.6.34",
|
|
43
|
+
"@go-hare/claude-code-darwin-x64": ">=2.6.34",
|
|
44
|
+
"@go-hare/claude-code-linux-x64": ">=2.6.34",
|
|
45
|
+
"@go-hare/claude-code-linux-arm64": ">=2.6.34",
|
|
46
|
+
"@go-hare/claude-code-linux-x64-musl": ">=2.6.34",
|
|
47
|
+
"@go-hare/claude-code-linux-arm64-musl": ">=2.6.34",
|
|
48
|
+
"@go-hare/claude-code-win32-x64": ">=2.6.34",
|
|
49
|
+
"@go-hare/claude-code-win32-arm64": ">=2.6.34",
|
|
50
50
|
"doubaoime-asr": "^0.1.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|