guide #009

hijack.js (Bionic Bypass + GC + Lazy Loading)

Problem
os.networkInterfaces() crashes on Android 6 bionic libc. Multiple runtime incompatibilities.

Solution
hijack.js loaded via Node -r flag. Patches os, fs, adds GC timer, lazy loading, dashboard endpoints.

Context

hijack.js is the heart of PocketClaw. Running OpenClaw directly on Android 6 crashes immediately — os.networkInterfaces() triggers a segfault in bionic libc's NETLINK_ROUTE implementation. The file system layout doesn't match what OpenClaw expects (/root/ doesn't exist on Android). V8's garbage collector never runs aggressively enough for a 1 GB device. And 1547 modules load at startup even though only ~8 are used.

Rather than forking and patching OpenClaw's source code (which would break on updates), hijack.js is loaded before everything else via Node's -r (require) flag. It monkey-patches Node.js internals at the process level, making the entire runtime Android-compatible without changing a single line of OpenClaw code.

Implementation

hijack.js is deployed at $ROOTFS/root/hijack.js (proot) or the Termux equivalent for native mode. It's loaded via:

export NODE_OPTIONS='-r /root/hijack.js --expose-gc --no-warnings --max-old-space-size=112 --max-semi-space-size=2'

The file contains 7 major patches:

// 1. os.networkInterfaces() — bionic NETLINK_ROUTE crash fix
const _origNI = os.networkInterfaces;
os.networkInterfaces = function() {
  try { return _origNI.call(os); }
  catch(e) { return {}; }
};

// 2. fs path rewriting — /root/* -> actual Termux paths
function _fixPath(p) {
  if (typeof p === 'string' && p.startsWith('/root/'))
    return p.replace('/root/', PREFIX + '/');
  return p;
}
// Applied to: readFile, writeFile, mkdir, stat, access, etc.

// 3. Periodic GC — frees ~15 MB per cycle
if (global.gc) {
  setInterval(() => { global.gc(); }, 60000);
}

// 4. Lazy loading — Proxy-based deferred require for 37 prefixes
// (see Hack #18 for full implementation)

// 5. Dead stubs — 23 packages return empty objects instantly
// (see Hack #19)

// 6. Dashboard endpoints — /dashboard, /api/status injected into HTTP server
// (see Hack #48)

// 7. fs.promises patching — same path rewriting for async API
// (see Hack #13)

Verification

# Verify hijack.js loads:
node -r /root/hijack.js -e "console.log('hijack loaded')"
# Expected: hijack loaded

# Test os.networkInterfaces() doesn't crash:
node -r /root/hijack.js -e "console.log(JSON.stringify(require('os').networkInterfaces()))"
# Expected: JSON object (possibly empty {} on Android 6)

# Test path rewriting:
node -r /root/hijack.js -e "require('fs').existsSync('/root/.openclaw') && console.log('path rewrite OK')"
# Expected: path rewrite OK

# Test GC runs (with --expose-gc):
node --expose-gc -r /root/hijack.js -e "setTimeout(() => console.log('GC timer active'), 2000)"

Gotchas

  • hijack.js MUST be deployed at the path referenced by -r, NOT inside the openclaw npm package. After npm update, the package is overwritten but hijack.js survives
  • The -r flag runs the file synchronously before any other code. This means hijack.js can patch require() itself to intercept all subsequent module loads
  • --expose-gc is required for the periodic GC to work. Without it, global.gc is undefined
  • The path rewriting must cover BOTH fs and fs.promises — they're separate objects in Node.js
  • On native mode (no proot), the path prefix changes. hijack.js auto-detects this via process.env.PREFIX

Result

MetricBeforeAfter
os.networkInterfaces()SegfaultReturns {} safely
fs path resolutionFails (/root not found)Redirected to Termux
RAM (after 60s)Grows unboundedGC frees ~15 MB/cycle
Modules loaded at startup1547~8 (rest lazy/dead)
DashboardNone/dashboard + /api/status
Continue reading
guide
Pocket AI complete guide
Running self-hosted AI on portable hardware
guide
Edge AI hardware buyer's guide 2026
Pi 5 vs Mini PC vs Mac Mini
report
Self-hosted AI landscape 2026
Quarterly state of the ecosystem
section
Pocket AI hardware hub
All portable hosts reviewed
section
Agent tracker
Live stats on every agent
newsletter
Thursday digest
Weekly summary in your inbox