Knit

Local AI. Woven in.

A pocket-sized AI gallery for Android. Run modern open-weight models entirely on your phone, triage your inbox via tool-using agents, talk to it hands-free, and ask grounded questions of your own documents — all without a single byte of conversation leaving the device.

🔒 100% on-device ⚡ GPU-accelerated 📦 34 bundled models 🛠️ ~50 agent tools 🔌 opt-in MCP connections 🎧 offline voice (STT + TTS) 📄 RAG document Q&A
Get started → View on GitHub
Overview

What Knit is, and what it isn't

Knit is an on-device LLM gallery for Android. Pick a model, pick an agent, chat. Your conversations, documents, and Gmail tokens never leave the phone in plaintext — inference happens locally on the CPU (with KleidiAI ARM optimisations) or the GPU (via Google AI Edge LiteRT-LM, Mali / Adreno).

What it does

  • Runs 34 bundled models across two backends (GGUF on llama.cpp, .task/.litertlm on LiteRT-LM) — plus sideload your own .gguf
  • Hosts agents with system prompts, optional knowledge files, and tool calling
  • Reads your Gmail via OAuth — labels priorities, drafts replies, asks before sending
  • Talks & listens offline — Whisper speech-to-text, VITS text-to-speech, and a hands-free voice-assistant loop, all on-device
  • Answers questions from your documents via BM25 + TF-IDF hybrid retrieval
  • Generates files — agents can write a .txt or render a .pdf straight to your Downloads
  • Provides ~50 tools agents can call: web fetch, weather, news, calendar, calculator, units, files, memory, finance, translation, OCR
  • Connects MCP servers (opt-in, off by default) — link a hosted gateway and its tools merge into the agent toolset, on-device tools always winning name collisions

What it isn't

  • Not a cloud chatbot — no OpenAI / Anthropic / Google calls for inference
  • Not training infrastructure — Knit runs pre-quantised public weights, doesn't fine-tune
  • Not a launcher replacement — it's an app, not a system overlay
  • Not a financial / medical / legal advisor — agents surface info, you make decisions
  • Not built for Android < 8.0 — minSdk 26, GPU acceleration needs Vulkan 1.1+ GPUs
Why Knit

Six things no other on-device app does together

Plenty of apps wrap a single local model. Knit is its own on-device AI platform — model variety, agent orchestration, offline voice, encrypted storage, and real productivity workflows in one package.

1

Truly on-device

Inference, speech-to-text, and text-to-speech all run locally. Chats sit in an SQLCipher-encrypted DB, documents in EncryptedFile, OAuth tokens in EncryptedSharedPreferences — keys bound to the Android Keystore.

2

Two backends, one UI

GGUF via llama.cpp (CPU + KleidiAI) for breadth. .task via Google AI Edge LiteRT-LM (Mali / Adreno GPU, CPU fallback) for speed. The dispatcher picks based on the catalog.

3

Real agents, not just chat

Tool-calling loop, JSON protocol, ~50 native tools, multi-turn workflows (the Email Triage agent runs 10+ tool calls per request). A consent gate guards anything user-visible.

4

Fully offline voice

Whisper STT + VITS TTS + Silero VAD via sherpa-onnx — press-to-talk dictation, spoken replies, and a hands-free listen→answer→speak loop. Audio never leaves the device, unlike the system voice keyboard.

5

Bring your own Gmail OAuth

No developer Client ID baked into the APK. Each user supplies their own Google Cloud OAuth client — quota, billing, audit logs stay yours. Settings UI walks you through Cloud Console.

6

Document Q&A grounded in source

Upload a PDF / image / text. BM25 + TF-IDF hybrid retrieval surfaces the relevant chunks. The Doc Q&A agent's prompt forbids falling back to world knowledge — answers are quotable.

Agents

Three defaults, thirteen starters, infinite custom

Three agents ship as defaults and can't be deleted. Thirteen more come pre-seeded as deletable starters. Tap + New agent in Home to write your own — system prompt, optional knowledge file, optional tool access — and it shows up in the picker.

Always present

💬

Quick Chat

General assistant. Concise, matches your tone, never writes code unless asked. Your "what's this thing called again?" agent.

Default · Non-deletable
📬

Email Triage

OAuth into Gmail. Categorises P0/P1/P2, applies Priority labels, drafts replies in your Drafts folder, asks for tap-confirmation before sending. Never auto-sends.

Default · Non-deletable
📄

Doc Q&A

Upload PDF / image / text. Answers strictly from the document. Refuses to guess. Hybrid BM25 + TF-IDF retrieval. Cites short phrases from the source chunks verbatim.

Default · Non-deletable

Pre-seeded, removable

☀️

Daily Briefing

Chains calendar + unread Gmail + weather + news into one morning summary.

🔍

Deep Researcher

Structured analysis with confidence labels.

⚙️

Senior Engineer

Code review, architecture decisions, debugging.

✍️

Writing Editor

Sharp edits, tone fixing, headline brainstorms.

📚

Study Buddy

Socratic tutor. Probes before explaining.

🚀

Founder's Co-pilot

Product, GTM, fundraising — operator framing.

த

Tamil Companion

Bilingual Tamil + English. Tanglish-friendly.

ह

Hindi Companion

Bilingual Hindi + English. Hinglish-friendly.

🏛

India Tax Helper

ITR, GST, deductions — old vs new regime.

💪

Fitness Coach

Workouts, nutrition basics, habit building.

💰

Money Coach

Upload your bank statement (last 6 months ideal) — it's parsed on-device into spending breakdowns and recurring subscriptions, then advised on. Nothing leaves the phone.

📨

Quick Messenger

Say what to send and to whom — it drafts the message and opens WhatsApp, SMS, or the share sheet, pre-filled. You tap Send.

📱

App Concierge

Your launcher-assistant: opens installed apps, pulls up directions, follows deep links, and tells you what's installed — just by asking.

Models

34 models. Two backends. One picker.

LiteRT-LM (.task / .litertlm files) targets the GPU on Mali / Adreno phones with CPU fallback via TFLite XNNPACK. llama.cpp (.gguf Q4_K_M files) runs on CPU with KleidiAI matmul kernels. The dispatcher picks based on the model's format field — you just pick the model. The in-app picker groups the catalog by engine (GPU vs CPU), exactly like the two tables below, with models you've already downloaded floated to the top.

LiteRT-LM (Google AI Edge)

ModelSizeContextBest for
SmolLM 135M Instruct159 MB1.3KInstant chat, tiny footprint
SmolLM2 360M Instruct new374 MB2KTiny but noticeably smarter than 135M
Qwen3 0.6B (INT4) new498 MB4KFast INT4 — snappier than the old Q8 small models
OLMo 2 1B Instruct new931 MB4KFully-open model (AI2), Q4 — light on RAM
Qwen2.5 0.5B Instruct521 MB1.3KLightweight reasoning
TinyLlama 1.1B Chat1.1 GB1.3KClassic small chatbot
Qwen2.5 1.5B Instruct1.5 GB1.3K / 4KBalanced default
DeepSeek-R1 Distill Qwen 1.5B1.78 GB1.3K / 4KStep-by-step reasoning
Qwen3 1.7B recommended2.06 GB4KCurrent size/quality sweet spot
Gemma 4 E2B IT 12 GB RAM2.6 GB4KGoogle's flagship edge model — needs a 12 GB device (crashes on 8 GB)
Qwen3 4B Instruct 2507 (INT4) new2.66 GB4KStrongest Qwen3 that fits a phone (8 GB RAM)
Phi-4 Mini Instruct strong tools3.77 GB1.3K / 4KStrongest small Phi, best at tool calls

llama.cpp (GGUF Q4_K_M)

ModelSizeContext
Qwen3 0.6B Instruct396 MB32K
Qwen2.5 1.5B Instruct1.04 GB32K
Gemma 2 2B Instruct1.59 GB8K
Qwen2.5 3B Instruct1.80 GB32K
Llama 3.2 1B Instruct808 MB128K
Llama 3.2 3B Instruct1.88 GB128K
LFM2 700M (LiquidAI)469 MB32K
LFM2 1.2B (LiquidAI) fast on-device731 MB32K
LFM2.5 1.2B Instruct (LiquidAI) new731 MB32K
Qwen2.5 Coder 1.5B Instruct new986 MB32K
SmolLM2 1.7B Instruct1.06 GB8K
Qwen3 1.7B Instruct1.11 GB32K
Ministral 3B Instruct 2512 new2.15 GB32K
Gemma 3 4B IT QAT2.32 GB128K
Qwen3 4B Instruct2.33 GB32K
Phi-4 Mini Instruct2.32 GB128K
xLAM-2 3B (function-calling) non-commercial1.80 GB32K
Mistral 7B Instruct v0.34.37 GB32K
Qwen2.5 7B Instruct4.36 GB128K
Sideloading: In the model picker, scroll to From your device → Choose a .gguf file. Knit copies it into private storage and runs it on llama.cpp — chat family auto-detected from the filename.
Voice

A voice assistant that never phones home

Three offline voice capabilities built on sherpa-onnx (Apache-2.0), wired as Knit's own backends — the same way llama.cpp and LiteRT-LM are. Audio is captured, transcribed, and synthesised entirely on the phone. Models download once from Settings → Voice.

🎙

Speech-to-text

Tap the mic in any chat → speak → Whisper-tiny transcribes locally → text drops in the input box. Replaces the system voice keyboard, which streams your audio to Google. ~101 MB model.

Whisper · sherpa-onnx
🔊

Text-to-speech

Flip "Speak agent replies" and every answer is read aloud by an on-device VITS voice. Code blocks, HTML, and tool JSON are stripped before speaking. ~40 MB voice.

VITS-LJSpeech · sherpa-onnx
🎧

Hands-free voice mode

Tap 🎧 for a full-screen loop: Silero VAD detects when you stop talking → Whisper → your agent answers (full tool loop) → VITS speaks → back to listening. The mic pauses while it thinks so it never hears itself.

VAD → STT → agent → TTS
Connections

Reach past the phone — on your terms

Everything above runs on-device. But sometimes you want an agent to touch a real service — Slack, GitHub, Notion, your inbox at large. Knit speaks the Model Context Protocol as a remote client: link an MCP server and its tools appear to your agents, alongside the native ones. Off by default — Knit stays fully on-device until you flip the switch, and the UI is blunt that calls to these tools leave the phone.

🔌

One key, many apps

Pick a provider from the built-in catalog — Composio (one key, 250+ apps), a dedicated Google Drive entry (search, read, create Drive files; the Google sign-in happens in the gateway dashboard, never in Knit), or any Smithery server — paste one API key, and the apps you've connected — Gmail, Slack, Instagram, Notion, GitHub, Drive — show up as tools. Or add any MCP server URL by hand.

Settings → Connections (MCP)
🔒

Opt-in & encrypted

Global switch is off until you enable it. Server URLs are HTTPS-only (localhost excepted for dev); API keys live in EncryptedSharedPreferences. Disable a server and its tools vanish on the next turn.

Off by default
🛡️

Hardened against rogue servers

A remote tool can never shadow a built-in one — collisions are dropped on a normalised name so lookalikes can't impersonate the consent-gated Gmail send. Untrusted tool names/descriptions are sanitised before they ever reach the prompt (injection defense). Pipeline agents keep a fixed tool surface regardless of what's connected.

Built-in tools always win
Why a gateway, not bundled apps? MCP servers are programs, not Android apps — a phone can't host them, and services like WhatsApp or Kite ship no plug-and-play endpoint. A hosted gateway runs the servers and exposes them over one HTTPS endpoint Knit connects to. Knit makes connecting a one-key affair; the gateway does the running.
How it works

Architecture

Knit is layered. The Compose UI talks to ViewModels (Hilt + StateFlow). ViewModels talk to a single InferenceBackend interface implemented by a dispatcher that routes to llama.cpp or LiteRT-LM. Tools and RAG sit alongside, accessed through the agent loop.

┌──────────────────────────────────────────────────────────┐ │ Compose UI ─ AppScreen / ChatScreen / Settings │ └─────────┬────────────────────────────────────────────────┘ │ ┌─────────▼────────────────────────────────────────────────┐ │ ViewModels (Hilt + StateFlow) │ │ MainViewModel / ChatViewModel / GmailConnect… │ └─────────┬────────────────────────────────────────────────┘ │ ┌─────────▼────────────────────────────────────────────────┐ │ Inference dispatcher │ │ DispatchingInferenceBackend │ │ ├─ LlamaCppBackend (GGUF via :llama JNI) │ │ └─ LiteRtLmBackend (.task, Mali / Adreno GPU) │ └─────────┬────────────────────────────────────────────────┘ │ ┌─────────▼────────────────────────────────────────────────┐ │ Agent + tool layer │ │ PromptBuilder + ChatTemplate (Qwen / Llama / Gemma / │ │ Phi-4) → tool loop → ToolCallParser → │ │ RealToolRegistry (~50 tools + merged MCP) │ │ McpSessionManager ← remote MCP servers (opt-in) │ └─────────┬────────────────────────────────────────────────┘ │ ┌─────────▼────────────────────────────────────────────────┐ │ Voice layer (sherpa-onnx backends) │ │ VoiceTranscriber (Whisper STT) │ │ VoiceSynthesizer (VITS TTS) · AudioRecorder │ │ VoiceAssistant (Silero VAD hands-free loop) │ └─────────┬────────────────────────────────────────────────┘ │ ┌─────────▼────────────────────────────────────────────────┐ │ Data + RAG │ │ SQLCipher Room (chats, agents) │ │ EncryptedFile (uploaded documents) │ │ HybridIndex (BM25 + TF-IDF retrieval) │ │ EncryptedSharedPreferences (Gmail + voice prefs) │ └──────────────────────────────────────────────────────────┘

The tool-calling loop

A tool-using agent emits a single JSON object (optionally wrapped in a <tool_call> tag):

{"tool":"gmail.list_unread","args":{"max":10}}

The chat layer parses it, dispatches via RealToolRegistry, then appends the result back into the conversation. The loop continues until the model emits plain text (final answer) or hits MAX_TOOL_ITERATIONS = 25.

The reliability framework

Small on-device models fumble JSON, arithmetic, and multi-step plans. Rather than hand-tune every agent's prompt, Knit wraps generation in a reliability layer (ReliabilityRuntime) that makes agents robust by construction. Four layers:

📏

Context Budgeter

Trims history → system prompt → oversized pastes to the loaded model's real window before every call. Keeps prefill fast and stops context-overflow garbage. Parity-preserving when under budget.

🧩

Typed tool schemas

Each tool declares its args; dispatch coerces stringy numbers, single→array, key aliases, and returns a structured invalid_args the model can self-correct from. Docs are generated from the schema — they never drift.

🛡️

Hardened parser + dedup

Accepts tags, truncated JSON (auto-balanced), <think> reasoning, and name variants. A repeated-identical-call guard breaks loops instead of spinning.

📋

Playbooks + grounding

Built-in pipeline agents run a declarative Playbook — the framework calls the tools itself and asks the model only for judgment. A NumericVerifier flags any figure not present in the tool results, so totals can't be fabricated.

Backward compatible by design: a tool with no schema skips validation, an agent with no playbook runs guarded autonomy. Every layer is unit-tested on the JVM with a stub backend. Settings → Debug surfaces live counters for each safeguard — playbook vs guarded runs, context trims, tool-JSON retries, dedup breaks, grounding regens — so you can watch the framework actually firing.
Use cases

Who Knit is for

Built for people who want AI without giving it their data. These are real workflows where the on-device + agent combination unlocks something cloud chatbots can't do (or shouldn't be trusted to).

Operator / Founder

"Triage 50 emails in 90 seconds"

Email Triage agent connects to Gmail, applies Priority/High labels to customer escalations and investor pings, ignores newsletters, and drafts replies to the urgent ones — all saved to Drafts. You glance, tap Send on each one.

Lawyer / Compliance / Procurement

"What does clause 4.2 say about termination?"

Upload a contract PDF. Doc Q&A agent answers strictly from the document. Quotes the exact phrase. Refuses to speculate if the document doesn't cover something. No fear that the model will hallucinate a clause that isn't there.

Researcher / Analyst

"Summarise this paper and tell me what's uncertain"

Doc Q&A on the arXiv PDF, or Deep Researcher agent for open questions. Structured answers with confidence labels — "the data shows X, but only with the assumption of Y". The Memory tools let the agent remember conclusions across sessions.

Traveller / Field worker

"AI that works offline"

Download a model on Wi-Fi. Loaded model lives in memory across backgrounding via a foreground service. Chat works on a flight, in a metro tunnel, at a remote site. No network, no degraded mode.

Driver / Hands-busy

"Talk to it without touching the screen"

Tap 🎧 once, then just speak. Silero VAD knows when you've finished, Whisper transcribes, your agent answers, and a VITS voice reads the reply back — all offline, looping until you exit. No audio ever leaves the phone, unlike the system voice keyboard.

Privacy-conscious individual

"Therapy-like reflection without the data trail"

Quick Chat or custom-built journaling agent. Conversations sit in an SQLCipher-encrypted DB whose key never leaves the Android Keystore. Even a full device backup can't decrypt them without the Keystore root.

Indian taxpayer

"Which ITR form, and what 80C deductions apply?"

India Tax Helper agent. Plain-language answers grounded in actual Section references. Distinguishes old vs new tax regime. Always recommends verifying with a CA — never claims authority.

Multilingual user

"Chat in Tanglish or Hinglish"

Tamil and Hindi Companion agents are bilingual. Mix languages mid-sentence — they follow your lead. Useful for Indian users who don't want to constantly switch keyboards.

Developer / Tinkerer

"Build my own agent in 5 minutes"

Tap + New Agent → write a system prompt → drop in a knowledge file (optional) → enable tools (optional). Persisted to encrypted prefs, available in the picker immediately. No app rebuild needed.

Scope

What ships today, what's planned, what won't ship

Shipping today

  • Two inference backends (llama.cpp + LiteRT-LM) with automatic dispatch
  • 34 bundled models + your-own-.gguf sideload
  • 3 default + 11 starter + unlimited custom agents
  • Gmail Email Triage with user-supplied OAuth
  • Daily Briefing agent (calendar + Gmail + weather + news)
  • Document Q&A (PDF / image / text → RAG)
  • Fully offline voice: Whisper STT, VITS TTS, hands-free VAD loop
  • File generation — agents write .txt / .pdf to Downloads
  • ~50 agent tools across 12 categories
  • Opt-in MCP connections — hosted-gateway catalog (Composio / Smithery) or any MCP server URL
  • 4-layer reliability framework (context budgeter, typed schemas, hardened parser + dedup, playbooks + numeric grounding)
  • Settings → Debug panel with live reliability telemetry
  • SQLCipher-encrypted chat history with multi-session threading
  • Edge-swipe / predictive back navigation
  • Foreground service so models survive backgrounding; Wi-Fi-only downloads

On the roadmap

  • Calendar Concierge agent (existing tools, new system prompt)
  • VLM — on-device image understanding (llama.cpp mmproj)
  • LoRA adapter hot-loading
  • Notification triage via NotificationListenerService
  • Health Coach via Health Connect API
  • MCP OAuth servers + resources/prompts (Slack / GitHub / Notion etc. work today via gateway API keys)
  • iOS port (Core ML + Foundation Models)

Explicitly out of scope

Setup

Get running in 3 minutes

Install the APK

  1. Download the latest Knit-debug.apk from the GitHub Releases page.
  2. Allow install from unknown sources in your Android settings (one-time toggle).
  3. Open the app. On first launch you'll see the model picker.
  4. Pick a model — start with SmolLM 135M (159 MB) or Qwen2.5 0.5B Instruct (LiteRT) (521 MB) for fastest first impression.
  5. Wait for the download (Wi-Fi-only is off by default; toggle it on in Settings if you're on cell data).
  6. Tap an agent — Quick Chat is the simplest to start with.

Enable voice (optional, one-time)

  1. Settings → Voice (on-device).
  2. Download STT model (~101 MB) for the mic 🎙, and/or Download TTS voice (~40 MB) for spoken replies. Use Wi-Fi.
  3. Tap Test voice to hear it, flip Speak agent replies on, and use 🎧 in any chat for hands-free mode (downloads the ~2 MB VAD model on first run).

Enable Email Triage (one-time, ~5 min)

Knit doesn't ship a developer OAuth Client ID. You make your own in Google Cloud — quota and tokens stay yours.

  1. Go to console.cloud.google.com → APIs & Services → Credentials. Create credentials → OAuth client ID → Application type Android (or Desktop). Google accepts the app's reversed-client-ID redirect automatically for these types — there's no redirect URI to paste.
  2. In APIs & Services → Library, enable the Gmail API.
  3. In OAuth consent screen, add the three Gmail scopes (gmail.readonly, gmail.modify, gmail.send) and add your Gmail address as a Test user.
  4. Copy the full Client ID (the whole …apps.googleusercontent.com string). Open Knit → Settings → Gmail (Email Triage) → paste it → Save → Connect Gmail.
Note: this build's redirect scheme is fixed to one Google project. Using a different project means rebuilding with that project's reversed-client-ID scheme.

Build from source

If you'd rather build the APK yourself, the toolchain is pinned:

git clone https://github.com/folkadonis/knit.git
cd knit
./gradlew assembleDebug
# → app/build/outputs/apk/debug/app-debug.apk

Requirements: JDK 17, Android SDK 34, NDK 27.x (for llama.cpp native build). Gradle 8.10.2, AGP 8.8.2, Kotlin 2.2.0, KSP 2.3.6, Hilt 2.58, Room 2.7.2 — all pulled by the wrapper / catalog.

Privacy

Where your data goes (and doesn't)

🧠

Inference

Entirely local. Models are downloaded from Hugging Face once; after that, every prompt and token is generated on the device CPU/GPU. Zero network traffic during chat.

💾

Chats

SQLCipher-encrypted SQLite (AES-256). The DB key is generated on first run and stored in EncryptedSharedPreferences, wrapped by the Android Keystore master key. A phone backup can't decrypt them.

📄

Uploaded documents

EncryptedFile (AES-256-GCM) on disk. Decrypted only at chunk time when the RAG retriever pulls relevant passages. Wiping the app clears them with no recovery path.

🔑

Gmail tokens

Access + refresh tokens in EncryptedSharedPreferences. Each user uses their own OAuth Client ID — no shared developer credential to exfiltrate.

🌐

Cloud tools (opt-in)

Off by default. When enabled, the web_search tool queries your SearXNG instance (self-hostable, or a public default). Off → only network is model downloads.

🎙️

Voice (STT + TTS)

Whisper transcription and VITS synthesis run on-device via sherpa-onnx. Your microphone audio is never uploaded — a deliberate departure from the system voice keyboard, which streams to Google.

📥

Generated files

Agent-written .txt / .pdf land in your Downloads/Knit/ folder via MediaStore. Created locally from the model's output — nothing is uploaded to make them.

About

The developer

FN

Folk Nallathambi

Solo founder · Backend & systems · Building Knit as an Android-first AI gallery

Knit is the work of one developer figuring out what genuinely useful on-device AI looks like on a mid-range phone. Strong background in backend systems; new to Android development — which is part of why Knit's architecture stays pragmatic: simple stores, simple state flows, no premature abstractions.

Tech stack

LayerTech
UIJetpack Compose + Material 3 + custom Knit theme
DIHilt 2.58
PersistenceRoom 2.7 (SQLCipher) + EncryptedSharedPreferences
LLM inferencellama.cpp (vendored, KleidiAI on) · LiteRT-LM 0.11.0
Voice (STT/TTS/VAD)sherpa-onnx 1.13.1 — Whisper · VITS · Silero (ONNX Runtime)
OAuthAppAuth 0.11.1 (PKCE, reversed-client-ID redirect)
RAGBM25 + TF-IDF hybrid retriever (hand-rolled)
PDF parsingPDFBox-Android 2.0.27.0
OCRGoogle ML Kit Text Recognition
Networkingjava.net.HttpURLConnection (no OkHttp dependency)
BuildGradle 8.10.2 · AGP 8.8.2 · Kotlin 2.2.0 · KSP 2.3.6 · NDK 27.x

Licenses

App code: Apache 2.0. Models each carry their own license — Apache 2.0 (Qwen, SmolLM, TinyLlama), MIT (Phi-4, DeepSeek-R1 distill), Gemma terms (Gemma 2/3), Llama 3 Community (Llama 3.2), CC-BY-NC-4.0 (xLAM-2 — non-commercial only). LiteRT-LM: Apache 2.0 (Google). llama.cpp: MIT (Georgi Gerganov). sherpa-onnx: Apache 2.0 (k2-fsa). AppAuth: Apache 2.0.