ee9d903866 fix(editor): preserve escaped Markdown during reconciliation (#21531)
* refactor(editor): show the preview affordance only after rich mode faults

Proactively classifying every Source-view markdown tab scanned content
nobody was looking at in Rich mode. The toggle and banner now read a
stored per-tab fault instead, recorded once Rich mode actually falls
back, so Source-view tabs never scan speculatively.

* docs(editor): state the fault-tracking constraints in present tense

* fix(editor): register the open-preview banner string

verify:localization-extraction failed because the rich-markdown
fallback banner's "Open preview" button called translate() with a
key never added to en.json.

* fix(editor): document isolated store harness cast

* fix(editor): stop the rich markdown editor from mangling dollar-heavy files

Opening a markdown file full of dollar amounts in rich mode reformatted it
on load, and any save then rewrote the whole file:

- marked emits an `escape` inline token for `\$`, `\*`, `\_`, `\[`; Tiptap's
  markdown parser has no case for it, so the escaped character was deleted
  from the document as soon as the file opened. The marked facade now
  rewrites escape tokens to text tokens, in place, so table cells keep them
  too.
- the inline-math tokenizer treated any same-line `$...$` pair as LaTeX, so
  "from $10 to $20" or "entered 2021 at $0" became a KaTeX atom whose text
  was trimmed. It now requires Pandoc-style boundaries: both `$` must touch
  the formula and the closing `$` must not be followed by a digit.
- the source-preserving reconcile mis-applied any edit at the end of a file
  whose source ends with a newline: getMarkdown never emits one, so the
  end-of-document hunk landed one character late, failed the round-trip
  proof, and fell back to canonical output for the entire file, rewriting
  every `\$`, `&` and table in it. It now patches the newline-stripped
  bodies and re-attaches the source's trailing newline run.

* fix(editor): round-trip escapes as atoms and narrow the end-of-file reconcile

Review findings on the first commit, all reproduced with the real serializer:

- Rewriting marked's `escape` token to text kept the character on load but
  the serializer never re-escapes, so `\# x` came back as `# x` and became a
  heading on the next open; `\$x\$` became inline math. Replace the facade
  rewrite with an inline atom node that owns the escape token and renders
  `\` + character, so escapes round-trip byte for byte in every container.
- The body-strip reconcile ran for every trailing-newline shape. A source
  ending in a blank line parses to a trailing empty paragraph, so canonical
  ends in `\n\n` too; stripping and re-attaching there duplicated the
  paragraph, failed the branch-6 proof, and canonicalized the whole file.
  Only strip when the source ends in exactly one newline that canonical
  lacks; every other shape patches correctly whole, as on main.
- Canonical fallbacks now keep the source's single trailing newline.
- The inline-math regex allowed neither a soft line break inside a formula
  nor a trailing LaTeX line break; both are valid and upstream accepted
  them. Drop the newline and backslash exclusions and the dead `.trim()`.

* fix(editor): carry escapes as a mark so emphasis and links stay continuous

Second-round review of the atom approach: Tiptap's serializer closes every
active mark before a non-text inline node and reopens it after, so an
escape atom inside bold split the run (`**cost \$5 total**` came back as
`**cost **\$**5 total**`, which no longer parses as bold), a link containing
an escape became two links, and find/replace was disabled on any match
touching an escape because atoms are read-only.

The escape is now a non-inclusive mark on ordinary text. A mark's markdown
is one prefix for the whole run, so `getMarkdown` is wrapped to rewrite
marked text as `\X` per character before the manager serializes; inside a
code mark the character is emitted bare, and `& < >` are left to the
serializer's entity encoding. The mark is registered after `Markdown`
because that extension's onBeforeCreate installs the getMarkdown being
wrapped.

Also restores tiptap-marked-facade.ts to the base branch: the previous
commit meant to remove the escape-token rewrite there but restored the
file from the branch's own HEAD, leaving a dead override in the diff.

* fix(editor): retry the whole-text patch and refuse escaped dollars as math closers

Second-round review findings that survived the mark rewrite:

- A source whose last line is whitespace only (`Last.\n  \n`) has a trailing
  run of one newline, so the body strip ran, landed the end hunk after the
  spaces, failed the branch-6 proof, and canonicalized the whole file where
  the base branch had patched it correctly. The body strip is now the first
  attempt and the whole-text patch the second, so no file does worse than
  before; the extra round trip only runs when the first attempt fails.
- `costs $5 to \$x here` parsed as inline math with latex `5 to \`, because
  the tokenizer accepted an escaped `\$` as the closing delimiter. Escaped
  characters are now consumed inside the formula and cannot close it.
- The escaped-dollar test passed on the base branch for the wrong reason
  (the `\$` was deleted before the math tokenizer ran); it now also asserts
  the bytes round-trip, and a new test pins escapes as ordinary searchable
  text.

* fix(editor): keep table pipes, link destinations and display math faithful to source

Pre-existing serializer defects the review catalogued, now fixed in one
place: a serializer-fidelity extension that wraps getMarkdown and rewrites
the document JSON into its source form before Tiptap serializes it. The
escaped-character mark's per-character expansion moves there too.

- `\|` inside a table cell: marked unescapes it per cell before inline
  lexing, so the cell held a bare `|` that split the row on the next load
  and truncated it. Text inside tableCell/tableHeader now escapes `|`,
  code spans included, since the cell split happens before code lexing.
- `\)` inside a link or image destination came back bare and ended the
  destination early. Parentheses in destinations are escaped again.
  (Angle-bracket destinations are not an option: Orca's raw-HTML pass would
  placeholder them before parsing.) Image alt text escapes `[ ] \`, and
  link/image titles escape `"`.
- `$$` anywhere in a paragraph split it, because marked ends a paragraph
  wherever a block tokenizer's `start` points and upstream used
  `indexOf('$$')`. Display math now only starts at a line start.

# Conflicts:
#	src/renderer/src/components/editor/rich-markdown-extensions.ts

* fix(editor): accept indented display math with inner dollars, escape pipes in cell attributes

Review comments on the previous commit:

- Display math whose body holds a `$` (`$$\n\$5\n$$`) fell back to prose
  because the body pattern refused every dollar; it now runs to the
  closing `$$`.
- Display math indented by spaces or a tab no longer opened, because the
  line-start check wanted `$$` right after the newline. The start pattern
  tolerates the indent, and points marked at the newline rather than the
  first `$` so the indent does not stay behind in the paragraph.
- `|` inside a link or image attribute in a table cell was still written
  bare, so the row split on the next load. The cell context now reaches
  destinations, titles and alt text as well as text.

# Conflicts:
#	src/renderer/src/components/editor/rich-markdown-extensions.ts

* style(editor): format merged markdown extensions

* fix(editor): remove duplicate block math tokenizer

* fix(editor): restore inline math import

* fix(editor): avoid duplicate escape extension and preserve EOF shape

* fix(editor): keep existing source-preserving serializer active

* fix(editor): preserve baseline link and escape serializer behavior

* chore(editor): satisfy merged markdown lint rules

* fix(editor): retain escaped punctuation metadata during serialization

* fix(editor): keep escaped mark fallback neutral

* fix(editor): route marked escape tokens through rich markdown mark

* chore(editor): satisfy escape mark lint

* fix(editor): preserve escaped markdown entities through fast serialization

* fix(editor): normalize escaped dollar amounts

* chore(editor): satisfy serializer lint

* fix(editor): preserve nested markdown destinations and escaped entities

* chore(editor): satisfy destination serializer lint

* fix(editor): force source serialization for escaped entity marks

* fix(editor): retain balanced markdown destinations

* fix(editor): preserve escaped mark serialization in plain blocks

* fix(editor): normalize plain escaped money text

* fix(editor): keep table and display math dollar escapes

* chore(editor): remove unused escape helper

* fix(editor): retain raw link and image destinations

* chore(editor): satisfy raw destination lint

* fix(editor): admit comments inside image alt text

* fix(editor): keep plain money escapes out of math recovery

* fix(editor): preserve currency escapes in tables and formatted text

* chore(editor): remove diagnostics and satisfy serializer lint

* fix(editor): scope currency escape recovery to escaped source

* fix(editor): scope escape encoding to text nodes

* test(editor): keep stored preview fault aligned with saved content

* test(editor): cover destination repairs and remove unused serializer (#21532)

* fix(editor): honor edited markdown destinations

* refactor(editor): remove unused markdown serializer shim

* test(editor): cover saved preview and destination repairs

* test(editor): detect raw destination escape regressions

* test(editor): verify save position across hidden Electron clients

* perf(editor): scan fence lines without substring allocations

* fix(editor): match fence suffix whitespace rules

* fix(editor): match fence suffix whitespace rules

* fix(editor): match parser fence whitespace

* fix(editor): keep reconciliation cache contract

* fix(editor): preserve rich-mode validation option

* test(editor): cover source-mode validation skip

* fix(editor): keep rich mode classifier within lint limit

* test(editor): select rich copy ranges through Playwright

* fix(editor): wrap long rich markdown code lines

* test(e2e): retry rich selection before clipboard assertions

---------

Co-authored-by: Frederic Barthelemy <git@fbartho.com>
Co-authored-by: averydev <averybloom@gmail.com>
2026-09-19 23:50:29 -07:00
2026-09-19 00:58:02 +00:00
2026-05-04 20:42:03 -07:00
2026-03-16 22:27:51 -07:00
2026-03-28 10:19:14 -07:00

Orca Orca

GitHub stars Total downloads across all releases License: MIT Join the Orca Discord Follow Orca on X Supported platforms: macOS, Windows, and Linux

中文 · 日本語 · 한국어 · Español · Français · Português

The AI Orchestrator for 100x builders.
Run Codex, ClaudeCode, OpenCode or Pi side-by-side — each in its own worktree, tracked in one place.

Download Orca

Orca desktop app running agents in parallel worktrees, with the Orca mobile companion app in the corner

Features

Mobile Companion

Monitor and steer your agents from your phone — get notified when an agent finishes and send follow-ups from anywhere.

iOS App Store · TestFlight · Android APK 0.0.48 · Docs →

Orca desktop with the mobile companion app

Parallel Worktrees

Fan one prompt across five agents, each in its own isolated git worktree — compare the results and merge the winner.

Docs →

Parallel worktree orchestration

Terminal Splits

Ghostty-class terminals with WebGL rendering, infinite splits, and scrollback that survives restarts.

Docs →

Terminal splits

Design Mode

Click any UI element in a real Chromium window to send its HTML, CSS, and a cropped screenshot straight into your agent's prompt.

Docs →

Embedded browser and Design Mode

GitHub & Linear, Native

Browse PRs, issues, and project boards in-app — open a worktree from any task and review without a context switch.

Docs →

GitHub and Linear task workflows in Orca

SSH Worktrees

Run agents on a beefy remote box with full file editing, git, and terminals — auto-reconnect and port forwarding included.

Docs →

Remote worktrees over SSH

Annotate AI Diffs

Drop comments on any diff line and ship them back to the agent — review, edit, and commit without leaving Orca.

Docs →

Annotate AI-generated diffs

Drag Files to Agents

VS Code's editor with autosave everywhere — drag files or images straight into an agent prompt.

Docs →

Drag files and images into an agent prompt

Orca CLI

Agents drive Orca too — script every workflow with orca worktree create, snapshot, click, and fill.

Docs →

Script Orca from the CLI

Also in the box:

  • Quick open — Search across worktrees, files, agents, commands, and repo context without leaving your flow.
  • Account switcher & usage tracking — See Claude and Codex usage and rate-limit resets, and hot-swap accounts without re-logging in.
  • Rich repo previews — Preview Markdown, images, PDFs, and repo docs in the workspace.
  • Computer Use — Let agents operate desktop apps and visible UI when a workflow needs real interaction.
  • Notifications and unread state — Know when an agent finishes or needs attention, then mark threads unread to come back later.
  • And many, many more — we ship daily, so this list is perpetually behind. The changelog is the real feature list.

Supported Agents

Works with any CLI agent — if it runs in a terminal, it runs in Orca.

Claude Code logo Claude Code   Codex logo Codex   Grok logo Grok   Cursor logo Cursor   GitHub Copilot logo GitHub Copilot   OpenCode logo OpenCode   MiMo Code logo MiMo Code   Amp logo Amp   OpenClaude logo OpenClaude   Antigravity logo Antigravity   Pi logo Pi   oh-my-pi logo oh-my-pi   Hermes Agent logo Hermes Agent   Devin logo Devin   Goose logo Goose   Auggie logo Auggie   Autohand Code logo Autohand Code   Charm logo Charm   Cline logo Cline   Codebuff logo Codebuff   Command Code logo Command Code   Continue logo Continue   Droid logo Droid   Kilocode logo Kilocode   Kimi logo Kimi   Kiro logo Kiro   Mistral Vibe logo Mistral Vibe   Qwen Code logo Qwen Code   Rovo Dev logo Rovo Dev   + any CLI agent


Install

Desktop — macOS, Windows, Linux

Or via a package manager:

# macOS (Homebrew)
brew install --cask stablyai/orca/orca

# Arch Linux (AUR) — or stably-orca-git to build from source
yay -S stably-orca-bin

Mobile Companion — iOS, Android

Pair with your desktop app to monitor and steer your agents from your phone.


Community & Support

  • Discord: Join the community on Discord.

  • Twitter / X: Follow @orca_build for updates and announcements.

  • WeChat: Scan to join the Orca community WeChat group 8. Group 8 may be full; if so, scan the Group 9 QR code instead.

    WeChat group 8 QR code for the Orca community  WeChat group 9 QR code for the Orca community

  • Feedback & Ideas: We ship fast. Missing something? Request a new feature.

  • Privacy: See the privacy & telemetry docs for what anonymous usage data Orca collects and how to opt out.

  • Show Support: Star this repo to follow along with our daily ships.


Developing

Want to contribute or run locally? See our CONTRIBUTING.md guide.

The relay that pairs the mobile app with a desktop host is also in this repository under cloud/, with a separate pnpm workspace and setup guide.

Orca contributors

GitHub star history chart for stablyai/orca

Signed Builds

Windows code signing sponored/provided by SignPath.io, certificate by SignPath Foundation.

License

Orca is free and open source under the MIT License.

S
Description
Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.
Readme MIT
1.5 GiB
Languages
TypeScript 95.1%
JavaScript 4.1%
Swift 0.2%
CSS 0.2%
HCL 0.1%