Skip to main content

LocalHarness logo

LocalHarness

GitHub stars License: MIT

Run AI agents on the models you already run locally.

LocalHarness is an open-source, self-hosted agent harness for local LLMs. It connects to a model you serve over an OpenAI-compatible API (vLLM, llama.cpp, Ollama or LM Studio), or starts one for you, and gives it agents, defined in YAML, with tools, MCP servers, 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, the self-improvement loop and a headless browser for JavaScript-rendered pages are plugins that you turn on or off with one command. Use it as a coding and research agent on your own machine, with no account and no telemetry.

LocalHarness: init detects your local model, start drops you into a ready agent, and it researches a question live with web search and multi-step tool calls

Why an agent harness for local models

  • Local models. The harness sizes a launch from the model's own files. It reads the served, trained and fitted context windows, prices a llama.cpp launch from the GGUF tensor table, keeps an MoE's experts in RAM when the GPU cannot hold them, and refuses a model that fits nowhere. It will not launch below the window the agent loop needs. A model without native tool calling gets an XML fallback. /effort off|low|high|max caps how much a model may think per request.
  • The model server. localharness start finds a model on your machine or offers one to fetch, writes it a preset (KV cache type, drafting and parsers are chosen at launch), serves it, and remembers your last choice. /model lists every launch this box can make, each with its runtime, weight placement and window, and switches in place. localharness model --autostart on starts the server with the harness, and localharness model --script prints the launch as a shell script. A turn survives a server restart.
  • Private by default. Memory is SQLite in your home directory, config is YAML, and the event stream, logs and bench results stay on your disk. Plugins, tool hooks and the phone app use the same event bus and public plugin API as the bundled plugins. No account, no telemetry (what start contacts); web search runs over DuckDuckGo with no key. MIT licensed.
  • Permissions. One permission gate stands in front of every tool call, helper agents included. An agent that reads untrusted content, a web page or an MCP result, is not given tools that change your machine; the check runs when an agent's tools resolve and fails closed. The endpoint, credential and allowed senders are set in machine-level config, and a cloned repository cannot change them. Threat model: SECURITY.md.

Quick start

Python 3.12 or later and uv. You do not need a running model server: the first localharness start finds a model on your machine or offers one to fetch.

uv tool install 'localharness[embeddings,mobile]'  # memory's CPU model + the phone app's dependencies (`plugins enable mobile` turns it on)
localharness start                   # finds a model (or offers one), sets up, opens a 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
localharness update                  # the latest release from PyPI

plugins enable and plugins disable write overrides.yaml and leave your config.yaml alone; --workspace changes a bundled plugin for one project only. Inside a session, /plugins enable <name> asks what the plugin needs, checks it, and restarts with your conversation kept. Keyboard shortcuts and multi-line input: docs/terminal-keys.md.

What agents can do

Agents are YAML. The built-in tools are read, write, edit, glob, grep, bash, python, web search and fetch, delegation to helper agents, and MCP servers, so a session works as a coding agent or a research agent. Drive it from the terminal, from Zed (localharness acp), from your phone on your own network (localharness mobile) or from Discord (--channel discord). With a vision model, drop a screenshot on the terminal, paste one into Zed or the phone page, or attach one on Discord.

Supported runtimes

Point it at vLLM, llama.cpp, Ollama or LM Studio; the agents, tools, permission gate and plugins are the same on all four. Every runtime is reached through one OpenAI-compatible client, and init can attach to an endpoint that is already running. Live-validated means 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

A session with no temperature set sends none, so the server's sampling defaults apply; pin one on the server (llama-server's --temp, vLLM's --generation-config). Setup: llama.cpp, Ollama, LM Studio, vLLM (reference architectures); the code is the provider layer.

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 off; needs localharness[mobile] uv tool install 'localharness[mobile]' (name the other extras you use too: a reinstall keeps only the ones it names), then localharness plugins enable mobile --set public_url=<url>
memory persistent memory: facts recalled into each turn, memory tools, background consolidation on localharness plugins disable memory
dispatch chat: Discord off; needs localharness[dispatch] uv tool install 'localharness[dispatch]' (name the other extras you use too: a reinstall keeps only the ones it names), then localharness plugins enable dispatch --set discord.token=… --set discord.allow=<your user id>
autoresearch experiment loop on localharness plugins disable autoresearch
browser reads JavaScript-rendered pages through a sandboxed headless Chromium off; needs localharness[browser] uv tool install 'localharness[browser]' (name the other extras you use too: a reinstall keeps only the ones it names), then localharness plugins enable browser

Pages: image · mobile · memory · dispatch · autoresearch · browser, and on the site: image · mobile · memory · dispatch · autoresearch · browser.

Installed plugins live on your machine, not inside a project: a Python package with a localharness.plugins entry point beside LocalHarness, or a folder ~/.localharness/plugins/<name>/. None of its code is imported until localharness plugins enable <name>, which only your machine-level config can do. A plugin you turn on is trusted code that runs with your privileges: read SECURITY.md before you enable one.

Write a plugin

Copy the example plugin: one tool, one command, one slash command, one doctor check and two settings, tested in CI. The API is plugins/api.py; 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; the example plugin says how to port one.

Skills

A skill is a folder holding a SKILL.md in the open Agent Skills format: a name, a one-line description of when to use it, and a procedure. LocalHarness reads a project's .localharness/skills/ and .agents/skills/, ~/.localharness/skills/ and the bundled set. The model sees one line per skill and loads the procedure with its skill tool when a request matches. The model may not pick a skill up on its own; /<name> asks it to.

localharness skills lists what was found and why anything was skipped, and /skill-creator writes a new one with you, one approval per file. A skill is text: it grants no tool and installs nothing. A project's skills load with its config, so read them in a repository you did not write: SECURITY.md.

Status

Early stage (v0.22.0, pre-1.0). Interfaces and config schema may change without notice. Each release's known limitations are listed in the CHANGELOG.

License

MIT

Metadata

Release files for localharness 0.22.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 localharness 0.22.0
File Size Uploaded Provenance
localharness-0.22.0.tar.gz 1.8 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for localharness 0.22.0
File Interpreter ABI Platform
localharness-0.22.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.5 MB

Release files / localharness-0.22.0.tar.gz

Download URL localharness-0.22.0.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
812e37b1ec84b539a99fb2ae3a85b8d907330f71e579efb1d69dc0055f74670c
BLAKE2b-256 checksum
How to use checksums
c59564f78d2900b1a81ced68722fc023d9d71c5f4257d7fbb4fe20d488fb1c57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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":true}

Release files / localharness-0.22.0-py3-none-any.whl

Download URL localharness-0.22.0-py3-none-any.whl
Size 1.8 MB
Tags Python 3
SHA-256 checksum
How to use checksums
164e998132d6c7f306c303831b0065157daddd5496cbac98c71a2061323d40d7
BLAKE2b-256 checksum
How to use checksums
896914371d1027e261b1194a7fa3d959fe6fddb2bbd2c44c37166a0d777e6838
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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":true}

Security for localharness 0.22.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.

Release history Release notifications | RSS feed

This release

0.22.0 This release

2 release files No provenance

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