Built from: github.com/amareshhebbar/PocketLLM Framework: React Native + Expo + MediaPipe + llama.cpp + TrueNorth
Merge with your existing files. Later phases override earlier ones.
# Core
npm install zustand react-native-markdown-display
npx expo install expo-sqlite expo-file-system expo-device expo-haptics expo-clipboard expo-camera expo-image-picker expo-calendar expo-contacts
# Backend
cd backend && npm installcd backend
cp .env.example .env
# Fill in your Cloudflare R2 or AWS S3 credentials
node server.jsIn app/api/ModelRegistryAPI.ts and app/api/DownloadAPI.ts:
Replace YOUR-RAILWAY-URL with your deployed Railway URL.
npx expo run:android # NOT expo start — needs native buildPocketLLM_v2/
├── backend/ ← Node/Express API (Railway deploy)
│ ├── server.js ← Signed URL endpoint + model registry
│ ├── models.json ← Model catalog (no URLs in source)
│ └── .env.example ← R2/S3 credentials template
│
├── app/
│ ├── (tabs)/
│ │ ├── index.tsx ← Model Store screen (Phase 1)
│ │ └── chat.tsx ← Chat screen — FINAL (Phase 3)
│ ├── api/
│ │ ├── DownloadAPI.ts ← Signed URL download
│ │ ├── ModelRegistryAPI.ts ← Fetch model catalog
│ │ └── types.ts ← API response types
│ ├── personas.tsx ← Persona manager screen (Phase 4)
│ ├── memory-manager.tsx← Memory viewer + delete (Phase 4)
│ └── tools.tsx ← MCP Tool Store screen (Phase 5)
│
├── components/
│ ├── shared/ ← ErrorBoundary, EmptyState
│ ├── store/ ← ModelCard, DownloadProgress, StorageDashboard, CompatibilityBadge
│ ├── chat/ ← ChatBubble, ChatInput, TypingIndicator, ConversationList, ModelBadge
│ ├── routing/ ← RouterToast, ModelPicker
│ ├── persona/ ← PersonaCard, PersonaEditor, MemoryChip
│ └── mcp/ ← ToolCallCard
│
├── config/
│ └── models.ts ← Static model catalog (9 models)
│
├── db/
│ ├── schema.ts ← SQLite schema — FINAL (Phase 4)
│ ├── ChatRepository.ts
│ ├── PersonaRepository.ts
│ └── MemoryRepository.ts
│
├── engine/
│ ├── inference/
│ │ ├── index.ts ← Routes .bin/.task → MediaPipe, .gguf → llama.cpp
│ │ ├── mediapipe.ts ← Gemma inference wrapper
│ │ └── llama.ts ← GGUF inference wrapper (llama.rn)
│ ├── router/
│ │ ├── TaskTypes.ts ← 8 task categories
│ │ ├── IntentClassifier.ts ← Keyword-based intent detection
│ │ ├── ModelScorer.ts ← Ranks models per task type
│ │ └── RouterDecision.ts ← Main route() function
│ ├── truenorth/
│ │ ├── TrueNorthBridge.ts ← TrueNorth → local inference adapter
│ │ └── Pipeline.ts ← FINAL 6-stage pipeline (all phases)
│ └── memory/
│ ├── MemoryExtractor.ts ← Rule-based + model-based fact extraction
│ ├── MemoryManager.ts ← Coordinates extraction + storage
│ └── ContextInjector.ts ← Builds system prompt with memories
│
├── hooks/
│ ├── useModelDownload.ts ← Download with progress
│ ├── useChatSession.ts ← Multi-conversation state
│ ├── useRouter.ts ← Smart routing hook
│ ├── usePersona.ts ← Persona CRUD + active persona
│ ├── useMemory.ts ← Memory extraction + retrieval
│ └── useMCPTools.ts ← Tool store management
│
├── mcp/
│ ├── core/
│ │ ├── MCPTypes.ts ← Tool interfaces
│ │ ├── MCPParser.ts ← Parse <tool_call> from model output
│ │ ├── MCPToolRunner.ts ← Execute tool calls
│ │ └── MCPToolRegistry.ts← Register + enable/disable tools
│ └── tools/
│ ├── CalculatorTool.ts ← Exact arithmetic (Tier 1)
│ ├── DateTimeTool.ts ← Current date/time (Tier 1)
│ ├── ClipboardTool.ts ← Read/write clipboard (Tier 1)
│ ├── PDFReaderTool.ts ← Extract PDF text (Tier 2)
│ ├── ImageOCRTool.ts ← Camera/gallery OCR (Tier 2)
│ ├── CalendarTool.ts ← Read calendar events (Tier 3)
│ ├── ContactsTool.ts ← Search contacts (Tier 3)
│ └── WebSearchTool.ts ← DuckDuckGo search (Tier 3)
│
├── store/
│ ├── modelStore.ts ← Downloaded models + active model
│ ├── chatStore.ts ← Chat sessions + streaming state
│ ├── routerStore.ts ← Router decisions + manual override
│ └── personaStore.ts ← Personas + active persona
│
├── types/
│ ├── chat.ts ← ChatMessage, Conversation types
│ └── persona.ts ← Persona, Memory, ExtractedFact types
│
├── docs/ ← Phase guides (read before working on each phase)
│ ├── PHASE0_GUIDE.md
│ ├── PHASE1_GUIDE.md
│ ├── PHASE2_GUIDE.md
│ ├── PHASE3_GUIDE.md
│ ├── PHASE4_GUIDE.md
│ └── PHASE5_GUIDE.md
│
├── app.json.patch ← Merge into your app.json (Phase 0 permissions)
├── app.json.patch.phase5← Additional permissions for Phase 5 tools
└── eas.json ← EAS Build configuration
User sends message
↓
Stage 1: Intent classification → task type (coding/creative/emotional...)
↓
Stage 2: Model routing → best downloaded model for this task
↓
Stage 3: Context assembly → persona system prompt + top memories from SQLite
↓
Stage 4: Inference → MediaPipe (Gemma) or llama.cpp (GGUF)
↓
Stage 5: Tool loop → detect <tool_call>, execute tool, inject result, re-run (max 3 rounds)
↓
Stage 6: Hallucination gate → catch system prompt leaks, prompt injection
↓
Stage 7: Memory extraction → async, extracts facts from conversation, saves to SQLite
↓
Response shown to user
100% on-device. Nothing leaves the phone.
Phase 6 — Play Store Preparation:
- Privacy policy, Terms of Service
- App icon + screenshots + store description
- Target API 35, Proguard rules, 64-bit build
- Device testing matrix (5 real devices)
Phase 7 — Beta → Launch:
- Internal testing (20 users) → Closed (200) → Open (1000) → Production
- Product Hunt + Hacker News + Reddit launch
No clouds were harmed in the making of this app. ☁️🚫 Built in India, for the world. — PocketLLM × TrueNorth