@bash0816/claude-code 2.1.157 → 2.1.159

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.
@@ -6,6 +6,7 @@ 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}"
9
10
  TERMUX_TMPDIR="${TMPDIR:-/data/data/com.termux/files/usr/tmp}"
10
11
  SSL_CERT_DIR="${SSL_CERT_DIR:-/data/data/com.termux/files/usr/etc/tls}"
11
12
  SSL_CERT_FILE="${SSL_CERT_FILE:-/data/data/com.termux/files/usr/etc/tls/cert.pem}"
@@ -42,6 +43,10 @@ export CURRENT_CLAUDE_VERSION
42
43
  node - "$@" <<'NODE'
43
44
  const fs = require('fs');
44
45
  const path = require('path');
46
+ const {
47
+ BLOCK_MESSAGE,
48
+ createGuardedChildProcess,
49
+ } = require(path.join(process.env.CLAUDE_TERMUX_PACKAGE_DIR, 'lib', 'native-update-guard.js'));
45
50
 
46
51
  const sourceBin = process.env.SOURCE_BIN;
47
52
  const workdir = process.env.WORKDIR;
@@ -73,8 +78,20 @@ function ensureEntryFile() {
73
78
  return extractedFile;
74
79
  }
75
80
 
81
+ function stringWidth(value) {
82
+ const text = String(value ?? '');
83
+ if (typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function') {
84
+ const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
85
+ let width = 0;
86
+ for (const _segment of segmenter.segment(text)) width += 1;
87
+ return width;
88
+ }
89
+ return Array.from(text).length;
90
+ }
91
+
76
92
  function createFakeRequire(realRequire) {
77
93
  const realChild = realRequire('child_process');
94
+
78
95
  function rewriteArgs(args) {
79
96
  if (
80
97
  Array.isArray(args) &&
@@ -87,6 +104,18 @@ function createFakeRequire(realRequire) {
87
104
  return args;
88
105
  }
89
106
 
107
+ const guardedChild = createGuardedChildProcess(
108
+ {
109
+ spawn: (...args) => realChild.spawn(...rewriteArgs(args)),
110
+ execFile: (...args) => realChild.execFile(...args),
111
+ exec: (...args) => realChild.exec(...args),
112
+ spawnSync: (...args) => realChild.spawnSync(...rewriteArgs(args)),
113
+ execFileSync: (...args) => realChild.execFileSync(...args),
114
+ execSync: (...args) => realChild.execSync(...args),
115
+ },
116
+ value => process.stderr.write(value),
117
+ );
118
+
90
119
  return function fakeRequire(id) {
91
120
  if (id === 'ws') {
92
121
  class WS {
@@ -101,14 +130,11 @@ function createFakeRequire(realRequire) {
101
130
  }
102
131
 
103
132
  if (id === 'child_process') {
104
- return {
105
- spawn: (...args) => realChild.spawn(...rewriteArgs(args)),
106
- execFile: (...args) => realChild.execFile(...args),
107
- exec: (...args) => realChild.exec(...args),
108
- spawnSync: (...args) => realChild.spawnSync(...rewriteArgs(args)),
109
- execFileSync: (...args) => realChild.execFileSync(...args),
110
- execSync: (...args) => realChild.execSync(...args),
111
- };
133
+ return guardedChild;
134
+ }
135
+
136
+ if (id === 'node:child_process') {
137
+ return guardedChild;
112
138
  }
113
139
 
114
140
  if (id.startsWith('/$bunfs/root/')) {
@@ -119,336 +145,6 @@ function createFakeRequire(realRequire) {
119
145
  };
120
146
  }
121
147
 
122
- const ansiPattern =
123
- /[\u001B\u009B][[\]()#;?]*(?:(?:(?:;[-a-zA-Z\d\/\#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d\/\#&.:=?%@~_]*)*)?(?:\u0007|\u001B\u005C|\u009C)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;
124
- const ansiPatternSingle = new RegExp(ansiPattern.source);
125
- const debugBunShim = process.env.CLAUDE_TERMUX_DEBUG_BUN_SHIM === '1';
126
-
127
- function stripANSI(text) {
128
- if (typeof text !== 'string' || text.length === 0) return '';
129
- return text.replace(ansiPattern, '');
130
- }
131
-
132
- function codePointWidth(codePoint) {
133
- if (
134
- codePoint <= 0x1f ||
135
- (codePoint >= 0x7f && codePoint <= 0x9f) ||
136
- (codePoint >= 0x300 && codePoint <= 0x36f) ||
137
- (codePoint >= 0x200b && codePoint <= 0x200f) ||
138
- codePoint === 0xfeff ||
139
- (codePoint >= 0xfe00 && codePoint <= 0xfe0f)
140
- ) {
141
- return 0;
142
- }
143
-
144
- if (
145
- (codePoint >= 0x1100 && codePoint <= 0x115f) ||
146
- (codePoint >= 0x2329 && codePoint <= 0x232a) ||
147
- (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
148
- (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
149
- (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
150
- (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
151
- (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
152
- (codePoint >= 0xff00 && codePoint <= 0xff60) ||
153
- (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
154
- (codePoint >= 0x1f300 && codePoint <= 0x1faf8) ||
155
- (codePoint >= 0x20000 && codePoint <= 0x3fffd)
156
- ) {
157
- return 2;
158
- }
159
-
160
- return 1;
161
- }
162
-
163
- function stringWidth(value) {
164
- const text = stripANSI(typeof value === 'string' ? value : String(value ?? ''));
165
- let width = 0;
166
- for (const char of text) {
167
- const codePoint = char.codePointAt(0);
168
- width += codePointWidth(codePoint);
169
- }
170
- return width;
171
- }
172
-
173
- function toHashBytes(value) {
174
- if (Buffer.isBuffer(value)) return Buffer.from(value);
175
- if (value instanceof Uint8Array) return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
176
- if (value instanceof ArrayBuffer) return Buffer.from(value);
177
- if (ArrayBuffer.isView(value)) {
178
- return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
179
- }
180
- return Buffer.from(String(value ?? ''));
181
- }
182
-
183
- function hashValue(value, seed = 0) {
184
- const FNV_OFFSET_BASIS_64 = 0xcbf29ce484222325n;
185
- const FNV_PRIME_64 = 0x100000001b3n;
186
- const MASK_64 = 0xffffffffffffffffn;
187
-
188
- const seedNumber = typeof seed === 'bigint' ? Number(seed) : Number(seed);
189
- const seedValue = Number.isFinite(seedNumber) ? Math.trunc(seedNumber) : 0;
190
- let result = BigInt.asUintN(64, FNV_OFFSET_BASIS_64 ^ BigInt(seedValue));
191
-
192
- const bytes = toHashBytes(value);
193
- for (const byte of bytes) {
194
- result ^= BigInt(byte);
195
- result = (result * FNV_PRIME_64) & MASK_64;
196
- }
197
-
198
- return BigInt(result);
199
- }
200
-
201
- function which(cmd) {
202
- const fs = require('fs');
203
- const path = require('path');
204
-
205
- if (typeof cmd !== 'string' || cmd.length === 0) return null;
206
-
207
- const isExecutable = candidate => {
208
- try {
209
- fs.accessSync(candidate, fs.constants.X_OK);
210
- const stat = fs.statSync(candidate);
211
- return stat.isFile();
212
- } catch {
213
- return false;
214
- }
215
- };
216
-
217
- if (cmd.includes(path.sep)) {
218
- return isExecutable(cmd) ? path.resolve(cmd) : null;
219
- }
220
-
221
- const searchPath = process.env.PATH || '';
222
- for (const entry of searchPath.split(path.delimiter)) {
223
- if (!entry) continue;
224
- const candidate = path.join(entry, cmd);
225
- if (isExecutable(candidate)) return candidate;
226
- }
227
- return null;
228
- }
229
-
230
- function wrapAnsi(str, columns, options) {
231
- const input = typeof str === 'string' ? str : String(str ?? '');
232
- const widthLimit = Number(columns);
233
- if (!Number.isFinite(widthLimit) || widthLimit <= 0) return input;
234
-
235
- const wordWrap = !options || options.wordWrap !== false;
236
- const hard = !!(options && options.hard);
237
-
238
- if (!wordWrap || hard) {
239
- const result = [];
240
- let width = 0;
241
-
242
- for (let i = 0; i < input.length; ) {
243
- const char = input[i];
244
-
245
- if (char === '\u001b' || char === '\u009b') {
246
- const match = input.slice(i).match(ansiPatternSingle);
247
- if (match && match.index === 0) {
248
- result.push(match[0]);
249
- i += match[0].length;
250
- continue;
251
- }
252
- }
253
-
254
- if (char === '\n') {
255
- result.push(char);
256
- width = 0;
257
- i += 1;
258
- continue;
259
- }
260
-
261
- const codePoint = input.codePointAt(i);
262
- const charText = String.fromCodePoint(codePoint);
263
- const charWidth = codePointWidth(codePoint);
264
-
265
- if (width > 0 && width + charWidth > widthLimit) {
266
- result.push('\n');
267
- width = 0;
268
- }
269
-
270
- result.push(charText);
271
- width += charWidth;
272
- i += charText.length;
273
- }
274
-
275
- return result.join('');
276
- }
277
-
278
- const result = [];
279
- let line = '';
280
- let lineWidth = 0;
281
- let pendingSpaces = '';
282
-
283
- for (let i = 0; i < input.length; ) {
284
- const char = input[i];
285
-
286
- if (char === '\u001b' || char === '\u009b') {
287
- const match = input.slice(i).match(ansiPatternSingle);
288
- if (match && match.index === 0) {
289
- line += match[0];
290
- i += match[0].length;
291
- continue;
292
- }
293
- }
294
-
295
- if (char === '\n') {
296
- if (line.length > 0) result.push(line);
297
- result.push('\n');
298
- line = '';
299
- lineWidth = 0;
300
- pendingSpaces = '';
301
- i += 1;
302
- continue;
303
- }
304
-
305
- const codePoint = input.codePointAt(i);
306
- const charText = String.fromCodePoint(codePoint);
307
- if (charText === ' ' || charText === '\t') {
308
- pendingSpaces += charText;
309
- i += charText.length;
310
- continue;
311
- }
312
-
313
- let end = i + charText.length;
314
- while (end < input.length) {
315
- const nextChar = input[end];
316
- if (nextChar === '\n' || nextChar === ' ' || nextChar === '\t' || nextChar === '\u001b' || nextChar === '\u009b') {
317
- break;
318
- }
319
- const nextCodePoint = input.codePointAt(end);
320
- end += String.fromCodePoint(nextCodePoint).length;
321
- }
322
-
323
- const text = input.slice(i, end);
324
- const textWidth = stringWidth(text);
325
- const pendingWidth = pendingSpaces ? stringWidth(pendingSpaces) : 0;
326
-
327
- if (lineWidth > 0 && lineWidth + pendingWidth + textWidth > widthLimit) {
328
- result.push(line);
329
- result.push('\n');
330
- line = '';
331
- lineWidth = 0;
332
- pendingSpaces = '';
333
- }
334
-
335
- if (lineWidth > 0 && pendingSpaces) {
336
- line += pendingSpaces;
337
- lineWidth += pendingWidth;
338
- }
339
- pendingSpaces = '';
340
-
341
- line += text;
342
- lineWidth += textWidth;
343
- i = end;
344
- }
345
-
346
- if (pendingSpaces && lineWidth > 0) {
347
- line += pendingSpaces;
348
- }
349
- if (line.length > 0) result.push(line);
350
-
351
- return result.join('');
352
- }
353
-
354
- const YAML = {
355
- parse(text) {
356
- try {
357
- const lines = String(text).split('\n');
358
- const result = {};
359
- for (const line of lines) {
360
- const m = line.match(/^([^:#]+):\s*(.*)$/);
361
- if (m) result[m[1].trim()] = m[2].trim().replace(/^['"]|['"]$/g, '');
362
- }
363
- return result;
364
- } catch { return {}; }
365
- },
366
- stringify(obj) {
367
- try {
368
- return Object.entries(obj || {}).map(([k, v]) => k + ': ' + v).join('\n') + '\n';
369
- } catch { return ''; }
370
- },
371
- };
372
-
373
- function parseSemverVersion(value) {
374
- const text = String(value ?? '').trim().replace(/^[v=]/, '');
375
- const match = text.match(/^(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:\.(0|[1-9]\d*))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/);
376
- if (!match) return null;
377
- return {
378
- parts: [match[1], match[2] ?? '0', match[3] ?? '0'].map(Number),
379
- pre: match[4] ? match[4].split('.') : null,
380
- };
381
- }
382
-
383
- function comparePrerelease(a, b) {
384
- const size = Math.max(a.length, b.length);
385
- for (let i = 0; i < size; i++) {
386
- if (a[i] === undefined) return -1;
387
- if (b[i] === undefined) return 1;
388
- const aNum = /^\d+$/.test(a[i]);
389
- const bNum = /^\d+$/.test(b[i]);
390
- if (aNum && bNum) { const d = Number(a[i]) - Number(b[i]); if (d) return d < 0 ? -1 : 1; }
391
- else if (aNum) return -1;
392
- else if (bNum) return 1;
393
- else if (a[i] < b[i]) return -1;
394
- else if (a[i] > b[i]) return 1;
395
- }
396
- return 0;
397
- }
398
-
399
- const semver = {
400
- order(left, right) {
401
- const a = parseSemverVersion(left), b = parseSemverVersion(right);
402
- if (!a || !b) return NaN;
403
- for (let i = 0; i < 3; i++) {
404
- const d = a.parts[i] - b.parts[i];
405
- if (d) return d < 0 ? -1 : 1;
406
- }
407
- if (a.pre && !b.pre) return -1;
408
- if (!a.pre && b.pre) return 1;
409
- if (a.pre && b.pre) return comparePrerelease(a.pre, b.pre);
410
- return 0;
411
- },
412
- satisfies(version, range) {
413
- if (!version || !range) return false;
414
- const v = String(version).replace(/^[v=]/, '');
415
- const clean = String(range).trim();
416
- if (!clean) return false;
417
- if (clean.includes('||')) return clean.split('||').some(r => semver.satisfies(v, r.trim()));
418
- const parts = clean.split(/\s+/).filter(Boolean);
419
- if (parts.length > 1) return parts.every(p => semver.satisfies(v, p));
420
- const caret = clean.match(/^\^([0-9].*)$/);
421
- if (caret) {
422
- const p = parseSemverVersion(caret[1]);
423
- if (!p) return false;
424
- const upper = p.parts[0] > 0 ? (p.parts[0] + 1) + '.0.0'
425
- : p.parts[1] > 0 ? '0.' + (p.parts[1] + 1) + '.0'
426
- : '0.0.' + (p.parts[2] + 1);
427
- return semver.satisfies(v, '>=' + caret[1]) && semver.satisfies(v, '<' + upper);
428
- }
429
- const tilde = clean.match(/^~([0-9].*)$/);
430
- if (tilde) {
431
- const p = parseSemverVersion(tilde[1]);
432
- if (!p) return false;
433
- const original = tilde[1].split('.');
434
- const upper = original.length >= 2
435
- ? p.parts[0] + '.' + (p.parts[1] + 1) + '.0'
436
- : (p.parts[0] + 1) + '.0.0';
437
- return semver.satisfies(v, '>=' + tilde[1]) && semver.satisfies(v, '<' + upper);
438
- }
439
- const m = clean.match(/^([><=!]{1,2})\s*([0-9].*)$/);
440
- if (m) {
441
- const cmp = semver.order(v, m[2]);
442
- if (!Number.isFinite(cmp)) return false;
443
- return m[1] === '>=' ? cmp >= 0 : m[1] === '>' ? cmp > 0 :
444
- m[1] === '<=' ? cmp <= 0 : m[1] === '<' ? cmp < 0 :
445
- m[1] === '=' || m[1] === '==' ? cmp === 0 : m[1] === '!=' ? cmp !== 0 : false;
446
- }
447
- const exact = parseSemverVersion(clean);
448
- return exact ? semver.order(v, clean) === 0 : false;
449
- },
450
- };
451
-
452
148
  async function main() {
453
149
  const extractedFile = ensureEntryFile();
454
150
  const code = fs.readFileSync(extractedFile, 'utf8');
@@ -470,33 +166,7 @@ async function main() {
470
166
  process.once('uncaughtException', onAsyncError);
471
167
  process.once('unhandledRejection', onAsyncError);
472
168
  Object.defineProperty(process.versions, 'bun', { value: '1.1.8', configurable: true });
473
- const BunShim = {
474
- version: '1.1.8',
475
- stringWidth,
476
- hash: hashValue,
477
- which,
478
- wrapAnsi,
479
- stripANSI,
480
- semver,
481
- YAML,
482
- gc: (sync) => {
483
- try {
484
- if (typeof global.gc === 'function') global.gc(sync === false ? false : true);
485
- } catch {}
486
- },
487
- stdin: { stream: null },
488
- embeddedFiles: [],
489
- };
490
- const BunProxy = new Proxy(BunShim, {
491
- get(target, key, receiver) {
492
- if (!(key in target) && typeof key !== 'symbol' && debugBunShim) {
493
- console.error('[BunShim missing]', key);
494
- }
495
- return Reflect.get(target, key, receiver);
496
- },
497
- });
498
- globalThis.Bun = BunProxy;
499
-
169
+ globalThis.Bun = { version: '1.1.8', stringWidth };
500
170
  process.argv = ['node', extractedFile, ...argv];
501
171
  process.exit = code => {
502
172
  throw new RequestedExit(code);
@@ -525,10 +195,16 @@ async function main() {
525
195
  Object.defineProperty(process.versions, 'bun', { value: originalBun, configurable: true });
526
196
  }
527
197
  } catch {}
198
+ if (hadGlobalBun) globalThis.Bun = originalGlobalBun;
199
+ else delete globalThis.Bun;
528
200
  }
529
201
  }
530
202
 
531
203
  main().catch(error => {
204
+ if (error && error.code === 'CLAUDE_TERMUX_OFFICIAL_UPDATE_BLOCKED') {
205
+ console.error(BLOCK_MESSAGE);
206
+ process.exit(error.status || 1);
207
+ }
532
208
  console.error(error && error.stack ? error.stack : String(error));
533
209
  process.exit(1);
534
210
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash0816/claude-code",
3
- "version": "2.1.157",
3
+ "version": "2.1.159",
4
4
  "description": "Termux-native Claude Code wrapper with audited native replay",
5
5
  "license": "MIT",
6
6
  "bin": {