@bash0816/claude-code 2.1.159-1 → 2.1.159-13
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 +3 -3
- package/config/claude-native-audited-versions.json +63 -0
- package/config/claude-termux-release-manifest.json +3 -3
- package/lib/check-updates.js +1 -11
- package/lib/termux-run-claude-native.sh +311 -194
- package/lib/version-utils.js +24 -0
- package/lib/version-utils.test.js +25 -0
- package/package.json +15 -9
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Current quick examples:
|
|
|
43
43
|
現在の quick example:
|
|
44
44
|
|
|
45
45
|
```sh
|
|
46
|
-
npm install -g @bash0816/claude-code@2.1.
|
|
46
|
+
npm install -g @bash0816/claude-code@2.1.159-13
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
## Update / 更新
|
|
@@ -68,8 +68,8 @@ Normal launch also checks the same manifest with a short timeout and prints a no
|
|
|
68
68
|
|
|
69
69
|
- Only audited versions in `config/claude-native-audited-versions.json` can run.
|
|
70
70
|
- `config/claude-native-audited-versions.json` にある監査済み version だけを実行できます。
|
|
71
|
-
- `2.1.
|
|
72
|
-
- `2.1.
|
|
71
|
+
- `2.1.118`, `2.1.119`, `2.1.121`, `2.1.122`, `2.1.123`, `2.1.126`, `2.1.128`, `2.1.136`, `2.1.137`, `2.1.138`, `2.1.139`, `2.1.140`, `2.1.141`, `2.1.142`, `2.1.143`, `2.1.144`, `2.1.150`, `2.1.150-1`, `2.1.150-2`, `2.1.150-3`, `2.1.153`, `2.1.153-1`, `2.1.153-2`, `2.1.153-3`, `2.1.153-4`, `2.1.157`, `2.1.159-4`, `2.1.159-8`, `2.1.159-10`, `2.1.159-13` are included in the package metadata.
|
|
72
|
+
- `2.1.118`、`2.1.119`、`2.1.121`、`2.1.122`、`2.1.123`、`2.1.126`、`2.1.128`、`2.1.136`、`2.1.137`、`2.1.138`、`2.1.139`、`2.1.140`、`2.1.141`、`2.1.142`、`2.1.143`、`2.1.144`、`2.1.150`、`2.1.150-1`、`2.1.150-2`、`2.1.150-3`、`2.1.153`、`2.1.153-1`、`2.1.153-2`、`2.1.153-3`、`2.1.153-4`、`2.1.157`、`2.1.159-4`、`2.1.159-8`、`2.1.159-10`、`2.1.159-13` を package metadata に含めています。
|
|
73
73
|
- The metadata file is the source of truth for the currently audited set.
|
|
74
74
|
- 現在の監査済み version 集合の source of truth は metadata file です。
|
|
75
75
|
- Native artifacts are cached under `${HOME}/.claude-termux-native-package`.
|
|
@@ -181,6 +181,69 @@
|
|
|
181
181
|
"entry_js_offset": 223210916,
|
|
182
182
|
"entry_end_offset": 238725072,
|
|
183
183
|
"status": "termux_verified"
|
|
184
|
+
},
|
|
185
|
+
"2.1.159-2": {
|
|
186
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
187
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
188
|
+
"entry_js_offset": 223232708,
|
|
189
|
+
"entry_end_offset": 238749397,
|
|
190
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
191
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
192
|
+
"status": "offset_discovered"
|
|
193
|
+
},
|
|
194
|
+
"2.1.159-4": {
|
|
195
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
196
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
197
|
+
"entry_js_offset": 223232708,
|
|
198
|
+
"entry_end_offset": 238749397,
|
|
199
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
200
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
201
|
+
"status": "termux_verified"
|
|
202
|
+
},
|
|
203
|
+
"2.1.159-5": {
|
|
204
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
205
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
206
|
+
"entry_js_offset": 223232708,
|
|
207
|
+
"entry_end_offset": 238749397,
|
|
208
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
209
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
210
|
+
"status": "offset_discovered"
|
|
211
|
+
},
|
|
212
|
+
"2.1.159-8": {
|
|
213
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
214
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
215
|
+
"entry_js_offset": 223232708,
|
|
216
|
+
"entry_end_offset": 238749397,
|
|
217
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
218
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
219
|
+
"status": "termux_verified"
|
|
220
|
+
},
|
|
221
|
+
"2.1.159-10": {
|
|
222
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
223
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
224
|
+
"entry_js_offset": 223232708,
|
|
225
|
+
"entry_end_offset": 238749397,
|
|
226
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
227
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
228
|
+
"status": "termux_verified"
|
|
229
|
+
},
|
|
230
|
+
"2.1.159-12": {
|
|
231
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
232
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
233
|
+
"entry_js_offset": 223232708,
|
|
234
|
+
"entry_end_offset": 238749397,
|
|
235
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
236
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
237
|
+
"status": "offset_discovered"
|
|
238
|
+
},
|
|
239
|
+
"2.1.159-13": {
|
|
240
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.159",
|
|
241
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.159",
|
|
242
|
+
"entry_js_offset": 223232708,
|
|
243
|
+
"entry_end_offset": 238749397,
|
|
244
|
+
"tarball_integrity": "sha512-c8dXbuQdrotGWll46GlnXm5IPpORK2VrBSosCmI6f8t7Snc/3F58fX0MbIjJ/ycXpY0aaKuOnufCuxf7wi1Xqw==",
|
|
245
|
+
"tarball_sha256": "0b551634f11742310ba3b6344fb7912ba1ed8ee0ef4702eab0099d31b4eeb070",
|
|
246
|
+
"status": "termux_verified"
|
|
184
247
|
}
|
|
185
248
|
}
|
|
186
249
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"package_name": "@bash0816/claude-code",
|
|
4
|
-
"latest_audited_version": "2.1.
|
|
5
|
-
"latest_candidate_version": "2.1.
|
|
6
|
-
"previous_stable_version": "2.1.
|
|
4
|
+
"latest_audited_version": "2.1.159-13",
|
|
5
|
+
"latest_candidate_version": "2.1.159-13",
|
|
6
|
+
"previous_stable_version": "2.1.159-10",
|
|
7
7
|
"manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
|
|
8
8
|
}
|
package/lib/check-updates.js
CHANGED
|
@@ -10,6 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const packageDir = path.resolve(__dirname, '..');
|
|
11
11
|
const pkg = require(path.join(packageDir, 'package.json'));
|
|
12
12
|
const localManifest = require(path.join(packageDir, 'config', 'claude-termux-release-manifest.json'));
|
|
13
|
+
const { compareVersions } = require('./version-utils');
|
|
13
14
|
const mode = process.argv[2] || 'notify';
|
|
14
15
|
const currentVersion = process.argv[3] || pkg.version;
|
|
15
16
|
const dryRun = process.argv.includes('--dry-run');
|
|
@@ -20,17 +21,6 @@ const ttlMs = Number(process.env.CLAUDE_TERMUX_UPDATE_CACHE_TTL_MS || String(24
|
|
|
20
21
|
const skipCheck = process.env.CLAUDE_TERMUX_SKIP_UPDATE_CHECK === '1';
|
|
21
22
|
const manifestUrl = process.env.CLAUDE_TERMUX_MANIFEST_URL || localManifest.manifest_url;
|
|
22
23
|
|
|
23
|
-
function compareVersions(a, b) {
|
|
24
|
-
const aParts = String(a).split('.').map(Number);
|
|
25
|
-
const bParts = String(b).split('.').map(Number);
|
|
26
|
-
const len = Math.max(aParts.length, bParts.length);
|
|
27
|
-
for (let index = 0; index < len; index += 1) {
|
|
28
|
-
const diff = (aParts[index] || 0) - (bParts[index] || 0);
|
|
29
|
-
if (diff !== 0) return diff;
|
|
30
|
-
}
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
function readCache() {
|
|
35
25
|
try {
|
|
36
26
|
return JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
@@ -6,7 +6,6 @@ WORKDIR="${WORKDIR:-${HOME}/.claude-termux-native-package/launcher-workdir}"
|
|
|
6
6
|
ENTRY_JS_OFFSET="${ENTRY_JS_OFFSET:?ENTRY_JS_OFFSET is required}"
|
|
7
7
|
ENTRY_END_OFFSET="${ENTRY_END_OFFSET:?ENTRY_END_OFFSET is required}"
|
|
8
8
|
CURRENT_CLAUDE_VERSION="${CURRENT_CLAUDE_VERSION:?CURRENT_CLAUDE_VERSION is required}"
|
|
9
|
-
CLAUDE_TERMUX_PACKAGE_DIR="${CLAUDE_TERMUX_PACKAGE_DIR:?CLAUDE_TERMUX_PACKAGE_DIR is required}"
|
|
10
9
|
TERMUX_TMPDIR="${TMPDIR:-/data/data/com.termux/files/usr/tmp}"
|
|
11
10
|
SSL_CERT_DIR="${SSL_CERT_DIR:-/data/data/com.termux/files/usr/etc/tls}"
|
|
12
11
|
SSL_CERT_FILE="${SSL_CERT_FILE:-/data/data/com.termux/files/usr/etc/tls/cert.pem}"
|
|
@@ -39,31 +38,30 @@ export WORKDIR
|
|
|
39
38
|
export ENTRY_JS_OFFSET
|
|
40
39
|
export ENTRY_END_OFFSET
|
|
41
40
|
export CURRENT_CLAUDE_VERSION
|
|
41
|
+
export CLAUDE_TERMUX_PACKAGE_DIR="${CLAUDE_TERMUX_PACKAGE_DIR:-}"
|
|
42
|
+
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="${CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:-1}"
|
|
43
|
+
export ENABLE_CLAUDEAI_MCP_SERVERS="${ENABLE_CLAUDEAI_MCP_SERVERS:-0}"
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
for _a in "$@"; do
|
|
45
|
-
case "$_a" in
|
|
46
|
-
-p|--print) _pf=1; break ;;
|
|
47
|
-
--) break ;;
|
|
48
|
-
esac
|
|
49
|
-
done
|
|
50
|
-
|
|
51
|
-
if [ "$_pf" = "1" ] && [ "${CLAUDE_TERMUX_STDIN:-}" != "inherit" ]; then
|
|
52
|
-
_helper=$(mktemp "${TMPDIR:-/tmp}/claude-helper.XXXXXX.js")
|
|
53
|
-
trap 'rm -f "$_helper"' EXIT HUP INT TERM
|
|
54
|
-
cat <<'NODE' > "$_helper"
|
|
45
|
+
node - "$@" <<'NODE'
|
|
55
46
|
const fs = require('fs');
|
|
56
47
|
const path = require('path');
|
|
57
|
-
const {
|
|
58
|
-
BLOCK_MESSAGE,
|
|
59
|
-
createGuardedChildProcess,
|
|
60
|
-
} = require(path.join(process.env.CLAUDE_TERMUX_PACKAGE_DIR, 'lib', 'native-update-guard.js'));
|
|
61
48
|
|
|
62
49
|
const sourceBin = process.env.SOURCE_BIN;
|
|
63
50
|
const workdir = process.env.WORKDIR;
|
|
64
51
|
const entryJsOffset = Number(process.env.ENTRY_JS_OFFSET);
|
|
65
52
|
const entryEndOffset = Number(process.env.ENTRY_END_OFFSET);
|
|
66
53
|
const argv = process.argv.slice(2);
|
|
54
|
+
const packageDir = process.env.CLAUDE_TERMUX_PACKAGE_DIR || "";
|
|
55
|
+
function loadNativeUpdateGuard() {
|
|
56
|
+
if (!packageDir) return null;
|
|
57
|
+
const guardPath = path.join(packageDir, 'lib', 'native-update-guard.js');
|
|
58
|
+
if (!fs.existsSync(guardPath)) return null;
|
|
59
|
+
try { return require(guardPath); } catch (e) {
|
|
60
|
+
process.stderr.write('[termux] native-update-guard load failed: ' + e.message + '\n');
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const _nativeUpdateGuard = loadNativeUpdateGuard();
|
|
67
65
|
|
|
68
66
|
class RequestedExit extends Error {
|
|
69
67
|
constructor(code) {
|
|
@@ -100,207 +98,244 @@ function stringWidth(value) {
|
|
|
100
98
|
return Array.from(text).length;
|
|
101
99
|
}
|
|
102
100
|
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
function rewriteArgs(args) {
|
|
107
|
-
if (
|
|
108
|
-
Array.isArray(args) &&
|
|
109
|
-
args[0] === 'xdg-open' &&
|
|
110
|
-
Array.isArray(args[1]) &&
|
|
111
|
-
typeof args[1][0] === 'string'
|
|
112
|
-
) {
|
|
113
|
-
return ['termux-open-url', [args[1][0]], ...args.slice(2)];
|
|
114
|
-
}
|
|
115
|
-
return args;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const guardedChild = createGuardedChildProcess(
|
|
119
|
-
{
|
|
120
|
-
spawn: (...args) => realChild.spawn(...rewriteArgs(args)),
|
|
121
|
-
execFile: (...args) => realChild.execFile(...args),
|
|
122
|
-
exec: (...args) => realChild.exec(...args),
|
|
123
|
-
spawnSync: (...args) => realChild.spawnSync(...rewriteArgs(args)),
|
|
124
|
-
execFileSync: (...args) => realChild.execFileSync(...args),
|
|
125
|
-
execSync: (...args) => realChild.execSync(...args),
|
|
126
|
-
},
|
|
127
|
-
value => process.stderr.write(value),
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
return function fakeRequire(id) {
|
|
131
|
-
if (id === 'ws') {
|
|
132
|
-
class WS {
|
|
133
|
-
on() {}
|
|
134
|
-
once() {}
|
|
135
|
-
addEventListener() {}
|
|
136
|
-
close() {}
|
|
137
|
-
send() {}
|
|
138
|
-
ping() {}
|
|
139
|
-
}
|
|
140
|
-
return { default: WS, WebSocket: WS };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (id === 'child_process') {
|
|
144
|
-
return guardedChild;
|
|
145
|
-
}
|
|
101
|
+
function stripANSI(text) {
|
|
102
|
+
return String(text ?? '').replace(/\u001B\[[0-9;]*m/g, '');
|
|
103
|
+
}
|
|
146
104
|
|
|
147
|
-
|
|
148
|
-
|
|
105
|
+
function wrapAnsi(text, columns) {
|
|
106
|
+
const value = String(text ?? '');
|
|
107
|
+
const width = Number(columns);
|
|
108
|
+
if (!Number.isFinite(width) || width <= 0) return value;
|
|
109
|
+
|
|
110
|
+
let lineWidth = 0;
|
|
111
|
+
let result = '';
|
|
112
|
+
for (const ch of value) {
|
|
113
|
+
if (ch === '\n') {
|
|
114
|
+
result += ch;
|
|
115
|
+
lineWidth = 0;
|
|
116
|
+
continue;
|
|
149
117
|
}
|
|
150
118
|
|
|
151
|
-
|
|
152
|
-
|
|
119
|
+
const chWidth = stringWidth(ch);
|
|
120
|
+
if (lineWidth > 0 && lineWidth + chWidth > width) {
|
|
121
|
+
result += '\n';
|
|
122
|
+
lineWidth = 0;
|
|
153
123
|
}
|
|
154
124
|
|
|
155
|
-
|
|
156
|
-
|
|
125
|
+
result += ch;
|
|
126
|
+
lineWidth += chWidth;
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
157
129
|
}
|
|
158
130
|
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
131
|
+
function hash(value) {
|
|
132
|
+
const crypto = require('crypto');
|
|
133
|
+
const digest = crypto.createHash('sha256').update(String(value ?? '')).digest();
|
|
134
|
+
return digest.readUInt32LE(0);
|
|
135
|
+
}
|
|
163
136
|
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
137
|
+
function compareSemver(left, right) {
|
|
138
|
+
const a = String(left).replace(/^[^0-9]*/, '').split('.').map(Number);
|
|
139
|
+
const b = String(right).replace(/^[^0-9]*/, '').split('.').map(Number);
|
|
140
|
+
const size = Math.max(a.length, b.length);
|
|
141
|
+
for (let i = 0; i < size; i += 1) {
|
|
142
|
+
const diff = (a[i] || 0) - (b[i] || 0);
|
|
143
|
+
if (diff !== 0) return diff > 0 ? 1 : -1;
|
|
144
|
+
}
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
170
147
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
148
|
+
function satisfiesSemver(version, range) {
|
|
149
|
+
const cleanRange = String(range ?? '').trim();
|
|
150
|
+
const match = cleanRange.match(/^([><=!]{1,2})\s*([0-9][^\s]*)$/);
|
|
151
|
+
if (!match) {
|
|
152
|
+
return /^[0-9]+(?:\.[0-9]+){0,2}$/.test(cleanRange)
|
|
153
|
+
? compareSemver(version, cleanRange) === 0
|
|
154
|
+
: true;
|
|
174
155
|
}
|
|
175
156
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
157
|
+
const [, op, target] = match;
|
|
158
|
+
const cmp = compareSemver(version, target);
|
|
159
|
+
if (op === '>') return cmp > 0;
|
|
160
|
+
if (op === '>=') return cmp >= 0;
|
|
161
|
+
if (op === '<') return cmp < 0;
|
|
162
|
+
if (op === '<=') return cmp <= 0;
|
|
163
|
+
if (op === '=' || op === '==') return cmp === 0;
|
|
164
|
+
if (op === '!=') return cmp !== 0;
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
185
167
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
else delete globalThis.Bun;
|
|
168
|
+
function createSemverShim() {
|
|
169
|
+
return {
|
|
170
|
+
order: compareSemver,
|
|
171
|
+
compare: compareSemver,
|
|
172
|
+
satisfies: satisfiesSemver,
|
|
173
|
+
gt: (left, right) => compareSemver(left, right) > 0,
|
|
174
|
+
gte: (left, right) => compareSemver(left, right) >= 0,
|
|
175
|
+
lt: (left, right) => compareSemver(left, right) < 0,
|
|
176
|
+
lte: (left, right) => compareSemver(left, right) <= 0,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function parseScalar(value) {
|
|
181
|
+
const text = String(value ?? '').trim();
|
|
182
|
+
if (text === '') return '';
|
|
183
|
+
if (text === 'true') return true;
|
|
184
|
+
if (text === 'false') return false;
|
|
185
|
+
if (text === 'null' || text === '~') return null;
|
|
186
|
+
if (/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/.test(text)) return Number(text);
|
|
187
|
+
if (
|
|
188
|
+
(text.startsWith('"') && text.endsWith('"')) ||
|
|
189
|
+
(text.startsWith("'") && text.endsWith("'"))
|
|
190
|
+
) {
|
|
191
|
+
return text.slice(1, -1);
|
|
211
192
|
}
|
|
193
|
+
return text;
|
|
212
194
|
}
|
|
213
195
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
196
|
+
function parseInlineArray(value) {
|
|
197
|
+
const inner = String(value ?? '').trim().slice(1, -1).trim();
|
|
198
|
+
if (inner === '') return [];
|
|
199
|
+
const items = [];
|
|
200
|
+
let current = '';
|
|
201
|
+
let quote = null;
|
|
202
|
+
|
|
203
|
+
for (let i = 0; i < inner.length; i += 1) {
|
|
204
|
+
const ch = inner[i];
|
|
205
|
+
if (quote) {
|
|
206
|
+
if (ch === quote && inner[i - 1] !== '\\') quote = null;
|
|
207
|
+
current += ch;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (ch === '"' || ch === "'") {
|
|
211
|
+
quote = ch;
|
|
212
|
+
current += ch;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (ch === ',') {
|
|
216
|
+
items.push(parseScalar(current));
|
|
217
|
+
current = '';
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
current += ch;
|
|
218
221
|
}
|
|
219
|
-
console.error(error && error.stack ? error.stack : String(error));
|
|
220
|
-
process.exit(1);
|
|
221
|
-
});
|
|
222
|
-
NODE
|
|
223
|
-
node "$_helper" "$@" </dev/null
|
|
224
|
-
_status=$?
|
|
225
|
-
rm -f "$_helper"
|
|
226
|
-
trap - EXIT HUP INT TERM
|
|
227
|
-
exit "$_status"
|
|
228
|
-
else
|
|
229
|
-
exec node - "$@" <<'NODE'
|
|
230
|
-
const fs = require('fs');
|
|
231
|
-
const path = require('path');
|
|
232
|
-
const {
|
|
233
|
-
BLOCK_MESSAGE,
|
|
234
|
-
createGuardedChildProcess,
|
|
235
|
-
} = require(path.join(process.env.CLAUDE_TERMUX_PACKAGE_DIR, 'lib', 'native-update-guard.js'));
|
|
236
222
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const entryEndOffset = Number(process.env.ENTRY_END_OFFSET);
|
|
241
|
-
const argv = process.argv.slice(2);
|
|
223
|
+
if (current !== '') items.push(parseScalar(current));
|
|
224
|
+
return items;
|
|
225
|
+
}
|
|
242
226
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
227
|
+
function yamlParse(text) {
|
|
228
|
+
const source = String(text ?? '');
|
|
229
|
+
const result = {};
|
|
230
|
+
for (const rawLine of source.split(/\r?\n/)) {
|
|
231
|
+
const line = rawLine.trim();
|
|
232
|
+
if (!line || line.startsWith('#')) continue;
|
|
233
|
+
const idx = line.indexOf(':');
|
|
234
|
+
if (idx < 0) continue;
|
|
235
|
+
const key = line.slice(0, idx).trim();
|
|
236
|
+
const rawValue = line.slice(idx + 1).trim();
|
|
237
|
+
if (!key) continue;
|
|
238
|
+
result[key] = rawValue.startsWith('[') && rawValue.endsWith(']')
|
|
239
|
+
? parseInlineArray(rawValue)
|
|
240
|
+
: parseScalar(rawValue);
|
|
248
241
|
}
|
|
242
|
+
return result;
|
|
249
243
|
}
|
|
250
244
|
|
|
251
|
-
function
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
245
|
+
function yamlStringify(value) {
|
|
246
|
+
if (!value || typeof value !== 'object') return String(value ?? '');
|
|
247
|
+
const lines = [];
|
|
248
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
249
|
+
if (Array.isArray(raw)) {
|
|
250
|
+
lines.push(`${key}: [${raw.map(item => JSON.stringify(String(item))).join(', ')}]`);
|
|
251
|
+
} else if (raw === null) {
|
|
252
|
+
lines.push(`${key}: null`);
|
|
253
|
+
} else if (typeof raw === 'string') {
|
|
254
|
+
lines.push(`${key}: ${JSON.stringify(raw)}`);
|
|
255
|
+
} else {
|
|
256
|
+
lines.push(`${key}: ${String(raw)}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return lines.join('\n');
|
|
265
260
|
}
|
|
266
261
|
|
|
267
|
-
function
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
return Array.from(text).length;
|
|
262
|
+
function createYamlShim() {
|
|
263
|
+
const yaml = {
|
|
264
|
+
parse: yamlParse,
|
|
265
|
+
stringify: yamlStringify,
|
|
266
|
+
};
|
|
267
|
+
yaml.YAML = yaml;
|
|
268
|
+
yaml.default = yaml;
|
|
269
|
+
return yaml;
|
|
276
270
|
}
|
|
277
271
|
|
|
278
272
|
function createFakeRequire(realRequire) {
|
|
279
273
|
const realChild = realRequire('child_process');
|
|
280
|
-
|
|
274
|
+
const realVm = realRequire('vm');
|
|
281
275
|
function rewriteArgs(args) {
|
|
282
|
-
if (
|
|
283
|
-
Array.isArray(args) &&
|
|
284
|
-
args[0] === 'xdg-open' &&
|
|
285
|
-
Array.isArray(args[1]) &&
|
|
286
|
-
typeof args[1][0] === 'string'
|
|
287
|
-
) {
|
|
276
|
+
if (Array.isArray(args) && args[0] === 'xdg-open' && Array.isArray(args[1]) && typeof args[1][0] === 'string') {
|
|
288
277
|
return ['termux-open-url', [args[1][0]], ...args.slice(2)];
|
|
289
278
|
}
|
|
290
279
|
return args;
|
|
291
280
|
}
|
|
281
|
+
const _baseChild = {
|
|
282
|
+
spawn: (...args) => realChild.spawn(...rewriteArgs(args)),
|
|
283
|
+
execFile: (...args) => realChild.execFile(...args),
|
|
284
|
+
exec: (...args) => realChild.exec(...args),
|
|
285
|
+
spawnSync: (...args) => realChild.spawnSync(...rewriteArgs(args)),
|
|
286
|
+
execFileSync: (...args) => realChild.execFileSync(...args),
|
|
287
|
+
execSync: (...args) => realChild.execSync(...args),
|
|
288
|
+
};
|
|
289
|
+
const guardedChild = _nativeUpdateGuard
|
|
290
|
+
? _nativeUpdateGuard.createGuardedChildProcess(_baseChild, v => process.stderr.write(v))
|
|
291
|
+
: _baseChild;
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
293
|
+
function injectBunIntoContext(context) {
|
|
294
|
+
if (!context || typeof context !== 'object') return context;
|
|
295
|
+
try {
|
|
296
|
+
if (!Object.prototype.hasOwnProperty.call(context, '__claudeBunShim')) {
|
|
297
|
+
Object.defineProperty(context, '__claudeBunShim', {
|
|
298
|
+
value: globalThis.__claudeBunShim,
|
|
299
|
+
configurable: true,
|
|
300
|
+
writable: true,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
if (!Object.prototype.hasOwnProperty.call(context, '__claudeYaml')) {
|
|
304
|
+
Object.defineProperty(context, '__claudeYaml', {
|
|
305
|
+
value: globalThis.__claudeYaml,
|
|
306
|
+
configurable: true,
|
|
307
|
+
writable: true,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
if (Object.prototype.hasOwnProperty.call(context, 'Bun')) {
|
|
311
|
+
if (context.Bun && typeof context.Bun === 'object' && context.Bun !== globalThis.Bun) {
|
|
312
|
+
try {
|
|
313
|
+
context.Bun = globalThis.Bun;
|
|
314
|
+
} catch {
|
|
315
|
+
Object.defineProperty(context, 'Bun', {
|
|
316
|
+
value: globalThis.Bun,
|
|
317
|
+
configurable: true,
|
|
318
|
+
writable: true,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (!context.Bun || typeof context.Bun !== 'object') {
|
|
323
|
+
Object.defineProperty(context, 'Bun', {
|
|
324
|
+
value: globalThis.Bun,
|
|
325
|
+
configurable: true,
|
|
326
|
+
writable: true,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
Object.defineProperty(context, 'Bun', {
|
|
331
|
+
value: globalThis.Bun,
|
|
332
|
+
configurable: true,
|
|
333
|
+
writable: true,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
} catch {}
|
|
337
|
+
return context;
|
|
338
|
+
}
|
|
304
339
|
|
|
305
340
|
return function fakeRequire(id) {
|
|
306
341
|
if (id === 'ws') {
|
|
@@ -315,6 +350,36 @@ function createFakeRequire(realRequire) {
|
|
|
315
350
|
return { default: WS, WebSocket: WS };
|
|
316
351
|
}
|
|
317
352
|
|
|
353
|
+
if (id === 'vm') {
|
|
354
|
+
if (!realVm.__bunShimPatched) {
|
|
355
|
+
const originalCreateContext = realVm.createContext.bind(realVm);
|
|
356
|
+
const originalRunInNewContext = realVm.runInNewContext.bind(realVm);
|
|
357
|
+
const ScriptProto = realVm.Script && realVm.Script.prototype;
|
|
358
|
+
|
|
359
|
+
realVm.createContext = (contextObject, ...rest) =>
|
|
360
|
+
originalCreateContext(injectBunIntoContext(contextObject), ...rest);
|
|
361
|
+
realVm.runInNewContext = (code, contextObject, ...rest) =>
|
|
362
|
+
originalRunInNewContext(code, injectBunIntoContext(contextObject), ...rest);
|
|
363
|
+
|
|
364
|
+
if (ScriptProto && !ScriptProto.__bunShimPatched) {
|
|
365
|
+
const originalRunInContext = ScriptProto.runInContext;
|
|
366
|
+
const originalRunInNewContext = ScriptProto.runInNewContext;
|
|
367
|
+
|
|
368
|
+
ScriptProto.runInContext = function (contextObject, ...rest) {
|
|
369
|
+
return originalRunInContext.call(this, injectBunIntoContext(contextObject), ...rest);
|
|
370
|
+
};
|
|
371
|
+
ScriptProto.runInNewContext = function (contextObject, ...rest) {
|
|
372
|
+
return originalRunInNewContext.call(this, injectBunIntoContext(contextObject), ...rest);
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
Object.defineProperty(ScriptProto, '__bunShimPatched', { value: true });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
Object.defineProperty(realVm, '__bunShimPatched', { value: true });
|
|
379
|
+
}
|
|
380
|
+
return realVm;
|
|
381
|
+
}
|
|
382
|
+
|
|
318
383
|
if (id === 'child_process') {
|
|
319
384
|
return guardedChild;
|
|
320
385
|
}
|
|
@@ -323,6 +388,14 @@ function createFakeRequire(realRequire) {
|
|
|
323
388
|
return guardedChild;
|
|
324
389
|
}
|
|
325
390
|
|
|
391
|
+
if (id === 'yaml' || id === 'yamljs' || id === 'js-yaml') {
|
|
392
|
+
return createYamlShim();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (id === 'vm' || id === 'node:vm') {
|
|
396
|
+
return realVm;
|
|
397
|
+
}
|
|
398
|
+
|
|
326
399
|
if (id.startsWith('/$bunfs/root/')) {
|
|
327
400
|
throw new Error('bunfs require blocked: ' + id);
|
|
328
401
|
}
|
|
@@ -332,8 +405,31 @@ function createFakeRequire(realRequire) {
|
|
|
332
405
|
}
|
|
333
406
|
|
|
334
407
|
async function main() {
|
|
408
|
+
let bunShim;
|
|
335
409
|
const extractedFile = ensureEntryFile();
|
|
336
|
-
|
|
410
|
+
let code = fs.readFileSync(extractedFile, 'utf8');
|
|
411
|
+
globalThis.__claudeYaml = createYamlShim();
|
|
412
|
+
if (!globalThis.__claudeBunShim || typeof globalThis.__claudeBunShim !== 'object') {
|
|
413
|
+
globalThis.__claudeBunShim = {};
|
|
414
|
+
}
|
|
415
|
+
code = code.replace(
|
|
416
|
+
/^function\(exports, require, module, __filename, __dirname\) \{/,
|
|
417
|
+
'function(exports, require, module, __filename, __dirname) {var __claudeBun = globalThis.__claudeBunShim;',
|
|
418
|
+
);
|
|
419
|
+
const patchedCode = code.replace(
|
|
420
|
+
/\btypeof Bun\b/g,
|
|
421
|
+
'typeof __claudeBun',
|
|
422
|
+
).replace(
|
|
423
|
+
/\bBun\./g,
|
|
424
|
+
'__claudeBun.',
|
|
425
|
+
).replace(
|
|
426
|
+
/function t5q\(q\)\{return Bun\.YAML\.parse\(q\)\}/g,
|
|
427
|
+
'function t5q(q){return globalThis.__claudeYaml.parse(q)}',
|
|
428
|
+
).replace(
|
|
429
|
+
/function VK6\(q\)\{return Bun\.YAML\.stringify\(q,null,2\)\+`/g,
|
|
430
|
+
'function VK6(q){return globalThis.__claudeYaml.stringify(q,null,2)+`',
|
|
431
|
+
);
|
|
432
|
+
code = patchedCode;
|
|
337
433
|
const fn = eval('(' + code);
|
|
338
434
|
|
|
339
435
|
const originalArgv = process.argv.slice();
|
|
@@ -352,7 +448,26 @@ async function main() {
|
|
|
352
448
|
process.once('uncaughtException', onAsyncError);
|
|
353
449
|
process.once('unhandledRejection', onAsyncError);
|
|
354
450
|
Object.defineProperty(process.versions, 'bun', { value: '1.1.8', configurable: true });
|
|
355
|
-
globalThis.Bun = {
|
|
451
|
+
globalThis.Bun = {
|
|
452
|
+
version: '1.1.8',
|
|
453
|
+
gc: () => {},
|
|
454
|
+
hash,
|
|
455
|
+
stripANSI,
|
|
456
|
+
YAML: createYamlShim(),
|
|
457
|
+
stringWidth,
|
|
458
|
+
which: cmd => {
|
|
459
|
+
try {
|
|
460
|
+
return require('child_process').execFileSync('which', [String(cmd)], { encoding: 'utf8' }).trim() || null;
|
|
461
|
+
} catch {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
wrapAnsi,
|
|
466
|
+
semver: createSemverShim(),
|
|
467
|
+
};
|
|
468
|
+
Object.assign(globalThis.__claudeBunShim, globalThis.Bun);
|
|
469
|
+
globalThis.Bun = globalThis.__claudeBunShim;
|
|
470
|
+
bunShim = globalThis.Bun;
|
|
356
471
|
process.argv = ['node', extractedFile, ...argv];
|
|
357
472
|
process.exit = code => {
|
|
358
473
|
throw new RequestedExit(code);
|
|
@@ -361,9 +476,14 @@ async function main() {
|
|
|
361
476
|
const moduleLike = { exports: {} };
|
|
362
477
|
const maybePromise = fn(moduleLike.exports, fakeRequire, moduleLike, extractedFile, workdir);
|
|
363
478
|
if (maybePromise && typeof maybePromise.then === 'function') await maybePromise;
|
|
364
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
479
|
+
await new Promise(resolve => setTimeout(resolve, Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 1000)));
|
|
365
480
|
if (asyncErrors.length > 0) throw asyncErrors[0];
|
|
366
481
|
} catch (error) {
|
|
482
|
+
if (_nativeUpdateGuard && error && error.code === 'CLAUDE_TERMUX_OFFICIAL_UPDATE_BLOCKED') {
|
|
483
|
+
console.error(_nativeUpdateGuard.BLOCK_MESSAGE);
|
|
484
|
+
process.exitCode = error.status || 1;
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
367
487
|
if (error instanceof RequestedExit) {
|
|
368
488
|
process.exitCode = error.code;
|
|
369
489
|
return;
|
|
@@ -381,18 +501,15 @@ async function main() {
|
|
|
381
501
|
Object.defineProperty(process.versions, 'bun', { value: originalBun, configurable: true });
|
|
382
502
|
}
|
|
383
503
|
} catch {}
|
|
504
|
+
delete globalThis.__claudeYaml;
|
|
505
|
+
delete globalThis.__claudeBunShim;
|
|
506
|
+
delete globalThis.Bun;
|
|
384
507
|
if (hadGlobalBun) globalThis.Bun = originalGlobalBun;
|
|
385
|
-
else delete globalThis.Bun;
|
|
386
508
|
}
|
|
387
509
|
}
|
|
388
510
|
|
|
389
511
|
main().catch(error => {
|
|
390
|
-
if (error && error.code === 'CLAUDE_TERMUX_OFFICIAL_UPDATE_BLOCKED') {
|
|
391
|
-
console.error(BLOCK_MESSAGE);
|
|
392
|
-
process.exit(error.status || 1);
|
|
393
|
-
}
|
|
394
512
|
console.error(error && error.stack ? error.stack : String(error));
|
|
395
513
|
process.exit(1);
|
|
396
514
|
});
|
|
397
515
|
NODE
|
|
398
|
-
fi
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function parseVersion(v) {
|
|
4
|
+
const str = String(v);
|
|
5
|
+
const dashIdx = str.lastIndexOf('-');
|
|
6
|
+
if (dashIdx !== -1) {
|
|
7
|
+
const base = str.slice(0, dashIdx);
|
|
8
|
+
const suffix = Number(str.slice(dashIdx + 1));
|
|
9
|
+
return { parts: base.split('.').map(Number), suffix: isNaN(suffix) ? 0 : suffix };
|
|
10
|
+
}
|
|
11
|
+
return { parts: str.split('.').map(Number), suffix: 0 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function compareVersions(a, b) {
|
|
15
|
+
const ap = parseVersion(a), bp = parseVersion(b);
|
|
16
|
+
const len = Math.max(ap.parts.length, bp.parts.length);
|
|
17
|
+
for (let i = 0; i < len; i++) {
|
|
18
|
+
const diff = (ap.parts[i] || 0) - (bp.parts[i] || 0);
|
|
19
|
+
if (diff !== 0) return diff;
|
|
20
|
+
}
|
|
21
|
+
return ap.suffix - bp.suffix;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { parseVersion, compareVersions };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
const assert = require('node:assert/strict');
|
|
5
|
+
|
|
6
|
+
const { parseVersion, compareVersions } = require('./version-utils');
|
|
7
|
+
|
|
8
|
+
test('parseVersion splits suffix versions', () => {
|
|
9
|
+
assert.deepEqual(parseVersion('2.1.159-2'), {
|
|
10
|
+
parts: [2, 1, 159],
|
|
11
|
+
suffix: 2,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('compareVersions orders suffix versions after the base release', () => {
|
|
16
|
+
assert.equal(compareVersions('2.1.159', '2.1.159-1') < 0, true);
|
|
17
|
+
assert.equal(compareVersions('2.1.159-1', '2.1.159-2') < 0, true);
|
|
18
|
+
assert.equal(compareVersions('2.1.159-2', '2.1.159') > 0, true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('compareVersions preserves numeric ordering across patch versions', () => {
|
|
22
|
+
assert.equal(compareVersions('2.1.136', '2.1.137') < 0, true);
|
|
23
|
+
assert.equal(compareVersions('2.1.137', '2.1.136') > 0, true);
|
|
24
|
+
assert.equal(compareVersions('2.1.137', '2.1.137'), 0);
|
|
25
|
+
});
|
package/package.json
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bash0816/claude-code",
|
|
3
|
-
"version": "2.1.159-
|
|
4
|
-
"description": "Termux-native Claude Code wrapper with audited native replay",
|
|
3
|
+
"version": "2.1.159-13",
|
|
4
|
+
"description": "Unofficial Termux-native Claude Code wrapper with audited native replay",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
7
7
|
"claude": "bin/claude"
|
|
8
8
|
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"preinstall": "node lib/preinstall.js",
|
|
11
|
-
"postinstall": "node lib/postinstall.js"
|
|
12
|
-
},
|
|
9
|
+
"scripts": {},
|
|
13
10
|
"files": [
|
|
14
|
-
"bin",
|
|
15
|
-
"lib",
|
|
16
|
-
"config",
|
|
11
|
+
"bin/",
|
|
12
|
+
"lib/",
|
|
13
|
+
"config/",
|
|
17
14
|
"README.md"
|
|
18
15
|
],
|
|
19
16
|
"engines": {
|
|
20
17
|
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"claude-code",
|
|
21
|
+
"termux",
|
|
22
|
+
"android",
|
|
23
|
+
"wrapper"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
21
27
|
}
|
|
22
28
|
}
|