Skip to main content

klava

README file written by hands primarily

Klava is a CLI tool for using code agents with any provider. Use Claude Code with your OpenAI-compatible provider. Make code agents more secure by filtering out leaked secret keys and cryptographic keys from your filesystem.

Features

  • Fast & Lightweight: Written in Rust with async I/O
  • Universal: Works with any OpenAI-compatible API (OpenRouter, Qwen, Cloud.ru, local LLMs)
  • Security Guardrails: Filters out leaked secret keys and cryptographic keys from your filesystem before sending requests to LLM APIs

Installation

You can install klava from pip, npm, cargo or mise!

# Python (uvx and uv tool run it without a permanent install)
pip install klava
uv tool install klava
uvx klava --help

# Node (npx runs it without a permanent install)
npm install --global @zatsepin/klava
npx @zatsepin/klava --help

# Rust
cargo install klava --locked
mise use -g cargo:klava

Prebuilt binaries ship for linux x86_64/arm64 (glibc ≥ 2.17), macOS (universal2: Intel + Apple Silicon) and Windows x86_64, so neither pip nor npm needs a Rust toolchain. Alpine/musl and other platforms fall back to cargo install klava.

Or you can build klava from source. You need to install rustup, clone the repository and then

cargo install --path . --locked

Releasing (maintainers)

Version and tag come from Cargo.toml [package] — bump it, plus pyproject.toml and npm/package.json (the test pipeline runs scripts/check-version.sh and fails on drift), then tag v<version>. The Woodpecker pipelines build and publish PyPI wheels/sdist and the npm platform packages per agent OS; both registries skip files that already exist, so a re-run of the same tag is safe.

Launch AI Code Agent

The launch command starts the proxy server and launches an AI code agent with appropriate environment variables:

klava launch
klava launch claude
klava launch claude --provider ~deepseek/deepseek-flash-latest
klava launch opencode
klava launch pi

The first run has no models yet: klava launch (or klava providers add) opens the onboarding wizard, which logs in to a provider, lists its models, checks the connection and writes the ones you pick.

--provider <model> uses that configured model for this launch.

Harnesses see the real model names (~deepseek/deepseek-flash-latest, glm-5.1, …) — the proxy advertises them on GET /v1/models and each agent's config lists them, so the model picker and the model label in the UI show what actually answers. A request picks the model named in its body; a name that is not configured falls back to the configured defaults.

When several [[models]] entries share a name they form a pool. Pick how it is used with routing:

routing Behaviour
"shuffle" (default) random entry per request — spreads load/cost across endpoints
"round_robin" cycles through the pool in declaration order
"first" always the first entry (declaration order = failover priority)

Managed background service (Linux/systemd, macOS/launchd)

klava launch (and klava up --daemon) manage the proxy as a per-port background service whenever a supported service manager is available:

  • Linux: systemd user unit klava-<port>.service — auto-started at login, Restart=always on crash;
  • macOS: launchd LaunchAgent ~/Library/LaunchAgents/klava-<port>.plist — RunAtLoad at login, KeepAlive on crash.

In both cases the unit/plist is created on first use and kept up to date (binary path, port, env keys), the service is started idempotently and health-checked via /health, and each port is its own instance — so several proxies can run side by side. Since the service takes over the port, agents started later just reuse it — no per-session proxy spawn, no "proxy is dead" surprises.

klava status                                   # list managed instances
klava restart                                  # restart the proxy on the configured port
klava stop                                     # stop the proxy on the configured port
systemctl --user status klava-48017            # Linux: unit status
journalctl --user -u klava-48017 -f            # Linux: live proxy logs
launchctl list | grep klava                    # macOS: instance state
tail -f ~/Library/Logs/klava-48017.log         # macOS: live proxy logs

Pass --no-service to klava launch (or use plain klava up) to run a short-lived child/foreground proxy instead — e.g. for CI or custom ports. On Windows the managed service is not available yet; klava up keeps working there.

Supported code agents:

Agent Description Link
claude Claude Code https://code.claude.com
opencode OpenCode Agent https://opencode.ai/
pi Pi Agent https://pi.dev

Configuration File Location

To find the config file path on your system, run:

klava config

Platform-specific config file locations:

  • Linux and macOS: ~/.config/klava/config.toml
  • Windows: %APPDATA%\klava\config\config.toml

Set KLAVA_CONFIG_FILE=/path/to/config.toml to use another file (a second profile, or a throwaway config for tests and CI).

Config file

klava providers add       # onboarding wizard: Klava, OpenRouter, Cloudflare, Qwen, custom
klava providers list      # what is configured, which model is the default
klava providers check     # one tiny completion per model
klava providers set       # choose the default model
klava providers remove m  # drop a model (all entries with that name)

The wizard writes self-contained [[models]] entries — each carries its own connection (type, base URL, key), so the same name on two endpoints is a pool and no global "active provider" switch exists:

port = 48017
verbose = false
completion_model = "~deepseek/deepseek-flash-latest"
reasoning_model = "~deepseek/deepseek-flash-latest"
routing = "shuffle"                      # shuffle | round_robin | first
decide_model = "typesafe/jev-1.13"       # one entry; backend auto-detected

[[models]]
name = "~deepseek/deepseek-flash-latest"
type = "klava"                           # klava login, no key in the file

[[models]]
name = "~deepseek/deepseek-flash-latest"  # same name = pool with the entry above
type = "openai-compatible"
base_url = "https://openrouter.ai/api"
api_key_name = "OPENROUTER_API_KEY"

[[models]]
name = "glm-5.1"
type = "openai-compatible"
base_url = "https://foundation-models.api.cloud.ru"
api_key_name = "CLOUD_RU_KEY"

[[models]]
name = "deepseek-v4-flash"
type = "openai-compatible"
base_url = "https://chat.immers.cloud"
api_key_name = "IMMERSE_TOKEN"
chat_completions_path = "/v1/endpoints/generate/chat/completions"

[[models]]
name = "qwen3-coder-plus"
type = "qwen-code"

Notice: base_url should not include /v1 at the end!

Notice: If your provider exposes the chat completions endpoint at a nested path (e.g. …/v1/endpoints/generate/chat/completions), set chat_completions_path to that absolute path. It defaults to /v1/chat/completions otherwise.

Notice: You can use api_key_name if you have the api_key in your environment, if you want you can set api_key in the toml file with the api_key variable. For type = "klava" no key is needed: the wizard uses klava login and klava reads the saved session.

Notice: an entry with neither api_key nor api_key_name sends no Authorization header — that is how a local server (Ollama, llama.cpp) is configured. Naming an api_key_name whose variable is empty is an error.

Notice: upstream_model overrides the id sent upstream when the public name differs (e.g. a friendly alias). name is what agents send and see.

Notice: klava model names may start with ~, which the shell expands. Quote them on the command line: klava providers set '~deepseek/deepseek-flash-latest'.

Notice: The type can be openai-compatible, klava or qwen-code. qwen-code uses an authentication flow involving reverse engineering of the Qwen Code application. You can use 1000 free requests per day of the great large model, but with risks due to this being an unofficial implementation of qwen-code.

Cloudflare Workers AI

Cloudflare has no OpenAI-style /v1/models listing, so the wizard asks for the account id and stores the account-scoped endpoint:

[[models]]
name = "@cf/meta/llama-4-scout-17b-16e-instruct"
type = "openai-compatible"
base_url = "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/v1"
api_key_name = "CLOUDFLARE_AUTH_TOKEN"

Decide model (System One / jigor)

decide_model names exactly one [[models]] entry. Every classifier call klava makes — the web-search tuning and any extension that asks for a decide — uses it. The jigor backend is detected from that entry, so there is no backend switch to set:

Entry type / URL Backend
type = "klava" (the default) klava gateway
host openrouter.ai OpenRouter
host api.cloudflare.com (…/accounts/<id>/ai/…) Cloudflare Workers AI
any other OpenAI-compatible gateway klava wire (default)

Credentials come from the entry (api_key / api_key_name), falling back to the saved klava login. Without a configured entry the built-in klava gateway is used, so decide works out of the box after klava login. Set jigor = on the entry only for a self-hosted gateway that cannot be recognised.

Because a classifier must be deterministic, a decide_model name shared by several entries is rejected with an error — unlike regular models, which pool.

Manual Claude Execution

If you run klava up, and you want to run claude manually use this command

ANTHROPIC_BASE_URL=http://localhost:48017 claude

Don't forget to change the port to your klava proxy server port.

View Proxy Logs

View or follow proxy server logs:

klava logs          # View recent logs
klava logs -f       # Follow logs (like tail -f)
klava logs --follow # Follow logs (long form)

Note: The -v flag works only with the klava up command to enable verbose logging. When used with klava logs, it doesn't change the output. To see verbose logs, start the server with klava up -v first, then view the logs.

Known Limitations

The following Anthropic API features are not supported currently (Claude Code and similar tools work without these parameters): Many features like images are not ready yet... It's a work-in-progress tool.

Troubleshooting & Known Pitfalls

  • ❌ Wrong: https://openrouter.ai/api/v1
  • ✅ Correct: https://openrouter.ai/api
  • The proxy automatically adds /v1/chat/completions

Roadmap & Contributing

Contributions welcome!

Current vision is:

  • Refactoring -> split codebase into many crates like proxy, cli, providers ...)
  • Add more Guardrails
  • Add Token optimization algorithms. Reduce cost is a crucial goal
  • Extensions: installable at runtime, in any language. See EXTENSIONS.md.
  • Add more providers and agents
  • Add benchmark wars between agents
  • Add remote hand control using Telegram and Mobile

If you like it you can support me:

Metadata

Release files for klava 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for klava 0.3.0
File Size Uploaded Provenance Actions
klava-0.3.0.tar.gz 343.1 kB Without provenance Details for klava-0.3.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for klava 0.3.0
File Actions
klava-0.3.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for klava-0.3.0-py3-none-win_amd64.whl
klava-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for klava-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
klava-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for klava-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
klava-0.3.0-py3-none-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl Python 3 none macOS 11.0+ ARM64, macOS 11.0+ universal2 (ARM64, x86-64), macOS 11.0+ x86-64 Details for klava-0.3.0-py3-none-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl

Total release size: 16.6 MB

Release files / klava-0.3.0.tar.gz

Download URL klava-0.3.0.tar.gz
Size 343.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d59b548f4a6e8a15565fbf54dd75164c0c1ba9cdea6002e5f0791cd3223ef6b8
BLAKE2b-256 checksum
How to use checksums
10c1012c649bf2b74dc67d6b7177586404e05c91b3af79e4f96f2a8245ebe615
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CentOS Linux","version":"7","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / klava-0.3.0-py3-none-win_amd64.whl

Download URL klava-0.3.0-py3-none-win_amd64.whl
Size 3.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
d316a6d16ad4f4d4da1a1a4be1ccf5cf4c467707c263943093e88d0388ccec2b
BLAKE2b-256 checksum
How to use checksums
6676fdc3710d57fda58bab3c898ea9b342dca6bc089a36a951cf87336a7bc057
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / klava-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL klava-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.6 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
e80888fbf8d44599772b575040469514e9a375a313914c2fdc0ca16b78f3de36
BLAKE2b-256 checksum
How to use checksums
c9792459bc78608ceedc1b57eab0d649b826a6d456669998300440ddbd2fb078
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CentOS Linux","version":"7","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / klava-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL klava-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.4 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
b2f31257bbbeb535fe496993ebb473a02755d2927bca2a83b3f81bf01bb4e011
BLAKE2b-256 checksum
How to use checksums
b50b605a959928937a27f62ef03925eebaa5879818b39c25170f961f8b834469
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CentOS Linux","version":"7","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / klava-0.3.0-py3-none-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl

Download URL klava-0.3.0-py3-none-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl
Size 6.3 MB
Tags Python 3 macOS 11.0+ ARM64 macOS 11.0+ universal2 (ARM64, x86-64) macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
fc102667d090db52189c632e6a3083f0760efa7f01ea3c718d3032720e00cf2a
BLAKE2b-256 checksum
How to use checksums
39b6db83116c5fea72381a7c355a774d813a5c274a46161662d55454c254489e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for klava 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page