Klee: a native macOS MLX chat app with tool calling and no cloud dependency
A native macOS AI chat app powered by MLX. 100% local inference on Apple Silicon, no cloud required. Built with ShipSwift.
At a glance
- What is it?
- Klee is a SwiftUI macOS app that runs 4-bit MLX models on Apple Silicon and exposes file, shell and web tools to the model. The README is detailed on models and tools, but says almost nothing about sandboxing, token budgets or how to build a release from source.
- Who is it for?
- Klee is a reasonable fit if you have an Apple Silicon Mac with at least 16 GB of RAM and you want local chat plus file, shell and web tools without installing a Python stack or running a server. It is the wrong tool if you are on Intel, on macOS below 15.0, or if you need a documented security boundary around shell_exec and file_delete, because the README does not describe one.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 180 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Klee is trying to replace on a developer's Mac
The README frames Klee as a native macOS agent that runs entirely on the machine: no cloud, no account, no subscription. That is a narrower claim than it first appears. The app is not trying to be a general chat client. It is trying to remove the two things that usually sit between a developer and a local model: a Python environment and a server process. The README states that Klee uses MLX to run large language models directly on Apple Silicon, and the feature list calls out that there is no Electron, no Docker and no background services, with the app described as roughly 75MB. The audience is therefore someone who already accepts that a 4-bit quantized model on a laptop is a different product from a hosted frontier model, and who wants the tool-calling loop to run on the same machine as the files being edited. If your work depends on a model larger than the RAM table allows, or on a hosted API's context window, Klee is not addressing your problem at all.
The inference and tool-calling path inside the app
The mechanism visible in the README has two layers. The first is MLX through the mlx-swift-lm package, which the README names as the SPM dependency that resolves on first build. Models are 4-bit quantized variants pulled from the mlx-community organisation on HuggingFace, and the README states they are cached in ~/.klee/models/ and persist across app restarts. The second layer is tool calling. The README is explicit that Klee uses the mlx-swift-lm ToolCall API and that there is no MCP, no Node.js and no external processes. That is a deliberate architectural choice: tools are Swift functions inside the app rather than a separate protocol server, so the model's tool invocations never cross a process boundary. The tool list is small and concrete: file_write, file_read, file_list, file_delete, web_search, web_fetch and shell_exec. Streaming responses and an inline thinking card are presentation features; the thinking card implies the app parses reasoning output from models that emit it, such as the DeepSeek R1 entries in the model table. Web search is the one feature that leaves the device, and only when you supply a Jina API key.
Getting it running: download path versus source build
There are two install paths and they are not equivalent. The README says Klee is distributed directly as a signed macOS app under a Developer ID, not through the App Store. The steps are to download the latest .dmg from Releases, drag Klee into Applications, and open it; if Gatekeeper objects, you go to System Settings > Privacy & Security and click Open Anyway. The v1.0.0 release is dated 2026-03-19, one day before the last push to main, so the binary and the branch are not the same snapshot. The source path requires Xcode 16 or later and macOS 15.0 or later, and the README gives these commands: git clone https://github.com/signerlabs/Klee.git, then cd Klee, then open Klee.xcodeproj. You select the Klee scheme and build with Cmd+R, and the README notes the SPM dependency resolves automatically on first build. What the README does not give is any command-line build or archive step, so producing your own signed .dmg from source is undocumented. Web search setup is a four-step flow: get a free API key at jina.ai, click the sidebar toggle button in the top-right, enable Web Search and paste the key, then ask Klee to search.
RAM decides which model you can actually use
The model table is the most useful part of the README because it turns a vague hardware question into a budget. At 16 GB the recommended set is Qwen 3.5 9B, Qwen 3 8B, Gemma 3 12B and DeepSeek R1 8B, with download sizes between roughly 4.3 GB and 8 GB. At 32 GB you get Qwen 3.5 27B and Qwen 3.5 35B (MoE) at around 16 GB and 20 GB. Gemma 3 27B and DeepSeek R1 32B sit at the 64 GB tier, and Qwen 3.5 122B (MoE) needs 96 GB or more and about 70 GB of disk. Two details in that table matter more than the headline numbers. First, the minimum is 16 GB, so an 8 GB M1 or M2 machine is outside the supported range entirely. Second, the sizes are download sizes, not resident memory, and the README does not state peak memory during inference or how much headroom the app leaves. If you are near a tier boundary, the table tells you which model is recommended but not whether the machine will stay responsive while it runs. Vision support is also uneven: only the Qwen 3.5 entries in the table are marked as vision-capable, so attaching images is tied to a specific subset of models rather than to the app generally.
shell_exec and file_delete have no documented guardrails
This is the part of the README that stops short. The tool table lists file_write, file_read, file_list, file_delete, web_search, web_fetch and shell_exec, and the only stated constraint anywhere is a 30-second timeout on shell_exec. There is no description of a working-directory restriction, a confirmation prompt before destructive operations, a sandbox entitlement, or a deny list. The README does say the app is signed with a Developer ID, which is about distribution and Gatekeeper, not about what the model can reach once it is running. A language model with file_delete and shell_exec and no described boundary is a different risk category from a chat window, and the documentation does not address it. There is also a practical failure mode: models that are weak at tool calling will emit malformed or repeated calls, and nothing in the README describes retry limits, loop detection or how the app reports a failed tool invocation back to the model. If you plan to point Klee at a real project directory, the responsible move is to test tool behaviour on a scratch directory first, because the README gives you no other basis for predicting it.
How this differs from Ollama plus an Open WebUI front end
The obvious comparison is a local server such as Ollama with a browser-based chat UI in front of it. The difference is where the tool loop lives. In that arrangement the model server is a long-running daemon, the interface is typically a web app, and tool execution is usually added by the client or by a framework layered on top. Klee inverts this: the README states there are no background services, the UI is native SwiftUI, and tool calling goes through the mlx-swift-lm ToolCall API inside the same process. That buys you a single signed app to install and no daemon to keep alive, at the cost of flexibility. A server-based setup lets you swap runtimes, point multiple clients at one model, and run on non-Apple hardware. Klee is Apple Silicon only, macOS 15.0 or later, and the model list is a fixed set of mlx-community 4-bit builds rather than an arbitrary HuggingFace path. If you need to serve several machines or run on a Linux box with a discrete GPU, Klee is the wrong shape of tool regardless of how well it performs on a single Mac.
Licence, maintenance and what the repository does not tell you
The README ends with a single word under License: MIT. The repository metadata supplied here lists the licence as unknown, so the README text and the repository metadata disagree, and the licence file on the main branch is the thing to check rather than either summary. This is not legal advice; if you intend to redistribute a modified build, read the actual licence file and the licences of the bundled dependencies, including mlx-swift-lm and whatever the mlx-community model weights carry, since model licences are separate from the app's. On maintenance, the evidence is thin: v1.0.0 is the only release listed, published 2026-03-19, with the last push to main on 2026-03-20. A single release and a one-day gap is not enough to judge cadence, and the README marks platform modules as coming soon, which means part of the advertised surface is not shipped. Upgrading is the other cost. The README describes model downloads as resumable and cached in ~/.klee/models/, so model updates are a re-download rather than a rebuild, but the app itself is a manual .dmg replacement with no documented update channel. Budget for checking Releases yourself.
Editorial conclusion
Klee is a reasonable fit if you have an Apple Silicon Mac with at least 16 GB of RAM and you want local chat plus file, shell and web tools without installing a Python stack or running a server. It is the wrong tool if you are on Intel, on macOS below 15.0, or if you need a documented security boundary around shell_exec and file_delete, because the README does not describe one. Before adopting it, verify three things in the repository: the exact licence file on the main branch, whether the mlx-swift-lm ToolCall API version pinned in Klee.xcodeproj matches the tool behaviour described in the README, and whether the signed .dmg in the v1.0.0 release is built from the same commit you are reading.
Community notes