capacitor-mobile-claw 1.6.3 → 1.6.5
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 +141 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**On-device AI agent engine for mobile apps** — run Claude directly on your phone with file tools, code execution, git, and extensible MCP tool support.
|
|
8
8
|
|
|
9
|
-
Mobile Claw is a [Capacitor](https://capacitorjs.com/) plugin that embeds a full AI agent runtime on Android and iOS
|
|
9
|
+
Mobile Claw is a [Capacitor](https://capacitorjs.com/) plugin that embeds a full AI agent runtime on Android and iOS. Two execution modes: a **WebView agent** for instant cold start (agent loop runs in-process) or a **Node.js worker** for full sandboxed tooling. Both talk directly to the Anthropic API — no cloud relay, no proxy. Includes **on-device vector memory** via [LanceDB](https://www.npmjs.com/package/capacitor-lancedb), **background scheduling** via [MobileCron](https://www.npmjs.com/package/capacitor-mobilecron) (WorkManager / BGTaskScheduler), cron jobs with reusable skills, and native streaming HTTP for WebView CORS bypass.
|
|
10
10
|
|
|
11
11
|
> Built on [OpenClaw](https://github.com/openclaw/openclaw) and the [Pi framework](https://www.npmjs.com/package/@mariozechner/pi-ai) by [Mario Zechner](https://github.com/badlogic). Pi's philosophy of *"what you leave out matters more than what you put in"* — just 4 core tools and a system prompt under 1,000 tokens — is what makes running a capable AI agent on a phone possible at all.
|
|
12
12
|
|
|
@@ -79,13 +79,16 @@ npx cap open ios
|
|
|
79
79
|
### Running Tests
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
#
|
|
82
|
+
# Unit tests (64 tests)
|
|
83
|
+
npm test
|
|
84
|
+
|
|
85
|
+
# Android E2E (111 tests, requires ADB device)
|
|
83
86
|
npm run test:android
|
|
84
87
|
|
|
85
|
-
# iOS E2E (
|
|
88
|
+
# iOS E2E (111 tests, requires booted Simulator)
|
|
86
89
|
npm run test:ios
|
|
87
90
|
|
|
88
|
-
# Full suite:
|
|
91
|
+
# Full suite: unit + Android + iOS (skips unavailable platforms)
|
|
89
92
|
npm run test:full
|
|
90
93
|
```
|
|
91
94
|
|
|
@@ -93,29 +96,23 @@ Once the app launches, enter your Anthropic API key in settings and start chatti
|
|
|
93
96
|
|
|
94
97
|
## How It Works
|
|
95
98
|
|
|
99
|
+
The agent loop runs directly in the WebView for instant cold start — no waiting for Node.js worker boot. LLM API calls are routed through native HTTP (OkHttp / URLSession) to bypass WebView CORS, with full SSE streaming. Worker tools (file I/O, git, code exec) are transparently proxied via the bridge.
|
|
100
|
+
|
|
96
101
|
```
|
|
97
|
-
|
|
98
|
-
│ Your App (Vue, React, Svelte, vanilla JS)
|
|
99
|
-
│
|
|
100
|
-
│ │ MobileClawEngine (
|
|
101
|
-
│ │
|
|
102
|
-
│ │
|
|
103
|
-
│ │
|
|
104
|
-
│ │
|
|
105
|
-
│
|
|
106
|
-
│
|
|
107
|
-
│
|
|
108
|
-
│ │
|
|
109
|
-
│
|
|
110
|
-
|
|
111
|
-
│ │ │ (@mariozechner│ │ - Bridge transport │ │ │
|
|
112
|
-
│ │ │ /pi-ai) │ │ - STOMP transport │ │ │
|
|
113
|
-
│ │ │ │ │ - Custom tools (BYO) │ │ │
|
|
114
|
-
│ │ └──────┬───────┘ └──────────────────────┘ │ │
|
|
115
|
-
│ │ │ │ │
|
|
116
|
-
│ │ ▼ Anthropic Messages API │ │
|
|
117
|
-
│ └────────────────────────────────────────────────┘ │
|
|
118
|
-
└─────────────────────────────────────────────────────┘
|
|
102
|
+
┌──────────────────────────────────────────────────────────┐
|
|
103
|
+
│ Your App (Vue, React, Svelte, vanilla JS) │
|
|
104
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
105
|
+
│ │ MobileClawEngine (useWebViewAgent: true) │ │
|
|
106
|
+
│ │ ┌──────────────┐ │ │
|
|
107
|
+
│ │ │ Pi Agent │──── Anthropic API (native HTTP) │ │
|
|
108
|
+
│ │ │ (in WebView) │ │ │
|
|
109
|
+
│ │ └──────┬───────┘ │ │
|
|
110
|
+
│ │ │ ToolProxy (bridge IPC) │ │
|
|
111
|
+
│ │ ┌──────▼───────────────────────────────────────┐ │ │
|
|
112
|
+
│ │ │ Node.js Worker (file tools, git, code exec) │ │ │
|
|
113
|
+
│ │ └──────────────────────────────────────────────┘ │ │
|
|
114
|
+
│ └────────────────────────────────────────────────────┘ │
|
|
115
|
+
└──────────────────────────────────────────────────────────┘
|
|
119
116
|
```
|
|
120
117
|
|
|
121
118
|
## Install in Your Own App
|
|
@@ -124,6 +121,16 @@ Once the app launches, enter your Anthropic API key in settings and start chatti
|
|
|
124
121
|
npm install capacitor-mobile-claw @capacitor/core @capacitor/device @choreruiz/capacitor-node-js @capacitor-community/sqlite
|
|
125
122
|
```
|
|
126
123
|
|
|
124
|
+
If using Vite, add the bundler plugin to `vite.config.js` (stubs Node.js-only transitive deps):
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
import { mobileClawVitePlugin } from 'capacitor-mobile-claw/vite-plugin'
|
|
128
|
+
|
|
129
|
+
export default defineConfig({
|
|
130
|
+
plugins: [mobileClawVitePlugin(), vue()],
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
127
134
|
Then add these scripts to your `package.json`:
|
|
128
135
|
|
|
129
136
|
```json
|
|
@@ -156,13 +163,13 @@ import { MobileClawEngine } from 'capacitor-mobile-claw'
|
|
|
156
163
|
|
|
157
164
|
const engine = new MobileClawEngine()
|
|
158
165
|
|
|
159
|
-
//
|
|
160
|
-
await engine.init()
|
|
166
|
+
// WebView agent — instant cold start, streaming via native HTTP
|
|
167
|
+
await engine.init({ useWebViewAgent: true })
|
|
161
168
|
|
|
162
169
|
// Listen for streaming text
|
|
163
170
|
engine.addListener('agentEvent', (event) => {
|
|
164
171
|
if (event.eventType === 'text_delta') {
|
|
165
|
-
|
|
172
|
+
console.log(event.data.text)
|
|
166
173
|
}
|
|
167
174
|
})
|
|
168
175
|
|
|
@@ -189,12 +196,77 @@ const engine = new MobileClawEngine()
|
|
|
189
196
|
|
|
190
197
|
await engine.init({
|
|
191
198
|
tools: myTools,
|
|
192
|
-
|
|
199
|
+
useWebViewAgent: true,
|
|
200
|
+
})
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### With On-Device Memory
|
|
204
|
+
|
|
205
|
+
The agent remembers across sessions using [capacitor-lancedb](https://www.npmjs.com/package/capacitor-lancedb) — a Rust-powered vector database running entirely on-device. Memories are stored, deduplicated, and recalled via semantic search. Five built-in tools (`memory_store`, `memory_recall`, `memory_search`, `memory_forget`, `memory_get`) are passed to the agent automatically.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { MemoryManager } from 'capacitor-lancedb'
|
|
209
|
+
|
|
210
|
+
const memory = new MemoryManager({ dbPath: 'files://agent-memory' })
|
|
211
|
+
await memory.init()
|
|
212
|
+
|
|
213
|
+
const engine = new MobileClawEngine()
|
|
214
|
+
const memoryTools = memory.getTools()
|
|
215
|
+
await engine.init({ tools: memoryTools, useWebViewAgent: true })
|
|
216
|
+
|
|
217
|
+
// Agent can now store/recall memories across sessions.
|
|
218
|
+
// Auto-recall injects relevant context at turn start.
|
|
219
|
+
// Auto-capture extracts facts from agent responses.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### With Background Scheduling
|
|
223
|
+
|
|
224
|
+
[capacitor-mobilecron](https://www.npmjs.com/package/capacitor-mobilecron) enables the agent to wake and run in the background via Android WorkManager and iOS BGTaskScheduler. The engine's scheduler manages heartbeats (periodic check-ins) and cron jobs (recurring tasks).
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { MobileCron } from 'capacitor-mobilecron'
|
|
228
|
+
|
|
229
|
+
const engine = new MobileClawEngine()
|
|
230
|
+
await engine.init({ useWebViewAgent: true, mobileCron: MobileCron })
|
|
231
|
+
|
|
232
|
+
// Enable scheduler + heartbeat (runs every 30 minutes)
|
|
233
|
+
await engine.setSchedulerConfig({ enabled: true, schedulingMode: 'balanced' })
|
|
234
|
+
await engine.setHeartbeat({ enabled: true, everyMs: 1800000 })
|
|
235
|
+
|
|
236
|
+
// Listen for heartbeat results
|
|
237
|
+
engine.addListener('heartbeatCompleted', (event) => {
|
|
238
|
+
console.log(`Heartbeat: ${event.status} (${event.durationMs}ms)`)
|
|
239
|
+
})
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### With Cron Jobs
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// Create a skill (reusable prompt + tool constraints)
|
|
246
|
+
const skill = await engine.addSkill({
|
|
247
|
+
name: 'daily-summary',
|
|
248
|
+
maxTurns: 3,
|
|
249
|
+
timeoutMs: 60000,
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
// Schedule a recurring cron job
|
|
253
|
+
await engine.addCronJob({
|
|
254
|
+
name: 'morning-briefing',
|
|
255
|
+
enabled: true,
|
|
256
|
+
sessionTarget: 'isolated',
|
|
257
|
+
schedule: { kind: 'every', everyMs: 86400000 }, // 24h
|
|
258
|
+
skillId: skill.id,
|
|
259
|
+
prompt: 'Summarize my workspace changes since yesterday',
|
|
260
|
+
deliveryMode: 'notification',
|
|
193
261
|
})
|
|
194
262
|
```
|
|
195
263
|
|
|
196
264
|
## Features
|
|
197
265
|
|
|
266
|
+
- **Instant cold start** — agent loop runs in the WebView, worker tools proxied transparently
|
|
267
|
+
- **On-device vector memory** — store, recall, and search memories via [LanceDB](https://www.npmjs.com/package/capacitor-lancedb) with auto-recall context injection and deduplication
|
|
268
|
+
- **Background scheduling** — heartbeat check-ins and cron jobs via [MobileCron](https://www.npmjs.com/package/capacitor-mobilecron) (Android WorkManager / iOS BGTaskScheduler)
|
|
269
|
+
- **Cron jobs & skills** — recurring agent tasks with reusable skill definitions, run history, and delivery modes
|
|
198
270
|
- **Real-time streaming** — text deltas, tool use, and thinking events
|
|
199
271
|
- **Multi-turn conversations** — session persistence via native SQLite
|
|
200
272
|
- **OAuth PKCE + API key** — sign in with Claude Max or use a direct API key
|
|
@@ -202,8 +274,9 @@ await engine.init({
|
|
|
202
274
|
- **Code execution** — JavaScript (sandbox) + Python (Pyodide/WebAssembly)
|
|
203
275
|
- **Git** — clone, commit, push, diff via isomorphic-git
|
|
204
276
|
- **MCP device tools** — extensible via Model Context Protocol
|
|
205
|
-
- **Tool approval gate** — approve/deny tool executions before they run
|
|
277
|
+
- **Tool approval gate** — approve/deny tool executions before they run (120s TTL)
|
|
206
278
|
- **Agent steering** — inject follow-up instructions into a running turn
|
|
279
|
+
- **Vite plugin** — stubs Node.js-only transitive deps for browser bundling
|
|
207
280
|
|
|
208
281
|
## API Reference
|
|
209
282
|
|
|
@@ -211,18 +284,38 @@ await engine.init({
|
|
|
211
284
|
|
|
212
285
|
| Method | Description |
|
|
213
286
|
|--------|-------------|
|
|
214
|
-
| `init(options?)` | Start
|
|
287
|
+
| `init(options?)` | Start engine. Options: `useWebViewAgent`, `tools`, `mobileCron`, `enableBridge`, `enableStomp` |
|
|
215
288
|
| `sendMessage(prompt, agentId?)` | Send a prompt to the agent |
|
|
216
289
|
| `stopTurn()` | Cancel the running agent turn |
|
|
217
|
-
| `
|
|
290
|
+
| `respondToPreExecute(toolCallId, args, deny?)` | Approve/deny a tool execution |
|
|
218
291
|
| `steerAgent(text)` | Inject a follow-up instruction |
|
|
219
|
-
| `updateConfig(config)` | Update
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
292
|
+
| `updateConfig(config)` | Update config (auth, model, provider) |
|
|
293
|
+
| `exchangeOAuthCode(tokenUrl, body)` | OAuth token exchange via native HTTP |
|
|
294
|
+
| `getAuthStatus(provider?)` | Get current auth profile status |
|
|
295
|
+
| `getModels(provider?)` | List available models |
|
|
222
296
|
| `readFile(path)` / `writeFile(path, content)` | Workspace file operations |
|
|
223
297
|
| `listSessions()` / `resumeSession(key)` | Session management |
|
|
224
298
|
| `invokeTool(toolName, args?)` | Call a tool directly |
|
|
225
|
-
| `addListener(eventName, handler)` | Subscribe to
|
|
299
|
+
| `addListener(eventName, handler)` | Subscribe to events |
|
|
300
|
+
|
|
301
|
+
#### Scheduler & Heartbeat
|
|
302
|
+
|
|
303
|
+
| Method | Description |
|
|
304
|
+
|--------|-------------|
|
|
305
|
+
| `setSchedulerConfig(config)` | Set scheduler state (enabled, mode, runOnCharging, activeHours) |
|
|
306
|
+
| `getSchedulerConfig()` | Read scheduler + heartbeat config |
|
|
307
|
+
| `setHeartbeat(config)` | Configure heartbeat (enabled, interval, skillId, prompt) |
|
|
308
|
+
| `triggerHeartbeatWake(source?)` | Trigger immediate heartbeat (`manual` bypasses scheduler gate) |
|
|
309
|
+
|
|
310
|
+
#### Cron Jobs & Skills
|
|
311
|
+
|
|
312
|
+
| Method | Description |
|
|
313
|
+
|--------|-------------|
|
|
314
|
+
| `addCronJob(job)` / `updateCronJob(id, patch)` / `removeCronJob(id)` | CRUD for cron jobs |
|
|
315
|
+
| `listCronJobs()` / `runCronJob(id)` | List or manually trigger a job |
|
|
316
|
+
| `getCronRunHistory(jobId?, limit?)` | Get historical run records |
|
|
317
|
+
| `addSkill(skill)` / `updateSkill(id, patch)` / `removeSkill(id)` | CRUD for skills |
|
|
318
|
+
| `listSkills()` | List all defined skills |
|
|
226
319
|
|
|
227
320
|
### Events
|
|
228
321
|
|
|
@@ -231,8 +324,11 @@ await engine.init({
|
|
|
231
324
|
| `agentEvent` | Text delta, tool use, tool result, or thinking update |
|
|
232
325
|
| `agentCompleted` | Agent turn finished (includes token usage) |
|
|
233
326
|
| `agentError` | Agent execution failed |
|
|
234
|
-
| `
|
|
327
|
+
| `toolPreExecute` | Agent wants to run a tool (approval gate) |
|
|
235
328
|
| `workerReady` | Node.js worker initialized |
|
|
329
|
+
| `heartbeatStarted` / `heartbeatCompleted` / `heartbeatSkipped` | Heartbeat lifecycle |
|
|
330
|
+
| `cronJobStarted` / `cronJobCompleted` / `cronJobError` | Cron job lifecycle |
|
|
331
|
+
| `schedulerStatus` | Scheduler state changed (next run times) |
|
|
236
332
|
|
|
237
333
|
## Documentation
|
|
238
334
|
|
|
@@ -243,6 +339,8 @@ await engine.init({
|
|
|
243
339
|
## Related Packages
|
|
244
340
|
|
|
245
341
|
- [capacitor-mobile-claw-device-tools](https://www.npmjs.com/package/capacitor-mobile-claw-device-tools) — 64+ pre-built device tools (camera, clipboard, sensors, SSH, etc.)
|
|
342
|
+
- [capacitor-lancedb](https://www.npmjs.com/package/capacitor-lancedb) — on-device vector database for agent memory
|
|
343
|
+
- [capacitor-mobilecron](https://www.npmjs.com/package/capacitor-mobilecron) — native background scheduling (WorkManager / BGTaskScheduler)
|
|
246
344
|
|
|
247
345
|
## Contributing
|
|
248
346
|
|
|
@@ -257,11 +355,14 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, workflow, and guid
|
|
|
257
355
|
| Embedded runtime | [@choreruiz/capacitor-node-js](https://github.com/rogelioRuiz/capacitor-node-js) |
|
|
258
356
|
| Tool protocol | [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) |
|
|
259
357
|
| LLM provider | [Anthropic Claude](https://anthropic.com/) |
|
|
358
|
+
| Vector memory | [LanceDB](https://lancedb.com/) via [capacitor-lancedb](https://www.npmjs.com/package/capacitor-lancedb) (Rust FFI, on-device) |
|
|
359
|
+
| Background scheduling | [capacitor-mobilecron](https://www.npmjs.com/package/capacitor-mobilecron) (WorkManager / BGTaskScheduler) |
|
|
260
360
|
| Git | [isomorphic-git](https://isomorphic-git.org/) |
|
|
261
|
-
| Database | [@capacitor-community/sqlite](https://github.com/nicepkg/capacitor-community-sqlite) (native SQLite
|
|
361
|
+
| Database | [@capacitor-community/sqlite](https://github.com/nicepkg/capacitor-community-sqlite) (native SQLite) |
|
|
262
362
|
| Python | [Pyodide](https://pyodide.org/) (CPython via WebAssembly) |
|
|
263
363
|
| Type system | TypeScript (strict mode) |
|
|
264
|
-
|
|
|
364
|
+
| Lint | [Biome](https://biomejs.dev/) |
|
|
365
|
+
| Tests | [Vitest](https://vitest.dev/) (64 unit) + Sentinel E2E (111 on-device) |
|
|
265
366
|
|
|
266
367
|
## Acknowledgments
|
|
267
368
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-mobile-claw",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "On-device AI agent engine for Capacitor apps — embedded Node.js worker with LLM, file tools, code execution, git, and extensible MCP server",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|