Skip to content
Kotoshu Kotoshu 言修

Documentation

HTTP API server

kotoshu-server: seven JSON endpoints over Rack, Sinatra, and Puma — check, suggest, detect, health, version, languages. The contract every SDK speaks.

kotoshu-server is the deployment surface for every SDK — Python, JavaScript, and Go all speak this contract, and an OpenAPI 3.1 spec generates the rest.

Run it

gem install kotoshu-server ships the fixed 0.1.1 gem — published through trusted publishing after the 0.1.0 packaging bug (an empty file list from a git ls-files gemspec built outside git). Installing pinned to -v 0.1.0 still gets the empty gem — that version predates the 30-day window rubygems allows for yanking, so it stays listed; use 0.1.1 or later. From source works too:

git clone https://github.com/kotoshu/kotoshu-server && cd kotoshu-server
bundle install

# Default: :9292, English pre-warmed. Pre-warm happens off the boot
# critical path — the server serves first, warms in background.
KOTOSHU_SERVER_PORT=9292 KOTOSHU_SERVER_BIND=127.0.0.1 \
bundle exec exe/kotoshu-server

The Docker image installs the gem from RubyGems unpinned, so it now pulls the fixed 0.1.1 — only a build pinned to 0.1.0 inherits the empty gem. Languages are set up through the kotoshu gem underneath — kotoshu setup en de before boot, or KOTOSHU_SERVER_LANGUAGES="en de" to pre-warm on start.

Endpoints

MethodPathBodyReturns
GET/—service metadata
GET/v1/health—{ status, ready, timestamp }
GET/v1/version—{ server, kotoshu, ruby }
GET/v1/languages—{ cached: […] }
POST/v1/check{ text, language?, format? }{ file, word_count, errors: […] }
POST/v1/suggest{ word, language?, max? }{ word, suggestions: […] }
POST/v1/detect{ text }{ language, confidence, engine }

Each error and suggestion row mirrors the engine’s serialization — word, distance, confidence, source. Omit language and the server default applies. Since 0.1.2, detection prefers the gem’s lid-176 model through the native path - the engine field says lid-176 or heuristic (the 7-language fallback on old gems, KOTOSHU_BACKEND=ruby, or KOTOSHU_DETECT=heuristic). Without a model the server falls back to its default language. A 422 means the language is not set up — the response carries a hint.

curl

# Check a document
curl -X POST http://127.0.0.1:9292/v1/check \
-H 'Content-Type: application/json' \
-d '{"text":"helo wrold","language":"en"}'

# Suggestions for one word
curl -X POST http://127.0.0.1:9292/v1/suggest \
-H 'Content-Type: application/json' \
-d '{"word":"helo","language":"en","max":3}'
{"file":null,"word_count":2,"errors":[{"word":"helo","position":0,
"suggestions":[{"word":"hello","distance":1,"confidence":1.0,"source":"edit_distance"}, ...]},
...]}

{"word":"helo","suggestions":[{"word":"hello","distance":1,"confidence":1.0,
"source":"edit_distance"}, ...]}

Configuration

Env varDefaultPurpose
KOTOSHU_SERVER_PORT9292listen port
KOTOSHU_SERVER_BIND0.0.0.0bind address
KOTOSHU_SERVER_LANGUAGESenlanguages to pre-warm on boot
KOTOSHU_SERVER_LAZY0skip pre-warm; load on first request
KOTOSHU_SERVER_DEFAULT_LANGenwhen the client omits language
KOTOSHU_OFFLINE1 in Dockernever trigger downloads

Verified 2026-09-05 — server 0.1.0 from source (its lock pins kotoshu 0.6); health, check, suggest, and detect all exercised. The empty-gem and Docker findings are real runs, not assumptions. kotoshu-server repo · OpenAPI 3.1 spec