@bash0816/claude-code 2.1.154 → 2.1.157-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,84 +1,31 @@
1
1
  # @bash0816/cluade-code
2
2
 
3
- Termux-native Claude Code wrapper package.
3
+ > **This package has been renamed.**
4
+ > Please migrate to the canonical package: [@bash0816/claude-code](https://www.npmjs.com/package/@bash0816/claude-code)
4
5
 
5
- Termux 向け Claude Code native wrapper package です。
6
+ ## Migration / 移行
6
7
 
7
- Legacy compatibility package:
8
+ Run the following command to migrate:
8
9
 
9
- 互換維持用の legacy package:
10
-
11
- - canonical package: `@bash0816/claude-code`
12
-
13
- ## Install / インストール
10
+ 移行するには以下を実行してください:
14
11
 
15
12
  ```sh
16
- npm install -g @bash0816/cluade-code@latest
13
+ npm uninstall -g @bash0816/cluade-code
14
+ npm install -g @bash0816/claude-code@latest
17
15
  ```
18
16
 
19
- If an older audited launcher from this repository already exists at `$PREFIX/bin/claude`, migrate through the updated launcher.
17
+ Or use the built-in migration:
20
18
 
21
- この repository の古い監査済み launcher が `$PREFIX/bin/claude` にある場合は、更新済み launcher 経由で移行します。
19
+ 内蔵の migration を使う場合:
22
20
 
23
21
  ```sh
24
22
  claude update
25
23
  ```
26
24
 
27
- If npm reports `EEXIST` before package scripts run, use a one-time forced migration.
28
-
29
- package script 実行前に npm が `EEXIST` を返す場合は、初回だけ forced migration を使います。
30
-
31
- ```sh
32
- npm install -g --force @bash0816/cluade-code@latest
33
- ```
34
-
35
- After npm owns the `claude` bin link, normal `npm install -g` updates work.
36
-
37
- npm が `claude` bin link を管理する状態になれば、通常の `npm install -g` 更新が使えます。
38
-
39
- Specific audited version:
40
-
41
- 監査済みの固定 version:
42
-
43
- ```sh
44
- npm install -g @bash0816/cluade-code@2.1.123
45
- ```
46
-
47
- ## Update / 更新
48
-
49
- ```sh
50
- claude update
51
- ```
52
-
53
- `claude update` checks the GitHub release manifest and installs the latest audited package version.
54
-
55
- `claude update` は GitHub release manifest を確認し、最新の監査済み package version を install します。
56
-
57
- For the final legacy bridge release, `claude update` migrates this typo package to the canonical package.
58
-
59
- 最終 legacy bridge release では、`claude update` がこの typo package から canonical package へ移行します。
60
-
61
- This final bridge package is frozen at package version `2.1.123` and launches audited native `2.1.150` by default from the synced metadata set.
62
-
63
- この最終 bridge package は package version `2.1.123` で凍結し、同期済み metadata 集合から既定では監査済み native `2.1.150` を起動します。
64
-
65
- ```sh
66
- npm install -g @bash0816/claude-code@<latest_audited_version>
67
- ```
68
-
69
- Normal launch also checks the same manifest with a short timeout and prints a notice when a newer audited version is available.
70
-
71
- 通常起動時も、同じ manifest を短い timeout で確認し、新しい監査済み version があれば通知します。
25
+ ## Note
72
26
 
73
- ## Policy / 方針
27
+ This is a legacy compatibility package with a typo in the package name.
28
+ All new releases are published under [@bash0816/claude-code](https://www.npmjs.com/package/@bash0816/claude-code).
74
29
 
75
- - Only audited versions in `config/claude-native-audited-versions.json` can run.
76
- - `config/claude-native-audited-versions.json` にある監査済み version だけを実行できます。
77
- - This legacy package is frozen at `2.1.123` and exists only as a migration bridge to `@bash0816/claude-code`.
78
- - この legacy package は `2.1.123` で凍結しており、`@bash0816/claude-code` への migration bridge としてのみ存在します。
79
- - The metadata file remains the source of truth for the audited version set.
80
- - 監査済み version 集合の source of truth は引き続き metadata file です。
81
- - Native artifacts are cached under `${HOME}/.claude-termux-native-package`.
82
- - native artifact は `${HOME}/.claude-termux-native-package` に cache します。
83
- - If native preparation fails, the command exits with an error.
84
- - native preparation に失敗した場合、command は error で終了します。
30
+ このパッケージはパッケージ名に typo がある legacy 互換パッケージです。
31
+ 新しいリリースはすべて [@bash0816/claude-code](https://www.npmjs.com/package/@bash0816/claude-code) で公開されています。
@@ -181,6 +181,27 @@
181
181
  "entry_js_offset": 222957396,
182
182
  "entry_end_offset": 238482842,
183
183
  "status": "termux_verified"
184
+ },
185
+ "2.1.156": {
186
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.156",
187
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.156",
188
+ "entry_js_offset": 222957812,
189
+ "entry_end_offset": 238483519,
190
+ "status": "termux_verified"
191
+ },
192
+ "2.1.157": {
193
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.157",
194
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.157",
195
+ "entry_js_offset": 223210916,
196
+ "entry_end_offset": 238725072,
197
+ "status": "termux_verified"
198
+ },
199
+ "2.1.157-1": {
200
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.157",
201
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.157",
202
+ "entry_js_offset": 223210916,
203
+ "entry_end_offset": 238725072,
204
+ "status": "candidate"
184
205
  }
185
206
  }
186
207
  }
@@ -4,10 +4,10 @@
4
4
  "canonical_package_name": "@bash0816/claude-code",
5
5
  "canonical_manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json",
6
6
  "canonical_repository_url": "https://github.com/bash0816/ClaudeCode-Termux",
7
- "bridge_package_version": "2.1.154",
8
- "default_native_version": "2.1.154",
9
- "latest_audited_version": "2.1.154",
10
- "latest_candidate_version": "2.1.154",
11
- "previous_stable_version": "2.1.126",
7
+ "bridge_package_version": "2.1.157-1",
8
+ "default_native_version": "2.1.157-1",
9
+ "latest_audited_version": "2.1.157",
10
+ "latest_candidate_version": "2.1.157-1",
11
+ "previous_stable_version": "2.1.157",
12
12
  "manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
13
13
  }
@@ -235,7 +235,29 @@ async function runUpdate() {
235
235
  return 0;
236
236
  }
237
237
  if (target.migration) {
238
- console.error(`Migrating from legacy package ${pkg.name} to canonical package ${target.packageName}@${target.targetVersion}`);
238
+ console.error(`Migrating from ${pkg.name} to ${target.packageName}@${target.targetVersion}`);
239
+ if (dryRun) {
240
+ console.log(`npm uninstall -g ${pkg.name}`);
241
+ console.log(`npm install -g ${target.packageName}@${target.targetVersion}`);
242
+ return 0;
243
+ }
244
+ console.error(`Step 1: Uninstalling ${pkg.name}...`);
245
+ const uninstall = cp.spawnSync('npm', ['uninstall', '-g', pkg.name], { stdio: 'inherit', env: process.env });
246
+ if (uninstall.status !== 0) {
247
+ console.error(`Uninstall failed (exit ${uninstall.status}). Cannot safely continue migration.`);
248
+ console.error(`Run manually:`);
249
+ console.error(` npm uninstall -g ${pkg.name}`);
250
+ console.error(` npm install -g ${target.packageName}@${target.targetVersion}`);
251
+ return 1;
252
+ }
253
+ console.error(`Step 2: Installing ${target.packageName}@${target.targetVersion}...`);
254
+ const result = cp.spawnSync('npm', ['install', '-g', `${target.packageName}@${target.targetVersion}`], { stdio: 'inherit', env: process.env });
255
+ if (result.status !== 0) {
256
+ console.error(`Install failed. To restore, run:`);
257
+ console.error(` npm install -g ${target.packageName}@${target.targetVersion}`);
258
+ console.error(` # or to restore legacy: npm install -g ${pkg.name}@${pkg.version}`);
259
+ }
260
+ return result.status === null ? 1 : result.status;
239
261
  }
240
262
  return installTarget(target.packageName, target.targetVersion);
241
263
  }
@@ -74,7 +74,6 @@ function ensureEntryFile() {
74
74
  }
75
75
 
76
76
  function createFakeRequire(realRequire) {
77
- const realChild = realRequire('child_process');
78
77
  const realVm = realRequire('vm');
79
78
 
80
79
  function injectBunIntoContext(context) {
@@ -107,6 +106,7 @@ function createFakeRequire(realRequire) {
107
106
  Object.defineProperty(realVm, '__bunShimPatched', { value: true });
108
107
  }
109
108
 
109
+ const realChild = realRequire('child_process');
110
110
  function rewriteArgs(args) {
111
111
  if (
112
112
  Array.isArray(args) &&
@@ -120,8 +120,6 @@ function createFakeRequire(realRequire) {
120
120
  }
121
121
 
122
122
  return function fakeRequire(id) {
123
- if (id === 'vm') return realVm;
124
-
125
123
  if (id === 'ws') {
126
124
  class WS {
127
125
  on() {}
@@ -145,6 +143,8 @@ function createFakeRequire(realRequire) {
145
143
  };
146
144
  }
147
145
 
146
+ if (id === 'vm') return realVm;
147
+
148
148
  if (id.startsWith('/$bunfs/root/')) {
149
149
  throw new Error('bunfs require blocked: ' + id);
150
150
  }
@@ -153,321 +153,511 @@ function createFakeRequire(realRequire) {
153
153
  };
154
154
  }
155
155
 
156
- function createBunShim() {
157
- const childProcess = require('child_process');
158
- const crypto = require('crypto');
159
- const net = require('net');
160
- const os = require('os');
161
- const ansiPattern =
162
- /[\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;
156
+ const ansiPattern =
157
+ /[\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;
158
+ const ansiPatternSingle = new RegExp(ansiPattern.source);
159
+ const debugBunShim = process.env.CLAUDE_TERMUX_DEBUG_BUN_SHIM === '1';
163
160
 
164
- function stripANSI(value) {
165
- if (typeof value !== 'string' || value.length === 0) return '';
166
- return value.replace(ansiPattern, '');
167
- }
161
+ function stripANSI(text) {
162
+ if (typeof text !== 'string' || text.length === 0) return '';
163
+ return text.replace(ansiPattern, '');
164
+ }
168
165
 
169
- function isZeroWidth(codePoint) {
170
- return (
171
- codePoint <= 0x1f ||
172
- (codePoint >= 0x7f && codePoint <= 0x9f) ||
173
- (codePoint >= 0x300 && codePoint <= 0x36f) ||
174
- (codePoint >= 0x200b && codePoint <= 0x200f) ||
175
- codePoint === 0xfeff ||
176
- (codePoint >= 0xfe00 && codePoint <= 0xfe0f)
177
- );
166
+ function codePointWidth(codePoint) {
167
+ if (
168
+ codePoint <= 0x1f ||
169
+ (codePoint >= 0x7f && codePoint <= 0x9f) ||
170
+ (codePoint >= 0x300 && codePoint <= 0x36f) ||
171
+ (codePoint >= 0x200b && codePoint <= 0x200f) ||
172
+ codePoint === 0xfeff ||
173
+ (codePoint >= 0xfe00 && codePoint <= 0xfe0f)
174
+ ) {
175
+ return 0;
178
176
  }
179
177
 
180
- function isWide(codePoint) {
181
- return (
182
- (codePoint >= 0x1100 && codePoint <= 0x115f) ||
183
- (codePoint >= 0x2329 && codePoint <= 0x232a) ||
184
- (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
185
- (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
186
- (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
187
- (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
188
- (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
189
- (codePoint >= 0xff00 && codePoint <= 0xff60) ||
190
- (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
191
- (codePoint >= 0x1f300 && codePoint <= 0x1faf8) ||
192
- (codePoint >= 0x20000 && codePoint <= 0x3fffd)
193
- );
178
+ if (
179
+ (codePoint >= 0x1100 && codePoint <= 0x115f) ||
180
+ (codePoint >= 0x2329 && codePoint <= 0x232a) ||
181
+ (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
182
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
183
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
184
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
185
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
186
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
187
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
188
+ (codePoint >= 0x1f300 && codePoint <= 0x1faf8) ||
189
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd)
190
+ ) {
191
+ return 2;
194
192
  }
195
193
 
196
- function stringWidth(value) {
197
- const text = stripANSI(typeof value === 'string' ? value : String(value ?? ''));
198
- let width = 0;
199
- for (const char of text) {
200
- const codePoint = char.codePointAt(0);
201
- if (isZeroWidth(codePoint)) continue;
202
- width += isWide(codePoint) ? 2 : 1;
203
- }
204
- return width;
194
+ return 1;
195
+ }
196
+
197
+ function stringWidth(value) {
198
+ const text = stripANSI(typeof value === 'string' ? value : String(value ?? ''));
199
+ let width = 0;
200
+ for (const char of text) {
201
+ const codePoint = char.codePointAt(0);
202
+ width += codePointWidth(codePoint);
205
203
  }
204
+ return width;
205
+ }
206
206
 
207
- function normalizeInput(value) {
208
- if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value);
209
- if (typeof value === 'string') return Buffer.from(value);
210
- return Buffer.from(String(value ?? ''));
207
+ function toHashBytes(value) {
208
+ if (Buffer.isBuffer(value)) return Buffer.from(value);
209
+ if (value instanceof Uint8Array) return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
210
+ if (value instanceof ArrayBuffer) return Buffer.from(value);
211
+ if (ArrayBuffer.isView(value)) {
212
+ return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
211
213
  }
214
+ return Buffer.from(String(value ?? ''));
215
+ }
216
+
217
+ function hashValue(value, seed = 0) {
218
+ const FNV_OFFSET_BASIS_64 = 0xcbf29ce484222325n;
219
+ const FNV_PRIME_64 = 0x100000001b3n;
220
+ const MASK_64 = 0xffffffffffffffffn;
212
221
 
213
- function hash(value) {
214
- const digest = crypto.createHash('sha256').update(normalizeInput(value)).digest();
215
- return digest.readUInt32LE(0);
222
+ const seedNumber = typeof seed === 'bigint' ? Number(seed) : Number(seed);
223
+ const seedValue = Number.isFinite(seedNumber) ? Math.trunc(seedNumber) : 0;
224
+ let result = BigInt.asUintN(64, FNV_OFFSET_BASIS_64 ^ BigInt(seedValue));
225
+
226
+ const bytes = toHashBytes(value);
227
+ for (const byte of bytes) {
228
+ result ^= BigInt(byte);
229
+ result = (result * FNV_PRIME_64) & MASK_64;
216
230
  }
217
231
 
218
- function which(command) {
219
- if (typeof command !== 'string' || command.length === 0) return null;
220
- const pathValue = process.env.PATH || '';
221
- const separator = os.platform() === 'win32' ? ';' : ':';
222
- for (const entry of pathValue.split(separator)) {
223
- if (!entry) continue;
224
- const candidate = path.join(entry, command);
225
- try {
226
- fs.accessSync(candidate, fs.constants.X_OK);
227
- return candidate;
228
- } catch {}
232
+ return BigInt(result);
233
+ }
234
+
235
+ function which(cmd) {
236
+ const fs = require('fs');
237
+ const path = require('path');
238
+
239
+ if (typeof cmd !== 'string' || cmd.length === 0) return null;
240
+
241
+ const isExecutable = candidate => {
242
+ try {
243
+ fs.accessSync(candidate, fs.constants.X_OK);
244
+ const stat = fs.statSync(candidate);
245
+ return stat.isFile();
246
+ } catch {
247
+ return false;
229
248
  }
230
- return null;
249
+ };
250
+
251
+ if (cmd.includes(path.sep)) {
252
+ return isExecutable(cmd) ? path.resolve(cmd) : null;
231
253
  }
232
254
 
233
- function spawn(argv, options = {}) {
234
- if (!Array.isArray(argv) || argv.length === 0) {
235
- throw new TypeError('Bun.spawn expects a non-empty argv array');
255
+ const searchPath = process.env.PATH || '';
256
+ for (const entry of searchPath.split(path.delimiter)) {
257
+ if (!entry) continue;
258
+ const candidate = path.join(entry, cmd);
259
+ if (isExecutable(candidate)) return candidate;
260
+ }
261
+ return null;
262
+ }
263
+
264
+ function wrapAnsi(str, columns, options) {
265
+ const input = typeof str === 'string' ? str : String(str ?? '');
266
+ const widthLimit = Number(columns);
267
+ if (!Number.isFinite(widthLimit) || widthLimit <= 0) return input;
268
+
269
+ const wordWrap = !options || options.wordWrap !== false;
270
+ const hard = !!(options && options.hard);
271
+
272
+ if (!wordWrap || hard) {
273
+ const result = [];
274
+ let width = 0;
275
+
276
+ for (let i = 0; i < input.length; ) {
277
+ const char = input[i];
278
+
279
+ if (char === '\u001b' || char === '\u009b') {
280
+ const match = input.slice(i).match(ansiPatternSingle);
281
+ if (match && match.index === 0) {
282
+ result.push(match[0]);
283
+ i += match[0].length;
284
+ continue;
285
+ }
286
+ }
287
+
288
+ if (char === '\n') {
289
+ result.push(char);
290
+ width = 0;
291
+ i += 1;
292
+ continue;
293
+ }
294
+
295
+ const codePoint = input.codePointAt(i);
296
+ const charText = String.fromCodePoint(codePoint);
297
+ const charWidth = codePointWidth(codePoint);
298
+
299
+ if (width > 0 && width + charWidth > widthLimit) {
300
+ result.push('\n');
301
+ width = 0;
302
+ }
303
+
304
+ result.push(charText);
305
+ width += charWidth;
306
+ i += charText.length;
236
307
  }
237
- const [command, ...args] = argv;
238
- const terminal = options.terminal || null;
239
308
 
240
- function resolveStdio(val, fallback) {
241
- if (val === 'ignore' || val === 'inherit' || val === 'pipe') return val;
242
- return fallback;
309
+ return result.join('');
310
+ }
311
+
312
+ const result = [];
313
+ let line = '';
314
+ let lineWidth = 0;
315
+ let pendingSpaces = '';
316
+
317
+ for (let i = 0; i < input.length; ) {
318
+ const char = input[i];
319
+
320
+ if (char === '\u001b' || char === '\u009b') {
321
+ const match = input.slice(i).match(ansiPatternSingle);
322
+ if (match && match.index === 0) {
323
+ line += match[0];
324
+ i += match[0].length;
325
+ continue;
326
+ }
243
327
  }
244
328
 
245
- let stdioSpec;
246
- if (terminal) {
247
- stdioSpec = ['pipe', 'pipe', 'pipe'];
248
- } else if (Array.isArray(options.stdio)) {
249
- stdioSpec = options.stdio.map(s => resolveStdio(s, 'pipe'));
250
- } else {
251
- stdioSpec = [
252
- resolveStdio(options.stdin, 'pipe'),
253
- resolveStdio(options.stdout, 'pipe'),
254
- resolveStdio(options.stderr, 'pipe'),
255
- ];
329
+ if (char === '\n') {
330
+ if (line.length > 0) result.push(line);
331
+ result.push('\n');
332
+ line = '';
333
+ lineWidth = 0;
334
+ pendingSpaces = '';
335
+ i += 1;
336
+ continue;
256
337
  }
257
338
 
258
- const nodeChild = childProcess.spawn(command, args, {
259
- cwd: options.cwd,
260
- env: options.env || process.env,
261
- detached: options.detached,
262
- windowsHide: options.windowsHide,
263
- stdio: stdioSpec,
264
- });
339
+ const codePoint = input.codePointAt(i);
340
+ const charText = String.fromCodePoint(codePoint);
341
+ if (charText === ' ' || charText === '\t') {
342
+ pendingSpaces += charText;
343
+ i += charText.length;
344
+ continue;
345
+ }
265
346
 
266
- if (terminal) {
267
- const fireData = chunk => {
268
- if (!terminal._closed && terminal._options && typeof terminal._options.data === 'function') {
269
- terminal._options.data(terminal, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
270
- }
271
- };
272
- nodeChild.stdout?.on('data', fireData);
273
- nodeChild.stderr?.on('data', fireData);
274
- const origWrite = terminal.write.bind(terminal);
275
- terminal.write = data => {
276
- if (nodeChild.stdin && !nodeChild.stdin.destroyed) {
277
- nodeChild.stdin.write(Buffer.isBuffer(data) ? data : Buffer.from(data));
278
- }
279
- return origWrite(data);
280
- };
347
+ let end = i + charText.length;
348
+ while (end < input.length) {
349
+ const nextChar = input[end];
350
+ if (nextChar === '\n' || nextChar === ' ' || nextChar === '\t' || nextChar === '\u001b' || nextChar === '\u009b') {
351
+ break;
352
+ }
353
+ const nextCodePoint = input.codePointAt(end);
354
+ end += String.fromCodePoint(nextCodePoint).length;
281
355
  }
282
356
 
283
- nodeChild.exited = new Promise(resolve => {
284
- nodeChild.once('exit', (code, signal) => resolve(code != null ? code : (signal ? 1 : 0)));
285
- });
357
+ const text = input.slice(i, end);
358
+ const textWidth = stringWidth(text);
359
+ const pendingWidth = pendingSpaces ? stringWidth(pendingSpaces) : 0;
286
360
 
287
- function makeTextReader(stream) {
288
- return {
289
- text() {
290
- return new Promise((resolve, reject) => {
291
- if (!stream) return resolve('');
292
- const chunks = [];
293
- stream.on('data', chunk => chunks.push(chunk));
294
- stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
295
- stream.on('error', reject);
296
- });
297
- },
298
- };
361
+ if (lineWidth > 0 && lineWidth + pendingWidth + textWidth > widthLimit) {
362
+ result.push(line);
363
+ result.push('\n');
364
+ line = '';
365
+ lineWidth = 0;
366
+ pendingSpaces = '';
367
+ }
368
+
369
+ if (lineWidth > 0 && pendingSpaces) {
370
+ line += pendingSpaces;
371
+ lineWidth += pendingWidth;
299
372
  }
300
- if (nodeChild.stdout) Object.assign(nodeChild.stdout, makeTextReader(nodeChild.stdout));
301
- if (nodeChild.stderr) Object.assign(nodeChild.stderr, makeTextReader(nodeChild.stderr));
302
- return nodeChild;
373
+ pendingSpaces = '';
374
+
375
+ line += text;
376
+ lineWidth += textWidth;
377
+ i = end;
378
+ }
379
+
380
+ if (pendingSpaces && lineWidth > 0) {
381
+ line += pendingSpaces;
303
382
  }
383
+ if (line.length > 0) result.push(line);
384
+
385
+ return result.join('');
386
+ }
304
387
 
305
- class TerminalShim {
306
- constructor(options = {}) {
307
- this._options = options;
308
- this._cols = options.cols || 80;
309
- this._rows = options.rows || 24;
310
- this._closed = false;
388
+ const YAML = {
389
+ parse(text) {
390
+ try {
391
+ const lines = String(text).split('\n');
392
+ const result = {};
393
+ for (const line of lines) {
394
+ const m = line.match(/^([^:#]+):\s*(.*)$/);
395
+ if (m) result[m[1].trim()] = m[2].trim().replace(/^['"]|['"]$/g, '');
396
+ }
397
+ return result;
398
+ } catch { return {}; }
399
+ },
400
+ stringify(obj) {
401
+ try {
402
+ return Object.entries(obj || {}).map(([k, v]) => k + ': ' + v).join('\n') + '\n';
403
+ } catch { return ''; }
404
+ },
405
+ };
406
+
407
+ function parseSemverVersion(value) {
408
+ const text = String(value ?? '').trim().replace(/^[v=]/, '');
409
+ 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-]+)*)?$/);
410
+ if (!match) return null;
411
+ return {
412
+ parts: [match[1], match[2] ?? '0', match[3] ?? '0'].map(Number),
413
+ pre: match[4] ? match[4].split('.') : null,
414
+ };
415
+ }
416
+
417
+ function comparePrerelease(a, b) {
418
+ const size = Math.max(a.length, b.length);
419
+ for (let i = 0; i < size; i++) {
420
+ if (a[i] === undefined) return -1;
421
+ if (b[i] === undefined) return 1;
422
+ const aNum = /^\d+$/.test(a[i]);
423
+ const bNum = /^\d+$/.test(b[i]);
424
+ if (aNum && bNum) { const d = Number(a[i]) - Number(b[i]); if (d) return d < 0 ? -1 : 1; }
425
+ else if (aNum) return -1;
426
+ else if (bNum) return 1;
427
+ else if (a[i] < b[i]) return -1;
428
+ else if (a[i] > b[i]) return 1;
429
+ }
430
+ return 0;
431
+ }
432
+
433
+ const semver = {
434
+ order(left, right) {
435
+ const a = parseSemverVersion(left), b = parseSemverVersion(right);
436
+ if (!a || !b) return NaN;
437
+ for (let i = 0; i < 3; i++) {
438
+ const d = a.parts[i] - b.parts[i];
439
+ if (d) return d < 0 ? -1 : 1;
311
440
  }
312
- write(data) {
313
- if (this._closed) return;
314
- if (this._options.data) this._options.data(this, Buffer.isBuffer(data) ? data : Buffer.from(data));
441
+ if (a.pre && !b.pre) return -1;
442
+ if (!a.pre && b.pre) return 1;
443
+ if (a.pre && b.pre) return comparePrerelease(a.pre, b.pre);
444
+ return 0;
445
+ },
446
+ satisfies(version, range) {
447
+ if (!version || !range) return false;
448
+ const v = String(version).replace(/^[v=]/, '');
449
+ const clean = String(range).trim();
450
+ if (!clean) return false;
451
+ if (clean.includes('||')) return clean.split('||').some(r => semver.satisfies(v, r.trim()));
452
+ const parts = clean.split(/\s+/).filter(Boolean);
453
+ if (parts.length > 1) return parts.every(p => semver.satisfies(v, p));
454
+ const caret = clean.match(/^\^([0-9].*)$/);
455
+ if (caret) {
456
+ const p = parseSemverVersion(caret[1]);
457
+ if (!p) return false;
458
+ const upper = p.parts[0] > 0 ? (p.parts[0] + 1) + '.0.0'
459
+ : p.parts[1] > 0 ? '0.' + (p.parts[1] + 1) + '.0'
460
+ : '0.0.' + (p.parts[2] + 1);
461
+ return semver.satisfies(v, '>=' + caret[1]) && semver.satisfies(v, '<' + upper);
315
462
  }
316
- resize(cols, rows) {
317
- this._cols = cols;
318
- this._rows = rows;
463
+ const tilde = clean.match(/^~([0-9].*)$/);
464
+ if (tilde) {
465
+ const p = parseSemverVersion(tilde[1]);
466
+ if (!p) return false;
467
+ const original = tilde[1].split('.');
468
+ const upper = original.length >= 2
469
+ ? p.parts[0] + '.' + (p.parts[1] + 1) + '.0'
470
+ : (p.parts[0] + 1) + '.0.0';
471
+ return semver.satisfies(v, '>=' + tilde[1]) && semver.satisfies(v, '<' + upper);
319
472
  }
320
- close() {
321
- this._closed = true;
473
+ const m = clean.match(/^([><=!]{1,2})\s*([0-9].*)$/);
474
+ if (m) {
475
+ const cmp = semver.order(v, m[2]);
476
+ if (!Number.isFinite(cmp)) return false;
477
+ return m[1] === '>=' ? cmp >= 0 : m[1] === '>' ? cmp > 0 :
478
+ m[1] === '<=' ? cmp <= 0 : m[1] === '<' ? cmp < 0 :
479
+ m[1] === '=' || m[1] === '==' ? cmp === 0 : m[1] === '!=' ? cmp !== 0 : false;
322
480
  }
481
+ const exact = parseSemverVersion(clean);
482
+ return exact ? semver.order(v, clean) === 0 : false;
483
+ },
484
+ };
485
+
486
+ function bunSpawn(argv, options) {
487
+ const childProcess = require('child_process');
488
+ options = options || {};
489
+ if (!Array.isArray(argv) || argv.length === 0) {
490
+ throw new TypeError('Bun.spawn expects a non-empty argv array');
323
491
  }
492
+ const command = argv[0];
493
+ const args = argv.slice(1);
494
+ const terminal = options.terminal || null;
324
495
 
325
- function listen(options) {
326
- const sockets = new Set();
327
- const server = net.createServer(socket => {
328
- sockets.add(socket);
329
- const connection = {
330
- data: undefined,
331
- write(chunk) {
332
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
333
- const ok = socket.write(buffer);
334
- return ok ? buffer.length : 0;
335
- },
336
- end(chunk) {
337
- socket.end(chunk);
338
- },
339
- destroy(error) {
340
- socket.destroy(error);
341
- },
342
- };
343
- socket.on('data', chunk => {
344
- if (options.socket && typeof options.socket.data === 'function') {
345
- options.socket.data(connection, chunk);
346
- }
347
- });
348
- socket.on('drain', () => {
349
- if (options.socket && typeof options.socket.drain === 'function') {
350
- options.socket.drain(connection);
351
- }
352
- });
353
- socket.on('close', () => {
354
- sockets.delete(socket);
355
- if (options.socket && typeof options.socket.close === 'function') {
356
- options.socket.close(connection);
357
- }
358
- });
359
- socket.on('error', error => {
360
- if (options.socket && typeof options.socket.error === 'function') {
361
- options.socket.error(connection, error);
362
- }
363
- });
364
- if (options.socket && typeof options.socket.open === 'function') {
365
- options.socket.open(connection);
496
+ function resolveStdio(val, fallback) {
497
+ if (val === 'ignore' || val === 'inherit' || val === 'pipe') return val;
498
+ return fallback;
499
+ }
500
+
501
+ let stdioSpec;
502
+ if (terminal) {
503
+ stdioSpec = ['pipe', 'pipe', 'pipe'];
504
+ } else if (Array.isArray(options.stdio)) {
505
+ stdioSpec = options.stdio.map(function(s) { return resolveStdio(s, 'pipe'); });
506
+ } else {
507
+ stdioSpec = [
508
+ resolveStdio(options.stdin, 'pipe'),
509
+ resolveStdio(options.stdout, 'pipe'),
510
+ resolveStdio(options.stderr, 'pipe'),
511
+ ];
512
+ }
513
+
514
+ const nodeChild = childProcess.spawn(command, args, {
515
+ cwd: options.cwd,
516
+ env: options.env || process.env,
517
+ detached: options.detached,
518
+ windowsHide: options.windowsHide,
519
+ stdio: stdioSpec,
520
+ });
521
+
522
+ if (terminal) {
523
+ const fireData = function(chunk) {
524
+ if (!terminal._closed && terminal._options && typeof terminal._options.data === 'function') {
525
+ terminal._options.data(terminal, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
366
526
  }
367
- });
527
+ };
528
+ if (nodeChild.stdout) nodeChild.stdout.on('data', fireData);
529
+ if (nodeChild.stderr) nodeChild.stderr.on('data', fireData);
530
+ const origWrite = terminal.write.bind(terminal);
531
+ terminal.write = function(data) {
532
+ if (nodeChild.stdin && !nodeChild.stdin.destroyed) {
533
+ nodeChild.stdin.write(Buffer.isBuffer(data) ? data : Buffer.from(data));
534
+ }
535
+ return origWrite(data);
536
+ };
537
+ }
368
538
 
369
- server.listen(options.port || 0, options.hostname || '127.0.0.1');
539
+ nodeChild.exited = new Promise(function(resolve) {
540
+ nodeChild.once('exit', function(code, signal) {
541
+ resolve(code != null ? code : (signal ? 1 : 0));
542
+ });
543
+ });
370
544
 
545
+ function makeTextReader(stream) {
371
546
  return {
372
- get port() {
373
- const address = server.address();
374
- return address && typeof address === 'object' ? address.port : 0;
375
- },
376
- stop(closeConnections) {
377
- server.close();
378
- if (closeConnections) {
379
- for (const socket of sockets) socket.destroy();
380
- }
547
+ text: function() {
548
+ return new Promise(function(resolve, reject) {
549
+ if (!stream) return resolve('');
550
+ const chunks = [];
551
+ stream.on('data', function(chunk) { chunks.push(chunk); });
552
+ stream.on('end', function() { resolve(Buffer.concat(chunks).toString('utf8')); });
553
+ stream.on('error', reject);
554
+ });
381
555
  },
382
556
  };
383
557
  }
558
+ if (nodeChild.stdout) Object.assign(nodeChild.stdout, makeTextReader(nodeChild.stdout));
559
+ if (nodeChild.stderr) Object.assign(nodeChild.stderr, makeTextReader(nodeChild.stderr));
560
+ return nodeChild;
561
+ }
384
562
 
385
- const semver = {
386
- order(left, right) {
387
- const leftParts = String(left).replace(/^[^0-9]*/, '').split('.').map(Number);
388
- const rightParts = String(right).replace(/^[^0-9]*/, '').split('.').map(Number);
389
- const size = Math.max(leftParts.length, rightParts.length);
390
- for (let index = 0; index < size; index += 1) {
391
- const diff = (leftParts[index] || 0) - (rightParts[index] || 0);
392
- if (diff !== 0) return diff > 0 ? 1 : -1;
393
- }
394
- return 0;
395
- },
396
- satisfies(version, range) {
397
- const v = String(version).replace(/^[^0-9]*/, '');
398
- const clean = String(range).trim();
399
- const match = clean.match(/^([><=!^~]+)\s*([0-9][^\s]*)/);
400
- if (!match) return true;
401
- const [, op, rv] = match;
402
- const cmp = semver.order(v, rv);
403
- if (op === '>=' || op === '=>') return cmp >= 0;
404
- if (op === '>') return cmp > 0;
405
- if (op === '<=' || op === '=<') return cmp <= 0;
406
- if (op === '<') return cmp < 0;
407
- if (op === '==' || op === '=') return cmp === 0;
408
- if (op === '!=') return cmp !== 0;
409
- return true;
410
- },
411
- };
563
+ class TerminalShim {
564
+ constructor(options) {
565
+ options = options || {};
566
+ this._options = options;
567
+ this._cols = options.cols || 80;
568
+ this._rows = options.rows || 24;
569
+ this._closed = false;
570
+ }
571
+ write(data) {
572
+ if (this._closed) return;
573
+ if (this._options.data) this._options.data(this, Buffer.isBuffer(data) ? data : Buffer.from(data));
574
+ }
575
+ resize(cols, rows) {
576
+ this._cols = cols;
577
+ this._rows = rows;
578
+ }
579
+ close() {
580
+ this._closed = true;
581
+ }
582
+ }
412
583
 
413
- const YAML = {
414
- parse(text) {
415
- try {
416
- const lines = String(text).split('\n');
417
- const result = {};
418
- for (const line of lines) {
419
- const m = line.match(/^([^:#]+):\s*(.*)$/);
420
- if (m) result[m[1].trim()] = m[2].trim().replace(/^["']|["']$/g, '');
421
- }
422
- return result;
423
- } catch { return {}; }
584
+ function bunListen(options) {
585
+ const net = require('net');
586
+ options = options || {};
587
+ const sockets = new Set();
588
+ const server = net.createServer(function(socket) {
589
+ sockets.add(socket);
590
+ const connection = {
591
+ data: undefined,
592
+ write: function(chunk) {
593
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
594
+ const ok = socket.write(buffer);
595
+ return ok ? buffer.length : 0;
596
+ },
597
+ end: function(chunk) { socket.end(chunk); },
598
+ destroy: function(error) { socket.destroy(error); },
599
+ };
600
+ socket.on('data', function(chunk) {
601
+ if (options.socket && typeof options.socket.data === 'function') {
602
+ options.socket.data(connection, chunk);
603
+ }
604
+ });
605
+ socket.on('drain', function() {
606
+ if (options.socket && typeof options.socket.drain === 'function') {
607
+ options.socket.drain(connection);
608
+ }
609
+ });
610
+ socket.on('close', function() {
611
+ sockets.delete(socket);
612
+ if (options.socket && typeof options.socket.close === 'function') {
613
+ options.socket.close(connection);
614
+ }
615
+ });
616
+ socket.on('error', function(error) {
617
+ if (options.socket && typeof options.socket.error === 'function') {
618
+ options.socket.error(connection, error);
619
+ }
620
+ });
621
+ if (options.socket && typeof options.socket.open === 'function') {
622
+ options.socket.open(connection);
623
+ }
624
+ });
625
+ server.listen(options.port || 0, options.hostname || '127.0.0.1');
626
+ return {
627
+ get port() {
628
+ const address = server.address();
629
+ return address && typeof address === 'object' ? address.port : 0;
424
630
  },
425
- stringify(obj) {
426
- try {
427
- return Object.entries(obj || {}).map(([k, v]) => `${k}: ${v}`).join('\n') + '\n';
428
- } catch { return ''; }
631
+ stop: function(closeConnections) {
632
+ server.close();
633
+ if (closeConnections) {
634
+ for (const socket of sockets) socket.destroy();
635
+ }
429
636
  },
430
637
  };
638
+ }
431
639
 
432
- class Transpiler {
433
- constructor(_options) {}
434
- transformSync(code) { return typeof code === 'string' ? code : ''; }
435
- scanImports(code) {
436
- const imports = [];
437
- const reStatic = /(?:^|[^.])import\s+(?:[^'"]+\s+from\s+)?['"]([^'"]+)['"]/gm;
438
- const reDynamic = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
439
- const reRequire = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
440
- let m;
441
- while ((m = reStatic.exec(String(code))) !== null) imports.push({ path: m[1], kind: 'import-statement' });
442
- while ((m = reDynamic.exec(String(code))) !== null) imports.push({ path: m[1], kind: 'dynamic-import' });
443
- while ((m = reRequire.exec(String(code))) !== null) imports.push({ path: m[1], kind: 'require-call' });
444
- return imports;
445
- }
640
+ class BunTranspiler {
641
+ constructor(_options) {}
642
+ transformSync(code) { return typeof code === 'string' ? code : ''; }
643
+ scanImports(code) {
644
+ const imports = [];
645
+ const str = String(code);
646
+ const reStatic = /(?:^|[^.])import\s+(?:[^'"]+\s+from\s+)?['"]([^'"]+)['"]/gm;
647
+ const reDynamic = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
648
+ const reRequire = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
649
+ let m;
650
+ while ((m = reStatic.exec(str)) !== null) imports.push({ path: m[1], kind: 'import-statement' });
651
+ while ((m = reDynamic.exec(str)) !== null) imports.push({ path: m[1], kind: 'dynamic-import' });
652
+ while ((m = reRequire.exec(str)) !== null) imports.push({ path: m[1], kind: 'require-call' });
653
+ return imports;
446
654
  }
447
-
448
- return {
449
- version: '1.1.8',
450
- embeddedFiles: [],
451
- gc: typeof global.gc === 'function' ? () => global.gc() : () => {},
452
- generateHeapSnapshot: () => Buffer.alloc(0),
453
- hash,
454
- listen,
455
- semver,
456
- spawn,
457
- stdin: process.stdin,
458
- stripANSI,
459
- stringWidth,
460
- Terminal: TerminalShim,
461
- Transpiler,
462
- which,
463
- wrapAnsi: value => String(value ?? ''),
464
- YAML,
465
- };
466
655
  }
467
656
 
468
657
  async function main() {
469
658
  const extractedFile = ensureEntryFile();
470
659
  const code = fs.readFileSync(extractedFile, 'utf8');
660
+ const fn = eval('(' + code);
471
661
 
472
662
  const originalArgv = process.argv.slice();
473
663
  const originalExit = process.exit;
@@ -476,6 +666,7 @@ async function main() {
476
666
  const originalGlobalBun = globalThis.Bun;
477
667
  const asyncErrors = [];
478
668
 
669
+ const fakeRequire = createFakeRequire(require);
479
670
  function onAsyncError(error) {
480
671
  asyncErrors.push(error);
481
672
  }
@@ -484,14 +675,43 @@ async function main() {
484
675
  process.once('uncaughtException', onAsyncError);
485
676
  process.once('unhandledRejection', onAsyncError);
486
677
  Object.defineProperty(process.versions, 'bun', { value: '1.1.8', configurable: true });
487
- globalThis.Bun = createBunShim();
488
- const fakeRequire = createFakeRequire(require);
678
+ const BunShim = {
679
+ version: '1.1.8',
680
+ stringWidth,
681
+ hash: hashValue,
682
+ which,
683
+ spawn: bunSpawn,
684
+ wrapAnsi,
685
+ stripANSI,
686
+ semver,
687
+ Terminal: TerminalShim,
688
+ listen: bunListen,
689
+ Transpiler: BunTranspiler,
690
+ YAML,
691
+ gc: (sync) => {
692
+ try {
693
+ if (typeof global.gc === 'function') global.gc(sync === false ? false : true);
694
+ } catch {}
695
+ },
696
+ generateHeapSnapshot: () => Buffer.alloc(0),
697
+ stdin: { stream: null },
698
+ embeddedFiles: [],
699
+ };
700
+ const BunProxy = new Proxy(BunShim, {
701
+ get(target, key, receiver) {
702
+ if (!(key in target) && typeof key !== 'symbol' && debugBunShim) {
703
+ console.error('[BunShim missing]', key);
704
+ }
705
+ return Reflect.get(target, key, receiver);
706
+ },
707
+ });
708
+ globalThis.Bun = BunProxy;
709
+
489
710
  process.argv = ['node', extractedFile, ...argv];
490
711
  process.exit = code => {
491
712
  throw new RequestedExit(code);
492
713
  };
493
714
 
494
- const fn = eval('(' + code);
495
715
  const moduleLike = { exports: {} };
496
716
  const maybePromise = fn(moduleLike.exports, fakeRequire, moduleLike, extractedFile, workdir);
497
717
  if (maybePromise && typeof maybePromise.then === 'function') await maybePromise;
@@ -515,14 +735,12 @@ async function main() {
515
735
  Object.defineProperty(process.versions, 'bun', { value: originalBun, configurable: true });
516
736
  }
517
737
  } catch {}
518
- try {
519
- if (hadGlobalBun) globalThis.Bun = originalGlobalBun;
520
- else delete globalThis.Bun;
521
- } catch {}
522
738
  }
523
739
  }
524
740
 
525
- main().catch(error => {
741
+ main().then(() => {
742
+ process.exit(process.exitCode ?? 0);
743
+ }).catch(error => {
526
744
  console.error(error && error.stack ? error.stack : String(error));
527
745
  process.exit(1);
528
746
  });
package/package.json CHANGED
@@ -1,15 +1,11 @@
1
1
  {
2
2
  "name": "@bash0816/claude-code",
3
- "version": "2.1.154",
3
+ "version": "2.1.157-1",
4
4
  "description": "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
- },
13
9
  "files": [
14
10
  "bin",
15
11
  "lib",
@@ -17,6 +13,6 @@
17
13
  "README.md"
18
14
  ],
19
15
  "engines": {
20
- "node": ">=20"
16
+ "node": ">=18"
21
17
  }
22
18
  }