# ClawdNode Android

AI-powered phone assistant that connects to Clawdbot Gateway. Enables Claude to answer calls, screen notifications, and act on your behalf.

## Features (v0.1)

### Notification Interception
- Captures all notifications from all apps
- Forwards to Gateway: app name, title, text, available actions
- Can trigger actions (Reply, Mark read, etc.) via Gateway commands
- Can dismiss notifications remotely

### Call Screening & Voice
- Intercepts incoming calls before ring
- Sends caller info to Gateway for Claude to decide
- **Answer calls programmatically**
- **Speak into calls via TTS** (Text-to-Speech)
- **Listen to caller via STT** (Speech-to-Text)
- Full voice conversation loop with Claude as the brain

### Security
- **Tailscale-only** — no public internet exposure
- Encrypted credential storage (EncryptedSharedPreferences)
- Local audit log of all actions
- All permissions clearly explained

## Protocol

### Events (Phone → Gateway)

```json
// Notification received
{"type": "notification", "id": "com.whatsapp:123:1706400000", "app": "WhatsApp", "package": "com.whatsapp", "title": "Mom", "text": "Call me when you can", "actions": ["Reply", "Mark read"]}

// Incoming call
{"type": "call_incoming", "call_id": "tel:+1234567890", "number": "+1234567890", "contact": "Mom"}

// Caller speech (transcribed)
{"type": "call_audio", "call_id": "tel:+1234567890", "transcript": "Hi, I'm calling about the appointment", "is_final": true}

// Call ended
{"type": "call_ended", "call_id": "tel:+1234567890", "duration": 45, "outcome": "completed"}
```

### Commands (Gateway → Phone)

```json
// Take screenshot
{"cmd": "screenshot"}

// Trigger notification action
{"cmd": "notification_action", "id": "com.whatsapp:123:...", "action": "Reply", "text": "I'll call you back in 30 min"}

// Dismiss notification
{"cmd": "notification_dismiss", "id": "com.whatsapp:123:..."}

// Answer incoming call with greeting
{"cmd": "call_answer", "call_id": "tel:+1234567890", "greeting": "Hello, this is Johan's phone. Who's calling?"}

// Reject call
{"cmd": "call_reject", "call_id": "tel:+1234567890"}

// Speak into active call
{"cmd": "call_speak", "call_id": "tel:+1234567890", "text": "Thank you for calling. I'll let Johan know about the appointment."}

// Hang up
{"cmd": "call_hangup", "call_id": "tel:+1234567890"}
```

## Setup

### 1. Build the APK

```bash
# Clone and build
cd clawdnode-android
./gradlew assembleDebug

# APK will be at:
# app/build/outputs/apk/debug/app-debug.apk
```

Or open in Android Studio and build.

### 2. Install on Phone

```bash
adb install app/build/outputs/apk/debug/app-debug.apk
```

Or transfer APK and install manually (enable "Unknown sources").

### 3. Configure Gateway

1. Open ClawdNode app
2. Enter Gateway URL: `http://<tailscale-ip>:18789`
3. Enter Gateway Token: (from your Clawdbot config)
4. Save Configuration

### 4. Grant Permissions

The app needs several permissions:

1. **Notification Access** — System settings, enable ClawdNode
2. **Call Screening Role** — Become the call screener
3. **Runtime Permissions**:
   - Phone state
   - Call log
   - Answer calls
   - Record audio (for STT)
   - Contacts (for caller ID)

### 5. Test Connection

- Status should show "✓ Connected to Gateway"
- Send a test notification to your phone
- Check Gateway logs for the notification event

## Voice Flow Example

```
1. Call comes in from unknown number
2. ClawdNode sends: {"type": "call_incoming", "number": "+1234567890", "contact": null}
3. Claude decides to answer and screen
4. Gateway sends: {"cmd": "call_answer", "greeting": "Hi, this is Johan's assistant. Who's calling?"}
5. ClawdNode answers, plays TTS greeting
6. Caller speaks: "Hi, I'm calling from Dr. Smith's office about tomorrow's appointment"
7. ClawdNode sends: {"type": "call_audio", "transcript": "Hi, I'm calling from Dr. Smith's office..."}
8. Claude processes, decides to confirm details
9. Gateway sends: {"cmd": "call_speak", "text": "Thank you for calling. Can you confirm the time?"}
10. ... conversation continues ...
11. Gateway sends: {"cmd": "call_hangup"}
12. Claude sends summary to Johan via Signal
```

## Project Structure

```
app/src/main/java/com/inou/clawdnode/
├── ClawdNodeApp.kt           # Application class, initialization
├── service/
│   ├── NodeService.kt        # Foreground service, command routing
│   └── GatewayClient.kt      # WebSocket connection
├── notifications/
│   └── NotificationListener.kt  # Notification capture & actions
├── calls/
│   ├── CallScreener.kt       # Call screening service
│   └── VoiceCallService.kt   # InCallService for voice interaction
├── security/
│   ├── TokenStore.kt         # Encrypted credential storage
│   └── AuditLog.kt           # Local audit trail
├── protocol/
│   └── Messages.kt           # Event/Command data classes
└── ui/
    └── MainActivity.kt       # Setup UI
```

## Requirements

- Android 10+ (API 29) — required for CallScreeningService
- Tailscale installed and connected
- Clawdbot Gateway running and accessible

## Security Notes

- Gateway connection is via Tailscale mesh network only
- Credentials are stored using Android's EncryptedSharedPreferences
- All actions are logged locally with timestamps
- No data leaves your network (except to Gateway)

## License

MIT — Use freely, contribute back.
