openclaw-droid 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mithun Gowda B
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # ClawDroid šŸ¤–
2
+
3
+ > **Run OpenClaw AI Gateway on Android via Termux**
4
+ > One-command setup. Optimized for mobile. Bionic Bypass included.
5
+
6
+ ![License](https://img.shields.io/badge/license-MIT-blue.svg)
7
+ ![Platform](https://img.shields.io/badge/platform-Android%20%7C%20Termux-green.svg)
8
+ ![Version](https://img.shields.io/badge/version-1.0.0-orange.svg)
9
+
10
+ **ClawDroid** makes running [OpenClaw](https://github.com/openclaw/openclaw) on Android effortless. It handles the environment setup (proot-distro, Ubuntu, Node.js) and fixes Android-specific issues automatically.
11
+
12
+ ## šŸš€ Why ClawDroid?
13
+
14
+ Running standard Node.js AI tools on Android is painful because of:
15
+ * **Bionic libc**: Android's C library differs from Linux (glibc), breaking `os.networkInterfaces()` and DNS lookups.
16
+ * **Permissions**: Termux has restricted access to system resources.
17
+ * **Environment**: Many tools expect a full Linux userland (Ubuntu/Debian).
18
+
19
+ **ClawDroid solves this by:**
20
+ 1. Creating a lightweight **Ubuntu** container inside Termux.
21
+ 2. Injecting a **Bionic Bypass** script to fix networking.
22
+ 3. Providing a simple CLI (`clawdroid`) to manage the gateway.
23
+
24
+ ## šŸ“¦ Installation
25
+
26
+ ### Prerequisites
27
+ * **Android 10+**
28
+ * **Termux** (Install from [F-Droid](https://f-droid.org/packages/com.termux/), NOT Play Store)
29
+ * ~2GB free storage
30
+
31
+ ### One-Command Setup
32
+ Open Termux and run:
33
+
34
+ ```bash
35
+ curl -fsSL https://raw.githubusercontent.com/NOSYTLABS/clawdroid/main/install.sh | bash
36
+ ```
37
+
38
+ Or via npm:
39
+
40
+ ```bash
41
+ npm install -g clawdroid
42
+ clawdroid setup
43
+ ```
44
+
45
+ ## šŸŽ® Usage
46
+
47
+ ### 1. Initialize
48
+ First, configure your API keys:
49
+
50
+ ```bash
51
+ clawdroid onboarding
52
+ ```
53
+ > **IMPORTANT:** Select **Loopback (127.0.0.1)** for Binding.
54
+
55
+ ### 2. Start Gateway
56
+ Launch the OpenClaw gateway:
57
+
58
+ ```bash
59
+ clawdroid start
60
+ ```
61
+ The dashboard will be available at: **http://127.0.0.1:18789**
62
+
63
+ ### 3. Other Commands
64
+
65
+ | Command | Description |
66
+ | :--- | :--- |
67
+ | `clawdroid status` | Check installation health |
68
+ | `clawdroid update` | Update OpenClaw to the latest version |
69
+ | `clawdroid shell` | Open the Ubuntu shell |
70
+ | `clawdroid repair` | Re-install dependencies if broken |
71
+ | `clawdroid <cmd>` | Run any OpenClaw command (e.g., `clawdroid doctor`) |
72
+
73
+ ## 🧩 Architecture
74
+
75
+ ```mermaid
76
+ graph TD
77
+ A[User] -->|clawdroid start| B(Termux)
78
+ B -->|proot-distro| C{Ubuntu Container}
79
+ C -->|Bionic Bypass| D[OpenClaw Gateway]
80
+ D -->|HTTP| E[Web Dashboard]
81
+ D -->|API| F[LLM Providers]
82
+ ```
83
+
84
+ ## āš ļø Troubleshooting
85
+
86
+ **"Setup not complete" error**
87
+ * Run `clawdroid setup` again.
88
+ * If it persists, run `clawdroid repair`.
89
+
90
+ **Process killed in background**
91
+ * Go to Android Settings → Apps → Termux → Battery → **Unrestricted**.
92
+
93
+ ## šŸ“œ License
94
+
95
+ MIT License.
package/bin/openclaw ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from '../lib/index.js';
4
+
5
+ main(process.argv.slice(2)).catch((err) => {
6
+ console.error('Error:', err.message);
7
+ process.exit(1);
8
+ });
package/install.sh ADDED
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ #
3
+ # OpenClaw Droid Installer
4
+ # One-liner: curl -fsSL https://raw.githubusercontent.com/NosytLabs/openclaw-droid/main/install.sh | bash
5
+ #
6
+
7
+ set -e
8
+
9
+ # Colors
10
+ RED='\033[0;31m'
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ BLUE='\033[0;34m'
14
+ NC='\033[0m'
15
+
16
+ echo -e "${BLUE}"
17
+ echo "-------------------------------------------"
18
+ echo " OpenClaw Droid Installer v1.0.0"
19
+ echo "-------------------------------------------"
20
+ echo -e "${NC}"
21
+
22
+ # Check if running in Termux
23
+ if [ ! -d "/data/data/com.termux" ] && [ -z "$TERMUX_VERSION" ]; then
24
+ echo -e "${YELLOW}Warning:${NC} Not running in Termux - some features may not work"
25
+ fi
26
+
27
+ # Update and install packages
28
+ echo -e "\n${BLUE}[1/3]${NC} Installing required packages..."
29
+
30
+ # Update Termux repositories
31
+ echo -e " ${BLUE}•${NC} Updating Termux repositories..."
32
+ pkg update -y || true
33
+ pkg upgrade -y || true
34
+
35
+ echo -e " ${BLUE}•${NC} Installing dependencies..."
36
+ pkg install -y nodejs-lts git proot-distro android-tools termux-api
37
+
38
+ echo -e " ${GREEN}āœ“${NC} Node.js $(node --version)"
39
+ echo -e " ${GREEN}āœ“${NC} npm $(npm --version)"
40
+ echo -e " ${GREEN}āœ“${NC} git installed"
41
+ echo -e " ${GREEN}āœ“${NC} proot-distro installed"
42
+ echo -e " ${GREEN}āœ“${NC} adb $(adb version | head -n 1)"
43
+ echo -e " ${GREEN}āœ“${NC} termux-api installed"
44
+
45
+ # Install openclaw-droid from npm
46
+ echo -e "\n${BLUE}[2/3]${NC} Installing OpenClaw Droid..."
47
+ npm install -g openclaw-droid
48
+
49
+ echo -e "\n${BLUE}[3/3]${NC} Verifying Android tools..."
50
+ adb start-server >/dev/null 2>&1 || true
51
+ adb devices || true
52
+
53
+ echo -e "\n${GREEN}═══════════════════════════════════════════${NC}"
54
+ echo -e "${GREEN}Installation complete!${NC}"
55
+ echo -e "${GREEN}═══════════════════════════════════════════${NC}"
56
+ echo ""
57
+ echo -e "${YELLOW}Next steps:${NC}"
58
+ echo " 1. Run setup: openclaw setup"
59
+ echo " 2. Run onboarding: openclaw onboarding"
60
+ echo " → Select 'Loopback (127.0.0.1)' when asked!"
61
+ echo " 3. Start gateway: openclaw start"
62
+ echo ""
63
+ echo -e "Dashboard: ${BLUE}http://127.0.0.1:18789${NC}"
64
+ echo ""
65
+ echo -e "${YELLOW}Tip:${NC} Disable battery optimization for Termux in Android settings"
66
+ echo -e "${YELLOW}Tip:${NC} Install Termux:API app from F-Droid for camera, wakelock, and sensors"
67
+ echo ""
@@ -0,0 +1,64 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const BYPASS_SCRIPT = `
5
+ const os = require('os');
6
+ const originalNetworkInterfaces = os.networkInterfaces;
7
+
8
+ os.networkInterfaces = function() {
9
+ try {
10
+ const interfaces = originalNetworkInterfaces.call(os);
11
+ if (interfaces && Object.keys(interfaces).length > 0) {
12
+ return interfaces;
13
+ }
14
+ } catch (e) {}
15
+
16
+ return {
17
+ lo: [
18
+ {
19
+ address: '127.0.0.1',
20
+ netmask: '255.0.0.0',
21
+ family: 'IPv4',
22
+ mac: '00:00:00:00:00:00',
23
+ internal: true,
24
+ cidr: '127.0.0.1/8'
25
+ }
26
+ ]
27
+ };
28
+ };
29
+ `;
30
+
31
+ export function getBypassScriptPath() {
32
+ const homeDir = process.env.HOME || '/data/data/com.termux/files/home';
33
+ return path.join(homeDir, '.clawdroid', 'bionic-bypass.js');
34
+ }
35
+
36
+ export function installBypass() {
37
+ const scriptPath = getBypassScriptPath();
38
+ const scriptDir = path.dirname(scriptPath);
39
+
40
+ if (!fs.existsSync(scriptDir)) {
41
+ fs.mkdirSync(scriptDir, { recursive: true });
42
+ }
43
+
44
+ fs.writeFileSync(scriptPath, BYPASS_SCRIPT, 'utf8');
45
+ fs.chmodSync(scriptPath, '644');
46
+
47
+ return scriptPath;
48
+ }
49
+
50
+ export function getNodeOptions() {
51
+ const scriptPath = getBypassScriptPath();
52
+ return `--require "${scriptPath}"`;
53
+ }
54
+
55
+ export function isAndroid() {
56
+ return process.platform === 'android' ||
57
+ fs.existsSync('/data/data/com.termux') ||
58
+ process.env.TERMUX_VERSION !== undefined;
59
+ }
60
+
61
+ export function checkBypassInstalled() {
62
+ const scriptPath = getBypassScriptPath();
63
+ return fs.existsSync(scriptPath);
64
+ }
package/lib/index.js ADDED
@@ -0,0 +1,304 @@
1
+ import {
2
+ configureTermux,
3
+ getInstallStatus,
4
+ installProot,
5
+ installUbuntu,
6
+ setupProotUbuntu,
7
+ setupBionicBypassInProot,
8
+ runInProot,
9
+ runInProotWithCallback
10
+ } from './installer.js';
11
+ import { isAndroid } from './bionic-bypass.js';
12
+ import { spawn } from 'child_process';
13
+
14
+ const VERSION = '1.0.0';
15
+
16
+ function printBanner() {
17
+ console.log(`
18
+
19
+ OPENCLAW-DROID v${VERSION}
20
+
21
+ `);
22
+ }
23
+
24
+ function printHelp() {
25
+ console.log(`
26
+ Usage: openclaw [command] [args...]
27
+
28
+ If run without arguments, it starts the OpenClaw gateway.
29
+
30
+ Commands:
31
+ start Start OpenClaw gateway (Default)
32
+ setup Full installation (proot + Ubuntu + OpenClaw)
33
+ update Update OpenClaw to the latest version
34
+ repair Re-install OpenClaw and dependencies
35
+ status Check installation status
36
+ shell Open Ubuntu shell with OpenClaw ready
37
+ help Show this help message
38
+ openclaw onboarding
39
+ openclaw gateway -v
40
+ openclaw doctor
41
+
42
+ Examples:
43
+ openclaw # Start gateway
44
+ openclaw setup # First-time setup
45
+ openclaw update # Update OpenClaw
46
+ openclaw repair # Fix installation
47
+ openclaw shell # Enter Ubuntu shell
48
+ `);
49
+ }
50
+
51
+ async function runSetup() {
52
+ console.log('Starting OpenClaw Droid setup for Termux...\n');
53
+
54
+ if (!isAndroid()) {
55
+ console.log('Warning: This package is designed for Android/Termux.');
56
+ console.log('Some features may not work on other platforms.\n');
57
+ }
58
+
59
+ let status = getInstallStatus();
60
+
61
+ console.log('[1/5] Checking proot-distro...');
62
+ if (!status.proot) {
63
+ installProot();
64
+ } else {
65
+ console.log(' āœ“ proot-distro installed');
66
+ }
67
+ console.log('');
68
+
69
+ console.log('[2/5] Checking Ubuntu in proot...');
70
+ status = getInstallStatus();
71
+ if (!status.ubuntu) {
72
+ installUbuntu();
73
+ } else {
74
+ console.log(' āœ“ Ubuntu installed');
75
+ }
76
+ console.log('');
77
+
78
+ console.log('[3/5] Setting up Node.js and OpenClaw in Ubuntu...');
79
+ status = getInstallStatus();
80
+ if (!status.openClawInProot) {
81
+ setupProotUbuntu();
82
+ } else {
83
+ console.log(' āœ“ OpenClaw already installed in proot');
84
+ }
85
+ console.log('');
86
+
87
+ console.log('[4/5] Setting up Bionic Bypass in proot...');
88
+ setupBionicBypassInProot();
89
+ console.log('');
90
+
91
+ console.log('[5/5] Configuring Termux...');
92
+ configureTermux();
93
+ console.log('');
94
+
95
+ console.log('═══════════════════════════════════════════');
96
+ console.log('Setup complete!');
97
+ console.log('');
98
+ console.log('Next steps:');
99
+ console.log(' 1. Run onboarding: openclaw onboarding');
100
+ console.log(' → Select "Loopback (127.0.0.1)" when asked!');
101
+ console.log(' 2. Start gateway: openclaw start');
102
+ console.log('');
103
+ console.log('Dashboard: http://127.0.0.1:18789');
104
+ console.log('═══════════════════════════════════════════');
105
+ }
106
+
107
+ function showStatus() {
108
+ process.stdout.write('Checking installation status...');
109
+ const status = getInstallStatus();
110
+ process.stdout.write('\r' + ' '.repeat(35) + '\r');
111
+
112
+ console.log('Installation Status:\n');
113
+ console.log('Termux:');
114
+ console.log(` proot-distro: ${status.proot ? 'āœ“ installed' : 'āœ— missing'}`);
115
+ console.log(` Ubuntu (proot): ${status.ubuntu ? 'āœ“ installed' : 'āœ— not installed'}`);
116
+ console.log('');
117
+
118
+ if (status.ubuntu) {
119
+ console.log('Inside Ubuntu:');
120
+ console.log(` OpenClaw: ${status.openClawInProot ? 'āœ“ installed' : 'āœ— not installed'}`);
121
+ console.log(` Bionic Bypass: ${status.bionicBypassInProot ? 'āœ“ configured' : 'āœ— not configured'}`);
122
+ console.log('');
123
+ }
124
+
125
+ if (status.proot && status.ubuntu && status.openClawInProot) {
126
+ console.log('Status: āœ“ Ready to run!');
127
+ console.log('');
128
+ } else {
129
+ console.log('Status: āœ— Setup incomplete');
130
+ console.log('Run: clawdroid setup');
131
+ }
132
+ }
133
+
134
+ function updateOpenClaw() {
135
+ const status = getInstallStatus();
136
+
137
+ if (!status.proot || !status.ubuntu) {
138
+ console.error('proot/Ubuntu not installed. Run: openclaw setup');
139
+ process.exit(1);
140
+ }
141
+
142
+ console.log('Updating OpenClaw to the latest version...');
143
+
144
+ const proc = runInProotWithCallback('npm install -g openclaw@latest', () => {
145
+ console.log('npm output:');
146
+ });
147
+
148
+ proc.on('close', (code) => {
149
+ if (code === 0) {
150
+ console.log('\nāœ“ OpenClaw updated successfully!');
151
+ console.log('Run "openclaw start" to launch the gateway.');
152
+ } else {
153
+ console.error(`\nāœ— Update failed with code ${code}`);
154
+ }
155
+ });
156
+ }
157
+
158
+ function startGateway() {
159
+ const status = getInstallStatus();
160
+
161
+ if (!status.proot || !status.ubuntu) {
162
+ console.error('proot/Ubuntu not installed. Run: clawdroid setup');
163
+ process.exit(1);
164
+ }
165
+
166
+ if (!status.openClawInProot) {
167
+ console.error('OpenClaw not installed in proot. Run: clawdroid setup');
168
+ process.exit(1);
169
+ }
170
+
171
+ const frames = ['ā ‹', 'ā ™', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ‡', 'ā '];
172
+ let i = 0;
173
+ let started = false;
174
+ const DASHBOARD_URL = 'http://127.0.0.1:18789';
175
+
176
+ const spinner = setInterval(() => {
177
+ if (!started) {
178
+ process.stdout.write(`\r${frames[i++ % frames.length]} Starting OpenClaw gateway...`);
179
+ }
180
+ }, 80);
181
+
182
+ const checkDashboard = setInterval(async () => {
183
+ if (started) return;
184
+ try {
185
+ const response = await fetch(DASHBOARD_URL, { method: 'HEAD', signal: AbortSignal.timeout(1000) });
186
+ if (response.ok || response.status < 500) {
187
+ started = true;
188
+ clearInterval(spinner);
189
+ clearInterval(checkDashboard);
190
+ process.stdout.write('\r' + ' '.repeat(40) + '\r');
191
+ console.log('āœ“ OpenClaw gateway started!\n');
192
+ console.log(`Dashboard: ${DASHBOARD_URL}`);
193
+ console.log('Press Ctrl+C to stop\n');
194
+ console.log('─'.repeat(45) + '\n');
195
+ }
196
+ } catch {}
197
+ }, 500);
198
+
199
+ const gateway = runInProot('openclaw gateway --verbose');
200
+
201
+ gateway.on('error', (err) => {
202
+ clearInterval(spinner);
203
+ clearInterval(checkDashboard);
204
+ console.error('\nFailed to start gateway:', err.message);
205
+ });
206
+
207
+ gateway.on('close', (code) => {
208
+ clearInterval(spinner);
209
+ clearInterval(checkDashboard);
210
+ if (!started) {
211
+ console.log('\nGateway exited before starting. Run: clawdroid onboarding');
212
+ }
213
+ });
214
+ }
215
+
216
+ function runOpenclawCommand(args) {
217
+ const status = getInstallStatus();
218
+
219
+ if (!status.proot || !status.ubuntu || !status.openClawInProot) {
220
+ console.error('Setup not complete. Run: clawdroid setup');
221
+ process.exit(1);
222
+ }
223
+
224
+ const command = args.join(' ');
225
+ console.log(`Running: openclaw ${command}\n`);
226
+
227
+ if (args[0] === 'onboarding') {
228
+ console.log('TIP: Select "Loopback (127.0.0.1)" when asked for binding!\n');
229
+ }
230
+
231
+ const proc = runInProot(`openclaw ${command}`);
232
+
233
+ proc.on('error', (err) => {
234
+ console.error('Failed to run command:', err.message);
235
+ });
236
+ }
237
+
238
+ function openShell() {
239
+ const status = getInstallStatus();
240
+
241
+ if (!status.proot || !status.ubuntu) {
242
+ console.error('proot/Ubuntu not installed. Run: clawdroid setup');
243
+ process.exit(1);
244
+ }
245
+
246
+ console.log('Entering Ubuntu shell...');
247
+ console.log('Type "exit" to return to Termux\n');
248
+
249
+ const shell = spawn('proot-distro', ['login', 'ubuntu'], {
250
+ stdio: 'inherit'
251
+ });
252
+
253
+ shell.on('error', (err) => {
254
+ console.error('Failed to open shell:', err.message);
255
+ });
256
+ }
257
+
258
+ export async function main(args) {
259
+ const command = args[0] || 'start';
260
+
261
+ printBanner();
262
+
263
+ switch (command) {
264
+ case 'setup':
265
+ case 'install':
266
+ await runSetup();
267
+ break;
268
+
269
+ case 'status':
270
+ showStatus();
271
+ break;
272
+
273
+ case 'update':
274
+ updateOpenClaw();
275
+ break;
276
+
277
+ case 'repair':
278
+ console.log('Repairing installation...');
279
+ await setupProotUbuntu();
280
+ setupBionicBypassInProot();
281
+ console.log('Repair complete!');
282
+ break;
283
+
284
+ case 'start':
285
+ case 'run':
286
+ startGateway();
287
+ break;
288
+
289
+ case 'shell':
290
+ case 'ubuntu':
291
+ openShell();
292
+ break;
293
+
294
+ case 'help':
295
+ case '--help':
296
+ case '-h':
297
+ printHelp();
298
+ break;
299
+
300
+ default:
301
+ runOpenclawCommand(args);
302
+ break;
303
+ }
304
+ }
@@ -0,0 +1,282 @@
1
+ import { execSync, spawn } from 'child_process';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { installBypass, getBypassScriptPath, getNodeOptions } from './bionic-bypass.js';
5
+
6
+ const HOME = process.env.HOME || '/data/data/com.termux/files/home';
7
+ const BASHRC = path.join(HOME, '.bashrc');
8
+ const ZSHRC = path.join(HOME, '.zshrc');
9
+ const PROOT_ROOTFS = '/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs';
10
+ const PROOT_UBUNTU_ROOT = path.join(PROOT_ROOTFS, 'ubuntu', 'root');
11
+
12
+ export function checkDependencies() {
13
+ const deps = {
14
+ node: false,
15
+ npm: false,
16
+ git: false,
17
+ proot: false
18
+ };
19
+
20
+ try {
21
+ execSync('node --version', { stdio: 'pipe' });
22
+ deps.node = true;
23
+ } catch {}
24
+
25
+ try {
26
+ execSync('npm --version', { stdio: 'pipe' });
27
+ deps.npm = true;
28
+ } catch {}
29
+
30
+ try {
31
+ execSync('git --version', { stdio: 'pipe' });
32
+ deps.git = true;
33
+ } catch {}
34
+
35
+ try {
36
+ execSync('which proot-distro', { stdio: 'pipe' });
37
+ deps.proot = true;
38
+ } catch {}
39
+
40
+ return deps;
41
+ }
42
+
43
+ export function installTermuxDeps() {
44
+ console.log('Installing Termux dependencies...');
45
+ const packages = ['nodejs-lts', 'git', 'openssh'];
46
+ try {
47
+ execSync('pkg update -y', { stdio: 'inherit' });
48
+ execSync(`pkg install -y ${packages.join(' ')}`, { stdio: 'inherit' });
49
+ return true;
50
+ } catch (err) {
51
+ console.error('Failed to install Termux packages:', err.message);
52
+ return false;
53
+ }
54
+ }
55
+
56
+ export function setupBionicBypass() {
57
+ console.log('Setting up Bionic Bypass...');
58
+ const scriptPath = installBypass();
59
+ const nodeOptions = getNodeOptions();
60
+ const exportLine = `export NODE_OPTIONS="${nodeOptions}"`;
61
+
62
+ for (const rcFile of [BASHRC, ZSHRC]) {
63
+ if (fs.existsSync(rcFile)) {
64
+ const content = fs.readFileSync(rcFile, 'utf8');
65
+ if (!content.includes('bionic-bypass')) {
66
+ fs.appendFileSync(rcFile, `\n# ClawDroid Bionic Bypass\n${exportLine}\n`);
67
+ }
68
+ }
69
+ }
70
+
71
+ process.env.NODE_OPTIONS = nodeOptions;
72
+ return scriptPath;
73
+ }
74
+
75
+ export function installOpenClaw() {
76
+ console.log('Installing OpenClaw...');
77
+ try {
78
+ execSync('npm install -g openclaw', { stdio: 'inherit' });
79
+ return true;
80
+ } catch (err) {
81
+ console.error('Failed to install OpenClaw:', err.message);
82
+ return false;
83
+ }
84
+ }
85
+
86
+ export function configureTermux() {
87
+ console.log('Configuring Termux for background operation...');
88
+ const configDir = path.join(HOME, '.clawdroid');
89
+ if (!fs.existsSync(configDir)) {
90
+ fs.mkdirSync(configDir, { recursive: true });
91
+ }
92
+
93
+ const wakeLockScript = path.join(configDir, 'wakelock.sh');
94
+ const wakeLockContent = `#!/bin/bash
95
+ termux-wake-lock
96
+ trap "termux-wake-unlock" EXIT
97
+ exec "$@"
98
+ `;
99
+
100
+ fs.writeFileSync(wakeLockScript, wakeLockContent, 'utf8');
101
+ fs.chmodSync(wakeLockScript, '755');
102
+
103
+ return true;
104
+ }
105
+
106
+ export function getInstallStatus() {
107
+ const PROOT_ROOTFS = '/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs';
108
+
109
+ let hasProot = false;
110
+ try {
111
+ execSync('command -v proot-distro', { stdio: 'pipe' });
112
+ hasProot = true;
113
+ } catch {}
114
+
115
+ let hasUbuntu = false;
116
+ try {
117
+ hasUbuntu = fs.existsSync(path.join(PROOT_ROOTFS, 'ubuntu'));
118
+ } catch {}
119
+
120
+ let hasOpenClawInProot = false;
121
+ if (hasUbuntu) {
122
+ try {
123
+ const checkCmd = 'test -f /usr/local/bin/openclaw || test -f /usr/bin/openclaw || command -v openclaw';
124
+ execSync(`proot-distro login ubuntu -- bash -c "${checkCmd}"`, { stdio: 'pipe', timeout: 15000 });
125
+ hasOpenClawInProot = true;
126
+ } catch {}
127
+ }
128
+
129
+ let hasBionicBypassInProot = false;
130
+ try {
131
+ const prootBypassPath = path.join(PROOT_ROOTFS, 'ubuntu', 'root', '.clawdroid', 'bionic-bypass.js');
132
+ hasBionicBypassInProot = fs.existsSync(prootBypassPath);
133
+ } catch {}
134
+
135
+ return {
136
+ proot: hasProot,
137
+ ubuntu: hasUbuntu,
138
+ openClawInProot: hasOpenClawInProot,
139
+ bionicBypassInProot: hasBionicBypassInProot,
140
+ bionicBypass: fs.existsSync(getBypassScriptPath()),
141
+ nodeOptions: process.env.NODE_OPTIONS?.includes('bionic-bypass') || false,
142
+ openClaw: (() => {
143
+ try {
144
+ execSync('command -v openclaw', { stdio: 'pipe' });
145
+ return true;
146
+ } catch { return false; }
147
+ })()
148
+ };
149
+ }
150
+
151
+ export function installProot() {
152
+ console.log('Installing proot-distro...');
153
+ try {
154
+ execSync('pkg install -y proot-distro', { stdio: 'inherit' });
155
+ return true;
156
+ } catch (err) {
157
+ console.error('Failed to install proot-distro:', err.message);
158
+ return false;
159
+ }
160
+ }
161
+
162
+ export function installUbuntu() {
163
+ console.log('Installing Ubuntu in proot...');
164
+ try {
165
+ execSync('proot-distro install ubuntu', { stdio: 'inherit' });
166
+ return true;
167
+ } catch (err) {
168
+ console.error('Failed to install Ubuntu:', err.message);
169
+ return false;
170
+ }
171
+ }
172
+
173
+ export function setupProotUbuntu() {
174
+ console.log('Setting up Node.js and OpenClaw in Ubuntu...');
175
+ const setupScript = `
176
+ set -e
177
+ apt update
178
+ apt install -y curl wget git build-essential python3
179
+ curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
180
+ apt install -y nodejs
181
+ npm install -g openclaw
182
+ `;
183
+
184
+ try {
185
+ execSync(`proot-distro login ubuntu -- bash -c '${setupScript}'`, { stdio: 'inherit' });
186
+ return true;
187
+ } catch (err) {
188
+ console.error('Failed to setup Ubuntu:', err.message);
189
+ return false;
190
+ }
191
+ }
192
+
193
+ export function setupBionicBypassInProot() {
194
+ console.log('Setting up Bionic Bypass in proot Ubuntu...');
195
+
196
+ const bypassScript = `
197
+ const os = require('os');
198
+ const originalNetworkInterfaces = os.networkInterfaces;
199
+ os.networkInterfaces = function() {
200
+ try {
201
+ const interfaces = originalNetworkInterfaces.call(os);
202
+ if (interfaces && Object.keys(interfaces).length > 0) {
203
+ return interfaces;
204
+ }
205
+ } catch (e) {}
206
+ return {
207
+ lo: [{
208
+ address: '127.0.0.1',
209
+ netmask: '255.0.0.0',
210
+ family: 'IPv4',
211
+ mac: '00:00:00:00:00:00',
212
+ internal: true,
213
+ cidr: '127.0.0.1/8'
214
+ }]
215
+ };
216
+ };
217
+ `;
218
+
219
+ const prootBypassPath = path.join(PROOT_UBUNTU_ROOT, '.clawdroid', 'bionic-bypass.js');
220
+ const prootBypassDir = path.dirname(prootBypassPath);
221
+
222
+ try {
223
+ if (!fs.existsSync(prootBypassDir)) {
224
+ fs.mkdirSync(prootBypassDir, { recursive: true });
225
+ }
226
+ fs.writeFileSync(prootBypassPath, bypassScript, 'utf8');
227
+
228
+ const prootBashrc = path.join(PROOT_UBUNTU_ROOT, '.bashrc');
229
+ const exportLine = 'export NODE_OPTIONS="--require /root/.clawdroid/bionic-bypass.js"';
230
+
231
+ let bashrcContent = '';
232
+ if (fs.existsSync(prootBashrc)) {
233
+ bashrcContent = fs.readFileSync(prootBashrc, 'utf8');
234
+ }
235
+
236
+ if (!bashrcContent.includes('bionic-bypass')) {
237
+ fs.appendFileSync(prootBashrc, `\n# ClawDroid Bionic Bypass\n${exportLine}\n`);
238
+ }
239
+
240
+ return true;
241
+ } catch (err) {
242
+ console.error('Failed to setup Bionic Bypass in proot:', err.message);
243
+ return false;
244
+ }
245
+ }
246
+
247
+ export function runInProot(command) {
248
+ const nodeOptions = '--require /root/.clawdroid/bionic-bypass.js';
249
+ return spawn('proot-distro', ['login', 'ubuntu', '--', 'bash', '-c', `export NODE_OPTIONS="${nodeOptions}" && ${command}`], {
250
+ stdio: 'inherit'
251
+ });
252
+ }
253
+
254
+ export function runInProotWithCallback(command, onFirstOutput) {
255
+ const nodeOptions = '--require /root/.clawdroid/bionic-bypass.js';
256
+ let firstOutput = true;
257
+
258
+ const proc = spawn('proot-distro', ['login', 'ubuntu', '--', 'bash', '-c', `export NODE_OPTIONS="${nodeOptions}" && ${command}`], {
259
+ stdio: ['inherit', 'pipe', 'pipe']
260
+ });
261
+
262
+ proc.stdout.on('data', (data) => {
263
+ if (firstOutput) {
264
+ firstOutput = false;
265
+ onFirstOutput();
266
+ }
267
+ process.stdout.write(data);
268
+ });
269
+
270
+ proc.stderr.on('data', (data) => {
271
+ if (firstOutput) {
272
+ firstOutput = false;
273
+ onFirstOutput();
274
+ }
275
+ const str = data.toString();
276
+ if (!str.includes('proot warning') && !str.includes("can't sanitize")) {
277
+ process.stderr.write(data);
278
+ }
279
+ });
280
+
281
+ return proc;
282
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Post-install script - runs after npm install
3
+ */
4
+
5
+ import { isAndroid, installBypass, getNodeOptions } from './bionic-bypass.js';
6
+
7
+ function main() {
8
+ console.log('\nšŸ“± ClawDroid post-install\n');
9
+
10
+ if (!isAndroid()) {
11
+ console.log('Not running on Android/Termux - skipping Bionic Bypass setup.');
12
+ console.log('You can still use this package on other systems.\n');
13
+ return;
14
+ }
15
+
16
+ // Install the bypass script
17
+ try {
18
+ const scriptPath = installBypass();
19
+ console.log(`āœ“ Bionic Bypass installed at: ${scriptPath}`);
20
+ } catch (err) {
21
+ console.error('āœ— Failed to install Bionic Bypass:', err.message);
22
+ return;
23
+ }
24
+
25
+ // Show instructions
26
+ const nodeOptions = getNodeOptions();
27
+
28
+ console.log('\n' + '═'.repeat(50));
29
+ console.log('IMPORTANT: Add this to your shell config (~/.bashrc):');
30
+ console.log('═'.repeat(50));
31
+ console.log(`\nexport NODE_OPTIONS="${nodeOptions}"\n`);
32
+ console.log('Or run: clawdroid setup');
33
+ console.log('═'.repeat(50) + '\n');
34
+ }
35
+
36
+ main();
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "openclaw-droid",
3
+ "version": "1.0.0",
4
+ "description": "OpenClaw Droid - Optimized OpenClaw AI Gateway for Android Termux",
5
+ "main": "lib/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "openclaw": "bin/openclaw"
9
+ },
10
+ "scripts": {
11
+ "postinstall": "node lib/postinstall.js"
12
+ },
13
+ "keywords": [
14
+ "openclaw",
15
+ "termux",
16
+ "android",
17
+ "ai",
18
+ "gateway",
19
+ "gemini",
20
+ "claude",
21
+ "openclaw-termux",
22
+ "openclaw-droid",
23
+ "clawdroid",
24
+ "ai-gateway",
25
+ "android-ai",
26
+ "termux-ai",
27
+ "openclaw-droid"
28
+ ],
29
+ "author": "NOSYTLABS",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/NosytLabs/openclaw-droid.git"
34
+ },
35
+ "homepage": "https://github.com/NosytLabs/openclaw-droid#readme",
36
+ "bugs": {
37
+ "url": "https://github.com/NosytLabs/openclaw-droid/issues"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ },
42
+ "os": [
43
+ "android",
44
+ "linux",
45
+ "win32"
46
+ ],
47
+ "dependencies": {
48
+ "chalk": "^5.3.0",
49
+ "inquirer": "^9.2.12",
50
+ "ora": "^7.0.1"
51
+ }
52
+ }