Skip to content

feat(chat): show Grok chat on macOS when Herdr's session is newest - #1858

Merged
devswha merged 6 commits into
devswha:mainfrom
345ml:feat/grok-macos-chat
Oct 25, 2026
Merged

devswha merged 6 commits into
devswha:mainfrom
345ml:feat/grok-macos-chat

Conversation

@345ml

@345ml 345ml commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1387.

Summary

Grok Chat now works on macOS with the binding rule already on main (#1352). Only the source of the evidence changes:

  • Held files and executable: lsof -nPbw -a -p <pid> -FfDin, the read agy-store.ts makes, with device and inode fields added. Only numeric descriptors count as holds. The first txt entry is the executable; macOS lists mapped files such as dyld as later txt entries.
  • Home: the Grok process's own environment as the kernel keeps it (sysctl KERN_PROCARGS2, through claude-store.ts's existing darwinProcess.environment), parsed by the same grokHomeFromEnvironment as Linux's /proc/<pid>/environ. This replaces ps -E: its space-joined line cannot tell an argument or a value containing GROK_HOME= from the environment, and it would be a second child per poll.
  • Windows: unchanged, stays on Terminal.

Linux and macOS now share the held-path rules (heldSessionDir) and the binding check (reportedSessionPath), so the two platforms cannot drift.

How each point from #1387 is met

  • herdr's reported id (herdr:grok) chooses the session; a held file only confirms it. If the reported id's unique held directory is not the directory holding its updates.jsonl, the pane stays on Terminal.
  • The pane needs exactly one Grok foreground process, and its executable (first lsof txt) must pass isGrokExecutable.
  • The home comes from that process's GROK_HOME, else its HOME/.grok. A relative value fails, and the bridge's own home is never used.
  • The lookup is by exact id across groups (grokTranscriptPath). Duplicates fail closed, and symlinks are not followed.
  • herdr's session must be held and have the strictly newest write time among held events.jsonl files. A tie fails closed.
  • A held file that is deleted (lsof keeps the old path, which no longer stats), renamed (events.jsonl.old), replaced (different inode), or reported without a device or inode keeps the pane on Terminal. This holds for herdr's session and for every competing hold. An inode past 2^53 is treated as unknown.
  • lsof runs as an awaited Bun.spawn child with a 3 s timeout and a 1 MiB byte cap. Nothing uses spawnSync, and the environment read spawns no process at all.

Workflow change

.github/workflows/ci.yml: the Native macOS session identity job's fixed test list now includes ./server/grok.test.ts. On macOS, the real-process resolver scenarios already used on Linux run against real lsof and the real kernel environment. They copy bun as grok, hold the descriptors, and name the store through the child's GROK_HOME. Covered: older open sessions, an unreported /resume, duplicate ids, tied times, and unlinked, renamed or replaced files.

Docs

  • docs/grok-chat.md: platform line and the macOS evidence sources.
  • docs/guide.md and README (en, ja, ko, zh-CN): Grok chat on Linux and macOS, Windows on Terminal.
  • Changelog fragment changelog.d/grok-macos-chat.md.

Testing

  • bun test ./server/grok.test.ts on macOS 26.5 (Apple silicon): 45 pass, 0 skip. The 8 real-process scenarios run natively.
  • bun test ./server/claude-store.test.ts ./server/process-start.test.ts ./server/grok.test.ts: the macOS CI list passes.
  • Checked by hand against live Grok 1.0.52 and 1.0.60 on Apple silicon.
  • bun run typecheck and the conventions and changelog-fold tests pass.
  • bun run check fast locally: typecheck and build pass. 14 unit tests in unrelated files (agy, files, shell-agent, remote-entry, scripts/check, install-star, ci-browser) fail identically on an untouched main checkout on this Mac, so they are environmental and not caused by this PR.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: devswha/ovis
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 6e729da
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d56bd605-cfd0-496e-ac20-2e7e7292c488

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: devswha/ovis
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 8fe7da9
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e238d3b0-0493-4a0f-bd67-b6009d667f38
Commits

Reviewing files that changed from the base of the PR and between 8fe7da9 and 93b3639.

Files selected for processing: 11
  • .github/workflows/ci.yml
  • README.ja.md
  • README.ko.md
  • README.md
  • README.zh-CN.md
  • changelog.d/grok-macos-chat.md
  • docs/grok-chat.md
  • docs/guide.md
  • scripts/grok-chat-browser-qa.ts
  • server/grok-store.ts
  • server/grok.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

📝 Summary

Summary by CodeRabbit

  • New Features

    • Grok chat now supports macOS as well as Linux when the active session can be identified unambiguously.
    • Windows continues to display Grok in the terminal.
  • Documentation

    • Updated the Grok support guides and FAQs to describe macOS availability and clarify when chat is shown instead of the terminal.

Grok chat store resolution now supports macOS as well as Linux. On macOS, the resolver uses lsof and process environment evidence to validate the reported session. Tests, CI coverage, and documentation now include macOS support.

Changes: Grok macOS chat support

Layer / File(s) Summary
Process and session resolution
server/grok-store.ts
The resolver adds macOS process-environment and lsof evidence. It validates held session files and selects Herdr’s reported session only when its ID is unique and its timestamp is strictly newer than other held sessions. Linux retains /proc checks; other platforms return null.
Resolver tests and CI coverage
server/grok.test.ts, .github/workflows/ci.yml
Tests cover macOS evidence parsing, session selection, environment handling, and failure cases. The macOS CI command now runs the Grok tests.
Platform support documentation
docs/grok-chat.md, docs/guide.md, README*.md, changelog.d/grok-macos-chat.md, scripts/grok-chat-browser-qa.ts
Documentation describes macOS Grok chat support and its session conditions. Windows remains on Terminal. The browser QA skip message identifies its Linux /proc dependency.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature · Severity of issue fixed: Medium

Possibly related PRs

  • devswha/ovis#1598: Provides darwinProcess.environment, which the macOS Grok resolver uses to read the process environment.

Suggested reviewers: devswha, infowolfe, snowykr

Merge Risk: Minimal · up to 93b36

No actionable issue is established that would hold up the macOS Grok chat change; normal checks can proceed.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Linked Issues check Warning Issue #1387 requires fail-closed handling for incomplete macOS lsof evidence. grokLsofEvidence creates a record for each f line but silently omits records without a following n line. For examp… Make grokLsofEvidence return null when any f record is missing its n field or when the listing has another incomplete or malformed required record. Add a regression test where an incomplete competing hold cannot produce a chat bindi…
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the primary change: enabling Grok chat on macOS when Herdr’s session is the newest.
Description check Passed The description explains the behavior, implementation, platform differences, linked issue, documentation changes, and validation results. It uses different headings from the template, but it provides …
Out of Scope Changes check Passed The changed workflow entry, resolver tests, documentation, README updates, changelog entry, and QA skip-message update support macOS Grok chat, its fail-closed behavior, or its platform documentation.…
Docstring Coverage Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 3 files. (8 skipped: 8 …
Full details: Description check

Explanation

The description explains the behavior, implementation, platform differences, linked issue, documentation changes, and validation results. It uses different headings from the template, but it provides equivalent and complete Change and Validation content.

Full details: Out of Scope Changes check

Explanation

The changed workflow entry, resolver tests, documentation, README updates, changelog entry, and QA skip-message update support macOS Grok chat, its fail-closed behavior, or its platform documentation. No unrelated functional change is demonstrated.

Full details: Docstring Coverage

Explanation

Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 3 files. (8 skipped: 8 unsupported.)

Full details: Linked Issues check

Explanation

Issue #1387 requires fail-closed handling for incomplete macOS lsof evidence. grokLsofEvidence creates a record for each f line but silently omits records without a following n line. For example, a truncated newer competitor record can be omitted, after which reportedSessionPath can treat the reported session as newest and bind Grok chat. The macOS binding, environment source, executable check, identity checks, and tests otherwise address the issue requirements.

Resolution

Make grokLsofEvidence return null when any f record is missing its n field or when the listing has another incomplete or malformed required record. Add a regression test where an incomplete competing hold cannot produce a chat binding.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@345ml 345ml mentioned this pull request Oct 24, 2026
@devswha
devswha force-pushed the feat/grok-macos-chat branch from 93b3639 to 8e9d7f6 Compare October 25, 2026 03:35
@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Rebased onto current main 718f0e087 and pushed the reviewed follow-ups.

  • Kept main's broader fail-closed rules for renamed, deleted and replaced held files, and applied the same rules to macOS lsof evidence.
  • Added 8e9d7f609 (fix(chat): reject incomplete Grok lsof evidence): a shortened listing can no longer hide an unnamed newer descriptor and leave an older conversation visible.
  • The new regression fails on the pre-fix rebased tree, where it returns the old transcript.

Verification:

  • Linux: HERDR_TEST_MODE=unit bun test ./server/grok.test.ts — 53 pass, 0 fail.
  • macOS fresh clone: the same suite — 53 pass, 0 fail, including real lsof and kernel environment reads.
  • bun run check fast — 6,733 pass, 0 fail, 13 skip; workflow syntax, generated files, typecheck and build all pass.
  • Independent binding audit: approved; exact Herdr ID, duplicate/newer/tied holds and malformed/incomplete evidence all fail closed.

Review prepared with a code-review agent and checked against the code. The merge decision stays with the maintainer's merge pass.

@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Merge pass gate review (Astra, gpt-6-astra) of 8e9d7f6: changes requested. The maintainer approved merging this once it passes review. It touches .github/workflows/ci.yml and a session-binding check, so it gets the full gate. The full report is .omo/evidence/pr1858-gate-review.md in the merge pass worktree.

What holds:

Blocking:

  1. A truncated lsof filename still fails open (server/grok-store.ts:156-183, :104-113). The fix in 8e9d7f6 handles a record whose name is missing, but not one cut off mid-name. A listing that ends in n/fixture hides a newer competing hold, so the older reported transcript binds anyway. This reproduces through the real resolver with boundary mocks. Needed: reject any lsof output whose last record isn't fully framed, for example by checking the trailing NUL or newline of the -F output. Add a test for a name truncated mid-record.
  2. PID reuse can bind another Grok process (server/grok-store.ts:231-260). Foreground membership is checked once. After that, lsof and environment evidence for that numeric PID are accepted without checking that it's still the same process, for example by its start time. In a modelled replacement Grok using the same custom session ID, the replacement's store bound to the original pane. A real PID reuse wasn't forced. Needed: check that the process is the same one, using its start time (sysctl KERN_PROC / ps -o lstart), before and after the evidence is read. If the Claude macOS resolver already accepts this exact window, please say so and point to it: matching that precedent is acceptable.
  3. The guide names the wrong reader (docs/guide.md:166). It says macOS uses ps, but the code reads the environment through sysctl KERN_PROCARGS2 (server/grok-store.ts:237, as server/claude-store.ts:241-252 does).

Once these are fixed, the merge pass rechecks the new commits only.

345ml and others added 5 commits October 26, 2026 00:53
macOS reads lsof and ps for the binding rule already on main. Herdr's
reported session must be held and strictly newer than every other held
events file. Windows stays on the terminal view.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…eams

Both platforms now classify a held path through one heldSessionDir, so
the deleted/renamed/three-part rules live in one place. resolveGrokStore
takes a plain platform argument like claude-store, and tests spy on
paneProcessInfo and Bun.spawn instead of an injected lookup. lsof and ps
run through one hostOutput with the timeout and output cap, and the
lsof parser is shorter. The held-file checks run before the store walk,
which no longer happens when the evidence has already failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Snvz4RDRkDS4kpDRQqrDDC
The macOS home now comes from KERN_PROCARGS2 through claude-store's
darwinProcess.environment, parsed by the same grokHomeFromEnvironment as
Linux, so an argument or a value holding " GROK_HOME=" can no longer
name the store and no ps child runs. The lsof cap counts bytes.

The real-process resolver scenarios now run on macOS too, with the
store named by the child's own GROK_HOME, so the Native macOS session
identity job exercises real lsof output. The mocked macOS tests add a
transcript in another directory than the hold, broken competing holds,
a missing inode, an over-cap listing, a real timeout kill and an inode
past 2^53; the "does not select" test no longer passes on mtime alone.

README in all four languages now lists Grok chat on Linux and macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Snvz4RDRkDS4kpDRQqrDDC
@devswha
devswha force-pushed the feat/grok-macos-chat branch from 8e9d7f6 to 55f09f6 Compare October 25, 2026 15:59
@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Thank you for the macOS Grok support. I rebased the contributor commits onto current main and addressed the three latest merge-pass findings in 55f09f6c0 (fix(chat): validate complete macOS Grok process evidence):

  1. Truncated lsof names: grokLsofEvidence now requires the trailing newline used by lsof -FfDin, so a listing ending midway through n/fixture cannot hide a competing hold and bind the reported transcript.
  2. PID reuse: the macOS resolver reads the process's start time with /bin/ps -o lstart= before lsof/environment evidence and again after resolving the held files. A changed, missing, or failed start-time read returns no binding. The reads use the C locale and UTC, with a 3-second timeout.
  3. Guide wording: docs/guide.md now names sysctl KERN_PROCARGS2 as the environment reader, lsof as the held-file reader, and ps as the start-time check.

Verification:

  • Both new regression tests failed before the resolver fixes, returning the transcript instead of null.
  • Linux: HERDR_TEST_MODE=unit bun test ./server/grok.test.ts — 55 pass, 0 fail.
  • dori heavy ext-pr-fixes -- bun run check fast — exit 0; 6,821 pass, 0 fail, 13 skip across 471 files. Workflow syntax, generated files, typecheck, and build passed; the verification report marks the tested source unchanged and verified.
  • Codex Sol (gpt-6.1-sol, xhigh) reviewed only the fix delta against rebased commit f72aa961e: no HIGH/MAJOR findings. It also ran all 55 Grok tests successfully and modified no files.
  • Touched TypeScript diagnostics and git diff --check are clean. The macOS evidence boundary cases ran with mocks on Linux; I did not run the optional fresh-clone macOS check.

There were no review threads to reply to or resolve. No workflow files were changed by these fixes. This delta review does not replace the maintainer's gate for the PR's existing workflow change.

Fixes prepared by a maintainer agent and checked against the code. The merge decision stays with the maintainer's merge pass.

@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Merge pass gate re-check of 55f09f6 (Astra): still REJECT, on two narrow PID-reuse windows. The full report, with reproduction code, is .omo/evidence/pr1858-gate-review-2.md.

Fixed:

  • A truncated lsof name now fails closed.
  • The guide names sysctl KERN_PROCARGS2.
  • LC_ALL=C and TZ=UTC are set and whitespace is normalised. Missing, failed or empty ps output binds nothing.
  • The workflow diff only adds ./server/grok.test.ts. Permissions, triggers, secrets and required checks are unchanged.
  • The Grok tests pass 55/55 on Linux and on eamac (fresh clone, deleted afterwards).

Blocking:

  1. A replacement before the first ps sample still binds (server/grok-store.ts:268-271, :233-245).
    • The pane's foreground process is read once, before either start-time sample. If the process is replaced between that read and the first ps, both samples come from the replacement, so they match, and its transcript binds to the stale pane.
    • Reproduced through the real resolver (case replacement-before-first-ps).
    • Needed: tie the sampled start time to the pane's foreground process. For example, take the foreground pid and its start time together, or read the foreground membership again after the last sample.
  2. Whole-second lstart equality doesn't prove it's the same process (server/grok-store.ts:245-255).
    • A replacement between the evidence reads that starts within the same displayed second passes the comparison (case reuse-between-reads-same-second). The control case, a different second, is rejected correctly.
    • Needed: use a start time that tells such a replacement apart. On macOS, sysctl kern.proc.pid gives p_starttime in microseconds. Or fail closed when the window can't be ruled out.

Alternative: if the Claude macOS resolver (server/claude-store.ts) already accepts exactly these two windows, say so and point to its code. The merge pass accepts matching that precedent as long as it's documented.

@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Thank you again for the macOS support. Round two addresses both PID-reuse findings in 01cb44a4e (fix(chat): bind Grok evidence to kernel process birth):

  1. Replacement before the first sample: after reading the evidence, the resolver asks pane.process_info again and requires exactly one foreground Grok with the sampled PID. The fresh lookup is itself bracketed by matching kernel start times, so a replacement during that asynchronous lookup also binds nothing.
  2. Reuse within the same displayed second: Grok no longer uses ps -o lstart. It reads extern_proc.p_starttime from sysctl kern.proc.pid through the existing libSystem/sysctl seam and preserves seconds plus microseconds as a bigint. A one-microsecond difference, an unreadable process, or an invalid/truncated timeval fails closed. The guide now describes this reader.

I checked the Claude precedent first: claudeProcessSession in server/claude-store.ts still compares its native PID record with whole-second darwinProcessStart output. These fixes do not rely on that precedent or change Claude's session resolver.

Regression evidence:

  • Both requested new cases failed before the resolver fix, returning a transcript instead of null: replacement before the initial sample, and reuse between samples within the same second.
  • Linux targeted run: HERDR_TEST_MODE=unit bun test ./server/grok.test.ts ./server/claude-store.test.ts — 137 pass, 0 fail, 2 platform skips.
  • Native macOS on ssh eamac, in a fresh /tmp clone: Grok — 58 pass, 0 fail; the kernel process-start tests — 2 pass, 0 fail. This includes real lsof, kernel environment reads, and the live kernel start-time reader.
  • The broader native run had one pre-existing Claude attach test failure (reads attach behind options only from a client whose environment is no background session's). I reproduced that same failure on pre-round-two commit 55f09f6c0; it is outside these fixes.
  • dori heavy ext-pr-fixes -- bun run check fast — exit 0; 6,825 pass, 0 fail, 14 skip across 471 files. Workflow syntax, generated files, typecheck, build, and unit tests passed. The final report verifies unchanged source at 01cb44a4e. An earlier run was invalidated by committing during verification and was replaced by this clean committed-tree run.
  • All four touched TypeScript files have no diagnostics; the patch passes git diff --check. The native temporary clone was deleted.
  • Codex Sol (gpt-6.1-sol, xhigh) reviewed 55f09f6c0..01cb44a4e: no HIGH/MAJOR findings. Its separate local run passed all added regressions (147 passed, 2 skipped) but one unrelated socket test failed with sandbox EPERM; the unsandboxed targeted and full fast runs above passed. It made no file changes.

There are no review threads to resolve. No workflow files were changed in this delta. The PR's existing workflow change still goes through the maintainer's merge gate.

Fixes prepared by a maintainer agent and checked against the code. The merge decision stays with the maintainer's merge pass.

@devswha

devswha commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Merge pass review-work report: PASSED. This outside-contributor PR changes session binding and .github/workflows/ci.yml, so it was gated by Astra (omo-native-gate-reviewer, gpt-6-astra) over three rounds. The maintainer approved merging it once review passed. The ext-pr-fixes lane rebased it and made the fixes.

Round Head Verdict
1 8e9d7f6 REJECT. A truncated lsof name failed open, PID reuse could bind another process, and the guide named ps.
2 55f09f6 REJECT. Two narrow windows were left: a replacement before the first ps sample, and whole-second lstart equality.
3 01cb44a APPROVE

Final head:

  • Process identity: the evidence is now bracketed by the kernel's p_starttime in microseconds, read with sysctl kern.proc.pid, and the pane's foreground process is read again after the evidence. A replacement before the first sample, between evidence reads, or during the final RPC is rejected. The stable control still binds.
  • Struct layout: checked against the Mac SDK for arm64 and x86_64. A missing, invalid, failed or throwing read fails closed.
  • lsof framing: it must end on a newline, so a truncated name fails closed.
  • Docs: the guide names sysctl KERN_PROCARGS2.
  • Claude unaffected: the Claude resolver keeps whole-second ps lstart; only Grok uses the kernel reader.
  • Workflow: the diff only adds ./server/grok.test.ts to the existing macOS test step. Permissions, triggers, secrets and required checks are unchanged.

Test results:

  • Linux: the Grok and Claude store suites pass 137, with 2 skipped.
  • eamac, native, in fresh clones that were deleted afterwards: Grok passes 58/58. The combined suite has one Claude attach failure, and it fails the same way on the baseline. The CI job "Native macOS session identity" passes.
  • Typecheck is clean, git merge-tree is clean, and there are 0 unresolved threads.
  • One Fast checks run failed in an unrelated timing test ("looks once for what closes a bracket…", 1515 ms against its bound). It was re-run on the same head.

CodeRabbit did not review this PR (rate-limited or skipped). The reviews above stand in for it.

@devswha
devswha merged commit b510ce3 into devswha:main Oct 25, 2026
25 of 28 checks passed
@345ml

345ml commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

@devswha
Thanks!!

devswha added a commit that referenced this pull request Oct 27, 2026
…a phone demo GIF (#1928)

**The maintainer has asked for this to be merged** (2026-10-27). It no
longer waits for his own review.

## What it does
Makes the README short. The top now answers what Ovis is, shows it, and
says how to install it on a computer and a phone, with the desktop
browser, Mac, Windows, Linux, iPhone and Android given equal weight. The
Korean, Japanese and Simplified Chinese copies have the same sections.

- Logo, the tagline "Every coding agent, on every screen.", four badges
(license, release, stars, herdr 0.9.0+). The PWA badge is dropped.
- One sentence on what Ovis is: the agents on your computer as chats you
answer with a click or a tap, in any browser, the Mac app or your phone.
"Formerly herdr web UI" stays.
- The hero is `docs/media/readme/hero.webp` (1200x675, 12 fps, 25 s, 1.5
MiB), linking to ovis.sh/demo. It is recorded on the demo build in the
default Codex theme: a Claude Code turn on the desktop; the desktop and
a phone side by side, where Codex's Allow command? card is answered on
the phone and closes on both; then the release tab's shell as a live
terminal. It replaces `desktop-demo.gif`.
- **install**: on your computer, Ovis.dmg (Mac), Ovis.exe (Windows) and
the curl one-liner (Linux), which add herdr and Bun when missing (no
Node), with INSTALL.md for every other way; on your phone, the iPhone
TestFlight and Android Google Play betas (each translation links its own
language's beta page) or the browser added to the home screen, and the
QR code to connect.
- **what you get**: six short bullets, then one line each on the limits
and on privacy, including that anonymous usage counts are on by default
and how to turn them off.
- **docs**, **thanks** (now also crediting @sanguneo for the icon and
website design), **agent instructions**, **development**, **license**.

## What moved
- The long install section goes to [INSTALL.md](INSTALL.md), which
already covers every way to install step by step.
- The FAQ goes to the user guide's [FAQ](docs/guide.md#faq), which
already has it; the README's docs list links it.
- The clip grid and the long video are dropped: their recordings show
the previous UI.

The `install` anchor stays, because ovis.sh/install redirects to
`README.md#install`; the translations keep their explicit `<a
id="install"></a>`. Nothing else in the repo or on ovis.sh links to a
README anchor that is gone (`git grep`).

## Merge with main
main's #1858 (Grok chat on macOS) edited the Grok lines in the README
feature list and FAQ. Both of those sections leave the README in this
PR, and the same change is already in docs/guide.md on main, so the
conflict was resolved by keeping this branch's READMEs.

## Verification
- `bun run check fast` passes on the merged head.
- The README header test (`src/lib/markdownHtml.test.ts`) passes: logo
width 100, language links, website link.

Documentation only, so there is no changelog fragment.

## Follow-ups (not in this PR)
- `ovis-site/llms.txt` describes the README as "features, install and
FAQ"; the FAQ now lives in docs/guide.md.
- `src/components/PhonePanel.tsx` links `devswha/ovis#on-your-phone` and
`#access-and-safety`, anchors that live in docs/guide.md (this was
already the case before this PR).
- `scripts/film/capture.ts` sets no theme, so it records the old amber
theme from stored settings, and its R5-terminal take no longer runs.

---------

Co-authored-by: mp <mp@local>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chat: Grok chat on macOS

2 participants