{"_id":"@alhazmiai/openharness","_rev":"3-8be71b6e0ec7081b9aaf87f710ed5819","name":"@alhazmiai/openharness","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@alhazmiai/openharness","version":"0.1.0","keywords":["ai","cli","coding-assistant","llm","anthropic","claude","openai","gemini","terminal","mcp","agent"],"license":"MIT","_id":"@alhazmiai/openharness@0.1.0","maintainers":[{"name":"alhazmiai","email":"fhhh09@gmail.com"}],"homepage":"https://github.com/fahd09/openharness","bugs":{"url":"https://github.com/fahd09/openharness/issues"},"bin":{"oh":"dist/index.js","openharness":"dist/index.js"},"dist":{"shasum":"70f7661ceb9c8a00d52f1e9d5f162f8b11583378","tarball":"https://registry.npmjs.org/@alhazmiai/openharness/-/openharness-0.1.0.tgz","fileCount":478,"integrity":"sha512-8dbBRKe1phNACEY6joXEL949z+JflEUvhEbajUYRzh9nyk+O5PIdbi/inI1IMFq2jvFDRE5Te6ngBbbJH/8tFw==","signatures":[{"sig":"MEUCIQDrbKwUmYzCjlW127xEGmcXiUNPQk6ZX1KSlB1a9JwfhAIgaf7TBcNIW5OVECQua0Y41KxzuWCnFCZEWIRM/Fy7EFw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1434177},"type":"module","engines":{"node":">=18"},"gitHead":"e3a310181cbc776a27599e4b7210b43790273902","scripts":{"dev":"tsx watch src/index.tsx","build":"tsc && cp -r src/prompts dist/prompts","start":"tsx src/index.tsx","prepublishOnly":"npm run build"},"_npmUser":{"name":"alhazmiai","email":"fhhh09@gmail.com"},"repository":{"url":"git+https://github.com/fahd09/openharness.git","type":"git"},"_npmVersion":"11.9.0","description":"Extensible, multi-provider AI coding assistant for the terminal","directories":{},"_nodeVersion":"25.6.1","dependencies":{"ink":"^5.2.1","zod":"^3.23.0","diff":"^8.0.3","chalk":"^5.3.0","react":"^18.3.1","dotenv":"^17.3.1","fast-glob":"^3.3.2","@anthropic-ai/sdk":"^0.39.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.0.0","@types/react":"^18.3.28"},"_npmOperationalInternal":{"tmp":"tmp/openharness_0.1.0_1772807406871_0.18896693342894566","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@alhazmiai/openharness","version":"0.1.1","keywords":["ai","cli","coding-assistant","llm","anthropic","claude","openai","gemini","terminal","mcp","agent"],"license":"MIT","_id":"@alhazmiai/openharness@0.1.1","maintainers":[{"name":"alhazmiai","email":"fhhh09@gmail.com"}],"homepage":"https://github.com/fahd09/openharness","bugs":{"url":"https://github.com/fahd09/openharness/issues"},"bin":{"oh":"dist/index.js","openharness":"dist/index.js"},"dist":{"shasum":"b71327ac6ebd9fe59b7cef6ccf287e834bfe76e0","tarball":"https://registry.npmjs.org/@alhazmiai/openharness/-/openharness-0.1.1.tgz","fileCount":480,"integrity":"sha512-ViqRbyGUdchBe2LfvJ/nMKzWzGj8CuNThYYAsg0hfTkWSgyrw7j55wMiowNSBwIGCzcJ0adzE8bAgN3U2NQxJw==","signatures":[{"sig":"MEUCIFddPQiZxQw2PNO+At33ZA489ymN56Hv7Oumm+ztEd9yAiEAiaGaNREX0ceHfq1namx1mDlS2A3GwRHcGTAiw/yW63g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1719895},"type":"module","engines":{"node":">=18"},"gitHead":"5ae5bd6ca0d888615ea78cc9bea62cdd255c5d89","scripts":{"dev":"tsx watch src/index.tsx","build":"tsc && cp -r src/prompts dist/prompts","start":"tsx src/index.tsx","prepublishOnly":"npm run build"},"_npmUser":{"name":"alhazmiai","email":"fhhh09@gmail.com"},"repository":{"url":"git+https://github.com/fahd09/openharness.git","type":"git"},"_npmVersion":"11.9.0","description":"Extensible, multi-provider AI coding assistant for the terminal","directories":{},"_nodeVersion":"25.6.1","dependencies":{"ink":"^5.2.1","zod":"^3.23.0","diff":"^8.0.3","chalk":"^5.3.0","react":"^18.3.1","dotenv":"^17.3.1","fast-glob":"^3.3.2","@anthropic-ai/sdk":"^0.39.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.0.0","@types/react":"^18.3.28"},"_npmOperationalInternal":{"tmp":"tmp/openharness_0.1.1_1772808011640_0.08851744541876538","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@alhazmiai/openharness","version":"0.1.2","description":"Extensible, multi-provider AI coding assistant for the terminal","type":"module","bin":{"oh":"dist/index.js","openharness":"dist/index.js"},"scripts":{"start":"tsx src/index.tsx","dev":"tsx watch src/index.tsx","build":"tsc && cp -r src/prompts dist/prompts","prepublishOnly":"npm run build"},"keywords":["ai","cli","coding-assistant","llm","anthropic","claude","openai","gemini","terminal","mcp","agent"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/fahd09/openharness.git"},"homepage":"https://github.com/fahd09/openharness","engines":{"node":">=18"},"dependencies":{"@anthropic-ai/sdk":"^0.39.0","chalk":"^5.3.0","diff":"^8.0.3","dotenv":"^17.3.1","fast-glob":"^3.3.2","ink":"^5.2.1","react":"^18.3.1","zod":"^3.23.0"},"devDependencies":{"@types/node":"^22.0.0","@types/react":"^18.3.28","tsx":"^4.19.0","typescript":"^5.6.0"},"gitHead":"cc40f0ee3f803dc7f525ee2ea2d7394b16941a69","_id":"@alhazmiai/openharness@0.1.2","bugs":{"url":"https://github.com/fahd09/openharness/issues"},"_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-Obxhh1O2HcmyIjRcoxLdFxLKV5P/rOgPd0UL/5W4AF7+g5q/D8flSdc85T6wY/Sy3a6yng+FNpnaVVWnCDU1oQ==","shasum":"7b7f297c9ff544d4711e0359c17e7378c4521534","tarball":"https://registry.npmjs.org/@alhazmiai/openharness/-/openharness-0.1.2.tgz","fileCount":480,"unpackedSize":1719843,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIF7osyEJuo9as1ky44oEODGowGzw+g7TCxDyvF4xITTTAiEAqndVBs/9RrTj610RW+1t8CDn5l9xhERbn2YI+FwzDtM="}]},"_npmUser":{"name":"alhazmiai","email":"fhhh09@gmail.com"},"directories":{},"maintainers":[{"name":"alhazmiai","email":"fhhh09@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openharness_0.1.2_1772808233449_0.15970944757629346"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-06T14:30:06.760Z","modified":"2026-03-06T14:43:53.782Z","0.1.0":"2026-03-06T14:30:07.074Z","0.1.1":"2026-03-06T14:40:11.850Z","0.1.2":"2026-03-06T14:43:53.679Z"},"bugs":{"url":"https://github.com/fahd09/openharness/issues"},"license":"MIT","homepage":"https://github.com/fahd09/openharness","keywords":["ai","cli","coding-assistant","llm","anthropic","claude","openai","gemini","terminal","mcp","agent"],"repository":{"type":"git","url":"git+https://github.com/fahd09/openharness.git"},"description":"Extensible, multi-provider AI coding assistant for the terminal","maintainers":[{"name":"alhazmiai","email":"fhhh09@gmail.com"}],"readme":"# OpenHarness\n\nAn extensible, multi-provider AI coding assistant for the terminal. Written in TypeScript with an Ink-based UI, OpenHarness connects to Anthropic Claude, OpenAI, Google Gemini, and any OpenAI-compatible endpoint — giving you 19 built-in tools, 30+ slash commands, custom agents, lifecycle hooks, MCP integration, and a plugin system, all in a single CLI.\n\n![OpenHarness demo](docs/demo.png)\n\n## Highlights\n\n- **Multi-provider** — Switch between Anthropic, OpenAI, Gemini, or local models (Ollama, LM Studio, vLLM) with one env var\n- **19 built-in tools** — File I/O, shell execution, code search, web search/fetch, subagent tasks, notebooks, and more\n- **30+ slash commands** — Session management, model switching, diagnostics, memory, plan mode, undo, clipboard\n- **Plugin architecture** — Register tools, commands, hooks, and prompt segments through a unified `Plugin` interface\n- **6 extension mechanisms** — Skills, custom agents, hooks, MCP servers, plugins, and prompt overrides — from zero-code markdown to full TypeScript\n- **Session management** — Save, resume, search, tag, and rename conversations\n- **Smart permissions** — 4 modes (default, acceptEdits, bypassPermissions, plan) with pattern-based auto-approval\n- **Extended thinking** — Configurable thinking budgets for Claude and Gemini with toggleable display\n- **Context management** — Auto-compaction at 80% context window; manual `/compact` with preservation instructions\n- **Claude Code compatible** — Read-only import of sessions, memory, commands, MCP configs, hooks, and permissions from `~/.claude/`\n\n## Supported Providers\n\n| Provider | Models | Thinking | Caching | Local |\n|----------|--------|----------|---------|-------|\n| **Anthropic Claude** | Opus 4, Sonnet 4, Haiku 4.5 | Budget-based | Automatic | No |\n| **OpenAI** | GPT-4o, GPT-4o-mini, o1, o3 | Internal (o1/o3) | No | No |\n| **Google Gemini** | 2.5 Flash/Pro, 3 Flash/Pro, 3.1 Pro | Budget-based | No | No |\n| **OpenAI-Compatible** | Any (Ollama, LM Studio, Groq, Together, Mistral, etc.) | No | No | Yes |\n\n## Quick Start\n\n```bash\n# Install globally\nnpm install -g @alhazmiai/openharness\n\n# Set your API key\nexport ANTHROPIC_API_KEY=sk-ant-...\n# Or: export OPENAI_API_KEY=sk-...\n# Or: export GEMINI_API_KEY=...\n\n# Start the interactive REPL\noh\n\n# Or run a one-shot prompt\noh -p \"Explain this codebase\"\n```\n\n### CLI Options\n\n| Option | Description |\n|--------|-------------|\n| `-m, --model <model>` | Model alias (`opus`, `sonnet`, `haiku`) or full ID (`gpt-4o`, `gemini-2.5-flash`) |\n| `-p, --prompt <text>` | One-shot mode — run prompt and exit |\n| `--max-turns <n>` | Maximum agentic turns per interaction |\n| `--thinking-budget <n>` | Extended thinking budget in tokens (min 1024) |\n| `--permission-mode <mode>` | `default` / `acceptEdits` / `bypassPermissions` / `plan` |\n| `-r, --resume <id>` | Resume a previous session |\n| `--system-prompt <text>` | Custom system prompt override |\n| `-v, --verbose` | Show detailed token usage and costs |\n\n### Provider Selection\n\n```bash\n# Anthropic Claude (default)\noh\n\n# OpenAI\nLLM_PROVIDER=openai oh -m gpt-4o\n\n# Google Gemini\nLLM_PROVIDER=gemini oh -m gemini-2.5-flash\n\n# Local Ollama\nLLM_PROVIDER=openai-compat OPENAI_BASE_URL=http://localhost:11434/v1 oh -m llama3.2\n```\n\n## Built-in Tools\n\n| Tool | Description |\n|------|-------------|\n| `Read` | Read files (text, images, PDFs, notebooks) |\n| `Write` | Create new files |\n| `Edit` | Exact string replacement edits |\n| `Bash` | Execute shell commands |\n| `Glob` | Fast file pattern matching |\n| `Grep` | Content search via ripgrep |\n| `WebSearch` | Web search (Brave or Serper) |\n| `WebFetch` | Fetch and extract content from URLs |\n| `Task` | Spawn subagent tasks (built-in + custom agent types) |\n| `NotebookEdit` | Edit Jupyter notebook cells |\n| `TodoWrite` | Structured task tracking |\n| `EnterPlanMode` / `ExitPlanMode` | Toggle read-only plan mode |\n\nAll tools are async generators that yield `progress` (transient UI) and `result` (AI-visible) events, enabling real-time streaming output.\n\n## Slash Commands\n\n**Session:** `/exit`, `/clear`, `/sessions [query]`, `/resume [id]`, `/rename <name>`, `/tag <tag>`\n\n**Model:** `/model [name]`, `/fast`, `/thinking [on|off]`, `/output-style [mode]`, `/config`\n\n**Info:** `/help`, `/cost`, `/status`, `/diff`, `/memory`, `/doctor`, `/hooks`, `/agents`\n\n**Actions:** `/compact [instructions]`, `/plan`, `/init`, `/copy`, `/undo`, `/skills`, `/plugin`, `/feedback`, `/login`\n\n## Extension Mechanisms\n\nOpenHarness has 6 ways to extend it, from zero-code to full TypeScript:\n\n| Mechanism | Effort | What It Extends | Format |\n|-----------|--------|-----------------|--------|\n| **Skills** | Zero-code | Slash commands | Markdown files |\n| **Custom Agents** | Zero-code | Subagent types | Markdown files |\n| **Hooks** | Low-code | Lifecycle events | JSON + shell scripts |\n| **MCP Servers** | Medium | External tools | MCP protocol |\n| **Plugins** | TypeScript | Tools, commands, hooks, prompts | TypeScript modules |\n| **Prompt Overrides** | Zero-code | System prompt sections | Markdown files |\n\n### Skills\n\nCreate custom slash commands as markdown files in `~/.openharness/skills/` or `.openharness/skills/`:\n\n```markdown\n---\nname: commit\ndescription: Create a git commit with a good message\ncommand: /commit\n---\n\nCreate a git commit for the current staged changes.\nWrite a concise commit message that describes the \"why\".\n```\n\nSkills support `$ARGUMENTS` substitution, shell command preprocessing (`` !`git status` ``), forked context execution, agent delegation, tool restrictions, and once-per-session limits.\n\n### Custom Agents\n\nDefine domain-specific subagents as markdown files in `~/.openharness/agents/` or `.openharness/agents/`:\n\n```markdown\n---\nname: db-reader\ndescription: Safe database query agent\ntools: [\"Read\", \"Bash\", \"Grep\"]\ndisallowedTools: [\"Write\", \"Edit\"]\nmodel: haiku\nmaxTurns: 10\nmemory: project\n---\n\nYou are a database query specialist. Only run SELECT queries.\nNever modify data. Always explain results clearly.\n```\n\nAgents support tool restrictions, model selection, persistent memory (user/project/local scope), scoped lifecycle hooks, and fork context. Invoke them via the Task tool or list them with `/agents`.\n\n### Hooks\n\n10 lifecycle events with shell command, LLM prompt, and programmatic handlers:\n\n| Event | When | Can Block? |\n|-------|------|------------|\n| `PreToolUse` | Before tool executes | Yes (+ input modification) |\n| `PostToolUse` | After tool succeeds | Context injection |\n| `PostToolUseFailure` | After tool fails | Context injection |\n| `Stop` | Agent wants to stop | Yes (continues loop) |\n| `SubagentStop` | Subagent completes | No |\n| `Notification` | Background notification | No |\n| `UserPromptSubmit` | User submits prompt | Yes |\n| `SessionStart` / `SessionEnd` | Session lifecycle | No |\n| `PreCompact` | Before context compaction | Yes |\n\nConfigure in `hooks.json` (global or project level):\n\n```json\n[\n  {\n    \"event\": \"PreToolUse\",\n    \"command\": \"echo '{\\\"action\\\":\\\"continue\\\"}'\",\n    \"toolFilter\": [\"Bash\"]\n  },\n  {\n    \"event\": \"Stop\",\n    \"type\": \"prompt\",\n    \"prompt\": \"Are all tasks complete? Context: $ARGUMENTS\"\n  }\n]\n```\n\nThe **Stop hook** is a powerful quality gate — it prevents premature stopping by having an LLM verify task completion before the agent loop ends.\n\n**PreToolUse hooks** can modify tool input at runtime via `updatedInput`. **PostToolUse hooks** can inject additional context via `additionalContext`.\n\n### MCP (Model Context Protocol)\n\nConnect to MCP servers for extended tool capabilities. Supports stdio and SSE transports:\n\n```json\n{\n  \"servers\": {\n    \"my-server\": {\n      \"transport\": \"stdio\",\n      \"command\": \"node\",\n      \"args\": [\"./mcp-server.js\"],\n      \"enabled\": true\n    }\n  }\n}\n```\n\nTools are auto-registered as `mcp__serverName__toolName`. Configuration is discovered from multiple locations (native + Claude Code paths).\n\n### Plugins\n\nRegister tools, commands, hooks, and prompt segments through a unified interface:\n\n```typescript\nconst myPlugin: Plugin = {\n  name: \"my-plugin\",\n  version: \"1.0.0\",\n  async init(ctx) {\n    ctx.registerTool(myTool);\n    ctx.registerCommand(myCommand);\n    ctx.registerHook({ event: \"PreToolUse\", handler: myHandler });\n    ctx.registerPromptSegment({ name: \"my-context\", priority: 50, build: () => \"...\" });\n  }\n};\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `LLM_PROVIDER` | `anthropic` (default), `openai`, `openai-compat`, or `gemini` |\n| `ANTHROPIC_API_KEY` | Required for Anthropic |\n| `OPENAI_API_KEY` | Required for OpenAI |\n| `OPENAI_BASE_URL` | Custom endpoint for OpenAI-compatible providers |\n| `GEMINI_API_KEY` | Required for Gemini (alias: `GOOGLE_API_KEY`) |\n| `BRAVE_SEARCH_API_KEY` | For web search (optional) |\n| `SERPER_API_KEY` | Alternative web search provider (optional) |\n| `CLAUDE_CODE_THINKING_BUDGET` | Extended thinking token budget |\n| `CLAUDE_CODE_MAX_OUTPUT_TOKENS` | Max output tokens (default: 16384) |\n| `API_TIMEOUT_MS` | API timeout in ms (default: 600000) |\n\n### Config Files\n\n| File | Location | Purpose |\n|------|----------|---------|\n| `CLAUDE.md` | Project root | Project instructions for the AI |\n| `hooks.json` | `~/.openharness/` or `.openharness/` | Lifecycle hook handlers |\n| `mcp.json` | `~/.openharness/` or project root | MCP server configuration |\n| `settings.json` | `~/.openharness/` | Global settings |\n| `MEMORY.md` | `~/.openharness/projects/{hash}/memory/` | Persistent memory per project |\n| `*.md` | `~/.openharness/agents/` or `.openharness/agents/` | Custom agent definitions |\n| `*.md` | `~/.openharness/skills/` or `.openharness/skills/` | Custom skill commands |\n\n### Tool Permissions\n\nAuto-approve tools with pattern-based permissions in project settings:\n\n```json\n{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(npm install:*)\",\n      \"Bash(npx tsx:*)\",\n      \"WebSearch\",\n      \"WebFetch(domain:docs.example.com)\"\n    ],\n    \"deny\": []\n  }\n}\n```\n\nDeny patterns take precedence. Unmatched tools fall through to the interactive prompt.\n\n## Claude Code Compatibility\n\nOpenHarness includes a read-only compatibility layer that discovers and loads data from `~/.claude/` and `<cwd>/.claude/`:\n\n- **Sessions** — Claude Code JSONL sessions appear in `/sessions` tagged `[cc]` and can be resumed\n- **Memory** — Falls back to Claude Code memory when no native memory exists\n- **Commands** — `.claude/commands/*.md` files are loaded as slash commands\n- **MCP** — Claude Code MCP configs are merged with native configs\n- **Hooks** — Hooks from `.claude/settings.local.json` are loaded alongside native hooks\n- **Permissions** — Tool permissions from `.claude/settings.local.json` are respected\n\nAll writes stay in `~/.openharness/` — Claude Code directories are never modified.\n\n## Architecture\n\n```\nsrc/\n├── index.tsx                  # CLI entry, REPL loop, Ink UI\n├── utils.ts                   # Shared utilities\n├── plugins/                   # Registration layer (what gets loaded at startup)\n│   ├── core-prompt-plugin.ts  # System prompt segments\n│   ├── memory-plugin.ts       # /memory + memory prompt\n│   ├── commands-plugin.ts     # All slash commands\n│   └── skills-plugin.ts       # Skill loading + /skills\n├── commands/                  # Slash command implementations\n├── tools/                     # Tool implementations (async generators)\n├── prompt/                    # Prompt assembly with cache hints\n├── prompts/                   # Overridable markdown templates\n├── core/\n│   ├── agent-loop.ts          # Main conversation loop\n│   ├── hooks.ts               # 10 lifecycle event hooks\n│   ├── session.ts             # Session persistence\n│   ├── context.ts             # Context management, compaction\n│   ├── providers/             # LLM providers (Anthropic, OpenAI, Gemini)\n│   ├── plugins/               # Plugin framework\n│   └── mcp/                   # MCP client\n├── ui/                        # Ink terminal UI components\n├── completions/               # Shell completions (bash, zsh, fish)\n└── lib/                       # Utilities (diff, spinner)\n```\n\n### Key Design Decisions\n\n- **Anthropic-shaped internals** — All message types follow the Anthropic SDK format. Other providers translate at the API boundary.\n- **Async generator tools** — Tools yield `progress` and `result` events, enabling real-time streaming UI.\n- **No build step for dev** — `tsx` runs TypeScript directly during development. `tsc` compiles to `dist/` for npm distribution.\n- **Zero-dependency rendering** — Syntax highlighting, markdown tables, hyperlinks, and diffs are all built-in with chalk.\n- **Plugin registration layer** — Plugins orchestrate startup loading. Implementation lives in dedicated directories (`commands/`, `tools/`, `core/`).\n\n## Development\n\n```bash\ngit clone https://github.com/fahd09/openharness.git\ncd openharness\nnpm install\ncp .env.example .env   # Add your API key(s)\n\nnpm start              # Interactive REPL\nnpm run dev            # Watch mode (tsx watch)\nnpm start -- -p \"...\"  # One-shot mode\nnpm run build          # Compile to dist/\nnpx tsc --noEmit       # Type-check\n```\n\n## Requirements\n\n- **Node.js 18+**\n- API key for at least one provider\n- **ripgrep** (`rg`) — required for the Grep tool\n- **git** — required for repo operations\n\n### Recommended Tools\n\n```bash\n# macOS\nbrew install ripgrep fd fzf jq gh ast-grep\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}