{"id":50912756,"url":"https://github.com/simonepriuli/openharness","last_synced_at":"2026-06-26T13:00:56.204Z","repository":{"id":365038310,"uuid":"1256273883","full_name":"simonepriuli/openharness","owner":"simonepriuli","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-23T12:27:13.000Z","size":4177,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T12:35:54.741Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://openharness-api.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonepriuli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-01T16:11:53.000Z","updated_at":"2026-06-23T12:27:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/simonepriuli/openharness","commit_stats":null,"previous_names":["simonepriuli/openharness"],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/simonepriuli/openharness","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepriuli%2Fopenharness","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepriuli%2Fopenharness/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepriuli%2Fopenharness/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepriuli%2Fopenharness/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonepriuli","download_url":"https://codeload.github.com/simonepriuli/openharness/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepriuli%2Fopenharness/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34817641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-16T12:00:16.628Z","updated_at":"2026-06-26T13:00:56.160Z","avatar_url":"https://github.com/simonepriuli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenHarness\n\nDesktop client for the [Pi coding agent](https://pi.dev/) harness via RPC.\n\nPi is vendored as a git submodule at [`vendor/pi`](vendor/pi) (upstream: [earendil-works/pi](https://github.com/earendil-works/pi)). OpenHarness builds and runs that copy in RPC mode—no global `pi` install required for development.\n\n## Prerequisites\n\n- Node.js **22.19+** (matches Pi)\n- [pnpm](https://pnpm.io/) 10.11+\n- A **model provider** configured in the app (recommended): **Settings → Cloud providers** or **Settings → Local providers** for API keys and local servers (OpenRouter, Anthropic, OpenAI, LM Studio, Ollama, etc.). You can also configure Pi credentials another way (see below)\n\n### Optional: your own Pi fork\n\nTo customize Pi internals, fork [earendil-works/pi](https://github.com/earendil-works/pi) on GitHub, then repoint the submodule:\n\n```bash\n# On GitHub: fork earendil-works/pi → \u003cyou\u003e/pi\ngit config -f .gitmodules submodule.vendor/pi.url https://github.com/\u003cyou\u003e/pi.git\ngit submodule sync vendor/pi\ncd vendor/pi \u0026\u0026 git remote add upstream https://github.com/earendil-works/pi.git\n```\n\nSync with upstream periodically:\n\n```bash\ncd vendor/pi\ngit fetch upstream\ngit merge upstream/main\ncd ../..\ngit add vendor/pi \u0026\u0026 git commit -m \"chore: bump vendor/pi\"\n```\n\n### Optional: global Pi on PATH\n\n`npm install -g @earendil-works/pi-coding-agent` still works as a fallback when the vendored CLI is not built.\n\nEnd users of a **packaged** OpenHarness app do not need Pi installed: the installer bundles a built Pi runtime and a standalone Node binary to run it (no second Dock icon on macOS).\n\n## Development\n\n```bash\ngit clone --recurse-submodules https://github.com/simonepriuli/openharness.git\ncd openharness\n# If you already cloned without submodules:\n# git submodule update --init --recursive\n\npnpm install   # builds Pi via postinstall unless skipped\npnpm dev\n```\n\nOn first clone, `pnpm install` runs `pnpm build:pi` unless `OPENHARNESS_SKIP_PI_BUILD=1` is set. Electron’s postinstall still requires [`.npmrc`](.npmrc) (`electron`, `esbuild` scripts).\n\nUse **Open folder** to pick a project directory, then chat with Pi.\n\nOpen **Workspace → Settings** to configure providers and Pi options.\n\n### Pi configuration (isolated by default)\n\nBy default, OpenHarness uses its **own** Pi profile (separate from a global terminal `pi` install):\n\n| | Isolated (default) | Global Pi (opt-in) |\n|--|-------------------|---------------------|\n| Config dir | App user data, e.g. `~/Library/Application Support/OpenHarness/pi/agent` on macOS | `~/.pi/agent` |\n| Sessions | Under that config dir | Shared with CLI `pi` |\n| `auth.json` | OpenHarness-only | Same as global `pi` |\n\nIn **Settings → General**, enable **Use global Pi configuration** to share `~/.pi` with the CLI. You can also **Import sessions from global Pi** without enabling full sharing.\n\nCloud provider API keys saved in **Settings → Cloud providers** are written to `auth.json` in the active config directory (never committed to git).\n\n### Model providers\n\n**Cloud providers** — **Settings → Cloud providers** for API keys (OpenRouter, Anthropic, OpenAI, Google Gemini, Groq, Mistral, DeepSeek). Keys are stored in Pi's `auth.json`.\n\n**Local providers** — **Settings → Local providers** for LM Studio, Ollama, and other OpenAI-compatible local servers. Discovered models are written to `models.json`.\n\nYou need at least one configured cloud or local provider to send messages. OpenRouter credits and usage use the management key on the OpenRouter card under **Settings → Cloud providers**.\n\n### Environment\n\n| Variable | Description |\n|----------|-------------|\n| `PI_BIN` | Path to the `pi` executable (overrides vendored and global resolution) |\n| `PI_NODE` | Node binary used to run vendored `cli.js` (default: system `node` in dev, bundled Node in packaged builds) |\n| `OPENHARNESS_ROOT` | Repo root for resolving `vendor/pi/.../cli.js` (auto-detected when unset) |\n| `OPENHARNESS_SKIP_PI_BUILD` | Set to `1` to skip Pi build during `pnpm install` |\n\n### Pi build only\n\n```bash\npnpm build:pi\n```\n\n## Workspace\n\n| Package | Description |\n|---------|-------------|\n| `apps/desktop` | Electron + React UI |\n| `packages/pi-rpc` | JSONL RPC client for `pi --mode rpc` |\n| `packages/pi-vendor` | Builds the `vendor/pi` submodule via npm |\n| `vendor/pi` | Pi monorepo submodule (agent, ai, tui, coding-agent) |\n\n## Scripts\n\n- `pnpm dev` — run desktop app in dev mode (builds Pi first)\n- `pnpm build` — build all packages\n- `pnpm build:pi` — build vendored Pi CLI only\n- `pnpm stage:pi` — copy Pi runtime into `apps/desktop/resources/pi-runtime` for packaging\n- `pnpm stage:node` — download Node.js into `apps/desktop/resources/node-runtime` for packaging\n- `pnpm dist` — stage Pi, build the app, and produce installers (macOS `.dmg`, etc.)\n- `pnpm typecheck` — TypeScript check across workspace\n\n## Distribution\n\n```bash\npnpm build:pi      # if not already built\npnpm dist          # or: pnpm --filter desktop dist:dir  (unpacked app for testing)\n```\n\nInstallers land in `apps/desktop/release/`. The bundled Pi runtime is copied from `vendor/pi` into the app’s `Resources/pi` (macOS). Configure API keys in the in-app settings (isolated profile by default), not via a separate `pi` install.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonepriuli%2Fopenharness","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonepriuli%2Fopenharness","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonepriuli%2Fopenharness/lists"}