LocalHarness
Run AI agents on the models you already run locally.
LocalHarness is an open-source agent harness for local LLMs. It does not serve models: it connects to one you already serve over an OpenAI-compatible API (vLLM, llama.cpp, Ollama or LM Studio) and gives it agents, defined in YAML, with tools, a permission gate in front of every tool call, and helper agents that each work in a fresh context with only the tools they are allowed. A small core runs the agent loop; memory, the phone app, Discord, image generation and the self-improvement loop are plugins that you turn on or off with one command.
A small core, five plugins
- Core owns the agent loop, the built-in tools (read, write, edit, glob, grep, bash, python, web search and fetch, delegation to helper agents), MCP servers, config, the permission gate, the bench and the CLI. With a vision model it also takes pictures: drop a screenshot onto the terminal or
/image <path>, paste one into Zed or the phone page, or attach one on Discord. - Plugins add tools, commands, slash commands,
doctorchecks, settings and chat channels through one plugin API. The five that ship with LocalHarness use the same API as a plugin you write yourself. Turning one off removes what it adds; turning off memory or autoresearch leaves their files on disk (the memories, the experiment archive).
Quick start
You need Python 3.12 or later, uv, and a model server running.
uv tool install 'localharness[embeddings,mobile]' # memory's CPU model + the phone app
localharness init # finds your model server, writes your config
localharness start # an interactive session
localharness plugins list # every plugin and whether it is on
localharness plugins disable autoresearch
localharness plugins enable image --set comfyui_url=http://127.0.0.1:8188
plugins enable and plugins disable write overrides.yaml, never your config.yaml. Add --workspace to change a bundled plugin for one project only. Add the dispatch extra for Discord.
init ends with every plugin and the command that sets it up. Inside a running session, /plugins enable <name> does the same and turns the plugin on right away: the first time, or while the plugin is not set up yet, it asks what the plugin needs and checks it, then it restarts the session with your conversation kept. A first localharness start with no config runs init's setup and goes on into the session.
Supported runtimes
Every runtime is reached through one OpenAI-compatible client; init can also attach to any endpoint that is already running. Live-validated means a real end-to-end run on the DGX Spark reference machine; recorded bench runs exist for vLLM only.
| Runtime | Harness starts the server | Tool calling | Token counting | Live-validated |
|---|---|---|---|---|
| vLLM | docker or binary | native | exact | reference machine and bench |
| llama.cpp | spawns llama-server |
XML / Hermes fallback | exact | reference machine |
| Ollama | spawns ollama serve |
native | exact with the exact-tokenizer extra, else estimated |
CPU round-trip |
| LM Studio | drives headless lms |
native | exact with the exact-tokenizer extra, else estimated |
CPU round-trip |
Setup: llama.cpp, Ollama, LM Studio, vLLM (reference architectures). Details: spec 13.
Security
An agent that reads untrusted content, such as a web page or an MCP tool's result, is never given tools that change your machine; this separation is on by default, checked when an agent's tools are resolved, and fails closed. Every tool call of every agent, helper agents included, passes one permission gate. A plugin you install has its tools' gate declarations clamped, except for a tool it registers directly on the tool registry instead of returning it from tools(), which skips that rule (SECURITY.md). Settings that say where the harness connects, which credential it uses or who may talk to it can be set only in your machine-level config, never by a repository you clone. A plugin you turn on is trusted code that runs with your privileges, and nothing contains a plugin that means harm: read SECURITY.md before you enable one.
Plugins
| Name | What it does | Default | How to switch |
|---|---|---|---|
image |
makes pictures with ComfyUI | off | localharness plugins enable image --set comfyui_url=<url> |
mobile |
Mobile: the phone page, served with its event API by localharness mobile |
on; needs localharness[mobile] |
localharness plugins disable mobile |
memory |
persistent memory: facts recalled into each turn, memory tools, background consolidation | on | localharness plugins disable memory |
dispatch |
chat: Discord | on; needs localharness[dispatch] |
localharness plugins disable dispatch |
autoresearch |
experiment loop | on | localharness plugins disable autoresearch |
Each plugin has its own page:
- image: a
generate_imagetool andlocalharness generate-image, against a ComfyUI server you run yourself. Page · site · Docs - Mobile (the
mobileplugin): drive a session from your phone on your own private network. Page · site · Docs - memory: per-agent SQLite memory recalled into each turn, with idle consolidation. Page · site · Docs
- dispatch:
localharness start --channel discorddrives a session from allowlisted Discord messages. Page · site · Docs - autoresearch: propose one harness change, run it through a statistical gate, adopt or reject it. Page · site · Docs
A plugin you install is found in two places, both on your machine and never in a project: a Python package with a localharness.plugins entry point in the same environment as LocalHarness, or a folder ~/.localharness/plugins/<name>/. It stays off, with none of its code imported, until localharness plugins enable <name>, which only your machine-level config can do.
Write a plugin
Copy the example plugin: one tool, one command, one slash command, one doctor check and two settings, exercised by the test suite and in CI. The API is spec 09; its version is "1", and changes since its first release have only added optional fields. Plugins written for the previous plugin API no longer load; spec 09 says how to port one.
Status
Early stage (v0.16.7, pre-1.0). Interfaces and config schema may change without notice. Each release's known limitations are listed in the CHANGELOG.
Links
- SECURITY.md: trust boundaries, the permission gate, the prompt-injection threat model
- docs/specs/: component specs, starting with the architecture overview; the CLI is spec 10
- docs/zed.md: use LocalHarness from Zed's agent panel
- docs/task-context.md: how a normal session keeps a working record for substantive work (references, checks, delegation, resume), with a synthetic example workflow
- docs/reference-architectures/: tested hardware and setup notes
- docs/running-agents-locally.md: where LocalHarness fits among local agent tools, and where it is behind
- LocalShift: the companion project that moves a headless Claude Code job onto LocalHarness once a local model proves good enough
- localharness.dev
License
Metadata
Release files for localharness 0.16.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| localharness-0.16.8.tar.gz | 1.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| localharness-0.16.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.5 MB
Release files / localharness-0.16.8.tar.gz
| Download URL | localharness-0.16.8.tar.gz |
|---|---|
| Size | 1.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6359c46476913ae7432e99df2493e6b5c6eab9a229b3d736128012f47f120d67
|
|
BLAKE2b-256 checksum How to use checksums |
83c37935645436864994369af448d1a35ee87f541c07c953758efcf988943564
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / localharness-0.16.8-py3-none-any.whl
| Download URL | localharness-0.16.8-py3-none-any.whl |
|---|---|
| Size | 1.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
02fd4d065fb6ef1f5de2341b7a84eb97c1fa392afe459a45a44dd62b5a201247
|
|
BLAKE2b-256 checksum How to use checksums |
70f9183ed76e654995bed688b2f8b075a7b63f94b6324fb7c0376987c7f35563
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|