All notable changes to OpenHarness should be recorded in this file.
The format is based on Keep a Changelog, and this project currently tracks changes in a lightweight, repository-oriented way.
- Hooks now support a
priorityfield (default0). Within an event, hooks run highest-priority first, and hooks sharing a priority keep their registration order. This lets users order, for example, a security-check hook ahead of a logging hook regardless of where each is declared in settings or contributed by plugins. edit_fileandwrite_filein the React TUI now preview a unified diff before applying file changes, let users approve once or for the rest of the session, and skip the extra prompt automatically infull_automode.
- Codex subscription requests now pass reasoning effort separately, enabling
gpt-5.5withxhigheffort instead of treatinggpt-5.5 xhighas an unsupported model name. - Telegram channel now delivers replies again under
ohmo init --no-interactiveand other configs that do not write areply_to_messagefield.TelegramConfigdeclaresreply_to_message: bool = Trueso the attribute access inTelegramChannel.sendno longer raisesAttributeErrorand outbound progress/tool-hint/final messages are sent as expected. See issue #243.
- Added a bundled
skill-creatorskill for creating, improving, and verifying OpenHarness/ohmo skills. - User-invocable skills can now be triggered directly as slash commands, with support for skill-specific arguments and model override metadata.
oh setupcan now update the API key for an already-configured API-key provider profile instead of only changing the model.oh provider edit <profile> --api-key <key>can now replace a saved profile API key, andoh provider add ... --api-key <key>can store one during profile creation.
- Built-in
nvidiaprovider profile sooh setupoffers NVIDIA NIM as a first-class OpenAI-compatible provider choice, withNVIDIA_API_KEYauth source,openai/gpt-oss-120bas the default model, and the NVIDIA NIM endpoint. - Built-in
qwenprovider profile sooh setupoffers Qwen (DashScope) as a first-class provider choice, withdashscope_api_keyauth source,qwen-plusas the default model, and the DashScope OpenAI-compatible endpoint. - Plugin tool discovery: plugins can now provide
BaseToolsubclasses in a<plugin>/tools/directory and they are auto-discovered, instantiated, and registered in the tool registry at runtime. Addtools_dirtoplugin.json(defaults to"tools"). oh --dry-runsafe preview mode for inspecting resolved runtime settings, auth state, prompt assembly, commands, skills, tools, and configured MCP servers without executing the model or tools.- Built-in
minimaxprovider profile sooh setupoffers MiniMax as a first-class provider choice, withMINIMAX_API_KEYauth source,MiniMax-M2.7as the default model, andMiniMax-M2.7-highspeedin the model picker. - Docker as an alternative sandbox backend (
sandbox.backend = "docker") for stronger execution isolation with configurable resource limits, network isolation, and automatic image management. - Built-in
geminiprovider profile sooh setupoffers Google Gemini as a first-class provider choice, withgemini_api_keyauth source andgemini-2.5-flashas the default model. diagnoseskill: trace agent run failures and regressions using structured evidence from run artifacts.- OpenAI-compatible API client (
--api-format openai) supporting any provider that implements the OpenAI/v1/chat/completionsformat, including Alibaba DashScope, DeepSeek, GitHub Models, Groq, Together AI, Ollama, and more. OPENHARNESS_API_FORMATenvironment variable for selecting the API format.OPENAI_API_KEYfallback when using OpenAI-format providers.- GitHub Actions CI workflow for Python linting, tests, and frontend TypeScript checks.
CONTRIBUTING.mdwith local setup, validation commands, and PR expectations.docs/SHOWCASE.mdwith concrete OpenHarness usage patterns and demo commands.- GitHub issue templates and a pull request template.
- React TUI assistant messages now render structured Markdown blocks, including headings, lists, code fences, blockquotes, links, and tables.
- Built-in
codexoutput style for compact, low-noise transcript rendering in React TUI.
-
Subprocess teammate spawn (
agenttool,task_create) now works on Windows under Git Bash.subprocess_backend.spawnbuilds a direct-execargvlist and passes it through newargv=andenv=kwargs onBackgroundTaskManager.create_agent_task/create_shell_task;_start_processthen runs the executable viaasyncio.create_subprocess_exec(*argv)with no shell in between. Previously the spawn command was a single string interpreted bybash -lc, which on Windows could not reliably exec a Windows-pathed Python interpreter (e.g.C:\Users\...\python.exe) — Git Bash's escape parser consumed the backslashes from the embedded env-prefix and, even with proper quoting, bash launched viaasyncio.create_subprocess_execreturnedcommand not foundfor Windows-pathed binaries that worked perfectly when invoked interactively. Bypassing the shell sidesteps the entire class of cross-platform quoting and path-translation hazard. The legacy shell-evaluatedcommand=path is preserved for callers (e.g.BashTool) that legitimately want shell semantics. See issue #230. -
Bundled skill loader now uses
yaml.safe_loadfor SKILL.md frontmatter, matching the user-skill loader. The shared parser is extracted toopenharness.skills._frontmatterso bundled and user skills handle YAML block scalars (>,|), quoted values, and other standard YAML constructs the same way. -
Compaction now detects llama.cpp/OpenAI-compatible context overflow errors, accounts for image blocks in auto-compact token estimates, and strips image payloads from summarizer-only compaction requests.
-
Large tool results are now bounded in conversation history: oversized outputs are saved under
tool_artifacts, old MCP results become microcompactable, and context collapse trims stale tool-result payloads. -
ohmo now keeps personal memory isolated from OpenHarness project memory:
/memoryin ohmo sessions targets the ohmo workspace memory store, and ohmo runtime prompt refreshes no longer inject project memory unless explicitly requested. -
Fixed
globandgreptools hanging indefinitely when thergsubprocess produced enough stderr output to fill the OS pipe buffer.stderris now redirected toDEVNULLso it is discarded rather than blocking the child process. -
Fixed
bash_toolhanging after a timed-out command when the subprocess stdout stream stayed open._read_remaining_outputnow applies a 2-secondasyncio.wait_fortimeout so the tool always returns promptly. -
Fixed
session_runnerbackground task deadlock caused by an unreadstderr=PIPEstream. The subprocess now usesstderr=STDOUTso all output merges into the single readable stdout pipe. -
React TUI prompt input now treats the raw DEL byte (
0x7f) as backward delete while preserving true forward-delete escape sequences, fixing backspace failures seen in some macOS terminal environments. -
todo_writetool now updates an existing unchecked item in-place whenchecked=Trueinstead of appending a duplicate[x]line. -
Built-in
Exploreandclaude-code-guideagents no longer hard-codemodel="haiku", which caused them to fail for users on non-Anthropic providers (OpenAI, Bedrock, custom base URLs, etc.). Both agents now usemodel="inherit"so they run with whatever model the parent session is using.build_inherited_cli_flagsis also fixed to skip the--modelflag entirely when the value is"inherit", letting the subprocess correctly inherit the parent model via theOPENHARNESS_MODELenvironment variable instead of receiving the literal string"inherit"as a model name. -
React TUI spinner now stays visible throughout the entire agent turn:
assistant_completeno longer resetsbusystate prematurely, andtool_startedexplicitly setsbusy=trueso the status bar remains active even when tool calls follow an assistant message.line_completeis the sole signal that ends the turn and clears the spinner. -
Skill loader now uses
yaml.safe_loadto parse SKILL.md frontmatter, correctly handling YAML block scalars (>,|), quoted values, and other standard YAML constructs instead of naive line-by-line splitting. -
BackendHostConfigwas missing thecwdfield, causingAttributeError: 'BackendHostConfig' object has no attribute 'cwd'on startup whenohwas run after the runtime refactor that addedcwdsupport tobuild_runtime. -
Shell-escape
$ARGUMENTSsubstitution in command hooks to prevent shell injection from payload values containing metacharacters like$(...)or backticks. -
Swarm
_READ_ONLY_TOOLSnow uses actual registered tool names (snake_case) instead of PascalCase, fixing read-only auto-approval inhandle_permission_request. -
Memory scanner now parses YAML frontmatter (
name,description,type) instead of returning raw---as description. -
Memory search matches against body content in addition to metadata, with metadata weighted higher for relevance.
-
Memory search tokenizer handles Han characters for multilingual queries.
-
Fixed duplicate response in React TUI caused by double Enter key submission in the input handler.
-
Fixed concurrent permission modals overwriting each other in TUI default mode when the LLM returns multiple tool calls in one response;
_ask_permissionnow serialises callers via anasyncio.Lockso each modal is shown and resolved before the next one is emitted. -
Fixed React TUI Markdown tables to size columns from rendered cell text so inline formatting like code spans and bold text no longer breaks alignment.
-
Fixed grep tool crashing with
ValueError/LimitOverrunErrorwhen ripgrep outputs a line longer than 64 KB (e.g. minified assets or lock files). The asyncio subprocess stream limit is now 8 MB and oversized lines are skipped rather than terminating the session. -
Fixed React TUI exit leaving the shell prompt concatenated with the last TUI line. The terminal cleanup handler now writes a trailing newline (
\n) alongside the cursor-show escape sequence so the shell prompt always starts on a fresh line. -
Reduced React TUI redraw pressure when
output_style=codexby avoiding token-level assistant buffer flushes during streaming.
- ohmo Feishu group routing now supports managed group creation, gateway-scoped provider/model commands, and stricter group mention handling so group conversations only wake ohmo when explicitly addressed.
- Dry-run output now reports a
ready/warning/blockedreadiness verdict, concretenext_actions, likely matching skills/tools for normal prompts, and richer slash-command previews for read-only vs stateful command paths. - React TUI now groups consecutive
tool+tool_resulttranscript rows into a single compound row: success shows the result line count inline (e.g.→ 24L), errors show a red icon and up to 5 lines of error detail beneath the tool row. Standalone successful tool results are suppressed to reduce transcript noise; standalone errors are still surfaced. - README now links to contribution docs, changelog, showcase material, and provider compatibility guidance.
- README quick start now includes a one-command demo and clearer provider compatibility notes.
- README provider compatibility section updated to include OpenAI-format providers.
- Install script now links
oh,ohmo, andopenharnessinto~/.local/bininstead of prepending the virtualenvbindirectory toPATH, which avoids overriding Conda-managed shells while preserving global command discovery. - React TUI prompt now supports
Shift+Enterfor inserting a newline without submitting the current prompt. - React TUI busy-state animation is less error-prone on Windows terminals: the extra pseudo-animation line was removed, Windows now uses conservative ASCII spinner frames, and the spinner interval was slightly slowed to reduce flashing.
- Initial public release of OpenHarness.
- Core agent loop, tool registry, permission system, hooks, skills, plugins, MCP support, and terminal UI.