Find the emotions in an English message, several at once: joy, gratitude, anger, sadness, nervousness and 23 more, plus an overall mood. 6 MB, 0.3 ms per message, no network.
Free up to 10k monthly active devices ยท No API key ยท On Maven Central ยท Android, iOS, desktop, web
This is the actual Emotion library, compiled to WebAssembly and running in your browser. Type any English message and see the feelings behind it. Your text never leaves this page.
Sentiment tells you a message is negative. Emotion tells you it is nervous, or disappointed, or angry, so your app can answer the right way.
The 27 GoEmotions emotions plus neutral, each with a score and its own tuned threshold. "Got the job, thank you!!" is joy and gratitude.
Every result also has a mood (positive, negative, ambiguous, neutral) and Ekman's six basic emotions, for apps that need a simpler answer.
Pure Kotlin inference. There is no ONNX Runtime, TFLite, ML Kit or native code, and it runs on Android (minSdk 21), iOS, macOS, JVM desktop, JavaScript and WebAssembly, from Kotlin or Java.
Diaries, chats and reviews are personal. Emotion reads them on the device; nothing is sent anywhere to be analysed.
Real output from the sample app on an Android emulator. These are not mockups.
Good news and a thank-you
A frustrated customer, not a question
Missing someone
Just information
The Kotlin Multiplatform sample app, built from the published artifacts, gives the same result on Android, iOS, desktop and the web.

Finally got the job!! โ Positive ยท gratitude 99%

Finally got the job!! โ Positive ยท gratitude 99%

Finally got the job!! โ Positive ยท gratitude 99%

Finally got the job!! โ Positive ยท gratitude 99%
One line in your Gradle file, from Maven Central. Works in commonMain for Android, iOS, macOS, JVM desktop, JavaScript and WebAssembly. No API key, no account.
// build.gradle.kts: commonMain, or any platform source set
dependencies {
implementation("io.github.rajumark:emotion:2.0.0")
}
// Gradle picks the right artifact per platform:
// emotion-android ยท emotion-jvm ยท emotion-iosarm64 ยท emotion-iossimulatorarm64
// emotion-macosarm64 ยท emotion-js ยท emotion-wasm-js
Add Emotion from rajumark to this Kotlin Multiplatform or Android project.
What it does: on-device emotion detection for English. It finds the emotions in a message (27 GoEmotions emotions such as joy, gratitude, anger, sadness, nervousness, plus neutral; several at once) and an overall mood. ~6 MB, no dependencies, no network.
Install (Maven Central, no extra repository):
build.gradle.kts (commonMain or any source set): implementation("io.github.rajumark:emotion:2.0.0")
Platforms: Android, iOS, macOS, JVM desktop, JavaScript, WebAssembly
Usage:
val emotion = Emotion() // off the main thread, keep one instance
val r = emotion.detect(message)
r.emotions // [joy 0.83, gratitude 0.78] (label + score, best first)
r.top // Label.JOY
r.mood // Mood.POSITIVE
Repo: https://github.com/rajumark/emotion#readme
Add the dependency, then follow the README for the exact API and current version.
Load once and reuse the instance. detect() is thread-safe.
val emotion = Emotion()
val r = emotion.detect("Finally got the job!! Thank you so much for helping me ๐")
r.emotions // [gratitude 0.99]
r.top // Label.GRATITUDE
r.mood // Mood.POSITIVE
r.basic[0] // joy 1.00
emotion.close()
try (Emotion emotion = new Emotion()) {
Result r = emotion.detect("I miss my grandma so much today");
if (r.getMood() == Mood.NEGATIVE) {
// offer a kinder reply, a helpline, or a softer UI
}
}
Anywhere people write how they feel, and your app should notice.
Send angry or disappointed customers to a human first, and thank the happy ones.
"The app keeps crashing and nobody reโฆ" โ disappointment ยท negativeTag diary entries with their feelings and show mood over the week, without the text ever leaving the phone.
"Long day, but the walk by the lake mโฆ" โ gratitude, joy ยท positiveSuggest the right emoji, sticker or reply for how the other person feels.
"OMG we won the match!!! ๐" โ joy, excitement ยท positiveLet a chatbot or game character react to fear, sadness or excitement before it answers.
"I'm scared about the surgery tomorrow" โ fear ยท negativeReal problems Emotion solves today. Pick one and ship it.
Mood journal ยท Tag each diary entry with its emotions and chart the week.
Support triage ยท Put angry and disappointed tickets at the top of the queue.
Review insights ยท See which reviews are joy, which are annoyance, and why.
Emoji suggestions ยท Suggest emojis that match the feeling, not only the words.
Smart replies ยท Offer "congrats!" for joy and "I'm sorry" for sadness.
Empathetic chatbots ยท Give the bot the user's mood before it answers.
Wellbeing check-ins ยท Notice nervousness or sadness and suggest a break.
Tone check before send ยท Warn "this sounds angry" before an email or message goes out.
Mood music ยท Pick a playlist from how the user's last messages feel.
Reactive game characters ยท NPCs that answer the player's excitement or fear.
Survey analytics ยท Turn free-text answers into emotion counts, on the device.
Shopping feedback ยท Spot disappointment in order feedback and follow up.
Learning apps ยท Notice confusion in a student's question and explain again.
Photo captions ยท Pick stickers and filters that match the caption's mood.
Writing coach ยท Show writers which emotion each paragraph carries.
Community health ยท Watch how a group chat feels over time, without reading it on a server.
Voice notes ยท Run it on the transcript and tag each note with its mood.
Gratitude tracker ยท Collect the thank-you messages a user got this month.
Story readers ยท Change colours or music as a story's mood changes.
Team pulse ยท Anonymous mood from stand-up notes, computed on each phone.
107 fresh everyday messages written by hand after training, never used to build, tune or pick any model, and the GoEmotions test set (5,427 Reddit comments, several raters each). Every model gets its own per-emotion thresholds, tuned the same way on the validation set.
| Emotion | RoBERTa-base GoEmotions | MiniLM GoEmotions | ModernBERT-large GoEmotions | |
|---|---|---|---|---|
| Fresh everyday messages: top emotion right | 38.3% | 35.5% | 33.6% | 33.6% |
| Fresh everyday messages: mood right | 46.7% | 40.2% | 43.0% | 35.5% |
| Fresh everyday messages: basic emotions, macro-F1 | 0.458 | 0.482 | 0.410 | 0.476 |
| GoEmotions test: top emotion right | 61.0% | 63.6% | 60.6% | 66.2% |
| GoEmotions test: macro-F1, 28 emotions | 0.475 | 0.522 | 0.510 | 0.538 |
| GoEmotions test: mood right | 70.3% | 73.7% | 72.5% | 75.4% |
| Size | 6.4 MB | 499 MB | 121 MB | 1583 MB |
| Latency, one message, 1 CPU thread (laptop) | ~0.3 ms | ~17 ms | ~2.6 ms | ~60 ms |
RoBERTa-base is a widely used GoEmotions model; ModernBERT-large is the large model Emotion learned from. On GoEmotions' own Reddit comments the larger models are ahead (macro-F1 0.475 vs 0.522 for RoBERTa-base). On everyday messages, where the emotion is often implied rather than named, Emotion is ahead, while being 78ร smaller and 60ร faster than RoBERTa-base. Where it falls short: sarcasm ("oh great, it's raining on my day off"), subtle approval and disapproval, and a few plain messages with times in them read as excitement.
| Member | Description |
|---|---|
Emotion() | Loads the bundled model. Implements AutoCloseable. |
detect(text) | Returns a Result. Thread-safe. A blank text is neutral. |
Result.emotions | The emotions that pass their thresholds, best first, as Score(label, score). Never empty. |
Result.top, Result.mood | The most likely Label, and the overall Mood. |
Result.all, Result.basic | All 28 scores; the 7 basic emotions as BasicScore(emotion, score). |
Label | ADMIRATION AMUSEMENT ANGER ANNOYANCE APPROVAL CARING CONFUSION CURIOSITY DESIRE DISAPPOINTMENT DISAPPROVAL DISGUST EMBARRASSMENT EXCITEMENT FEAR GRATITUDE GRIEF JOY LOVE NERVOUSNESS OPTIMISM PRIDE REALIZATION RELIEF REMORSE SADNESS SURPRISE NEUTRAL; each has a mood. |
Mood, BasicEmotion | POSITIVE NEGATIVE AMBIGUOUS NEUTRAL; ANGER DISGUST FEAR JOY SADNESS SURPRISE NEUTRAL |
No API key, no sign-up, no license file. Add Emotion to your project and ship. It stays free until your product passes 10,000 monthly active devices, and there's never a limit on how often each device runs it.
For indie developers, startups and growing apps, up to 10,000 monthly active devices.
For products above 10,000 monthly active devices on any platform.
A small, fast on-device model trained for your language, domain or task.
A monthly active device is a phone, tablet or other device that runs Emotion at least once in a calendar month.
The 10,000 limit applies separately to each product, each platform (Android, iOS, webโฆ) and each Hoverfly model. Crossed it? You have 30 days to get a commercial license.
Questions about licensing? Email raju348636@gmail.com or call / WhatsApp +91 63533 21951. Full terms: Hoverfly Community License.
A Kotlin Multiplatform library (Android, iOS, macOS, JVM desktop, JavaScript, WebAssembly) that reads an English message and tells you which emotions it carries, out of 27 plus neutral, with a score for each, an overall mood and Ekman's six basic emotions.
English only, including informal chat English, slang and emojis. Other languages and Hinglish are not supported.
Because people write that way: "Finally got the job, thank you so much!" is joy and gratitude. Each emotion has its own threshold, so emotions lists every one that is clearly there, best first.
Emotions are subjective, and many messages carry several at once, so no model is close to perfect. On fresh everyday messages, where the emotion is often implied ("waiting outside the principal's office"), Emotion names the top emotion right 38% of the time, ahead of every model we compared, including models 20 to 250 times larger (RoBERTa-base: 36%). On clear, explicit messages it is right far more often. See Quality.
About 0.3 ms per message on one laptop CPU thread, and a few milliseconds on a phone. Load it once, off the main thread, and reuse it.
On GoEmotions (Google, Apache 2.0), XED English and BRIGHTER English (CC BY 4.0), and on about a million everyday English sentences labelled by a large GoEmotions model that Emotion learned from.
Yes. Inference runs entirely on the device in plain Kotlin. It makes no server calls, needs no network permission and sends no telemetry.
Token ids and every score match the reference implementation on all 184 test vectors, both on the JVM and on an Android device.
Nothing for products with up to 10,000 monthly active devices per platform, including commercial apps. There is no API key or account, and no limit on how often it runs. Above that, a commercial license is needed; see Pricing.
Yes. Hoverfly trains custom on-device models for your language, domain or task and ships them as a small library like this one. Email raju348636@gmail.com or call / WhatsApp +91 63533 21951.
Built by a developer, for developers.
Every model here started as a problem I hit in my own apps. I made them small, private and free to start, so you can spend your time on the part your users will love.
Eight small on-device models, one job each. Same install, same free tier, and the same promise: nothing leaves the device.