Skip to content

Quickstart

The fastest useful thing knaif does is turn a sentence into a typed function call. No account, no key, no cloud.

Terminal window
pip install knaif
app.py
from typing import Annotated
import knaif.cli as nk
@nk.command(help="Return the current time", keywords=["now", "time", "current"])
def now(
tz: Annotated[str, nk.Opt(help="IANA timezone (e.g. Asia/Tokyo)")] = "UTC",
fmt: Annotated[str, nk.Opt(choices=["iso", "unix", "human"])] = "iso",
) -> dict:
from datetime import datetime
from zoneinfo import ZoneInfo
return {"time": datetime.now(tz=ZoneInfo(tz)).isoformat(), "timezone": tz}
nk.App([now]).run()
Terminal window
$ python app.py "what time is it in Tokyo"

The model never sees your function and never runs anything. It emits a plan — {"tool": "now", "args": {"tz": "Asia/Tokyo"}} — which knaif validates against the signature it derived from your annotations, then calls now(tz="Asia/Tokyo") with real typed arguments.

fmt shows why the annotations matter: because you declared choices, the model is shown exactly those three values and a plan proposing anything else is rejected before your function is called.

Wrap it. Your command functions do not change at all.

import knaif.cli as nk
from myapp.cli import cli # an existing click.Group
nk.from_click(cli).run()
Terminal window
$ python app.py "convert 2026-06-20T15:00 to Tokyo"
# calls: convert("2026-06-20T15:00", to_tz="Asia/Tokyo")

See Wrapping a click CLI for what maps cleanly and what does not.

Without an orchestrator, App.invoke() uses a mock backend with seeded responses. That is not a toy — it is how you test the plumbing in CI without shipping a GGUF:

app = nk.App([now])
result = app.invoke("what time is it in Tokyo", dry_run=True)

When you are ready for real inference, see Connecting a model — and read it before reaching for InferenceOrchestrator directly, because its raw defaults hang on reasoning models.

You want to Go to
Understand the decorators properly SDK reference
Wrap an existing click group Wrapping a click CLI
Point it at a real local model Connecting a model
Know what the model can and cannot do The boundary contract
Build a skill for knaif itself Author a skill

Three separate things carry the name, and search results will not tell you which one you have landed on. What separates them is who runs them:

You type What it is Who runs it
knaif The native binary, downloaded from knaif.org End users
knaif-cli The Python console script that runs skills from a repo checkout Skill authors and evaluators
import knaif.cli The library on this page — the knaif SDK Developers embedding knaif