@bash0816/claude-code 2.1.218 → 2.1.220-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
@@ -37,7 +37,7 @@ npm が `claude` bin link を管理する状態になれば、通常の `npm ins
37
37
  Latest audited version / 最新監査済み版:
38
38
 
39
39
  ```sh
40
- npm install -g @bash0816/claude-code@2.1.217
40
+ npm install -g @bash0816/claude-code@2.1.220
41
41
  ```
42
42
 
43
43
  ## Update / 更新
@@ -562,6 +562,33 @@
562
562
  "entry_end_offset": 263624682,
563
563
  "tarball_integrity": "sha512-CcbVQCzXd9EnlktCEPrkElhdBZuqIWhkeinRGxUuZa6aal4h6J+8Dbo+OnfchBEzd1mahRDQK8BckGBAYozv2g==",
564
564
  "tarball_sha256": "1d3cb5e12f0b653929e34ba046a7ba0a4f5c01eb25ea57b478dbac27e4af9619",
565
+ "status": "termux_verified"
566
+ },
567
+ "2.1.219": {
568
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.219",
569
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.219",
570
+ "entry_js_offset": 243825700,
571
+ "entry_end_offset": 265451802,
572
+ "tarball_integrity": "sha512-G5yLidk2u6djL5PPuBYXVwVhTsZY5zLoZwh1Jnrd/IRyYb0P0x4gKTzVvGlsGepkBrOp0H2k/KuicyNPrXt57Q==",
573
+ "tarball_sha256": "cf4ae671f08b91ac75ea63c8497e7ff4e3bdbe522b0f83bff2de162d44e0eb15",
574
+ "status": "termux_verified"
575
+ },
576
+ "2.1.220": {
577
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.220",
578
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.220",
579
+ "entry_js_offset": 243831156,
580
+ "entry_end_offset": 265457701,
581
+ "tarball_integrity": "sha512-VHFI8mKruIntKn7eq81sbyS19/KWmQcmJQsS/C+j9M/E+w0s4UytgsL7DADPjBE/GByNiKoRtLYDMntCjRlOdA==",
582
+ "tarball_sha256": "e38454d73576a08a2e707f26539d73fc9ef33e890228ca5c58a2bbe810ac884d",
583
+ "status": "termux_verified"
584
+ },
585
+ "2.1.220-1": {
586
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.220",
587
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.220",
588
+ "entry_js_offset": 243831156,
589
+ "entry_end_offset": 265457701,
590
+ "tarball_integrity": "sha512-VHFI8mKruIntKn7eq81sbyS19/KWmQcmJQsS/C+j9M/E+w0s4UytgsL7DADPjBE/GByNiKoRtLYDMntCjRlOdA==",
591
+ "tarball_sha256": "e38454d73576a08a2e707f26539d73fc9ef33e890228ca5c58a2bbe810ac884d",
565
592
  "status": "offset_discovered"
566
593
  }
567
594
  }
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "manifest_version": 1,
3
3
  "package_name": "@bash0816/claude-code",
4
- "latest_audited_version": "2.1.217",
5
- "latest_candidate_version": "2.1.218",
6
- "previous_stable_version": "2.1.216",
4
+ "latest_audited_version": "2.1.220",
5
+ "latest_candidate_version": "2.1.220-1",
6
+ "previous_stable_version": "2.1.219",
7
7
  "stable_pinned_version": "2.1.193",
8
8
  "manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
9
9
  }
@@ -583,6 +583,7 @@ function rewriteNativeChunkSource(source) {
583
583
  const _bunPropertyAccessExpected = (() => {
584
584
  const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
585
585
  const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
586
+ if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
586
587
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 216)) return 40;
587
588
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 214)) return 39;
588
589
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 205)) return 38;
@@ -635,6 +636,12 @@ async function main() {
635
636
  function onAsyncError(error) {
636
637
  asyncErrors.push(error);
637
638
  }
639
+ const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
640
+ async function waitForPrintFlush() {
641
+ if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
642
+ await new Promise(resolve => setTimeout(resolve, printWaitMs));
643
+ }
644
+ }
638
645
 
639
646
  try {
640
647
  process.once('uncaughtException', onAsyncError);
@@ -696,18 +703,15 @@ async function main() {
696
703
  process.exit = code => {
697
704
  throw new RequestedExit(code);
698
705
  };
699
-
700
- const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
701
706
  const moduleLike = { exports: {} };
702
707
  const maybePromise = fn(moduleLike.exports, fakeRequire, moduleLike, extractedFile, workdir);
703
708
  if (maybePromise && typeof maybePromise.then === 'function') await maybePromise;
704
- if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
705
- await new Promise(resolve => setTimeout(resolve, printWaitMs));
706
- }
709
+ await waitForPrintFlush();
707
710
  if (asyncErrors.length > 0) throw asyncErrors[0];
708
711
  } catch (error) {
709
712
  if (error instanceof RequestedExit) {
710
713
  process.exitCode = error.code;
714
+ await waitForPrintFlush();
711
715
  return;
712
716
  }
713
717
  throw error;
@@ -757,6 +761,7 @@ else
757
761
  _bootstrap=$(mktemp "${TERMUX_TMPDIR}/claude-bootstrap.XXXXXX.js")
758
762
  trap 'rm -f "$_bootstrap"' EXIT HUP INT TERM
759
763
  export CLAUDE_TERMUX_TUI="${_tui}"
764
+ export CLAUDE_TERMUX_PRINT_MODE="${_pf}"
760
765
  cat <<'NODE' > "$_bootstrap"
761
766
  const fs = require('fs');
762
767
  const path = require('path');
@@ -1275,6 +1280,7 @@ function rewriteNativeChunkSource(source) {
1275
1280
  const _bunPropertyAccessExpected = (() => {
1276
1281
  const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
1277
1282
  const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
1283
+ if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
1278
1284
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 216)) return 40;
1279
1285
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 214)) return 39;
1280
1286
  if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 205)) return 38;
@@ -1327,6 +1333,13 @@ async function main() {
1327
1333
  function onAsyncError(error) {
1328
1334
  asyncErrors.push(error);
1329
1335
  }
1336
+ async function waitForPrintFlushIfNeeded() {
1337
+ if (process.env.CLAUDE_TERMUX_PRINT_MODE !== '1') return;
1338
+ const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
1339
+ if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
1340
+ await new Promise(resolve => setTimeout(resolve, printWaitMs));
1341
+ }
1342
+ }
1330
1343
 
1331
1344
  try {
1332
1345
  process.once('uncaughtException', onAsyncError);
@@ -1392,10 +1405,12 @@ async function main() {
1392
1405
  const moduleLike = { exports: {} };
1393
1406
  const maybePromise = fn(moduleLike.exports, fakeRequire, moduleLike, extractedFile, workdir);
1394
1407
  if (maybePromise && typeof maybePromise.then === 'function') await maybePromise;
1408
+ await waitForPrintFlushIfNeeded();
1395
1409
  if (asyncErrors.length > 0) throw asyncErrors[0];
1396
1410
  } catch (error) {
1397
1411
  if (error instanceof RequestedExit) {
1398
1412
  process.exitCode = error.code;
1413
+ await waitForPrintFlushIfNeeded();
1399
1414
  return;
1400
1415
  }
1401
1416
  throw error;
@@ -191,12 +191,32 @@ test('print path does not defer cleanup to exit', () => {
191
191
  test('bootstrap path defers cleanup to exit', () => {
192
192
  const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
193
193
 
194
- assert.equal(bootstrapBlock.includes('CLAUDE_TERMUX_PRINT_WAIT_MS'), false);
195
- assert.equal(bootstrapBlock.includes('setTimeout(resolve, printWaitMs)'), false);
196
194
  assert.equal(bootstrapBlock.includes('process.once(\'exit\''), true);
197
195
  assert.equal(bootstrapBlock.includes('process.removeListener(\'uncaughtException\''), true);
198
196
  });
199
197
 
198
+ test('bootstrap branch exports CLAUDE_TERMUX_PRINT_MODE before invoking node', () => {
199
+ const bootstrapShellRegion = extractFunction(
200
+ script,
201
+ 'export CLAUDE_TERMUX_TUI="${_tui}"',
202
+ 'cat <<\'NODE\' > "$_bootstrap"',
203
+ );
204
+ assert.equal(bootstrapShellRegion.includes('export CLAUDE_TERMUX_PRINT_MODE="${_pf}"'), true);
205
+ });
206
+
207
+ test('helper and bootstrap wait for print flush, including the RequestedExit path', () => {
208
+ const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
209
+ const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
210
+
211
+ assert.equal(helperBlock.includes('async function waitForPrintFlush()'), true);
212
+ assert.equal(helperBlock.includes('await waitForPrintFlush();\n if (asyncErrors.length > 0) throw asyncErrors[0];'), true);
213
+ assert.equal(helperBlock.includes('process.exitCode = error.code;\n await waitForPrintFlush();\n return;'), true);
214
+
215
+ assert.equal(bootstrapBlock.includes('async function waitForPrintFlushIfNeeded()'), true);
216
+ assert.equal(bootstrapBlock.includes('await waitForPrintFlushIfNeeded();\n if (asyncErrors.length > 0) throw asyncErrors[0];'), true);
217
+ assert.equal(bootstrapBlock.includes('process.exitCode = error.code;\n await waitForPrintFlushIfNeeded();\n return;'), true);
218
+ });
219
+
200
220
  test('entry extraction uses a process-unique filename', () => {
201
221
  const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
202
222
  const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
@@ -478,6 +498,43 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
478
498
  }
479
499
  });
480
500
 
501
+ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.219)', () => {
502
+ process.env.CURRENT_CLAUDE_VERSION = '2.1.219';
503
+ try {
504
+ const { rewriteNativeChunkSource } = loadHelperApi();
505
+ const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
506
+ const bunProps = Array.from({ length: 42 }, (_, index) => `Bun.p${index}`).join('; ');
507
+ const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
508
+ const patched = rewriteNativeChunkSource(source);
509
+
510
+ assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
511
+ assert.match(patched, /typeof __claudeBun/);
512
+ assert.match(patched, /typeof globalThis\.__claudeBun/);
513
+ assert.match(patched, /globalThis\.__claudeBun/);
514
+ assert.match(patched, /__claudeBun\./);
515
+ assert.equal((patched.match(/__claudeBun\./g) || []).length, 42);
516
+ } finally {
517
+ delete process.env.CURRENT_CLAUDE_VERSION;
518
+ }
519
+ });
520
+
521
+ test('rewriteNativeChunkSource rejects stale Bun property access count for version 2.1.219', () => {
522
+ process.env.CURRENT_CLAUDE_VERSION = '2.1.219';
523
+ try {
524
+ const { rewriteNativeChunkSource } = loadHelperApi();
525
+ const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
526
+ const bunProps = Array.from({ length: 41 }, (_, index) => `Bun.p${index}`).join('; ');
527
+ const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
528
+
529
+ assert.throws(
530
+ () => rewriteNativeChunkSource(source),
531
+ /unexpected Bun property access count 41/,
532
+ );
533
+ } finally {
534
+ delete process.env.CURRENT_CLAUDE_VERSION;
535
+ }
536
+ });
537
+
481
538
  test('rewriteNativeChunkSource rejects unexpected replacement counts', () => {
482
539
  const { rewriteNativeChunkSource } = loadHelperApi();
483
540
  const source = buildSyntheticBundleSource().replace('Bun.p30;', '');
@@ -507,3 +564,77 @@ test('tarball contents match the workspace runner and test file', { skip: !fs.ex
507
564
  test('CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC is never forced (regression guard)', () => {
508
565
  assert.equal(script.includes('CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC'), false);
509
566
  });
567
+
568
+ function buildScenarioFixtureSource() {
569
+ const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
570
+ const bunProps = Array.from({ length: 42 }, (_, i) => `Bun.p${i}`).join('; ');
571
+ return `function(exports, require, module, __filename, __dirname) {
572
+ ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps};
573
+ npmInstallDeprecated:!0; npmInstallDeprecated:!0;
574
+ const scenario = process.env.TEST_SCENARIO;
575
+ if (scenario === 'sync-exit') { process.stdout.write('ok'); process.exit(0); return; }
576
+ if (scenario === 'async-exit') {
577
+ setTimeout(() => { process.stdout.write('ok'); }, 100).unref();
578
+ return;
579
+ }
580
+ process.stdout.write('ok');
581
+ }`;
582
+ }
583
+
584
+ function runScenario({ printMode, stdinInherit, scenario }) {
585
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-stdin-test-'));
586
+ const sourceBin = path.join(tmpBase, 'fake-source.js');
587
+ const fixtureSource = buildScenarioFixtureSource();
588
+ fs.writeFileSync(sourceBin, fixtureSource, 'utf8');
589
+ const entryJsOffset = 0;
590
+ const entryEndOffset = Buffer.byteLength(fixtureSource, 'utf8');
591
+ const workdir = path.join(tmpBase, 'workdir');
592
+ fs.mkdirSync(workdir, { recursive: true });
593
+
594
+ const env = {
595
+ ...process.env,
596
+ SOURCE_BIN: sourceBin,
597
+ WORKDIR: workdir,
598
+ ENTRY_JS_OFFSET: String(entryJsOffset),
599
+ ENTRY_END_OFFSET: String(entryEndOffset),
600
+ CURRENT_CLAUDE_VERSION: '2.1.220',
601
+ CLAUDE_TERMUX_PACKAGE_DIR: path.join(__dirname, '..'),
602
+ MAGI_ENV: '1',
603
+ CLAUDE_TERMUX_PRINT_WAIT_MS: '300',
604
+ TMPDIR: tmpBase,
605
+ TEST_SCENARIO: scenario,
606
+ };
607
+ if (stdinInherit) env.CLAUDE_TERMUX_STDIN = 'inherit';
608
+ else delete env.CLAUDE_TERMUX_STDIN;
609
+
610
+ const args = printMode ? ['-p', 'x'] : [];
611
+ const start = Date.now();
612
+ const result = child_process.spawnSync('sh', [scriptPath, ...args], {
613
+ env,
614
+ input: 'test input\n',
615
+ encoding: 'utf8',
616
+ timeout: 10000,
617
+ });
618
+ const elapsedMs = Date.now() - start;
619
+ fs.rmSync(tmpBase, { recursive: true, force: true });
620
+ return { ...result, elapsedMs };
621
+ }
622
+
623
+ test('helper branch (CLI -p, no stdin inherit): normal/sync-exit/async-exit all produce output', () => {
624
+ for (const scenario of ['normal', 'sync-exit', 'async-exit']) {
625
+ const r = runScenario({ printMode: true, stdinInherit: false, scenario });
626
+ assert.ok((r.stdout || '').includes('ok'), `scenario=${scenario} stdout=${r.stdout} stderr=${r.stderr}`);
627
+ assert.equal(r.status, 0, `scenario=${scenario} status=${r.status} stderr=${r.stderr}`);
628
+ }
629
+ });
630
+
631
+ test('bootstrap branch (-p + CLAUDE_TERMUX_STDIN=inherit): normal/sync-exit/async-exit all produce output', () => {
632
+ for (const scenario of ['normal', 'sync-exit', 'async-exit']) {
633
+ const r = runScenario({ printMode: true, stdinInherit: true, scenario });
634
+ assert.ok((r.stdout || '').includes('ok'), `scenario=${scenario} stdout=${r.stdout} stderr=${r.stderr}`);
635
+ assert.equal(r.status, 0, `scenario=${scenario} status=${r.status} stderr=${r.stderr}`);
636
+ if (scenario === 'async-exit') {
637
+ assert.ok(r.elapsedMs >= 250, `expected wait >= 250ms, got ${r.elapsedMs}ms`);
638
+ }
639
+ }
640
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash0816/claude-code",
3
- "version": "2.1.218",
3
+ "version": "2.1.220-1",
4
4
  "description": "Unofficial Termux-native Claude Code wrapper with audited native replay",
5
5
  "license": "GPL-3.0-only",
6
6
  "bin": {