Local AI inference for C#, Go and the command line
Classification, embeddings, semantic search, and reranking. One native library. No Python. No CUDA. No containers. Reads from stdin, writes JSON, pipes like any UNIX tool.
Hybrid search with reranking, semantic + BM25

Text classification, no API keys, no cloud, runs locally

Embeddings and similarity

dotnet add package Kjarni
go get github.com/olafurjohannsson/kjarni-go@latest
curl -fsSL https://kjarni.ai/install.sh | sh
irm https://kjarni.ai/install.ps1 | iex
Four capabilities. Same API in C# and on the command line.
Sentiment, emotion, toxicity detection. Pass text in, get labels with confidence scores.
Dense vector representations for semantic similarity, clustering, and retrieval.
Index files from a directory. Keyword, semantic, and hybrid retrieval built in.
Cross-encoder scoring to reorder search results and improve retrieval quality.
You shouldn't need a PhD to classify an email.
One install, nothing else. No Python runtime, no CUDA toolkit, no Docker containers, no API keys. Models download on first use and cache locally.
dotnet add package Kjarnicargo install kjarni-cliYou get Classifier, not BertForSequenceClassification. Kjarni hides tokenizers, attention masks, and pooling strategies.
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 classifykjarni classify --format json | jqSame capabilities in C#, Go, or the terminal.
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%
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%
$ 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%
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, ...
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, ...
$ 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%
var emb = new Embedder("minilm-l6-v2");
float sim = emb.Similarity("doctor", "physician");
Console.WriteLine($"Similarity: {sim:P}");
// Similarity: 86.0%
e, _ := kjarni.NewEmbedder("minilm-l6-v2")
defer e.Close()
sim, _ := e.Similarity("doctor", "physician")
fmt.Printf("Similarity: %.1f%%\n", sim*100)
// Similarity: 86.0%
$ kjarni similarity "doctor" "physician"
█████████████████░░░ 86.0% highly similar
$ kjarni similarity "doctor" "banana"
███████░░░░░░░░░░░░░ 33.8% somewhat related
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}");
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)
}
# 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%
Native binaries for every major platform
x64
x64