@bash0816/claude-code 2.1.228 → 2.1.231

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.227
40
+ npm install -g @bash0816/claude-code@2.1.228
41
41
  ```
42
42
 
43
43
  ## Update / 更新
@@ -679,6 +679,15 @@
679
679
  "entry_end_offset": 297826425,
680
680
  "tarball_integrity": "sha512-rWSzUqON6kyIXUVz9KDU+9R6FdO11IVCO94D7kkWWyRPzFqzaAB80RmfgP//QgTIVFApEUzEUH2tfAGsUhD6ug==",
681
681
  "tarball_sha256": "31295a318aef235b1b818a8b46982757467fb4d13030520ac66d16a58c0d7e27",
682
+ "status": "termux_verified"
683
+ },
684
+ "2.1.231": {
685
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.231",
686
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.231",
687
+ "entry_js_offset": 273809585,
688
+ "entry_end_offset": 299210420,
689
+ "tarball_integrity": "sha512-a0YGXTjk6N5yRWE30dkbtS0tTZ5hOEXFCjTTX2slSa7XULMlJJLQ1X8oFJwpXmlvZu9FHx1YRLKJnni05uNIQQ==",
690
+ "tarball_sha256": "f50fa4b2270707208a3ae870deae8c562ec6b2f4d7bf778fca6275d13908b714",
682
691
  "status": "offset_discovered"
683
692
  }
684
693
  }
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "manifest_version": 1,
3
3
  "package_name": "@bash0816/claude-code",
4
- "latest_audited_version": "2.1.227",
5
- "latest_candidate_version": "2.1.228",
6
- "previous_stable_version": "2.1.226",
4
+ "latest_audited_version": "2.1.228",
5
+ "latest_candidate_version": "2.1.231",
6
+ "previous_stable_version": "2.1.227",
7
7
  "stable_pinned_version": "2.1.220-2",
8
8
  "manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
9
9
  }
@@ -680,6 +680,58 @@ async function main() {
680
680
  }
681
681
  const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
682
682
 
683
+ function installPlainTextWriteWatcher() {
684
+ const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
685
+ const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
686
+ const originalWrite = process.stdout.write.bind(process.stdout);
687
+ let foundOutput = false;
688
+ let resultPromiseResolve = null;
689
+ let restored = false;
690
+
691
+ process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
692
+ let cb = callback;
693
+ let enc = encoding;
694
+ if (typeof encoding === 'function') {
695
+ cb = encoding;
696
+ enc = undefined;
697
+ }
698
+ const combinedCallback = (err) => {
699
+ if (!err && !foundOutput) {
700
+ const len = typeof chunk === 'string'
701
+ ? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
702
+ : (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
703
+ if (len > 0) {
704
+ foundOutput = true;
705
+ if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
706
+ }
707
+ }
708
+ if (typeof cb === 'function') cb(err);
709
+ };
710
+ return originalWrite(chunk, enc, combinedCallback);
711
+ };
712
+
713
+ return {
714
+ waitForResult() {
715
+ if (foundOutput) return Promise.resolve();
716
+ return new Promise((resolve) => {
717
+ resultPromiseResolve = resolve;
718
+ });
719
+ },
720
+ hasOutput() {
721
+ return foundOutput;
722
+ },
723
+ restore() {
724
+ if (restored) return;
725
+ restored = true;
726
+ if (hadOwnWrite) {
727
+ Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
728
+ } else {
729
+ delete process.stdout.write;
730
+ }
731
+ },
732
+ };
733
+ }
734
+
683
735
  function installStreamJsonTerminalWatcher() {
684
736
  const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
685
737
  const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
@@ -768,6 +820,25 @@ async function main() {
768
820
  }
769
821
  return;
770
822
  }
823
+ if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
824
+ if (streamJsonWatcher.hasOutput()) {
825
+ return;
826
+ }
827
+ const gatingExitCode = process.exitCode;
828
+ const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
829
+ const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
830
+ const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
831
+ let timeoutHandle;
832
+ const timeoutPromise = new Promise(resolve => {
833
+ timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
834
+ });
835
+ try {
836
+ await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
837
+ } finally {
838
+ clearTimeout(timeoutHandle);
839
+ }
840
+ return;
841
+ }
771
842
  if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
772
843
  await new Promise(resolve => setTimeout(resolve, printWaitMs));
773
844
  }
@@ -882,6 +953,8 @@ async function main() {
882
953
 
883
954
  if (isStreamJsonPrintMode(argv)) {
884
955
  streamJsonWatcher = installStreamJsonTerminalWatcher();
956
+ } else {
957
+ streamJsonWatcher = installPlainTextWriteWatcher();
885
958
  }
886
959
 
887
960
  const moduleLike = { exports: {} };
@@ -1561,6 +1634,58 @@ async function main() {
1561
1634
  asyncErrors.push(error);
1562
1635
  }
1563
1636
 
1637
+ function installPlainTextWriteWatcher() {
1638
+ const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
1639
+ const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
1640
+ const originalWrite = process.stdout.write.bind(process.stdout);
1641
+ let foundOutput = false;
1642
+ let resultPromiseResolve = null;
1643
+ let restored = false;
1644
+
1645
+ process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
1646
+ let cb = callback;
1647
+ let enc = encoding;
1648
+ if (typeof encoding === 'function') {
1649
+ cb = encoding;
1650
+ enc = undefined;
1651
+ }
1652
+ const combinedCallback = (err) => {
1653
+ if (!err && !foundOutput) {
1654
+ const len = typeof chunk === 'string'
1655
+ ? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
1656
+ : (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
1657
+ if (len > 0) {
1658
+ foundOutput = true;
1659
+ if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
1660
+ }
1661
+ }
1662
+ if (typeof cb === 'function') cb(err);
1663
+ };
1664
+ return originalWrite(chunk, enc, combinedCallback);
1665
+ };
1666
+
1667
+ return {
1668
+ waitForResult() {
1669
+ if (foundOutput) return Promise.resolve();
1670
+ return new Promise((resolve) => {
1671
+ resultPromiseResolve = resolve;
1672
+ });
1673
+ },
1674
+ hasOutput() {
1675
+ return foundOutput;
1676
+ },
1677
+ restore() {
1678
+ if (restored) return;
1679
+ restored = true;
1680
+ if (hadOwnWrite) {
1681
+ Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
1682
+ } else {
1683
+ delete process.stdout.write;
1684
+ }
1685
+ },
1686
+ };
1687
+ }
1688
+
1564
1689
  function installStreamJsonTerminalWatcher() {
1565
1690
  const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
1566
1691
  const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
@@ -1650,6 +1775,26 @@ async function main() {
1650
1775
  }
1651
1776
  return;
1652
1777
  }
1778
+ if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
1779
+ if (streamJsonWatcher.hasOutput()) {
1780
+ return;
1781
+ }
1782
+ const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
1783
+ const gatingExitCode = process.exitCode;
1784
+ const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
1785
+ const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
1786
+ const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
1787
+ let timeoutHandle;
1788
+ const timeoutPromise = new Promise(resolve => {
1789
+ timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
1790
+ });
1791
+ try {
1792
+ await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
1793
+ } finally {
1794
+ clearTimeout(timeoutHandle);
1795
+ }
1796
+ return;
1797
+ }
1653
1798
  const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
1654
1799
  if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
1655
1800
  await new Promise(resolve => setTimeout(resolve, printWaitMs));
@@ -1765,6 +1910,8 @@ async function main() {
1765
1910
 
1766
1911
  if (isStreamJsonPrintMode(argv)) {
1767
1912
  streamJsonWatcher = installStreamJsonTerminalWatcher();
1913
+ } else if (process.env.CLAUDE_TERMUX_PRINT_MODE === '1') {
1914
+ streamJsonWatcher = installPlainTextWriteWatcher();
1768
1915
  }
1769
1916
 
1770
1917
  const moduleLike = { exports: {} };
@@ -709,11 +709,22 @@ function buildScenarioFixtureSource() {
709
709
  process.exit(0);
710
710
  return;
711
711
  }
712
+ if (scenario === 'plain-late-write') {
713
+ setTimeout(() => { process.stdout.write('late-output'); }, 800);
714
+ return;
715
+ }
716
+ if (scenario === 'plain-no-output-error') {
717
+ process.exitCode = 1;
718
+ return;
719
+ }
720
+ if (scenario === 'plain-no-output-success') {
721
+ return;
722
+ }
712
723
  process.stdout.write('ok');
713
724
  }`;
714
725
  }
715
726
 
716
- function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
727
+ function runScenario({ printMode, stdinInherit, scenario, extraArgs, extraEnv }) {
717
728
  const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-stdin-test-'));
718
729
  const sourceBin = path.join(tmpBase, 'fake-source.js');
719
730
  const fixtureSource = buildScenarioFixtureSource();
@@ -735,6 +746,7 @@ function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
735
746
  CLAUDE_TERMUX_PRINT_WAIT_MS: '300',
736
747
  TMPDIR: tmpBase,
737
748
  TEST_SCENARIO: scenario,
749
+ ...(extraEnv || {}),
738
750
  };
739
751
  if (stdinInherit) env.CLAUDE_TERMUX_STDIN = 'inherit';
740
752
  else delete env.CLAUDE_TERMUX_STDIN;
@@ -808,15 +820,82 @@ test('bootstrap branch (-p + CLAUDE_TERMUX_STDIN=inherit): normal/sync-exit/asyn
808
820
  try {
809
821
  assert.ok((r.stdout || '').includes('ok'), `scenario=${scenario} stdout=${r.stdout} stderr=${r.stderr}`);
810
822
  assert.equal(r.status, 0, `scenario=${scenario} status=${r.status} stderr=${r.stderr}`);
811
- if (scenario === 'async-exit') {
812
- assert.ok(r.elapsedMs >= 250, `expected wait >= 250ms, got ${r.elapsedMs}ms`);
813
- }
814
823
  } finally {
815
824
  fs.rmSync(r.tmpBase, { recursive: true, force: true });
816
825
  }
817
826
  }
818
827
  });
819
828
 
829
+ test('helper branch plain mode waits for late write beyond default printWaitMs', () => {
830
+ const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-late-write' });
831
+ try {
832
+ assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
833
+ assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
834
+ } finally {
835
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
836
+ }
837
+ });
838
+
839
+ test('bootstrap branch plain mode waits for late write beyond default printWaitMs', () => {
840
+ const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-late-write' });
841
+ try {
842
+ assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
843
+ assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
844
+ } finally {
845
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
846
+ }
847
+ });
848
+
849
+ test('helper branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
850
+ const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-no-output-error' });
851
+ try {
852
+ assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
853
+ assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
854
+ } finally {
855
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
856
+ }
857
+ });
858
+
859
+ test('bootstrap branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
860
+ const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-no-output-error' });
861
+ try {
862
+ assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
863
+ assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
864
+ } finally {
865
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
866
+ }
867
+ });
868
+
869
+ test('helper branch plain mode with no output and successful exit waits up to configured ceiling', () => {
870
+ const r = runScenario({
871
+ printMode: true,
872
+ stdinInherit: false,
873
+ scenario: 'plain-no-output-success',
874
+ extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
875
+ });
876
+ try {
877
+ assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
878
+ assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
879
+ } finally {
880
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
881
+ }
882
+ });
883
+
884
+ test('bootstrap branch plain mode with no output and successful exit waits up to configured ceiling', () => {
885
+ const r = runScenario({
886
+ printMode: true,
887
+ stdinInherit: true,
888
+ scenario: 'plain-no-output-success',
889
+ extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
890
+ });
891
+ try {
892
+ assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
893
+ assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
894
+ } finally {
895
+ fs.rmSync(r.tmpBase, { recursive: true, force: true });
896
+ }
897
+ });
898
+
820
899
  test('helper branch intercepts self-directed SIGKILL (string signal) and exits with proper code', () => {
821
900
  const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'self-sigkill-fallback-string' });
822
901
  try {
@@ -1075,6 +1154,31 @@ test('helper and bootstrap installStreamJsonTerminalWatcher helpers stay identic
1075
1154
  assert.equal(helperWatcher, bootstrapWatcher, 'installStreamJsonTerminalWatcher must be identical in both heredocs');
1076
1155
  });
1077
1156
 
1157
+ test('helper and bootstrap installPlainTextWriteWatcher helpers stay identical', () => {
1158
+ const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
1159
+ const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
1160
+
1161
+ const extractFn = (block) => {
1162
+ const startMarker = 'function installPlainTextWriteWatcher() {';
1163
+ const start = block.indexOf(startMarker);
1164
+ assert.ok(start > -1, 'installPlainTextWriteWatcher function not found');
1165
+ let depth = 0;
1166
+ let i = start + startMarker.length - 1;
1167
+ for (; i < block.length; i++) {
1168
+ if (block[i] === '{') depth++;
1169
+ if (block[i] === '}') {
1170
+ depth--;
1171
+ if (depth === 0) break;
1172
+ }
1173
+ }
1174
+ return block.slice(start, i + 1);
1175
+ };
1176
+
1177
+ const helperFn = extractFn(helperBlock);
1178
+ const bootstrapFn = extractFn(bootstrapBlock);
1179
+ assert.equal(helperFn, bootstrapFn, 'installPlainTextWriteWatcher must be identical in helper and bootstrap');
1180
+ });
1181
+
1078
1182
  test('helper and bootstrap forceTimeoutExit helpers stay identical', () => {
1079
1183
  const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
1080
1184
  const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash0816/claude-code",
3
- "version": "2.1.228",
3
+ "version": "2.1.231",
4
4
  "description": "Unofficial Termux-native Claude Code wrapper with audited native replay",
5
5
  "license": "GPL-3.0-only",
6
6
  "bin": {