@xurxuo/claude-code-termux 2.1.140 → 2.1.141

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
@@ -29,8 +29,14 @@ claude
29
29
  ```bash
30
30
  claude # Start Claude Code
31
31
  claude --version # Check version
32
+ claude update # Force update to latest Claude Code packages
32
33
  ```
33
34
 
35
+ The wrapper checks npm at most once per day. If
36
+ `@anthropic-ai/claude-code-linux-arm64` has a newer version, it automatically
37
+ installs the latest Claude Code packages before launching. Set
38
+ `CLAUDE_CODE_TERMUX_NO_AUTO_UPDATE=1` to disable the daily check.
39
+
34
40
  ## Auth
35
41
 
36
42
  Set your API key:
@@ -42,4 +48,4 @@ Or run `claude` and follow auth flow.
42
48
 
43
49
  ## Source
44
50
 
45
- Based on @anthropic-ai/claude-code with Termux patches.
51
+ Based on @anthropic-ai/claude-code with Termux patches.
package/cli-wrapper.cjs CHANGED
@@ -4,11 +4,14 @@
4
4
 
5
5
  const { spawnSync } = require('child_process')
6
6
  const { arch, constants } = require('os')
7
+ const fs = require('fs')
8
+ const os = require('os')
7
9
  const path = require('path')
8
10
 
9
11
  const PACKAGE_PREFIX = '@anthropic-ai/claude-code'
10
12
  const BINARY_NAME = 'claude'
11
13
  const WRAPPER_NAME = require('./package.json').name
14
+ const UPDATE_INTERVAL_MS = 24 * 60 * 60 * 1000
12
15
 
13
16
  const PLATFORMS = {
14
17
  'darwin-arm64': { pkg: PACKAGE_PREFIX + '-darwin-arm64', bin: BINARY_NAME },
@@ -73,7 +76,104 @@ function getPlatformKey() {
73
76
  return platform + '-' + cpu
74
77
  }
75
78
 
76
- function getBinaryPath() {
79
+ function readPackageJson(pkg) {
80
+ const pkgJsonPath = require.resolve(pkg + '/package.json')
81
+ return {
82
+ dir: path.dirname(pkgJsonPath),
83
+ json: require(pkgJsonPath),
84
+ }
85
+ }
86
+
87
+ function compareVersions(a, b) {
88
+ const left = String(a).split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0)
89
+ const right = String(b).split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0)
90
+ const len = Math.max(left.length, right.length)
91
+ for (let i = 0; i < len; i++) {
92
+ if ((left[i] || 0) > (right[i] || 0)) return 1
93
+ if ((left[i] || 0) < (right[i] || 0)) return -1
94
+ }
95
+ return 0
96
+ }
97
+
98
+ function getStateFile() {
99
+ return path.join(os.homedir(), '.cache', 'claude-code-termux', 'update-check.json')
100
+ }
101
+
102
+ function shouldCheckForUpdates(force) {
103
+ if (force) return true
104
+ if (process.env.CLAUDE_CODE_TERMUX_NO_AUTO_UPDATE === '1') return false
105
+
106
+ try {
107
+ const state = JSON.parse(fs.readFileSync(getStateFile(), 'utf8'))
108
+ return Date.now() - Number(state.lastChecked || 0) > UPDATE_INTERVAL_MS
109
+ } catch {
110
+ return true
111
+ }
112
+ }
113
+
114
+ function markUpdateChecked() {
115
+ const file = getStateFile()
116
+ fs.mkdirSync(path.dirname(file), { recursive: true })
117
+ fs.writeFileSync(file, JSON.stringify({ lastChecked: Date.now() }) + '\n')
118
+ }
119
+
120
+ function npmViewLatest(pkg) {
121
+ const command = process.env.npm_execpath ? process.execPath : 'npm'
122
+ const args = process.env.npm_execpath
123
+ ? [process.env.npm_execpath, 'view', pkg, 'version', '--silent']
124
+ : ['view', pkg, 'version', '--silent']
125
+ const result = spawnSync(command, args, {
126
+ encoding: 'utf8',
127
+ shell: process.platform === 'win32',
128
+ })
129
+ if (result.status !== 0) return null
130
+ return result.stdout.trim()
131
+ }
132
+
133
+ function npmInstallLatest(packages) {
134
+ const command = process.env.npm_execpath ? process.execPath : 'npm'
135
+ const installArgs = ['install', '-g', ...packages.map((pkg) => pkg + '@latest')]
136
+ const args = process.env.npm_execpath
137
+ ? [process.env.npm_execpath, ...installArgs]
138
+ : installArgs
139
+ const result = spawnSync(
140
+ command,
141
+ args,
142
+ {
143
+ stdio: 'inherit',
144
+ shell: process.platform === 'win32',
145
+ },
146
+ )
147
+ return result.status === 0
148
+ }
149
+
150
+ function refreshNativePackage(info, force = false) {
151
+ if (!shouldCheckForUpdates(force)) return
152
+
153
+ let current = null
154
+ try {
155
+ current = readPackageJson(info.pkg).json.version
156
+ } catch {}
157
+
158
+ const latest = npmViewLatest(info.pkg)
159
+ if (!latest) {
160
+ if (force) {
161
+ console.error(`[${WRAPPER_NAME}] Could not fetch latest ${info.pkg} version.`)
162
+ }
163
+ return
164
+ }
165
+
166
+ if (!current || compareVersions(latest, current) > 0 || force) {
167
+ console.error(
168
+ `[${WRAPPER_NAME}] Updating Claude Code native package ${current || 'missing'} -> ${latest}`,
169
+ )
170
+ npmInstallLatest([PACKAGE_PREFIX, info.pkg])
171
+ }
172
+
173
+ markUpdateChecked()
174
+ }
175
+
176
+ function getBinaryPath(options = {}) {
77
177
  const platformKey = getPlatformKey()
78
178
  const info = PLATFORMS[platformKey]
79
179
  if (!info) {
@@ -82,8 +182,9 @@ function getBinaryPath() {
82
182
  )
83
183
  process.exit(1)
84
184
  }
185
+ refreshNativePackage(info, options.forceUpdate)
85
186
  try {
86
- const pkgDir = path.dirname(require.resolve(info.pkg + '/package.json'))
187
+ const pkgDir = readPackageJson(info.pkg).dir
87
188
  return path.join(pkgDir, info.bin)
88
189
  } catch {
89
190
  console.error(
@@ -95,8 +196,16 @@ function getBinaryPath() {
95
196
  }
96
197
 
97
198
  function main() {
199
+ const args = process.argv.slice(2)
200
+ const forceUpdate = args[0] === 'update' || args[0] === '--update' || args[0] === '-update'
201
+
202
+ if (forceUpdate) {
203
+ getBinaryPath({ forceUpdate: true })
204
+ process.exit(0)
205
+ }
206
+
98
207
  const binaryPath = getBinaryPath()
99
- const result = spawnSync(binaryPath, process.argv.slice(2), {
208
+ const result = spawnSync(binaryPath, args, {
100
209
  stdio: 'inherit',
101
210
  env: { ...process.env, CLAUDE_CODE_INSTALLED_VIA_NPM_WRAPPER: '1' },
102
211
  })
@@ -115,4 +224,4 @@ function main() {
115
224
  }
116
225
  }
117
226
 
118
- main()
227
+ main()
package/install.cjs CHANGED
@@ -3,15 +3,6 @@
3
3
  // Patches: android -> linux for platform detection
4
4
 
5
5
  const { spawnSync } = require('child_process')
6
- const {
7
- copyFileSync,
8
- linkSync,
9
- unlinkSync,
10
- chmodSync,
11
- readFileSync,
12
- writeFileSync,
13
- statSync,
14
- } = require('fs')
15
6
  const { arch } = require('os')
16
7
  const path = require('path')
17
8
 
@@ -82,36 +73,40 @@ function getPlatformKey() {
82
73
  return platform + '-' + cpu
83
74
  }
84
75
 
85
- function placeBinary(src, dest) {
86
- try {
87
- linkSync(src, dest)
88
- } catch (err) {
89
- if (err.code === 'EEXIST') {
90
- const stub = statSync(dest).size < 4096 ? readFileSync(dest) : null
91
- unlinkSync(dest)
92
- try {
93
- linkSync(src, dest)
94
- } catch {
95
- try {
96
- copyFileSync(src, dest)
97
- } catch (copyErr) {
98
- if (stub) {
99
- try {
100
- writeFileSync(dest, stub, { mode: 0o755 })
101
- } catch {}
102
- }
103
- throw copyErr
104
- }
105
- }
106
- } else if (err.code === 'EXDEV' || err.code === 'EPERM') {
107
- copyFileSync(src, dest)
108
- } else {
109
- throw err
110
- }
111
- }
112
- if (process.platform !== 'win32') {
113
- chmodSync(dest, 0o755)
76
+ function installLatestNativePackage(pkg) {
77
+ console.error(`[${WRAPPER_NAME} postinstall] Installing ${pkg}@latest...`)
78
+ const command = process.env.npm_execpath ? process.execPath : 'npm'
79
+ const args = process.env.npm_execpath
80
+ ? [process.env.npm_execpath, 'install', '-g', pkg + '@latest']
81
+ : ['install', '-g', pkg + '@latest']
82
+ const result = spawnSync(command, args, {
83
+ stdio: 'inherit',
84
+ shell: process.platform === 'win32',
85
+ })
86
+ return result.status === 0
87
+ }
88
+
89
+ function npmViewLatest(pkg) {
90
+ const command = process.env.npm_execpath ? process.execPath : 'npm'
91
+ const args = process.env.npm_execpath
92
+ ? [process.env.npm_execpath, 'view', pkg, 'version', '--silent']
93
+ : ['view', pkg, 'version', '--silent']
94
+ const result = spawnSync(command, args, {
95
+ encoding: 'utf8',
96
+ shell: process.platform === 'win32',
97
+ })
98
+ return result.status === 0 ? result.stdout.trim() : null
99
+ }
100
+
101
+ function compareVersions(a, b) {
102
+ const left = String(a).split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0)
103
+ const right = String(b).split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0)
104
+ const len = Math.max(left.length, right.length)
105
+ for (let i = 0; i < len; i++) {
106
+ if ((left[i] || 0) > (right[i] || 0)) return 1
107
+ if ((left[i] || 0) < (right[i] || 0)) return -1
114
108
  }
109
+ return 0
115
110
  }
116
111
 
117
112
  function main() {
@@ -126,32 +121,25 @@ function main() {
126
121
  return
127
122
  }
128
123
 
129
- let src
130
124
  try {
131
125
  const pkgDir = path.dirname(require.resolve(info.pkg + '/package.json'))
132
- src = path.join(pkgDir, info.bin)
133
- } catch {
134
- console.error(
135
- `[${WRAPPER_NAME} postinstall] Native package "${info.pkg}" not found.`,
136
- )
126
+ const pkgJson = require(path.join(pkgDir, 'package.json'))
137
127
  console.error(
138
- ' The `claude` command will print instructions when invoked.',
128
+ `[${WRAPPER_NAME} postinstall] Native package ready: ${info.pkg}@${pkgJson.version}`,
139
129
  )
140
- console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
141
- return
142
- }
143
-
144
- const dest = path.join(__dirname, 'bin', 'claude.exe')
145
-
146
- try {
147
- placeBinary(src, dest)
148
- } catch (err) {
149
- console.error(
150
- `[${WRAPPER_NAME} postinstall] Failed to place binary: ${err.message}`,
151
- )
152
- console.error(' Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
153
- process.exitCode = 1
130
+ const latest = npmViewLatest(info.pkg)
131
+ if (latest && compareVersions(latest, pkgJson.version) > 0) {
132
+ installLatestNativePackage(info.pkg)
133
+ }
134
+ } catch {
135
+ if (!installLatestNativePackage(info.pkg)) {
136
+ console.error(
137
+ `[${WRAPPER_NAME} postinstall] Native package "${info.pkg}" not found and latest install failed.`,
138
+ )
139
+ console.error(' Try again with: npm install -g ' + info.pkg + '@latest')
140
+ process.exitCode = 1
141
+ }
154
142
  }
155
143
  }
156
144
 
157
- main()
145
+ main()
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@xurxuo/claude-code-termux",
3
- "version": "2.1.140",
3
+ "version": "2.1.141",
4
4
  "bin": {
5
- "claude": "bin/claude.exe"
5
+ "claude": "cli-wrapper.cjs"
6
6
  },
7
7
  "scripts": {
8
8
  "postinstall": "node install.cjs"
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {},
22
22
  "optionalDependencies": {
23
- "@anthropic-ai/claude-code-linux-arm64": "2.1.140"
23
+ "@anthropic-ai/claude-code-linux-arm64": "latest"
24
24
  },
25
25
  "files": [
26
26
  "bin/claude.exe",
@@ -28,4 +28,4 @@
28
28
  "cli-wrapper.cjs",
29
29
  "sdk-tools.d.ts"
30
30
  ]
31
- }
31
+ }