@zhijiewang/openharness 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,741 +1,741 @@
1
- <p align="center">
2
- <img src="assets/logo-256.png" alt="openHarness logo" width="128" />
3
- </p>
4
-
5
- # OpenHarness
6
-
7
- ```
8
- ___
9
- / \
10
- ( ) ___ ___ ___ _ _ _ _ _ ___ _ _ ___ ___ ___
11
- `~w~` / _ \| _ \| __| \| | || | /_\ | _ \ \| | __/ __/ __|
12
- (( )) | (_) | _/| _|| .` | __ |/ _ \| / .` | _|\__ \__ \
13
- ))(( \___/|_| |___|_|\_|_||_/_/ \_\_|_\_|\_|___|___/___/
14
- (( ))
15
- `--`
16
- ```
17
-
18
- AI coding agent in your terminal. Works with any LLM -- free local models or cloud APIs.
19
-
20
- <p align="center">
21
- <img src="assets/openharness_v0.11.1_4.gif" alt="OpenHarness demo" width="800" />
22
- </p>
23
-
24
- [![npm version](https://img.shields.io/npm/v/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![npm downloads](https://img.shields.io/npm/dm/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![license](https://img.shields.io/npm/l/@zhijiewang/openharness)](LICENSE) ![tests](https://img.shields.io/badge/tests-624-brightgreen) ![tools](https://img.shields.io/badge/tools-35-blue) ![Node.js 18+](https://img.shields.io/badge/node-18%2B-green) ![TypeScript](https://img.shields.io/badge/typescript-strict-blue) [![GitHub stars](https://img.shields.io/github/stars/zhijiewong/openharness)](https://github.com/zhijiewong/openharness) [![GitHub issues](https://img.shields.io/github/issues-raw/zhijiewong/openharness)](https://github.com/zhijiewong/openharness/issues) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://github.com/zhijiewong/openharness/pulls)
25
-
26
- ---
27
-
28
- ## Table of Contents
29
-
30
- - [Quick Start](#quick-start)
31
- - [Why OpenHarness?](#why-openharness)
32
- - [Terminal UI](#terminal-ui)
33
- - [Tools (35)](#tools-35)
34
- - [Slash Commands (33)](#slash-commands-33)
35
- - [Permission Modes](#permission-modes)
36
- - [Hooks](#hooks)
37
- - [Checkpoints & Rewind](#checkpoints--rewind)
38
- - [Agent Roles](#agent-roles)
39
- - [Headless Mode & CI/CD](#headless-mode)
40
- - [Cybergotchi](#cybergotchi)
41
- - [MCP Servers](#mcp-servers)
42
- - [Providers](#providers)
43
- - [FAQ](#faq)
44
- - [Install](#install)
45
- - [Development](#development)
46
- - [Contributing](#contributing)
47
- - [Community](#community)
48
-
49
- ---
50
-
51
- ## Quick Start
52
-
53
- ```bash
54
- npm install -g @zhijiewang/openharness
55
- oh
56
- ```
57
-
58
- That's it. OpenHarness auto-detects Ollama and starts chatting. No API key needed.
59
-
60
- ```bash
61
- oh init # interactive setup wizard (provider + cybergotchi)
62
- oh # auto-detect local model
63
- oh --model ollama/qwen2.5:7b # specific model
64
- oh --model gpt-4o # cloud model (needs OPENAI_API_KEY)
65
- oh --trust # auto-approve all tool calls
66
- oh --auto # auto-approve, block dangerous bash
67
- oh -p "fix the tests" --trust # headless mode (single prompt, exit)
68
- oh run "review code" --json # CI/CD with JSON output
69
- ```
70
-
71
- **In-session commands:**
72
- ```
73
- /rewind # undo last AI file change (checkpoint restore)
74
- /roles # list agent specializations
75
- /vim # toggle vim mode
76
- Ctrl+O # flush transcript to scrollback for review
77
- ```
78
-
79
- ## Why OpenHarness?
80
-
81
- Most AI coding agents are locked to one provider or cost $20+/month. OpenHarness works with any LLM -- run it free with Ollama on your own machine, or connect to any cloud API. Every AI edit is git-committed and reversible with `/undo`.
82
-
83
- | | OpenHarness | Claude Code | Aider | OpenCode |
84
- |---|---|---|---|---|
85
- | Any LLM | Yes (Ollama, OpenAI, Anthropic, OpenRouter, any OpenAI-compatible) | Anthropic only | Yes | Yes |
86
- | Free local models | Ollama native | No | Yes | Yes |
87
- | Tools | 35 with permission gates | 43+ | File-focused | 20+ |
88
- | Permission modes | 7 (ask, trust, deny, acceptEdits, plan, auto, bypass) | 7 | Basic | Basic |
89
- | Git integration | Auto-commit + /undo + /rewind checkpoints | Yes | Deep git | Basic |
90
- | Slash commands | 30+ built-in | 80+ | Some | Some |
91
- | Headless/CI mode | `oh -p "prompt"` or `oh run --json` | Yes | Yes | Yes |
92
- | GitHub Action | Built-in PR review action | Yes | No | No |
93
- | Agent roles | 6 specializations (reviewer, tester, debugger...) | Yes | No | No |
94
- | Vim mode | hjkl, w/b/e, 0/$, x, d, i/a/I/A/o | Full vim | No | No |
95
- | Prompt caching | Anthropic cache_control | Yes | No | No |
96
- | Bash security | AST-based command analysis | AST analysis | No | No |
97
- | Companion | Cybergotchi virtual pet | Basic | No | No |
98
- | Terminal UI | Sequential renderer (Ink pattern) | React + Ink | Basic | BubbleTea |
99
- | Language | TypeScript | TypeScript | Python | Go |
100
- | License | MIT | Proprietary | Apache 2.0 | MIT |
101
- | Price | Free (BYOK) | $20+/month | Free (BYOK) | Free (BYOK) |
102
-
103
- ## Terminal UI
104
-
105
- OpenHarness features a sequential terminal renderer inspired by Ink/Claude Code's default mode. Completed messages flush to native scrollback (scrollable), while the live area (streaming, spinner, input) rewrites in-place using relative cursor movement.
106
-
107
- ### Keybindings
108
-
109
- | Key | Action |
110
- |-----|--------|
111
- | `Enter` | Submit prompt |
112
- | `Alt+Enter` | Insert newline (multi-line input) |
113
- | `↑` / `↓` | Navigate input history |
114
- | `Ctrl+C` | Cancel current request / exit |
115
- | `Ctrl+A` / `Ctrl+E` | Jump to start / end of input |
116
- | `Ctrl+O` | Toggle thinking block expansion |
117
- | `Ctrl+K` | Toggle code block expansion in messages |
118
- | `Tab` | Autocomplete slash commands / file paths / cycle tool outputs |
119
- | `/vim` | Toggle Vim mode (normal/insert) |
120
-
121
- Scrolling is handled by the terminal's native scrollbar. Completed messages flow into the terminal scrollback buffer. Use your terminal's search (e.g., `Ctrl+Shift+F` in VS Code) to search conversation history.
122
-
123
- ### Features
124
-
125
- - **Markdown rendering** — headings, code blocks, bold, italic, lists, tables, blockquotes, links
126
- - **Syntax highlighting** — keywords, strings, comments, numbers, types (JS/TS/Python/Rust/Go and 20+ languages)
127
- - **Collapsible code blocks** — blocks over 8 lines auto-collapse; `Ctrl+K` to expand all
128
- - **Collapsible thinking** — thinking blocks collapse to a one-line summary after completion; `Ctrl+O` to expand
129
- - **Shimmer spinner** — animated "Thinking" indicator with color transitions (magenta → yellow at 30s → red at 60s)
130
- - **Tool call display** — args preview, live streaming output, result summaries (line counts, elapsed time), expand/collapse with `Tab`
131
- - **Permission prompts** — bordered box with risk coloring, bold colored **Y**es/**N**o/**D**iff keys, syntax-highlighted inline diffs
132
- - **Status line** — model name, token count, cost, context usage bar (customizable via config)
133
- - **Context warning** — yellow alert when context window exceeds 75%
134
- - **Native terminal scrollbar** — completed messages flow into scrollback; use your terminal's scrollbar and search
135
- - **Multi-line input** — `Alt+Enter` for newlines; paste detection auto-inserts newlines
136
- - **Autocomplete** — slash commands and file paths with descriptions; Tab to cycle
137
- - **File path autocomplete** — Tab-completes paths with `[dir]`/`[file]` indicators
138
- - **Session browser** — `/browse` to interactively browse and resume past sessions
139
- - **Companion mascot** — animated Cybergotchi in the footer (toggle with `/companion off|on`)
140
-
141
- ### Themes
142
-
143
- ```bash
144
- oh --light # light theme for bright terminals
145
- /theme light # switch mid-session (saved automatically)
146
- /theme dark # switch back
147
- ```
148
-
149
- Theme preference is saved to `.oh/config.yaml` and persists across sessions.
150
-
151
- ### Custom Status Line
152
-
153
- Customize the status bar format in `.oh/config.yaml`:
154
-
155
- ```yaml
156
- statusLineFormat: '{model} │ {tokens} │ {cost} │ {ctx}'
157
- ```
158
-
159
- Available variables: `{model}`, `{tokens}` (input↑ output↓), `{cost}` ($X.XXXX), `{ctx}` (context usage bar). Empty sections are automatically collapsed.
160
-
161
- ## Tools (35)
162
-
163
- | Tool | Risk | Description |
164
- |------|------|-------------|
165
- | **Core** | | |
166
- | Bash | high | Execute shell commands with live streaming output (AST safety analysis) |
167
- | Read | low | Read files with line ranges, PDF support |
168
- | ImageRead | low | Read images/PDFs for multimodal analysis |
169
- | Write | medium | Create or overwrite files |
170
- | Edit | medium | Search-and-replace edits |
171
- | MultiEdit | medium | Atomic multi-file edits (all succeed or none) |
172
- | Glob | low | Find files by pattern |
173
- | Grep | low | Regex content search with context lines |
174
- | LS | low | List directory contents with sizes |
175
- | **Web** | | |
176
- | WebFetch | medium | Fetch URL content (SSRF-protected) |
177
- | WebSearch | medium | Search the web |
178
- | RemoteTrigger | high | HTTP requests to webhooks/APIs |
179
- | **Tasks** | | |
180
- | TaskCreate | low | Create structured tasks |
181
- | TaskUpdate | low | Update task status |
182
- | TaskList | low | List all tasks |
183
- | TaskGet | low | Get task details |
184
- | TaskStop | low | Stop a running task |
185
- | TaskOutput | low | Get task output |
186
- | **Agents** | | |
187
- | Agent | medium | Spawn a sub-agent (with role specialization) |
188
- | ParallelAgent | medium | Dispatch multiple agents with DAG dependencies |
189
- | SendMessage | low | Agent-to-agent peer messaging |
190
- | AskUser | low | Ask user a question with options |
191
- | **Scheduling** | | |
192
- | CronCreate | medium | Schedule recurring tasks |
193
- | CronDelete | medium | Remove scheduled tasks |
194
- | CronList | low | List all scheduled tasks |
195
- | **Planning** | | |
196
- | EnterPlanMode | low | Enter structured planning mode |
197
- | ExitPlanMode | low | Exit planning mode |
198
- | **Code Intelligence** | | |
199
- | Diagnostics | low | LSP-based code diagnostics |
200
- | NotebookEdit | medium | Edit Jupyter notebooks |
201
- | **Memory & Discovery** | | |
202
- | Memory | low | Save/list/search persistent memories |
203
- | Skill | low | Invoke a skill from .oh/skills/ |
204
- | ToolSearch | low | Find tools by description |
205
- | **Git Worktrees** | | |
206
- | EnterWorktree | medium | Create isolated git worktree |
207
- | ExitWorktree | medium | Remove a git worktree |
208
- | **Process** | | |
209
- | KillProcess | high | Stop processes by PID or name |
210
-
211
- Low-risk read-only tools auto-approve. Medium and high risk tools require confirmation in `ask` mode. Use `--trust` or `--auto` to skip prompts.
212
-
213
- ## Slash Commands (33)
214
-
215
- Type these during a chat session. Aliases: `/q` exit, `/h` help, `/c` commit, `/m` model, `/s` status.
216
-
217
- **Session:**
218
- | Command | Description |
219
- |---------|-------------|
220
- | `/clear` | Clear conversation history |
221
- | `/compact` | Compress conversation to free context |
222
- | `/export` | Export conversation to markdown |
223
- | `/history [n]` | List recent sessions; `/history search <term>` to search |
224
- | `/browse` | Interactive session browser with preview |
225
- | `/resume <id>` | Resume a saved session |
226
- | `/fork` | Fork current session |
227
-
228
- **Git:**
229
- | Command | Description |
230
- |---------|-------------|
231
- | `/diff` | Show uncommitted git changes |
232
- | `/undo` | Undo last AI commit |
233
- | `/commit [msg]` | Create a git commit |
234
- | `/log` | Show recent git commits |
235
-
236
- **Info:**
237
- | Command | Description |
238
- |---------|-------------|
239
- | `/help` | Show all available commands (categorized) |
240
- | `/cost` | Show session cost and token usage |
241
- | `/status` | Show model, mode, git branch, MCP servers |
242
- | `/config` | Show configuration |
243
- | `/files` | List files in context |
244
- | `/model <name>` | Switch model mid-session |
245
- | `/memory` | View and search memories |
246
-
247
- **Settings:**
248
- | Command | Description |
249
- |---------|-------------|
250
- | `/theme dark\|light` | Switch theme (saved to config) |
251
- | `/vim` | Toggle Vim mode |
252
- | `/companion off\|on` | Toggle companion visibility |
253
-
254
- **AI:**
255
- | Command | Description |
256
- |---------|-------------|
257
- | `/plan <task>` | Enter plan mode |
258
- | `/review` | Review recent code changes |
259
-
260
- **Pet:**
261
- | Command | Description |
262
- |---------|-------------|
263
- | `/cybergotchi` | Feed, pet, rest, status, rename, or reset your companion |
264
-
265
- ## Permission Modes
266
-
267
- Control how aggressively OpenHarness auto-approves tool calls:
268
-
269
- | Mode | Flag | Behavior |
270
- |------|------|----------|
271
- | `ask` | `--permission-mode ask` | Prompt for medium/high risk operations (default) |
272
- | `trust` | `--trust` | Auto-approve everything |
273
- | `deny` | `--deny` | Only allow low-risk read-only operations |
274
- | `acceptEdits` | `--permission-mode acceptEdits` | Auto-approve file edits, ask for Bash/WebFetch/Agent |
275
- | `plan` | `--permission-mode plan` | Read-only mode — block all write operations |
276
- | `auto` | `--auto` | Auto-approve all, block dangerous bash (AST-analyzed) |
277
- | `bypassPermissions` | `--permission-mode bypassPermissions` | Approve everything unconditionally (CI only) |
278
-
279
- Bash commands are analyzed by a lightweight AST parser that detects destructive patterns (`rm -rf`, `git push --force`, `curl | bash`, etc.) and adjusts risk level accordingly.
280
-
281
- Set permanently in `.oh/config.yaml`: `permissionMode: 'acceptEdits'`
282
-
283
- ## Hooks
284
-
285
- Run shell scripts automatically at key session events by adding a `hooks` block to `.oh/config.yaml`:
286
-
287
- ```yaml
288
- hooks:
289
- - event: sessionStart
290
- command: "echo 'Session started' >> ~/.oh/session.log"
291
-
292
- - event: preToolUse
293
- command: "scripts/check-tool.sh"
294
- match: Bash # optional: only trigger for this tool name
295
-
296
- - event: postToolUse
297
- command: "scripts/after-tool.sh"
298
-
299
- - event: sessionEnd
300
- command: "scripts/cleanup.sh"
301
- ```
302
-
303
- **Event types:**
304
- - `sessionStart` — fires once when the session begins
305
- - `preToolUse` — fires before each tool call; **exit code 1 blocks the tool** and returns an error to the model
306
- - `postToolUse` — fires after each tool call completes
307
- - `sessionEnd` — fires when the session ends
308
-
309
- **Environment variables** available to hook scripts:
310
-
311
- | Variable | Description |
312
- |----------|-------------|
313
- | `OH_EVENT` | Event type (`sessionStart`, `preToolUse`, etc.) |
314
- | `OH_TOOL_NAME` | Name of the tool being called (tool events only) |
315
- | `OH_TOOL_ARGS` | JSON-encoded tool arguments (tool events only) |
316
- | `OH_TOOL_OUTPUT` | JSON-encoded tool output (`postToolUse` only) |
317
-
318
- Use `match` to restrict a hook to a specific tool name (e.g., `match: Bash` only triggers for the Bash tool).
319
-
320
- ## Cybergotchi
321
-
322
- OpenHarness ships with a Tamagotchi-style companion that lives in the side panel. It reacts to your session in real time — celebrating streaks, complaining when tools fail, and getting hungry if you ignore it.
323
-
324
- **Hatch one:**
325
- ```
326
- oh init # wizard includes cybergotchi setup
327
- /cybergotchi # or hatch mid-session
328
- ```
329
-
330
- **Commands:**
331
- ```
332
- /cybergotchi feed # +30 hunger
333
- /cybergotchi pet # +20 happiness
334
- /cybergotchi rest # +40 energy
335
- /cybergotchi status # show needs + lifetime stats
336
- /cybergotchi rename # give it a new name
337
- /cybergotchi reset # start over with a new species
338
- ```
339
-
340
- **Needs** decay over time (hunger fastest, happiness slowest). Feed and pet your gotchi to keep it happy.
341
-
342
- **Evolution** — your gotchi evolves based on lifetime milestones:
343
- - Stage 1 (✦ magenta): 10 sessions or 50 commits
344
- - Stage 2 (★ yellow + crown): 100 tasks completed or a 25-tool streak
345
-
346
- **18 species** to choose from: duck, cat, owl, penguin, rabbit, turtle, snail, octopus, axolotl, cactus, mushroom, chonk, capybara, goose, and more.
347
-
348
- ## MCP Servers
349
-
350
- Connect any MCP (Model Context Protocol) server by editing `.oh/config.yaml`:
351
-
352
- ```yaml
353
- provider: anthropic
354
- model: claude-sonnet-4-6
355
- permissionMode: ask
356
- mcpServers:
357
- - name: filesystem
358
- command: npx
359
- args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
360
- - name: github
361
- command: npx
362
- args: ["-y", "@modelcontextprotocol/server-github"]
363
- env:
364
- GITHUB_PERSONAL_ACCESS_TOKEN: ghp_...
365
- ```
366
-
367
- MCP tools appear alongside built-in tools. `/status` shows connected servers.
368
-
369
- **MCP Server Registry** — browse and install from a curated catalog:
370
-
371
- ```
372
- /mcp-registry # browse all available servers
373
- /mcp-registry github # show install config for a specific server
374
- /mcp-registry database # search by category
375
- ```
376
-
377
- Categories: filesystem, git, database, api, search, productivity, dev-tools, ai.
378
-
379
- ## Git Integration
380
-
381
- OpenHarness auto-commits AI edits in git repos:
382
-
383
- ```
384
- oh: Edit src/app.ts # auto-committed with "oh:" prefix
385
- oh: Write tests/app.test.ts
386
- ```
387
-
388
- - Every AI file change is committed automatically
389
- - `/undo` reverts the last AI commit (only OH commits, never yours)
390
- - `/diff` shows what changed
391
- - Your dirty files are safe — committed separately before AI edits
392
-
393
- ## Checkpoints & Rewind
394
-
395
- Every file modification is automatically checkpointed before execution. If something goes wrong:
396
-
397
- ```
398
- /rewind # restore files from the last checkpoint
399
- /undo # revert the last AI git commit
400
- ```
401
-
402
- Checkpoints are stored in `.oh/checkpoints/` and cover FileWrite, FileEdit, and Bash commands that modify files.
403
-
404
- ## Verification Loops
405
-
406
- After every file edit (Edit, Write, MultiEdit), openHarness automatically runs language-appropriate lint/typecheck commands and feeds the results back into the agent context. This is the single highest-impact harness engineering pattern — research shows 2-3x quality improvement from automated feedback.
407
-
408
- **Auto-detection** — if your project has `tsconfig.json`, `.eslintrc*`, `pyproject.toml`, `go.mod`, or `Cargo.toml`, verification rules are detected automatically. No configuration needed.
409
-
410
- **Custom rules** via `.oh/config.yaml`:
411
-
412
- ```yaml
413
- verification:
414
- enabled: true # default: true (auto-detect)
415
- mode: warn # 'warn' appends to output, 'block' marks as error
416
- rules:
417
- - extensions: [".ts", ".tsx"]
418
- lint: "npx tsc --noEmit 2>&1 | head -20"
419
- timeout: 15000
420
- - extensions: [".py"]
421
- lint: "ruff check {file} 2>&1 | head -10"
422
- ```
423
-
424
- The agent sees `[Verification passed]` or `[Verification FAILED]` with the linter output after each edit, enabling self-correction.
425
-
426
- ## Memory Consolidation
427
-
428
- On session exit, openHarness automatically prunes stale memories using temporal decay:
429
-
430
- - Memories not accessed in 30+ days lose 0.1 relevance per 30-day period
431
- - Memories below 0.1 relevance are permanently deleted
432
- - Updated relevance scores are persisted to memory files
433
-
434
- This keeps the memory system lean and relevant. Configure in `.oh/config.yaml`:
435
-
436
- ```yaml
437
- memory:
438
- consolidateOnExit: true # default: true
439
- ```
440
-
441
- ## Scheduled Tasks (Cron)
442
-
443
- Create recurring tasks that run automatically in the background:
444
-
445
- ```
446
- # Via slash commands
447
- /cron list # show all scheduled tasks
448
- /cron create "check-tests" # create a new task (interactive)
449
- /cron delete <id> # remove a task
450
- ```
451
-
452
- **Schedule syntax:** `every 5m`, `every 2h`, `every 1d`
453
-
454
- The cron executor checks every 60 seconds for due tasks and runs them via sub-queries. Results are stored in `~/.oh/crons/history/`.
455
-
456
- ## Agent Roles
457
-
458
- Dispatch specialized sub-agents for focused tasks:
459
-
460
- ```
461
- /roles # list all available roles
462
- ```
463
-
464
- | Role | Description | Tools |
465
- |------|-------------|-------|
466
- | `code-reviewer` | Find bugs, security issues, style problems | Read-only |
467
- | `test-writer` | Generate unit and integration tests | Read + Write |
468
- | `docs-writer` | Write documentation and comments | Read + Write + Edit |
469
- | `debugger` | Systematic bug investigation | Read-only + Bash |
470
- | `refactorer` | Simplify code without changing behavior | All file tools + Bash |
471
- | `security-auditor` | OWASP, injection, secrets, CVE scanning | Read-only + Bash |
472
- | `evaluator` | Evaluate code quality and run tests (read-only) | Read-only + Bash + Diagnostics |
473
- | `planner` | Design step-by-step implementation plans | Read-only + Bash |
474
- | `architect` | Analyze architecture and design structural changes | Read-only |
475
- | `migrator` | Systematic codebase migrations and upgrades | All file tools + Bash |
476
-
477
- Each role restricts the sub-agent to only its suggested tools. You can also pass `allowed_tools` explicitly:
478
-
479
- ```
480
- Agent({ subagent_type: 'evaluator', prompt: 'Run all tests and report results' })
481
- Agent({ allowed_tools: ['Read', 'Grep'], prompt: 'Search for all TODO comments' })
482
- ```
483
-
484
- ## Headless Mode
485
-
486
- Run a single prompt without interactive UI — perfect for CI/CD and scripting:
487
-
488
- ```bash
489
- # Chat command with -p flag (recommended)
490
- oh -p "fix the failing tests" --model ollama/llama3 --trust
491
- oh -p "review src/query.ts" --auto --output-format json
492
-
493
- # Run command (alternative)
494
- oh run "fix the failing tests" --model ollama/llama3 --trust
495
- oh run "add error handling to api.ts" --json # JSON output
496
-
497
- # Pipe stdin
498
- cat error.log | oh run "what's wrong here?"
499
- git diff | oh run "review these changes"
500
- ```
501
-
502
- ### GitHub Action for PR Review
503
-
504
- OpenHarness includes a built-in GitHub Action for automated code review:
505
-
506
- ```yaml
507
- # .github/workflows/ai-review.yml
508
- on:
509
- pull_request:
510
- types: [opened, synchronize]
511
-
512
- jobs:
513
- review:
514
- runs-on: ubuntu-latest
515
- steps:
516
- - uses: actions/checkout@v4
517
- with:
518
- fetch-depth: 0
519
- - uses: ./.github/actions/review
520
- with:
521
- model: 'claude-sonnet-4-6'
522
- anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
523
- ```
524
-
525
- Exit code 0 on success, 1 on failure.
526
-
527
- ## Providers
528
-
529
- ```bash
530
- # Local (free, no API key needed)
531
- oh --model ollama/llama3
532
- oh --model ollama/qwen2.5:7b
533
-
534
- # Cloud
535
- OPENAI_API_KEY=sk-... oh --model gpt-4o
536
- ANTHROPIC_API_KEY=sk-ant-... oh --model claude-sonnet-4-6
537
- OPENROUTER_API_KEY=sk-or-... oh --model openrouter/meta-llama/llama-3-70b
538
-
539
- # llama.cpp / GGUF
540
- oh --model llamacpp/my-model
541
-
542
- # LM Studio
543
- oh --model lmstudio/my-model
544
- ```
545
-
546
- ### llama.cpp / GGUF (local, no Ollama needed)
547
-
548
- For direct GGUF support via `llama-server`, without the overhead of Ollama. Often faster for large models.
549
-
550
- **Prerequisites:**
551
- - Install llama.cpp: `brew install llama.cpp` or download from [github.com/ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp)
552
- - Download a GGUF model (e.g., from [HuggingFace](https://huggingface.co))
553
-
554
- **Start llama-server:**
555
- ```bash
556
- llama-server --model ./your-model.gguf --port 8080 --alias my-model
557
- ```
558
-
559
- **Configure via `oh init`:**
560
- - Run `oh init` and select "llama.cpp / GGUF" when prompted
561
-
562
- **Or configure manually** in `.oh/config.yaml`:
563
- ```yaml
564
- provider: llamacpp
565
- model: my-model
566
- baseUrl: http://localhost:8080
567
- permissionMode: ask
568
- ```
569
-
570
- **Run:**
571
- ```bash
572
- oh
573
- oh --model llamacpp/my-model
574
- oh models # list available models
575
- ```
576
-
577
- ## Configuration Hierarchy
578
-
579
- Config is loaded in layers (later overrides earlier):
580
-
581
- 1. **Global** `~/.oh/config.yaml` — default provider, model, theme for all projects
582
- 2. **Project** `.oh/config.yaml` — project-specific settings
583
- 3. **Local** `.oh/config.local.yaml` — personal overrides (gitignored)
584
-
585
- Set your default provider once globally:
586
-
587
- ```yaml
588
- # ~/.oh/config.yaml
589
- provider: ollama
590
- model: llama3
591
- permissionMode: ask
592
- theme: dark
593
- ```
594
-
595
- Then per-project configs only need what's different:
596
-
597
- ```yaml
598
- # .oh/config.yaml
599
- model: codellama # override just the model
600
- ```
601
-
602
- ## Project Rules
603
-
604
- Create `.oh/RULES.md` in any repo (or run `oh init`):
605
-
606
- ```markdown
607
- - Always run tests after changes
608
- - Use strict TypeScript
609
- - Never commit to main directly
610
- ```
611
-
612
- Rules load automatically into every session.
613
-
614
- ## Skills & Plugins
615
-
616
- ### Skills
617
-
618
- Skills are markdown files with YAML frontmatter that add reusable behaviors:
619
-
620
- ```markdown
621
- ---
622
- name: deploy
623
- description: Deploy the application to production
624
- trigger: deploy
625
- tools: [Bash, Read]
626
- ---
627
-
628
- Run the deploy script with health checks...
629
- ```
630
-
631
- **Locations** (searched in order):
632
- 1. `.oh/skills/` — project-level skills
633
- 2. `~/.oh/skills/` — global skills (available in all projects)
634
-
635
- Skills auto-trigger when the user's message contains the trigger keyword, or can be invoked explicitly with `/skill deploy`.
636
-
637
- ### Plugins
638
-
639
- Plugins are npm packages that bundle skills, hooks, and MCP servers:
640
-
641
- ```json
642
- {
643
- "name": "my-openharness-plugin",
644
- "version": "1.0.0",
645
- "skills": ["skills/deploy.md", "skills/review.md"],
646
- "hooks": {
647
- "sessionStart": "scripts/setup.sh"
648
- },
649
- "mcpServers": [
650
- { "name": "my-api", "command": "npx", "args": ["-y", "@my-org/mcp-server"] }
651
- ]
652
- }
653
- ```
654
-
655
- Save as `openharness-plugin.json` in your npm package root. Install with `npm install`, and openHarness discovers it automatically from `node_modules/`.
656
-
657
- ## How It Works
658
-
659
- ```mermaid
660
- graph LR
661
- User[User Input] --> REPL[REPL Loop]
662
- REPL --> Query[Query Engine]
663
- Query --> Provider[LLM Provider]
664
- Provider --> LLM[Ollama / OpenAI / Anthropic]
665
- LLM --> Tools[Tool Execution]
666
- Tools --> Permissions{Permission Check}
667
- Permissions -->|Approved| Execute[Run Tool]
668
- Permissions -->|Blocked| Deny[Deny & Report]
669
- Execute --> Response[Stream Response]
670
- Response --> REPL
671
- ```
672
-
673
- ## FAQ
674
-
675
- **Does it work offline?**
676
- Yes. Use Ollama with a local model — no internet or API key needed.
677
-
678
- **How much does it cost?**
679
- Free. OpenHarness is MIT licensed. You bring your own API key (BYOK) for cloud models, or use Ollama for free.
680
-
681
- **Is it safe?**
682
- Yes. 7 permission modes control what tools can do. Bash commands are analyzed by an AST parser that blocks destructive patterns (`rm -rf`, `curl | bash`, etc.). Every file change is checkpointed and reversible with `/rewind`.
683
-
684
- **Can I use it in CI/CD?**
685
- Yes. Use `oh -p "prompt" --auto` for headless execution, or the built-in GitHub Action for PR reviews.
686
-
687
- **Does it support my language/framework?**
688
- Yes. OpenHarness is language-agnostic — it reads, writes, and executes code in any language. Syntax highlighting covers 20+ languages.
689
-
690
- **How does it compare to Claude Code?**
691
- ~90% feature parity for CLI use cases. Main advantage: works with ANY LLM (not just Anthropic). See the [comparison table](#why-openharness) above.
692
-
693
- ## Install
694
-
695
- Requires **Node.js 18+**.
696
-
697
- ```bash
698
- # From npm
699
- npm install -g @zhijiewang/openharness
700
-
701
- # From source
702
- git clone https://github.com/zhijiewong/openharness.git
703
- cd openharness
704
- npm install && npm install -g .
705
- ```
706
-
707
- ## Development
708
-
709
- ```bash
710
- npm install
711
- npx tsx src/main.tsx # run in dev mode
712
- npx tsc --noEmit # type check
713
- npm test # run tests
714
- ```
715
-
716
- ### Adding a tool
717
-
718
- Create `src/tools/YourTool/index.ts` implementing the `Tool` interface with a Zod input schema, register it in `src/tools.ts`.
719
-
720
- ### Adding a provider
721
-
722
- Create `src/providers/yourprovider.ts` implementing the `Provider` interface, add a case in `src/providers/index.ts`.
723
-
724
- ## Contributing
725
-
726
- See [CONTRIBUTING.md](CONTRIBUTING.md).
727
-
728
- ## Community
729
-
730
- Join the OpenHarness community to get help, share your workflows, and discuss the future of AI coding agents!
731
-
732
- | Platform | Details & Links |
733
- | :--- | :--- |
734
- | 🟣 **Discord** | [**Join our Discord Server**](https://discord.gg/ezVrqy3qu) to chat with developers and get real-time support. |
735
- | 🔵 **Feishu / Lark** | Scan the QR code below to collaborate with the community:<br><br><img src="https://github.com/user-attachments/assets/54ade077-22ad-45d2-b38a-623464677d53" width="160" alt="Feishu Group QR Code"> |
736
- | 🟢 **WeChat** | Scan the QR code below to join our WeChat group:<br><br><img src="https://github.com/user-attachments/assets/adcf291a-9ffe-4738-8608-f46a21e18db0" width="160" alt="WeChat Group QR Code"> |
737
-
738
- ## License
739
-
740
- MIT
741
-
1
+ <p align="center">
2
+ <img src="assets/logo-256.png" alt="openHarness logo" width="128" />
3
+ </p>
4
+
5
+ # OpenHarness
6
+
7
+ ```
8
+ ___
9
+ / \
10
+ ( ) ___ ___ ___ _ _ _ _ _ ___ _ _ ___ ___ ___
11
+ `~w~` / _ \| _ \| __| \| | || | /_\ | _ \ \| | __/ __/ __|
12
+ (( )) | (_) | _/| _|| .` | __ |/ _ \| / .` | _|\__ \__ \
13
+ ))(( \___/|_| |___|_|\_|_||_/_/ \_\_|_\_|\_|___|___/___/
14
+ (( ))
15
+ `--`
16
+ ```
17
+
18
+ AI coding agent in your terminal. Works with any LLM -- free local models or cloud APIs.
19
+
20
+ <p align="center">
21
+ <img src="assets/openharness_v0.11.1_4.gif" alt="OpenHarness demo" width="800" />
22
+ </p>
23
+
24
+ [![npm version](https://img.shields.io/npm/v/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![npm downloads](https://img.shields.io/npm/dm/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![license](https://img.shields.io/npm/l/@zhijiewang/openharness)](LICENSE) ![tests](https://img.shields.io/badge/tests-624-brightgreen) ![tools](https://img.shields.io/badge/tools-35-blue) ![Node.js 18+](https://img.shields.io/badge/node-18%2B-green) ![TypeScript](https://img.shields.io/badge/typescript-strict-blue) [![GitHub stars](https://img.shields.io/github/stars/zhijiewong/openharness)](https://github.com/zhijiewong/openharness) [![GitHub issues](https://img.shields.io/github/issues-raw/zhijiewong/openharness)](https://github.com/zhijiewong/openharness/issues) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://github.com/zhijiewong/openharness/pulls)
25
+
26
+ ---
27
+
28
+ ## Table of Contents
29
+
30
+ - [Quick Start](#quick-start)
31
+ - [Why OpenHarness?](#why-openharness)
32
+ - [Terminal UI](#terminal-ui)
33
+ - [Tools (35)](#tools-35)
34
+ - [Slash Commands (33)](#slash-commands-33)
35
+ - [Permission Modes](#permission-modes)
36
+ - [Hooks](#hooks)
37
+ - [Checkpoints & Rewind](#checkpoints--rewind)
38
+ - [Agent Roles](#agent-roles)
39
+ - [Headless Mode & CI/CD](#headless-mode)
40
+ - [Cybergotchi](#cybergotchi)
41
+ - [MCP Servers](#mcp-servers)
42
+ - [Providers](#providers)
43
+ - [FAQ](#faq)
44
+ - [Install](#install)
45
+ - [Development](#development)
46
+ - [Contributing](#contributing)
47
+ - [Community](#community)
48
+
49
+ ---
50
+
51
+ ## Quick Start
52
+
53
+ ```bash
54
+ npm install -g @zhijiewang/openharness
55
+ oh
56
+ ```
57
+
58
+ That's it. OpenHarness auto-detects Ollama and starts chatting. No API key needed.
59
+
60
+ ```bash
61
+ oh init # interactive setup wizard (provider + cybergotchi)
62
+ oh # auto-detect local model
63
+ oh --model ollama/qwen2.5:7b # specific model
64
+ oh --model gpt-4o # cloud model (needs OPENAI_API_KEY)
65
+ oh --trust # auto-approve all tool calls
66
+ oh --auto # auto-approve, block dangerous bash
67
+ oh -p "fix the tests" --trust # headless mode (single prompt, exit)
68
+ oh run "review code" --json # CI/CD with JSON output
69
+ ```
70
+
71
+ **In-session commands:**
72
+ ```
73
+ /rewind # undo last AI file change (checkpoint restore)
74
+ /roles # list agent specializations
75
+ /vim # toggle vim mode
76
+ Ctrl+O # flush transcript to scrollback for review
77
+ ```
78
+
79
+ ## Why OpenHarness?
80
+
81
+ Most AI coding agents are locked to one provider or cost $20+/month. OpenHarness works with any LLM -- run it free with Ollama on your own machine, or connect to any cloud API. Every AI edit is git-committed and reversible with `/undo`.
82
+
83
+ | | OpenHarness | Claude Code | Aider | OpenCode |
84
+ |---|---|---|---|---|
85
+ | Any LLM | Yes (Ollama, OpenAI, Anthropic, OpenRouter, any OpenAI-compatible) | Anthropic only | Yes | Yes |
86
+ | Free local models | Ollama native | No | Yes | Yes |
87
+ | Tools | 35 with permission gates | 43+ | File-focused | 20+ |
88
+ | Permission modes | 7 (ask, trust, deny, acceptEdits, plan, auto, bypass) | 7 | Basic | Basic |
89
+ | Git integration | Auto-commit + /undo + /rewind checkpoints | Yes | Deep git | Basic |
90
+ | Slash commands | 30+ built-in | 80+ | Some | Some |
91
+ | Headless/CI mode | `oh -p "prompt"` or `oh run --json` | Yes | Yes | Yes |
92
+ | GitHub Action | Built-in PR review action | Yes | No | No |
93
+ | Agent roles | 6 specializations (reviewer, tester, debugger...) | Yes | No | No |
94
+ | Vim mode | hjkl, w/b/e, 0/$, x, d, i/a/I/A/o | Full vim | No | No |
95
+ | Prompt caching | Anthropic cache_control | Yes | No | No |
96
+ | Bash security | AST-based command analysis | AST analysis | No | No |
97
+ | Companion | Cybergotchi virtual pet | Basic | No | No |
98
+ | Terminal UI | Sequential renderer (Ink pattern) | React + Ink | Basic | BubbleTea |
99
+ | Language | TypeScript | TypeScript | Python | Go |
100
+ | License | MIT | Proprietary | Apache 2.0 | MIT |
101
+ | Price | Free (BYOK) | $20+/month | Free (BYOK) | Free (BYOK) |
102
+
103
+ ## Terminal UI
104
+
105
+ OpenHarness features a sequential terminal renderer inspired by Ink/Claude Code's default mode. Completed messages flush to native scrollback (scrollable), while the live area (streaming, spinner, input) rewrites in-place using relative cursor movement.
106
+
107
+ ### Keybindings
108
+
109
+ | Key | Action |
110
+ |-----|--------|
111
+ | `Enter` | Submit prompt |
112
+ | `Alt+Enter` | Insert newline (multi-line input) |
113
+ | `↑` / `↓` | Navigate input history |
114
+ | `Ctrl+C` | Cancel current request / exit |
115
+ | `Ctrl+A` / `Ctrl+E` | Jump to start / end of input |
116
+ | `Ctrl+O` | Toggle thinking block expansion |
117
+ | `Ctrl+K` | Toggle code block expansion in messages |
118
+ | `Tab` | Autocomplete slash commands / file paths / cycle tool outputs |
119
+ | `/vim` | Toggle Vim mode (normal/insert) |
120
+
121
+ Scrolling is handled by the terminal's native scrollbar. Completed messages flow into the terminal scrollback buffer. Use your terminal's search (e.g., `Ctrl+Shift+F` in VS Code) to search conversation history.
122
+
123
+ ### Features
124
+
125
+ - **Markdown rendering** — headings, code blocks, bold, italic, lists, tables, blockquotes, links
126
+ - **Syntax highlighting** — keywords, strings, comments, numbers, types (JS/TS/Python/Rust/Go and 20+ languages)
127
+ - **Collapsible code blocks** — blocks over 8 lines auto-collapse; `Ctrl+K` to expand all
128
+ - **Collapsible thinking** — thinking blocks collapse to a one-line summary after completion; `Ctrl+O` to expand
129
+ - **Shimmer spinner** — animated "Thinking" indicator with color transitions (magenta → yellow at 30s → red at 60s)
130
+ - **Tool call display** — args preview, live streaming output, result summaries (line counts, elapsed time), expand/collapse with `Tab`
131
+ - **Permission prompts** — bordered box with risk coloring, bold colored **Y**es/**N**o/**D**iff keys, syntax-highlighted inline diffs
132
+ - **Status line** — model name, token count, cost, context usage bar (customizable via config)
133
+ - **Context warning** — yellow alert when context window exceeds 75%
134
+ - **Native terminal scrollbar** — completed messages flow into scrollback; use your terminal's scrollbar and search
135
+ - **Multi-line input** — `Alt+Enter` for newlines; paste detection auto-inserts newlines
136
+ - **Autocomplete** — slash commands and file paths with descriptions; Tab to cycle
137
+ - **File path autocomplete** — Tab-completes paths with `[dir]`/`[file]` indicators
138
+ - **Session browser** — `/browse` to interactively browse and resume past sessions
139
+ - **Companion mascot** — animated Cybergotchi in the footer (toggle with `/companion off|on`)
140
+
141
+ ### Themes
142
+
143
+ ```bash
144
+ oh --light # light theme for bright terminals
145
+ /theme light # switch mid-session (saved automatically)
146
+ /theme dark # switch back
147
+ ```
148
+
149
+ Theme preference is saved to `.oh/config.yaml` and persists across sessions.
150
+
151
+ ### Custom Status Line
152
+
153
+ Customize the status bar format in `.oh/config.yaml`:
154
+
155
+ ```yaml
156
+ statusLineFormat: '{model} │ {tokens} │ {cost} │ {ctx}'
157
+ ```
158
+
159
+ Available variables: `{model}`, `{tokens}` (input↑ output↓), `{cost}` ($X.XXXX), `{ctx}` (context usage bar). Empty sections are automatically collapsed.
160
+
161
+ ## Tools (35)
162
+
163
+ | Tool | Risk | Description |
164
+ |------|------|-------------|
165
+ | **Core** | | |
166
+ | Bash | high | Execute shell commands with live streaming output (AST safety analysis) |
167
+ | Read | low | Read files with line ranges, PDF support |
168
+ | ImageRead | low | Read images/PDFs for multimodal analysis |
169
+ | Write | medium | Create or overwrite files |
170
+ | Edit | medium | Search-and-replace edits |
171
+ | MultiEdit | medium | Atomic multi-file edits (all succeed or none) |
172
+ | Glob | low | Find files by pattern |
173
+ | Grep | low | Regex content search with context lines |
174
+ | LS | low | List directory contents with sizes |
175
+ | **Web** | | |
176
+ | WebFetch | medium | Fetch URL content (SSRF-protected) |
177
+ | WebSearch | medium | Search the web |
178
+ | RemoteTrigger | high | HTTP requests to webhooks/APIs |
179
+ | **Tasks** | | |
180
+ | TaskCreate | low | Create structured tasks |
181
+ | TaskUpdate | low | Update task status |
182
+ | TaskList | low | List all tasks |
183
+ | TaskGet | low | Get task details |
184
+ | TaskStop | low | Stop a running task |
185
+ | TaskOutput | low | Get task output |
186
+ | **Agents** | | |
187
+ | Agent | medium | Spawn a sub-agent (with role specialization) |
188
+ | ParallelAgent | medium | Dispatch multiple agents with DAG dependencies |
189
+ | SendMessage | low | Agent-to-agent peer messaging |
190
+ | AskUser | low | Ask user a question with options |
191
+ | **Scheduling** | | |
192
+ | CronCreate | medium | Schedule recurring tasks |
193
+ | CronDelete | medium | Remove scheduled tasks |
194
+ | CronList | low | List all scheduled tasks |
195
+ | **Planning** | | |
196
+ | EnterPlanMode | low | Enter structured planning mode |
197
+ | ExitPlanMode | low | Exit planning mode |
198
+ | **Code Intelligence** | | |
199
+ | Diagnostics | low | LSP-based code diagnostics |
200
+ | NotebookEdit | medium | Edit Jupyter notebooks |
201
+ | **Memory & Discovery** | | |
202
+ | Memory | low | Save/list/search persistent memories |
203
+ | Skill | low | Invoke a skill from .oh/skills/ |
204
+ | ToolSearch | low | Find tools by description |
205
+ | **Git Worktrees** | | |
206
+ | EnterWorktree | medium | Create isolated git worktree |
207
+ | ExitWorktree | medium | Remove a git worktree |
208
+ | **Process** | | |
209
+ | KillProcess | high | Stop processes by PID or name |
210
+
211
+ Low-risk read-only tools auto-approve. Medium and high risk tools require confirmation in `ask` mode. Use `--trust` or `--auto` to skip prompts.
212
+
213
+ ## Slash Commands (33)
214
+
215
+ Type these during a chat session. Aliases: `/q` exit, `/h` help, `/c` commit, `/m` model, `/s` status.
216
+
217
+ **Session:**
218
+ | Command | Description |
219
+ |---------|-------------|
220
+ | `/clear` | Clear conversation history |
221
+ | `/compact` | Compress conversation to free context |
222
+ | `/export` | Export conversation to markdown |
223
+ | `/history [n]` | List recent sessions; `/history search <term>` to search |
224
+ | `/browse` | Interactive session browser with preview |
225
+ | `/resume <id>` | Resume a saved session |
226
+ | `/fork` | Fork current session |
227
+
228
+ **Git:**
229
+ | Command | Description |
230
+ |---------|-------------|
231
+ | `/diff` | Show uncommitted git changes |
232
+ | `/undo` | Undo last AI commit |
233
+ | `/commit [msg]` | Create a git commit |
234
+ | `/log` | Show recent git commits |
235
+
236
+ **Info:**
237
+ | Command | Description |
238
+ |---------|-------------|
239
+ | `/help` | Show all available commands (categorized) |
240
+ | `/cost` | Show session cost and token usage |
241
+ | `/status` | Show model, mode, git branch, MCP servers |
242
+ | `/config` | Show configuration |
243
+ | `/files` | List files in context |
244
+ | `/model <name>` | Switch model mid-session |
245
+ | `/memory` | View and search memories |
246
+
247
+ **Settings:**
248
+ | Command | Description |
249
+ |---------|-------------|
250
+ | `/theme dark\|light` | Switch theme (saved to config) |
251
+ | `/vim` | Toggle Vim mode |
252
+ | `/companion off\|on` | Toggle companion visibility |
253
+
254
+ **AI:**
255
+ | Command | Description |
256
+ |---------|-------------|
257
+ | `/plan <task>` | Enter plan mode |
258
+ | `/review` | Review recent code changes |
259
+
260
+ **Pet:**
261
+ | Command | Description |
262
+ |---------|-------------|
263
+ | `/cybergotchi` | Feed, pet, rest, status, rename, or reset your companion |
264
+
265
+ ## Permission Modes
266
+
267
+ Control how aggressively OpenHarness auto-approves tool calls:
268
+
269
+ | Mode | Flag | Behavior |
270
+ |------|------|----------|
271
+ | `ask` | `--permission-mode ask` | Prompt for medium/high risk operations (default) |
272
+ | `trust` | `--trust` | Auto-approve everything |
273
+ | `deny` | `--deny` | Only allow low-risk read-only operations |
274
+ | `acceptEdits` | `--permission-mode acceptEdits` | Auto-approve file edits, ask for Bash/WebFetch/Agent |
275
+ | `plan` | `--permission-mode plan` | Read-only mode — block all write operations |
276
+ | `auto` | `--auto` | Auto-approve all, block dangerous bash (AST-analyzed) |
277
+ | `bypassPermissions` | `--permission-mode bypassPermissions` | Approve everything unconditionally (CI only) |
278
+
279
+ Bash commands are analyzed by a lightweight AST parser that detects destructive patterns (`rm -rf`, `git push --force`, `curl | bash`, etc.) and adjusts risk level accordingly.
280
+
281
+ Set permanently in `.oh/config.yaml`: `permissionMode: 'acceptEdits'`
282
+
283
+ ## Hooks
284
+
285
+ Run shell scripts automatically at key session events by adding a `hooks` block to `.oh/config.yaml`:
286
+
287
+ ```yaml
288
+ hooks:
289
+ - event: sessionStart
290
+ command: "echo 'Session started' >> ~/.oh/session.log"
291
+
292
+ - event: preToolUse
293
+ command: "scripts/check-tool.sh"
294
+ match: Bash # optional: only trigger for this tool name
295
+
296
+ - event: postToolUse
297
+ command: "scripts/after-tool.sh"
298
+
299
+ - event: sessionEnd
300
+ command: "scripts/cleanup.sh"
301
+ ```
302
+
303
+ **Event types:**
304
+ - `sessionStart` — fires once when the session begins
305
+ - `preToolUse` — fires before each tool call; **exit code 1 blocks the tool** and returns an error to the model
306
+ - `postToolUse` — fires after each tool call completes
307
+ - `sessionEnd` — fires when the session ends
308
+
309
+ **Environment variables** available to hook scripts:
310
+
311
+ | Variable | Description |
312
+ |----------|-------------|
313
+ | `OH_EVENT` | Event type (`sessionStart`, `preToolUse`, etc.) |
314
+ | `OH_TOOL_NAME` | Name of the tool being called (tool events only) |
315
+ | `OH_TOOL_ARGS` | JSON-encoded tool arguments (tool events only) |
316
+ | `OH_TOOL_OUTPUT` | JSON-encoded tool output (`postToolUse` only) |
317
+
318
+ Use `match` to restrict a hook to a specific tool name (e.g., `match: Bash` only triggers for the Bash tool).
319
+
320
+ ## Cybergotchi
321
+
322
+ OpenHarness ships with a Tamagotchi-style companion that lives in the side panel. It reacts to your session in real time — celebrating streaks, complaining when tools fail, and getting hungry if you ignore it.
323
+
324
+ **Hatch one:**
325
+ ```
326
+ oh init # wizard includes cybergotchi setup
327
+ /cybergotchi # or hatch mid-session
328
+ ```
329
+
330
+ **Commands:**
331
+ ```
332
+ /cybergotchi feed # +30 hunger
333
+ /cybergotchi pet # +20 happiness
334
+ /cybergotchi rest # +40 energy
335
+ /cybergotchi status # show needs + lifetime stats
336
+ /cybergotchi rename # give it a new name
337
+ /cybergotchi reset # start over with a new species
338
+ ```
339
+
340
+ **Needs** decay over time (hunger fastest, happiness slowest). Feed and pet your gotchi to keep it happy.
341
+
342
+ **Evolution** — your gotchi evolves based on lifetime milestones:
343
+ - Stage 1 (✦ magenta): 10 sessions or 50 commits
344
+ - Stage 2 (★ yellow + crown): 100 tasks completed or a 25-tool streak
345
+
346
+ **18 species** to choose from: duck, cat, owl, penguin, rabbit, turtle, snail, octopus, axolotl, cactus, mushroom, chonk, capybara, goose, and more.
347
+
348
+ ## MCP Servers
349
+
350
+ Connect any MCP (Model Context Protocol) server by editing `.oh/config.yaml`:
351
+
352
+ ```yaml
353
+ provider: anthropic
354
+ model: claude-sonnet-4-6
355
+ permissionMode: ask
356
+ mcpServers:
357
+ - name: filesystem
358
+ command: npx
359
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
360
+ - name: github
361
+ command: npx
362
+ args: ["-y", "@modelcontextprotocol/server-github"]
363
+ env:
364
+ GITHUB_PERSONAL_ACCESS_TOKEN: ghp_...
365
+ ```
366
+
367
+ MCP tools appear alongside built-in tools. `/status` shows connected servers.
368
+
369
+ **MCP Server Registry** — browse and install from a curated catalog:
370
+
371
+ ```
372
+ /mcp-registry # browse all available servers
373
+ /mcp-registry github # show install config for a specific server
374
+ /mcp-registry database # search by category
375
+ ```
376
+
377
+ Categories: filesystem, git, database, api, search, productivity, dev-tools, ai.
378
+
379
+ ## Git Integration
380
+
381
+ OpenHarness auto-commits AI edits in git repos:
382
+
383
+ ```
384
+ oh: Edit src/app.ts # auto-committed with "oh:" prefix
385
+ oh: Write tests/app.test.ts
386
+ ```
387
+
388
+ - Every AI file change is committed automatically
389
+ - `/undo` reverts the last AI commit (only OH commits, never yours)
390
+ - `/diff` shows what changed
391
+ - Your dirty files are safe — committed separately before AI edits
392
+
393
+ ## Checkpoints & Rewind
394
+
395
+ Every file modification is automatically checkpointed before execution. If something goes wrong:
396
+
397
+ ```
398
+ /rewind # restore files from the last checkpoint
399
+ /undo # revert the last AI git commit
400
+ ```
401
+
402
+ Checkpoints are stored in `.oh/checkpoints/` and cover FileWrite, FileEdit, and Bash commands that modify files.
403
+
404
+ ## Verification Loops
405
+
406
+ After every file edit (Edit, Write, MultiEdit), openHarness automatically runs language-appropriate lint/typecheck commands and feeds the results back into the agent context. This is the single highest-impact harness engineering pattern — research shows 2-3x quality improvement from automated feedback.
407
+
408
+ **Auto-detection** — if your project has `tsconfig.json`, `.eslintrc*`, `pyproject.toml`, `go.mod`, or `Cargo.toml`, verification rules are detected automatically. No configuration needed.
409
+
410
+ **Custom rules** via `.oh/config.yaml`:
411
+
412
+ ```yaml
413
+ verification:
414
+ enabled: true # default: true (auto-detect)
415
+ mode: warn # 'warn' appends to output, 'block' marks as error
416
+ rules:
417
+ - extensions: [".ts", ".tsx"]
418
+ lint: "npx tsc --noEmit 2>&1 | head -20"
419
+ timeout: 15000
420
+ - extensions: [".py"]
421
+ lint: "ruff check {file} 2>&1 | head -10"
422
+ ```
423
+
424
+ The agent sees `[Verification passed]` or `[Verification FAILED]` with the linter output after each edit, enabling self-correction.
425
+
426
+ ## Memory Consolidation
427
+
428
+ On session exit, openHarness automatically prunes stale memories using temporal decay:
429
+
430
+ - Memories not accessed in 30+ days lose 0.1 relevance per 30-day period
431
+ - Memories below 0.1 relevance are permanently deleted
432
+ - Updated relevance scores are persisted to memory files
433
+
434
+ This keeps the memory system lean and relevant. Configure in `.oh/config.yaml`:
435
+
436
+ ```yaml
437
+ memory:
438
+ consolidateOnExit: true # default: true
439
+ ```
440
+
441
+ ## Scheduled Tasks (Cron)
442
+
443
+ Create recurring tasks that run automatically in the background:
444
+
445
+ ```
446
+ # Via slash commands
447
+ /cron list # show all scheduled tasks
448
+ /cron create "check-tests" # create a new task (interactive)
449
+ /cron delete <id> # remove a task
450
+ ```
451
+
452
+ **Schedule syntax:** `every 5m`, `every 2h`, `every 1d`
453
+
454
+ The cron executor checks every 60 seconds for due tasks and runs them via sub-queries. Results are stored in `~/.oh/crons/history/`.
455
+
456
+ ## Agent Roles
457
+
458
+ Dispatch specialized sub-agents for focused tasks:
459
+
460
+ ```
461
+ /roles # list all available roles
462
+ ```
463
+
464
+ | Role | Description | Tools |
465
+ |------|-------------|-------|
466
+ | `code-reviewer` | Find bugs, security issues, style problems | Read-only |
467
+ | `test-writer` | Generate unit and integration tests | Read + Write |
468
+ | `docs-writer` | Write documentation and comments | Read + Write + Edit |
469
+ | `debugger` | Systematic bug investigation | Read-only + Bash |
470
+ | `refactorer` | Simplify code without changing behavior | All file tools + Bash |
471
+ | `security-auditor` | OWASP, injection, secrets, CVE scanning | Read-only + Bash |
472
+ | `evaluator` | Evaluate code quality and run tests (read-only) | Read-only + Bash + Diagnostics |
473
+ | `planner` | Design step-by-step implementation plans | Read-only + Bash |
474
+ | `architect` | Analyze architecture and design structural changes | Read-only |
475
+ | `migrator` | Systematic codebase migrations and upgrades | All file tools + Bash |
476
+
477
+ Each role restricts the sub-agent to only its suggested tools. You can also pass `allowed_tools` explicitly:
478
+
479
+ ```
480
+ Agent({ subagent_type: 'evaluator', prompt: 'Run all tests and report results' })
481
+ Agent({ allowed_tools: ['Read', 'Grep'], prompt: 'Search for all TODO comments' })
482
+ ```
483
+
484
+ ## Headless Mode
485
+
486
+ Run a single prompt without interactive UI — perfect for CI/CD and scripting:
487
+
488
+ ```bash
489
+ # Chat command with -p flag (recommended)
490
+ oh -p "fix the failing tests" --model ollama/llama3 --trust
491
+ oh -p "review src/query.ts" --auto --output-format json
492
+
493
+ # Run command (alternative)
494
+ oh run "fix the failing tests" --model ollama/llama3 --trust
495
+ oh run "add error handling to api.ts" --json # JSON output
496
+
497
+ # Pipe stdin
498
+ cat error.log | oh run "what's wrong here?"
499
+ git diff | oh run "review these changes"
500
+ ```
501
+
502
+ ### GitHub Action for PR Review
503
+
504
+ OpenHarness includes a built-in GitHub Action for automated code review:
505
+
506
+ ```yaml
507
+ # .github/workflows/ai-review.yml
508
+ on:
509
+ pull_request:
510
+ types: [opened, synchronize]
511
+
512
+ jobs:
513
+ review:
514
+ runs-on: ubuntu-latest
515
+ steps:
516
+ - uses: actions/checkout@v4
517
+ with:
518
+ fetch-depth: 0
519
+ - uses: ./.github/actions/review
520
+ with:
521
+ model: 'claude-sonnet-4-6'
522
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
523
+ ```
524
+
525
+ Exit code 0 on success, 1 on failure.
526
+
527
+ ## Providers
528
+
529
+ ```bash
530
+ # Local (free, no API key needed)
531
+ oh --model ollama/llama3
532
+ oh --model ollama/qwen2.5:7b
533
+
534
+ # Cloud
535
+ OPENAI_API_KEY=sk-... oh --model gpt-4o
536
+ ANTHROPIC_API_KEY=sk-ant-... oh --model claude-sonnet-4-6
537
+ OPENROUTER_API_KEY=sk-or-... oh --model openrouter/meta-llama/llama-3-70b
538
+
539
+ # llama.cpp / GGUF
540
+ oh --model llamacpp/my-model
541
+
542
+ # LM Studio
543
+ oh --model lmstudio/my-model
544
+ ```
545
+
546
+ ### llama.cpp / GGUF (local, no Ollama needed)
547
+
548
+ For direct GGUF support via `llama-server`, without the overhead of Ollama. Often faster for large models.
549
+
550
+ **Prerequisites:**
551
+ - Install llama.cpp: `brew install llama.cpp` or download from [github.com/ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp)
552
+ - Download a GGUF model (e.g., from [HuggingFace](https://huggingface.co))
553
+
554
+ **Start llama-server:**
555
+ ```bash
556
+ llama-server --model ./your-model.gguf --port 8080 --alias my-model
557
+ ```
558
+
559
+ **Configure via `oh init`:**
560
+ - Run `oh init` and select "llama.cpp / GGUF" when prompted
561
+
562
+ **Or configure manually** in `.oh/config.yaml`:
563
+ ```yaml
564
+ provider: llamacpp
565
+ model: my-model
566
+ baseUrl: http://localhost:8080
567
+ permissionMode: ask
568
+ ```
569
+
570
+ **Run:**
571
+ ```bash
572
+ oh
573
+ oh --model llamacpp/my-model
574
+ oh models # list available models
575
+ ```
576
+
577
+ ## Configuration Hierarchy
578
+
579
+ Config is loaded in layers (later overrides earlier):
580
+
581
+ 1. **Global** `~/.oh/config.yaml` — default provider, model, theme for all projects
582
+ 2. **Project** `.oh/config.yaml` — project-specific settings
583
+ 3. **Local** `.oh/config.local.yaml` — personal overrides (gitignored)
584
+
585
+ Set your default provider once globally:
586
+
587
+ ```yaml
588
+ # ~/.oh/config.yaml
589
+ provider: ollama
590
+ model: llama3
591
+ permissionMode: ask
592
+ theme: dark
593
+ ```
594
+
595
+ Then per-project configs only need what's different:
596
+
597
+ ```yaml
598
+ # .oh/config.yaml
599
+ model: codellama # override just the model
600
+ ```
601
+
602
+ ## Project Rules
603
+
604
+ Create `.oh/RULES.md` in any repo (or run `oh init`):
605
+
606
+ ```markdown
607
+ - Always run tests after changes
608
+ - Use strict TypeScript
609
+ - Never commit to main directly
610
+ ```
611
+
612
+ Rules load automatically into every session.
613
+
614
+ ## Skills & Plugins
615
+
616
+ ### Skills
617
+
618
+ Skills are markdown files with YAML frontmatter that add reusable behaviors:
619
+
620
+ ```markdown
621
+ ---
622
+ name: deploy
623
+ description: Deploy the application to production
624
+ trigger: deploy
625
+ tools: [Bash, Read]
626
+ ---
627
+
628
+ Run the deploy script with health checks...
629
+ ```
630
+
631
+ **Locations** (searched in order):
632
+ 1. `.oh/skills/` — project-level skills
633
+ 2. `~/.oh/skills/` — global skills (available in all projects)
634
+
635
+ Skills auto-trigger when the user's message contains the trigger keyword, or can be invoked explicitly with `/skill deploy`.
636
+
637
+ ### Plugins
638
+
639
+ Plugins are npm packages that bundle skills, hooks, and MCP servers:
640
+
641
+ ```json
642
+ {
643
+ "name": "my-openharness-plugin",
644
+ "version": "1.0.0",
645
+ "skills": ["skills/deploy.md", "skills/review.md"],
646
+ "hooks": {
647
+ "sessionStart": "scripts/setup.sh"
648
+ },
649
+ "mcpServers": [
650
+ { "name": "my-api", "command": "npx", "args": ["-y", "@my-org/mcp-server"] }
651
+ ]
652
+ }
653
+ ```
654
+
655
+ Save as `openharness-plugin.json` in your npm package root. Install with `npm install`, and openHarness discovers it automatically from `node_modules/`.
656
+
657
+ ## How It Works
658
+
659
+ ```mermaid
660
+ graph LR
661
+ User[User Input] --> REPL[REPL Loop]
662
+ REPL --> Query[Query Engine]
663
+ Query --> Provider[LLM Provider]
664
+ Provider --> LLM[Ollama / OpenAI / Anthropic]
665
+ LLM --> Tools[Tool Execution]
666
+ Tools --> Permissions{Permission Check}
667
+ Permissions -->|Approved| Execute[Run Tool]
668
+ Permissions -->|Blocked| Deny[Deny & Report]
669
+ Execute --> Response[Stream Response]
670
+ Response --> REPL
671
+ ```
672
+
673
+ ## FAQ
674
+
675
+ **Does it work offline?**
676
+ Yes. Use Ollama with a local model — no internet or API key needed.
677
+
678
+ **How much does it cost?**
679
+ Free. OpenHarness is MIT licensed. You bring your own API key (BYOK) for cloud models, or use Ollama for free.
680
+
681
+ **Is it safe?**
682
+ Yes. 7 permission modes control what tools can do. Bash commands are analyzed by an AST parser that blocks destructive patterns (`rm -rf`, `curl | bash`, etc.). Every file change is checkpointed and reversible with `/rewind`.
683
+
684
+ **Can I use it in CI/CD?**
685
+ Yes. Use `oh -p "prompt" --auto` for headless execution, or the built-in GitHub Action for PR reviews.
686
+
687
+ **Does it support my language/framework?**
688
+ Yes. OpenHarness is language-agnostic — it reads, writes, and executes code in any language. Syntax highlighting covers 20+ languages.
689
+
690
+ **How does it compare to Claude Code?**
691
+ ~90% feature parity for CLI use cases. Main advantage: works with ANY LLM (not just Anthropic). See the [comparison table](#why-openharness) above.
692
+
693
+ ## Install
694
+
695
+ Requires **Node.js 18+**.
696
+
697
+ ```bash
698
+ # From npm
699
+ npm install -g @zhijiewang/openharness
700
+
701
+ # From source
702
+ git clone https://github.com/zhijiewong/openharness.git
703
+ cd openharness
704
+ npm install && npm install -g .
705
+ ```
706
+
707
+ ## Development
708
+
709
+ ```bash
710
+ npm install
711
+ npx tsx src/main.tsx # run in dev mode
712
+ npx tsc --noEmit # type check
713
+ npm test # run tests
714
+ ```
715
+
716
+ ### Adding a tool
717
+
718
+ Create `src/tools/YourTool/index.ts` implementing the `Tool` interface with a Zod input schema, register it in `src/tools.ts`.
719
+
720
+ ### Adding a provider
721
+
722
+ Create `src/providers/yourprovider.ts` implementing the `Provider` interface, add a case in `src/providers/index.ts`.
723
+
724
+ ## Contributing
725
+
726
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
727
+
728
+ ## Community
729
+
730
+ Join the OpenHarness community to get help, share your workflows, and discuss the future of AI coding agents!
731
+
732
+ | Platform | Details & Links |
733
+ | :--- | :--- |
734
+ | 🟣 **Discord** | [**Join our Discord Server**](https://discord.gg/ezVrqy3qu) to chat with developers and get real-time support. |
735
+ | 🔵 **Feishu / Lark** | Scan the QR code below to collaborate with the community:<br><br><img src="https://github.com/user-attachments/assets/54ade077-22ad-45d2-b38a-623464677d53" width="160" alt="Feishu Group QR Code"> |
736
+ | 🟢 **WeChat** | Scan the QR code below to join our WeChat group:<br><br><img src="https://github.com/user-attachments/assets/adcf291a-9ffe-4738-8608-f46a21e18db0" width="160" alt="WeChat Group QR Code"> |
737
+
738
+ ## License
739
+
740
+ MIT
741
+