kjarni

Local AI inference for C#, Go, Rust and the command line

Embeddings, classification, semantic search, reranking, chat, transcription, summarization and translation. One native library, running inside your process. Your text stays on your machine. Reads from stdin, writes JSON, pipes like any UNIX tool.

Try it in your browser → No install. Runs on your machine via WebAssembly.

Text classification, running entirely on this machine

kjarni classify demo

Embeddings and similarity

kjarni embed demo
dotnet add package Kjarni
npm i kjarni-wasm
go get github.com/olafurjohannsson/kjarni-go@latest
curl -fsSL https://kjarni.ai/install.sh | sh
irm https://kjarni.ai/install.ps1 | iex
Zero dependencies
Models auto-download
Works offline
Reads from stdin
Written in Rust

What It Does

Encoders, decoders and seq2seq, from one dependency-free package. Every capability is available on the command line; the badges show where else it runs today.

Embeddings

Measure how close two pieces of text are in meaning. Powers related articles, duplicate detection, and matching a question to the right FAQ entry.

MiniLM-L6 · MPNet · Nomic
CLIC#RustBrowser demo

Classification

Sort text into categories without training anything. Route support tickets by tone, flag abusive comments before they post, track how customers feel about a release.

DistilBERT · RoBERTa · BERT Multilingual · Toxic-BERT
CLIC#RustWASM

Semantic Search

Find the right document when the user did not use your words for it. Point it at a directory and query by keyword, by meaning, or both. The index is a folder on disk.

Exact vectors · BM25 · Hybrid
CLIC#RustWASM

Reranking

Your search returns twenty results and the right one sits at position eleven. A cross-encoder rescores the shortlist and lifts it to the top.

MiniLM Cross-Encoder
CLIC#RustWASM

Chat & Generation

Add an assistant feature to software that has to keep working without a network, or where the text cannot leave the building. Streaming tokens, multi-turn, sampling control.

Llama 3.2 1B/3B · Qwen 2.5 · Phi 3.5 Mini
CLIC#RustWASM

Transcription

Turn recorded audio into searchable text: meetings, calls, interviews. Word-level timestamps and token streaming when you need them.

Whisper tiny · Whisper small
CLIRust

Summarization

Condense long documents into something a person will actually read. Works from a purpose-built model or an instruct model of your choice.

BART-large-CNN · DistilBART-CNN · FLAN-T5
CLIRust

Translation

Translate content between languages on your own hardware, which matters when the text is under contract or regulation and cannot be sent to a translation service.

FLAN-T5 base · FLAN-T5 large
CLIRust

Why Kjarni?

You shouldn't need a PhD to classify an email.

Self-Contained

One install, nothing else. A single native library that loads into your process, on CPU, offline after the first run. Models download on first use and cache locally.

  • dotnet add package Kjarni
  • cargo install kjarni-cli
  • Works offline after first run

Task-Level API

You get Classifier, not BertForSequenceClassification. Kjarni hides tokenizers, attention masks, and pooling strategies.

  • Classifier, Embedder, Searcher, Reranker
  • 6 classifiers, 3 embedders, cross-encoder
  • Pick a model name, call a method

UNIX-Native

The CLI reads from stdin, writes to stdout, and outputs JSON. Pipe it to jq, grep, or into your scripts. It's a tool, not a framework.

  • cat reviews.txt | kjarni classify
  • kjarni classify --format json | jq
  • SIMD-optimized (AVX2, NEON)

Three Lines of Code

Same capabilities in C#, Go, or the terminal.

C# Sentiment Analysis
using Kjarni;

var clf = new Classifier("distilbert-sentiment");
var result = clf.Classify("Best purchase I've ever made!");

Console.WriteLine($"{result.Label}: {result.Score:P}");
// POSITIVE: 100.0%
Go Sentiment Analysis
import "github.com/olafurjohannsson/kjarni-go"

c, _ := kjarni.NewClassifier("distilbert-sentiment")
defer c.Close()

result, _ := c.Classify("Best purchase I've ever made!")
fmt.Printf("%s: %.1f%%\n", result.Label, result.Score*100)
// POSITIVE: 100.0%
CLI Sentiment Analysis
$ kjarni classify "Best purchase I've ever made!"
  ✓       POSITIVE  ████████████████████  100.0%
          NEGATIVE  ░░░░░░░░░░░░░░░░░░░░    0.0%

# Pipe from stdin
$ echo "Terrible quality" | kjarni classify
  ✓       NEGATIVE  ████████████████████  100.0%
          POSITIVE  ░░░░░░░░░░░░░░░░░░░░    0.0%
C# Toxicity Detection
var clf = new Classifier("toxic-bert");
var result = clf.Classify(userMessage);

if (result.Label == "toxic" && result.Score > 0.8f)
{
    // flag for moderation
}
// Multi-label: toxic, insult, obscene, threat, ...
Go Toxicity Detection
c, _ := kjarni.NewClassifier("toxic-bert")
defer c.Close()

result, _ := c.Classify(userMessage)

if result.Label == "toxic" && result.Score > 0.8 {
    // flag for moderation
}
// Multi-label: toxic, insult, obscene, threat, ...
CLI Toxicity Detection
$ kjarni classify "You are the worst cook ever" --model toxic-bert
  ✓          toxic  ███████████████████░   92.8%
            insult  ██████████████░░░░░░   72.3%
           obscene  ██░░░░░░░░░░░░░░░░░░    7.6%
     identity_hate  ░░░░░░░░░░░░░░░░░░░░    0.5%
      severe_toxic  ░░░░░░░░░░░░░░░░░░░░    0.3%
C# Embeddings & Similarity
var emb = new Embedder("minilm-l6-v2");

float sim = emb.Similarity("doctor", "physician");
Console.WriteLine($"Similarity: {sim:P}");
// Similarity: 86.0%
Go Embeddings & Similarity
e, _ := kjarni.NewEmbedder("minilm-l6-v2")
defer e.Close()

sim, _ := e.Similarity("doctor", "physician")
fmt.Printf("Similarity: %.1f%%\n", sim*100)
// Similarity: 86.0%
CLI Embeddings & Similarity
$ kjarni similarity "doctor" "physician"
  █████████████████░░░   86.0%  highly similar

$ kjarni similarity "doctor" "banana"
  ███████░░░░░░░░░░░░░   33.8%  somewhat related
C# Document Search
var indexer = new Indexer("minilm-l6-v2");
indexer.Create("./my-index", new[] { "./docs" });

var searcher = new Searcher("minilm-l6-v2", "");
var results = searcher.Search("./my-index", "query");

foreach (var r in results)
    Console.WriteLine($"{r.Score:F3}: {r.Text}");
Go Document Search
idx, _ := kjarni.NewIndexer("minilm-l6-v2")
defer idx.Close()
idx.Create("./my-index", []string{"./docs"})

s, _ := kjarni.NewSearcher("minilm-l6-v2", "")
defer s.Close()
results, _ := s.Search("./my-index", "query", kjarni.Hybrid)

for _, r := range results {
    fmt.Printf("%.3f: %s\n", r.Score, r.Text)
}
CLI Index & Search
# Index a folder of documents
$ kjarni index create my-docs docs/*
✓ Indexed 15 documents (39.52 KB)

# Search with hybrid retrieval
$ kjarni search my-docs "keeping data safe" --top-k 3
  1. cryptocraphy.txt
     ████████████████████  100.0%
  2. tcpip.txt
     ██████████░░░░░░░░░░   49.2%
  3. neuralnetworks.txt
     ░░░░░░░░░░░░░░░░░░░░    0.0%

Run Anywhere

Native binaries for every major platform

Linux

x64

Windows

x64