ThinkRail at 5,047 Stars: JetBrains Built Its Agentic IDE on Monaco and a 118,000-Star Agent, Then Patched the Agent

ThinkRail has 5,047 stars but 12 watchers; its specs admit 13 patches around the pi agent it borrows, and no stable release ships the Intel Mac DMG.

ThinkRail is a desktop and browser IDE for AI coding agents, published by JetBrains under its incubator badge, licensed Apache-2.0, and trending on GitHub on 28-29 October 2026. It does the thing every agent IDE now does — cut a git worktree per task, run a chat beside the diff, keep a plan — and it does a few things the others do not, like storing project intent in a graph of SPEC.md files the agent can search and rewrite.

What makes it worth an afternoon of reading is not the feature list. It is that the repository is unusually honest about what it borrowed to get there, and unusually precise about the price of borrowing. Three quotes carry the whole story:

  • From the product spec: "pi is the only engine, run in-process — no second runtime (no claude-agent-sdk)."
  • From the contributor guide for AI agents: “Fatal provider/agent faults can take down the host; that lack of crash isolation is accepted.”
  • From the architecture decisions: "pi ships breaking releases daily, so a floating range is a live wire."

An IDE vendor that owns one of the most mature editor engines in the industry shipped an agent IDE on Monaco — VS Code’s editor — and on pi, a third-party TypeScript agent with 118,537 GitHub stars. Then it wrote a 19.5 KB registry of the patches and mirrors it needs to keep that arrangement working. That registry is the most interesting document in the repository, and almost nobody reads it.

The numbers, before the arguments

All figures read from the GitHub API and the cloned repository on 29 October 2026, 00:45-01:10 UTC.

MetricValueNote
Stars5,047trending badge on the landing page rounds to “5.0k”
Watchers120.24% of stars — the lowest ratio in any audit on this site
Forks2605.1%
Open items242188 issues + 54 pull requests
Closed issues121issues, not PRs
Commits60430 contributors; top two accounts hold 427 (70.7%)
Oldest commit2026-06-22message: “initial specs”
Repository created2026-07-0816 days after the first commit
Releases121 in 112 days93 nightly, 28 stable
Latest stablev0.2.02026-10-18
Tracked files2,11537 MB clone
TypeScript324,037 lines.ts + .tsx
Specs106 SPEC.md2,112,977 bytes ≈ 2.1 MB
Tests470 *.test.ts + 142 e2e specs
LicenceApache-2.0no CLA, no SECURITY.md, no CHANGELOG.md

Two rows deserve a sentence each. The watcher count is the number stars cannot fake: a star is a bookmark, a watch is “tell me when this changes”. Twelve people asked to be told. And the repository’s first commit is dated sixteen days before the repository existed, with the message “initial specs” — this was built inside JetBrains and published later, which is consistent with an incubator project rather than a launch.

Two borrowed engines, one thin host

The architecture is three rings: a Bun HTTP+WebSocket host (packages/server), a typed protocol (packages/contracts), and a React 19 UI (apps/web) that ships independently and can dial any host. The UI is Monaco, the editor engine from VS Code. The desktop wrapper is Electrobun. The agent is pi.

The spec is explicit about the division of labour: pi owns the model registry, system prompt, skills, extensions, compaction, cost accounting and session state. ThinkRail owns the workspace, the editor, the wire, and nothing else. There is even a rule against the obvious cheat — “Influence by feeding, never by assembling” — meaning features may only shape the agent by handing it context, files and skills, never by building prompts behind its back.

That discipline is admirable and it is also a hard constraint. The non-goals section names exactly two things as excluded by decision: a second agent runtime, and any kind of account or login UI. Which means the answer to “can I use Claude Code in this IDE?” is not “later” — it is “no”. A contributor to the repository, CommanderTvis, forked it to host Claude Code; the fork appears on Hacker News as “Show HN: I forked JetBrains’ new agent IDE to host Claude Code”, and the same account later ported ThinkRail from its webview to Avalonia with Ghostty. When people inside the project fork the project to swap the engine, the “pi is the only engine” rule is doing visible work.

The engine’s own scale is the part the comparison makes awkward. pi (earendil-works/pi, MIT, formerly published under the @mariozechner scope) has 118,537 stars, 15,193 forks, and @earendil-works/pi-coding-agent recorded 17,004,039 npm downloads in the last month — between Gemini CLI (1.45M), opencode (11.9M) and Claude Code (44.6M). ThinkRail has 5,047 stars. The host is 23 times smaller than the engine it hosts, and the engine is not JetBrains'.

The bill for borrowing: thirteen seams and one dist patch

ThinkRail pins every dependency to an exact version — enforced by scripts/check-catalog.ts in pre-commit and CI, which rejects ranges, catalog drift, and any lockfile graph resolving React outside its single catalog pin. The stated reason is the third quote at the top of this article: the engine moves daily, so a range is a live wire.

What that costs is documented in pi-compatibility.md, a registry of every place the host compensates for a missing pi API, a pi defect, or a packaging constraint — each with a removal gate describing what upstream change would let the workaround be deleted. Under “Other pi-sensitive host seams” there are 13 entries, plus five more areas for MCP alone.

SeamWhat it compensates forWho feels it
Anthropic SSE framing patchpi-ai fails non-retryably on a CRLF split across network chunks and on streams cut mid-eventAnyone on Anthropic models over a flaky link
Registry-tool reconcile at attachResumed chats restore a recorded tool loadout that keeps withheld tools offTool toggles after a reload
Registry tool precedenceNo inline-extension precedence, so a package can hijack a core tool nameExtensions that collide with ThinkRail’s
Image-only queued inputPi’s delivered-queue removal is text-onlyPasting a screenshot into a running turn
Account-scoped model availabilityPi’s OpenAI provider lists its whole catalog under ChatGPT sign-inModel picker accuracy
Default-model preferencedefaultModelPerProvider is not exported; the host mirrors the mapNew-chat defaults
Headless themeSDK session creation does not initialise a terminal themeNon-TUI theming
Trust discovery and exclusion reloadsResource loading has no public discovery APIOpening a cloned repository
Session discovery and prompt templatesNo public parsing API for the read/edit UIHistory and templates
Subagent usage totalsgetSessionStats is not exported for a bare session fileCost totals for crashed children
Rollback of a failed usage appendappendFileSync failure can leave a torn line in the transcriptHistory after a disk hiccup
Detached result holdSubagent results can arrive after their parent contextBackground delegation
Skill bodies across compactionSkill text is not carried through compactionLong sessions that rely on skills

The first row is the one to read twice. ThinkRail does not just call the SDK differently — it ships patches/@earendil-works%2Fpi-ai@1.4.0.patch against dist/api/anthropic-messages.js, the compiled output of the engine’s Anthropic streaming parser. Unpatched, “two streams fail with the non-retryable ‘Could not parse Anthropic SSE event’: a valid CRLF stream whose \r\n is split across network chunks, and a stream cut off mid-event.” Patched, the first succeeds and the second ends with a retryable truncation error. The upstream issue is earendil-works/pi#10390, still open as of this audit.

There is a second sentence in the same document that matters more to a user than any of this: the bundled model catalogue moved from 1,554 to 1,599 provider/model pairs, with 71 removed and 116 added — and “the host still does not surface Pi’s modelFallbackMessage. This upgrade adds no fallback or warning UI.” Removed pairs include openai-codex/gpt-5.5. So when you resume a chat whose recorded model has vanished from the bundle, the host picks something else according to rules documented elsewhere, and shows nothing. The spec’s own remedy is a release note telling users to check their default and restored-chat model by hand.

Isolation is a git branch, not a sandbox

The most repeated criticism on Hacker News was that running agents outside containers is reckless. Reading the specs, it is not a bug — it is the product.

Isolation here means one git worktree per workspace, with its own branch and working directory under ~/.thinkrail/worktrees, so a bad agent run stays on a branch until you merge it. That protects your uncommitted work, your main branch, and your ability to review. It does not protect your SSH keys, your ~/.pi/agent configuration, your cloud credentials, or anything else the process can reach, because the agent runs in the same process as the IDE with your user’s privileges. pi is spawned in-process, not as a subprocess, and the AGENTS.md line quoted above accepts that fatal faults can take the host down with them.

What ThinkRail does add is a trust gate, and it is more considered than most: a cloned repository’s committed skill aliases, its .pi/ settings, extensions, prompts, subagent definitions and MCP servers load only after a per-project grant, and a repo-defined MCP server needs a per-entry approval that lapses when the entry changes. That is a real defence against prompt injection from a repo you cloned. It is not a defence against an agent that decides to curl something.

Auth is the network, and the flag that moves it

The CLI defaults to localhost — DEFAULT_HOST = "localhost" in apps/cli/src/args.ts — so an untouched install listens on loopback only. Good default.

The architecture decision then says: “Auth is external. Tailscale ACLs / device identity are the auth; the app carries an owner field, not a login UI.” There is no token, no password, no session cookie on the WebSocket upgrade. The host exposes /ws, /health, a file route and a blob route, and the spec’s protection model is that only your own devices can reach the port.

Which makes --host the most consequential flag in the program. Its entire help text is --host <h> Bind host (default localhost). No warning that binding 0.0.0.0 hands an unauthenticated shell-running agent to every device on your LAN. The README does not mention --host at all; only the CLI’s own --help does. If you follow the documented path — desktop app, or thinkrail on loopback — you are fine. If you invent the phone-access path yourself, you are relying on a Tailscale ACL that nothing in the install instructions told you to create.

The install path that does not exist on any stable release

The README’s desktop section reads: “macOS 14+ (Apple Silicon or Intel) — open the DMG for your architecture: thinkrail-desktop-darwin-arm64.dmg or thinkrail-desktop-darwin-x64.dmg.”

Across all 28 stable releases the project has published, from v0.0.1 on 8 July to v0.2.0 on 18 October, thinkrail-desktop-darwin-x64.dmg has never been attached. Every stable release since v0.1.0 ships 17 assets: the arm64 DMG, a Windows zip, Linux tarballs, three CLI binaries, SHA256SUMS, and updater JSON. The Intel DMG appears for the first time in v0.3.0-nightly.9 on 28 October, after at least twelve consecutive releases without it. An Intel Mac user following the README has no file to download on the stable channel.

The rest of the platform matrix is honest about itself, which is why the missing DMG stands out: Windows CLI and setup are signed, the macOS CLI is “signed but not yet notarized”, and “Linux artifacts are unsigned.” Desktop builds need glibc 2.38+ with GTK 3, WebKitGTK 4.1, Ayatana AppIndicator 3 and librsvg 2 — Ubuntu 24.04 or newer. Yet the landing page’s primary button is “Download for Linux”, pointing at the one platform whose artifacts are unsigned and whose minimum distribution is two LTS releases ahead of the most common one.

Sizes are worth a glance too: CLI binaries run 121-145 MB (thinkrail-linux-x64 is 140 MB), while the desktop payload is a 45 MB tarball. For a project whose subtitle is “lightweight”, shipping a 140 MB single-file binary is a choice, not an accident — it is what a self-contained Bun runtime costs.

Two files that usually exist are absent: there is no SECURITY.md (so no stated vulnerability disclosure channel) and no CHANGELOG.md (so the release notes on 121 GitHub releases are the only changelog). The Code of Conduct points to JetBrains’ community-wide policy rather than a project-specific one.

What is genuinely well built

It would be dishonest to leave the audit there, because much of this repository is better than the average trending project.

  • Tests, not vibes. 470 unit test files and 142 end-to-end specs, with a documented sharding rule (half the CPUs, capped at eight) and separate gates for binary and desktop artifacts. The spec requires the complete browser suite before handoff, not per commit.
  • Specs that pull their weight. 106 SPEC.md files totalling 2.1 MB, one per module and sub-module, each stating responsibility, public surface, allowed dependencies and forbidden reaches. Whether you find the prose over-written or not, the boundary rules are enforced: bun run check:boundaries and check:seams are commit gates.
  • Exact pins with a checker. No ^, no ~, no .x. check:deps fails the build on a range or a catalog drift. That is more discipline than most monorepos manage.
  • A real installer. install.sh downloads SHA256SUMS, extracts the entry for the exact asset name, and verifies with sha256sum or shasum -a 256, failing loudly if neither exists. The checksums are published on the release page.
  • Trust grants for cloned repositories. Covered above; this is the mitigation that actually matters for the worktree-isolation model.
  • Analytics with an allow-list, not a deny-list. Error reports are classified by type, code, source, scope, request method and ThinkRail-only stack frames; message text is excluded by an allow-list in code, not by a promise in prose.

That last point is where the honest reading gets interesting, because the name of the flag does not match the behaviour.

--no-analytics does not turn off analytics

The README says error reports are always sent, which is unusual candour. The analytics spec says something sharper: PostHog error tracking is “unaffected by analyticsEnabled, --no-analytics or THINKRAIL_NO_ANALYTICS”, and later, "--no-analytics / THINKRAIL_NO_ANALYTICS suppress only additional events without changing consent."

So the flag suppresses the optional bucket and leaves basic events plus error reports running, tied to a random installation ID. Running thinkrail --no-analytics does not make the app quiet; it makes it less chatty. Whether that is misleading or merely badly named depends on how much you trust the reader of a --help string — and the help string says only “turns additional sharing off for that run”, which is technically accurate and reads like something else entirely.

The marketing-attribution mechanism is the part most people will never see. With additional sharing on, a packaged build may open the ThinkRail blog once, in your browser, to link that installation to the website visit that brought you there — the README’s words. The code is a small PKCE-style handshake: a 32-byte verifier, a SHA-256 challenge sent to https://thinkrail.ai, then up to 54 polls at 10-second intervals inside a 9-minute deadline, followed by one redeem. Attribution expires 30 days after last touch. It is disclosed, it is opt-out, and it is a desktop application phoning home a marketing claim about your own download — which is exactly the kind of thing that is normal now and would have been a scandal in 2019.

How the crowd read it

Two Hacker News threads ran within a day of each other: 24 October (59 points, 84 comments) and 25 October (242 points, 174 comments). Reading all 174 comments, the loudest argument was not about architecture.

It was about whether the README was written by a model. One commenter stated it was “100% AI according to Pangram” and refused to take the repo seriously; the replies split between “if you haven’t bothered to write a readme, what else have you not bothered to do” and “you cannot detect AI, care whether the readme is any good”. Another commenter went after the spec files directly: “How is this llm-vomit ‘specs that are ground truth’?”

The engineering objections were sharper, and got less airtime:

  • “Jetbrains using vs code is really sad.” and “Not even using their own core engine is genuinely bleak.” The answer is in the repo — pi is TypeScript and runs in-process, so a React plus Monaco host is the cheap way to wrap it — but “cheap way to wrap it” is not a rebuttal anyone wanted to make out loud.
  • “Running agents outside containers seems crazy to me.” Confirmed by the specs; see above.
  • “BTW, what’s ‘InnovationHub’ it’s mentioned but I can’t find a good link or explanation.” This one is a genuine gap. The README badge says “JetBrains incubator project” and links to a JetBrains GitHub page; the website says “JetBrains InnovationHub”; nothing public explains what either commitment means. Compare with the Fleet story in the same thread — Fleet was developed for years, alpha-released, then shuttered and apparently reborn as Air. An incubator badge is a hedge, and readers recognised it as one.

The most useful comment for anyone evaluating the product was the least dramatic: “why do I want to use Monaco? If I’m in the JetBrains ecosystem isn’t it because I prefer their IDEs over VSCode?” There is no answer in the repository, because the honest answer is that the editor is the part they did not build.

What to verify yourself before adopting it

Documentation cannot settle these; only your own checkout can.

  1. Check the asset you actually need exists. Open the latest stable release and confirm the file your platform needs is attached. On 29 October, the Intel Mac DMG required by the README was only in a nightly.
  2. Decide on the isolation boundary before the first agent run. Run it on a machine where losing your ~/.ssh, ~/.pi/agent and cloud credentials is survivable, or put it inside a container yourself. The tool will not do it for you.
  3. Never bind beyond loopback without a network ACL. If you use --host 0.0.0.0, put Tailscale or a firewall in front of it first, and confirm nothing else on the LAN can reach the port.
  4. Test a model fallback on purpose. Resume an old chat after a pi upgrade that changes the model catalogue, and see what the header says. The spec says there is no fallback UI, so the question is whether you notice the silent substitution.
  5. Verify the pi patch survives your next upgrade. The Anthropic SSE patch is keyed to pi-ai@1.4.0, and Bun silently skips a patch whose version does not match. Their own test file decides whether it still applies; if you fork, keep that test.
  6. Read pi-compatibility.md before filing a bug. A surprising number of “ThinkRail is broken” reports are pi behaviour the host has documented and chosen not to paper over.

FAQ

Is ThinkRail a JetBrains product? No. It carries a “JetBrains incubator project” badge in the README and “JetBrains InnovationHub” branding on the website, is Apache-2.0, and is distributed through GitHub releases and npm, not through JetBrains’ product pages. No public page defines what either program commits to.

Can I use Claude Code or another agent inside it? Not through configuration. The product spec lists “a second agent runtime” as one of exactly two non-goals, and the implementation runs pi in-process with no second runtime. A project contributor forked the codebase to host Claude Code rather than adding an option.

Is the agent sandboxed? No. The boundary is a git worktree with its own branch and working directory, which protects your working tree and your main branch. There is no container, VM, separate OS user or filesystem jail; the agent shares the host process and your privileges.

Does it phone home? Yes, by default, to PostHog: basic events (launches, chat creation, message sends, provider connections) tied to a random installation ID, plus always-on error reports carrying type, code and ThinkRail-only stack frames. --no-analytics turns off only the optional additional bucket. It does not turn off basic events or error reports.

What happens if a chat’s model disappears after an upgrade? The model catalogue between the audited versions moved from 1,554 to 1,599 pairs, removing 71 and adding 116. The spec states the host does not surface pi’s modelFallbackMessage and adds no fallback or warning UI, so check the header after any upgrade that touches the engine.

Which platform is best supported on the stable channel today? Windows and Linux arm64/x64 desktop artifacts, plus the arm64 macOS DMG. Linux needs glibc 2.38+ (Ubuntu 24.04 or newer) and desktop builds are unsigned; the macOS CLI is signed but not notarized; the Intel macOS DMG was absent from all 28 stable releases as of 29 October.

The takeaway

ThinkRail is a serious engineering effort with an unusually readable paper trail, and its most interesting claim is not the one on the landing page. It is that a large IDE vendor decided the agent engine was not the thing to own. It rented the engine from a project 23 times more popular than its own IDE, pinned it to one version, patched its compiled internals where they broke, and wrote down thirteen ways it compensates — with removal gates, so the borrowing stays honest.

That is a defensible strategy, and it is also a dependency you inherit. If you adopt ThinkRail you adopt pi’s release cadence, its catalogue churn, its streaming defects, and every parity test the host wrote to keep the mirror intact. The right first move is not to install it and start working; it is to read pi-compatibility.md, check which assets your platform actually has, and run it somewhere your credentials are not load-bearing.