Model or dataset
nobodywho-ooo/nobodywho avatar
nobodywho-ooo/nobodywho

NobodyWho: a llama.cpp wrapper that ships the same chat API to Kotlin, Swift, Flutter, React Native, Expo, Python and Godot

NobodyWho is an inference engine that lets you run LLMs locally and efficiently on any device.

1,107 stars79 forksRustEUPL-1.2

At a glance

What is it?
NobodyWho is a Rust inference engine built on llama.cpp that exposes on-device LLM chat, tool calling, speech-to-text and text-to-speech through seven language bindings. The interesting part is not the model support, it is the promise that one mental model of a Chat object survives across all of them. The risk sits in the version numbering, which is not shared.
Who is it for?
Adopt NobodyWho if you are shipping a client application in Kotlin, Swift, Flutter, React Native, Expo, Python or Godot and you want GGUF models loaded from a URL with a Chat object you already understand. Do not adopt it if you need a server-side inference stack, a stable cross-binding version number, or a licence you can relicense.
Can I use it commercially?
Yes, with conditions. EUPL-1.2 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem is binding count, not model support

Running a GGUF model locally is a solved problem in the sense that llama.cpp exists and works. The unsolved part is packaging. A team building a Godot game, a Flutter app and a Kotlin desktop tool needs three separate integrations, three sets of build files and three sets of native library loading rules, all against the same underlying C++ library. NobodyWho's answer is to write the engine once in Rust and generate or hand-write bindings for Kotlin, Swift, Python, Flutter, React Native, Expo and Godot, with the README listing a docs subdomain per platform. The intended audience is application developers who want a local model behind a familiar object, not infrastructure engineers running a GPU cluster. The README's own framing is 'On-device AI for any device', and the platform table is the real product. If you only ever target one runtime, the value of the wrapper is smaller and llama.cpp directly may be less indirection.

A Rust core over llama.cpp, with the Chat object as the shared surface

The README states the engine is 'Powered by the wonderful llama.cpp', so the inference path is the one llama.cpp already implements: GGUF weights, a context, token sampling. NobodyWho adds a Rust layer above it and then a per-language layer above that. The visible API shape is consistent across bindings: construct a Chat from a model path, call ask with a string, call completed to get the result. Kotlin and Swift both use Chat.fromPath, with Kotlin returning something you call .completed() on and Swift returning an awaitable that also ends in .completed(). Python uses Chat(...) directly, Flutter calls nobodywho.NobodyWho.init() before nobodywho.Chat.fromPath, and React Native awaits Chat.fromPath. That difference matters: Flutter needs an explicit init step, the others do not show one. Two engine-level features are named in the README rather than explained. The first is 'Conversation-aware preemptive context shifting', described as retaining conversation memory 'without any message length limits'. The second is tool calling, where the README says structured grammars are generated automatically from your function signatures so you do not write a JSON schema. Both are claims about mechanism, not benchmarks, and the README does not give numbers for either.

Model loading goes through hf:// and huggingface: URL schemes

NobodyWho does not ask you to download weights yourself. The model path is a URL. Kotlin, Swift and React Native use the form hf://NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf. Flutter and Python use huggingface: with the same repository and filename. The README also says models can load 'from Hugging Face or any URL', so a plain HTTPS path is presumably accepted, though the examples only show the two schemes. The choice of a 0.6B Q4_K_M Qwen3 model in every quick start is worth noting: it is small enough that a first run on a phone will not stall, which suggests the examples are tuned for a successful first impression rather than for output quality. Nothing in the README describes where downloaded weights are cached, how large the cache grows, or how to pin a revision. Those are the questions to answer before shipping a model URL in a client build.

Getting it running: four package managers and one AssetLib

Each binding has its own install line. Kotlin is a Gradle dependency, and the README splits it by target: implementation("ai.nobodywho:nobodywho-android:2.0.0") for Android and implementation("ai.nobodywho:nobodywho:2.0.0") for desktop JVM on Linux, macOS and Windows. Swift is a Swift Package Manager reference to https://github.com/nobodywho-ooo/nobodywho-swift.git. React Native is npm install react-native-nobodywho; Expo is npx expo install react-native-nobodywho. Flutter is flutter pub add nobodywho. Python is pip install nobodywho. Godot has no package manager line at all: the README says to open AssetLib in Godot 4.5 or later and search for 'NobodyWho', or to import a zip from the GitHub releases page, and it warns that 'the ignore asset root option is set in the import dialogue'. That Godot note is the kind of instruction that exists because someone lost an afternoon to it. Note the version drift in the same document: the Kotlin snippet says 2.0.0, the recent releases list shows nobodywho-swift-v3.0.0, nobodywho-react-native-v3.0.0 and nobodywho-python-v2.0.0. The bindings do not version together.

Speech in and speech out are separate backends, and the README names them

Beyond chat, NobodyWho advertises two audio paths. Text-to-speech synthesizes 'local WAV audio' with three named backends: Kokoro, Pocket TTS and Supertonic. Speech-to-text transcribes audio with Whisper. Multimodal input is listed separately, described as providing 'image and audio information to your LLM', which is a different capability from the STT pipeline: one feeds audio into the model's context, the other converts audio to text. The README does not say which languages, voices or sample rates the TTS backends support, nor which Whisper sizes are usable, nor whether these run on the same GPU path as inference. For a game or a mobile app that wants a talking character, three TTS backends with no comparison table is a selection problem handed to you. Expect to test each one against your target device before choosing.

Where NobodyWho is the wrong tool

The acceleration story is Vulkan or Metal, described as running 'fast on any OS'. That is a graphics-API path, not a CUDA path. If your deployment target is an NVIDIA server with CUDA, or a data-centre inference stack where you want tensor parallelism across multiple GPUs, this project is aimed elsewhere and the README offers no server story. The second limit is the binding count itself. Seven bindings means seven release trains, and the release list already shows Swift and React Native at 3.0.0 while Python is at 2.0.0. A breaking change in the Rust core does not arrive everywhere at once, and the README's quick starts reflect that: the Kotlin snippet still says 2.0.0. The third limit is documentation depth in the repository itself. The README ends by pointing at docs.nobodywho.ooo for 'everything you might w[ant]', which means the repository is an index, not a reference. Anyone evaluating NobodyWho from the repo alone will not find the context-shifting algorithm, the tool-calling grammar generation, or the audio pipeline explained here.

The alternative is llama.cpp bindings, and the difference is who owns the glue

The obvious comparison is using llama.cpp through an existing per-language binding. NobodyWho is explicit that llama.cpp is underneath, so the question is what the extra layer buys. With raw llama.cpp bindings you control the context, the sampling parameters and the token loop, and you write the same integration three times for three runtimes. With NobodyWho you get one Chat abstraction, one ask/completed call shape, automatic grammar generation for tool calls, and the context-shifting behaviour handled for you. The cost is that you inherit NobodyWho's release cadence, its URL scheme for model loading, and its choices about which llama.cpp features are surfaced. If your application needs fine control over sampling or KV cache behaviour, the wrapper is a layer between you and the thing you want to tune. If your application needs to ask a question and print an answer on six platforms, the wrapper removes most of the work.

Licence and maintenance: EUPL-1.2 and seven moving parts

NobodyWho is licensed under EUPL-1.2, a copyleft licence drafted for the European Union. It is not MIT or Apache-2.0. If you distribute a binary that includes NobodyWho, the obligations attach to that distribution, and the exact scope depends on whether your code is a derivative work and how you link. That is a question for your legal team, not for this article, but the practical point is that EUPL-1.2 is a deliberate choice by the maintainers and it is visible in the repository metadata. On maintenance: the project is not archived, and the most recent push date in the supplied material is 2026-09-09, with Swift and React Native 3.0.0 releases on 2026-08-22 and 2026-08-24 and Python 2.0.0 on 2026-08-23. Three binding releases inside three days is a sign of coordinated work, and it is also the shape of the maintenance burden: any core change has to be carried through Kotlin, Swift, Python, Flutter, React Native, Expo and Godot. The upgrade cost you should budget for is not the engine, it is re-testing each binding you ship against the version you pin.

Editorial conclusion

Adopt NobodyWho if you are shipping a client application in Kotlin, Swift, Flutter, React Native, Expo, Python or Godot and you want GGUF models loaded from a URL with a Chat object you already understand. Do not adopt it if you need a server-side inference stack, a stable cross-binding version number, or a licence you can relicense. Before committing, verify three things yourself: the exact binding version you will pin (3.0.0 for Swift and React Native, 2.0.0 for Python, 2.0.0 in the Kotlin build.gradle.kts snippet), whether your target platform has a Vulkan or Metal path, and whether your legal team accepts EUPL-1.2 for a distributed binary.

Official sources

  1. License: EUPL-1.2
  2. nobodywho-ooo/nobodywho on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes