DEV Community

Cover image for JetBrains open-sourced an agentic IDE where agents never touch your checkout

JetBrains open-sourced an agentic IDE where agents never touch your checkout

Sam LABBE on October 26, 2026

JetBrains just open-sourced an agentic IDE — Apache 2.0, on GitHub as of yesterday — and the name of the repository matters less than the three id...
Collapse
 
alexshev profile image
Alex Shev •

Worktree isolation is a strong default, but it needs a clear promotion step. Having an agent produce a patch plus a short manifest of files changed and tests run makes review and merge the intentional handoff rather than an implicit side effect.

Collapse
 
slabb profile image
Sam LABBE •

Your manifest is the run receipt missing its seal. Files changed plus tests run is exactly what a receipt binds — the verdict travels with its check — and the seal is what turns "here's what I did" from narration into evidence: the agent authored both, so without a signature the manifest is the worktree's diary entry about itself. With one, the promotion step you describe becomes what it should be — the merge as an intentional handoff between two recorded states, each carrying who ran what and what passed. Cheap addition, and it composes with the spec beside every module: the manifest names what changed, the spec says what it means.

Collapse
 
alexshev profile image
Alex Shev •

A useful next detail is whether the receipt records the base revision as well as the resulting patch. That makes the promotion check reproducible: a reviewer can apply the patch to the declared base, rerun the listed commands, and see whether the same verdict still holds.

Thread Thread
 
slabb profile image
Sam LABBE •

Yes — and the binding you describe is exactly what makes a receipt replayable: base revision, patch digest, the commands, and the evaluator identity all travel with the verdict, so the promotion check becomes what you said: apply the patch to the declared base, rerun, compare. One honest limit to carry alongside: reproducibility proves the verdict was derivable from the recorded inputs, not that the original run happened — a fabricated receipt is perfectly replayable. The authenticity half is the attempt-first seal: the attempt (base, task, inputs digest) sealed before the outcome exists, so a receipt with no run behind it lacks the earlier event and reconciliation names it. Reproducible is the replay's property; witnessed is the run's — a promotion check wants both.

Thread Thread
 
alexshev profile image
Alex Shev •

That distinction is important. The seal also needs a trust boundary: who signs the attempt, where the event is retained, and whether a missing or delayed seal blocks promotion. Replay can validate the recorded computation, while independent evidence of the earlier event supports the narrower claim that an attempt was witnessed.

Thread Thread
 
slabb profile image
Sam LABBE •

All three have shipped answers — the pleasant part of checking instead of designing. Who signs: the writer domain resolves by signature against the sealed known-writers registry, and the signing key loads once into a dedicated daemon the agent's user can't read — so an attempt's signature is attributable to a process, and the custody grade prices that process (unanchored and drift are named states, not vibes). Where retained: retention is the wrong-by-drift half of the grade — receipts authored grade-1 but kept in operator-controlled storage sit grade-3, retention changes are sealed events, and the drift check monitors the tail beyond the newest anchor, because retention is the one grade that fails by silence.

Does a missing or delayed seal block promotion: the journal surfaces rather than gates. outcomes ≤ attempts is the invariant — an outcome with no earlier attempt is a named finding, a late attempt surfaces as an ordering inversion the chain derives — and whether a finding blocks promotion is the deployer's gate. That's the honest division of labor: the journal is domain-blind, the promotion rule is yours. Your last line states the split correctly — replay validates the computation, independent evidence witnesses the event. A promotion check that wants both asks for the replay of one and the anchor or counterparty signature of the other.

Collapse
 
makayis_90942586425f8f6bb profile image
makayis •

The "one prompt injection away" point is the part I'd want ThinkRail to answer before anything else. A worktree protects your checkout, but SPEC.md is the thing the agent trusts most, and the agent can write to it.

The simplest fix I can think of: treat spec_* writes as proposals, not edits. The agent can suggest a change to the spec, but it lands as its own small diff that a human approves, separate from the code diff. Code changes are cheap to review because tests catch a lot. A quiet change to the "truth" file isn't caught by anything.

Did you see any sign that spec edits are logged or diffed separately from normal file changes? That would tell me a lot about how seriously they take that risk.

Collapse
 
slabb profile image
Sam LABBE •

Checked the repo: no. spec_update writes frontmatter straight to disk (its own docstring sends prose to the generic write/edit tools), spec_create scaffolds new files, and neither logs or diffs anything separately: a spec edit lands in git as an ordinary .md change like any other file. The proposal mechanism you describe does not exist.

Which makes your framing the design argument. The truth file is the one artifact every other artifact defers to, and it is the only one the agent can write with no detector at all: the mechanical check covers surfaces only (check:spec-surface compares declared exports against barrels), so a quiet narrative rewrite passes every gate until a human reads it.

Spec writes as proposals is pre-registration applied to the truth file: the diff exists before the code that depends on it, and reviewing the two separately is right because they fail differently.

Collapse
 
makayis_90942586425f8f6bb profile image
makayis •

Thanks for actually checking. That's the answer I was afraid of. The surface check makes it worse in a way, because it gives a green signal that sounds like the spec was verified when only the exports were. The cheapest version of the fix wouldn't even need a new mechanism: make SPEC.md a protected path, so an agent edit to it goes into its own commit that a human has to approve. Same idea as the proposal, built from what's already there.

Thread Thread
 
slabb profile image
Sam LABBE •

Your green-signal point is the sharpest thing in this thread: a check that verifies exports and reports green reads as the spec verified. The fix at that layer costs one word: the check's output should say what it checked, spec surface checked, never spec verified. A green light that names its scope cannot impersonate a bigger green light. An earlier thread on this blog landed the same law for the word verified itself, and it applies unchanged here.

And your protected path is the mechanism version of the same honesty: the proposal exists because the signal was carrying weight it did not earn. Branch protection plus a path-scoped owner on **/SPEC.md is exactly what the neighboring thread on this post converged on for the prose. Cheap, built from what is already there, and it turns an agent's spec edit into a first-class event instead of a rider.

Thread Thread
 
makayis_90942586425f8f6bb profile image
makayis •

"Spec surface checked" is a good rule for any check, not just this one. Half the trust problems with agent tooling come from a green light that's vaguer than what it actually tested. Naming the scope costs nothing and stops the over-reading.

Collapse
 
kevinhall profile image
Kevin Hall •

Worktrees answer "which tree does the agent live in". For research agents an even blunter version works for me: give the agent no tree at all. My Claude Code sessions that pull job and company data run with --allowedTools set to the MCP tools only, no file or shell tools. In one recorded session the agent still tried a shell command, to check whether an API token was set, and the call was simply refused; it carried on with the tools it had. The isolation came from the tool list, not the prompt, which is your point one level further down.

The SPEC.md idea is the part I'd want for those sessions. Right now the only memory between runs is what I paste back in.

Collapse
 
slabb profile image
Sam LABBE •

The no-tree mode is the schema argument taken past its own endpoint: heyvaldemar's "never hand the agent an HTTP API" minus the API — the tool list is the boundary, and the refused shell call you recorded is the negative control doing its job in public. Worth more than the refusal itself: an attempted-and-denied call is a denominator event — the agent probed the fence, the fence held, and the attempt was observable. That's the difference between isolation and the appearance of it; a prompt-only fence produces no refused calls to count, because the persuasion happens instead.

On inter-run memory: the SPEC.md pattern transfers directly — the durable home for what survives a session is a maintained artifact the next run reads first, which is exactly this post's bet. The piece to add from this thread's discipline: a memory the agent writes is a diary, and diaries don't bind the next session to anything; sealed per run (what it read, what it concluded, which corpus state it saw), the handoff becomes a receipt the next run can cite — your pasted-in context becomes "the state as of this digest." Research agents are where that pays double, because the corpus moves under them: last week's summary of a dataset is exactly the kind of belief that needs a consumed-head, not a paste.

Collapse
 
alexshev profile image
Alex Shev •

Keeping agents out of the checkout is a strong default because it makes the diff the handoff artifact. The next useful question is how the system proves the patch was produced and tested in an equivalent environment—base commit, commands run, dependency lockfile, and test evidence should travel with the proposal.

Collapse
 
slabb profile image
Sam LABBE •

That bundle has a name in this series: the run receipt. Base commit, commands, evaluator identity, sealed before the verdict exists. The journal side already binds it (attempt-first, spec_hash on the spec it loaded), and the two halves stay distinct: replay validates the recorded computation, the seal witnesses the run.

What Thinkrail lacks is not the idea but the seal: its archaeology receipt is a markdown file the same session writes, so the equivalent-environment claim rests on trust in the process rather than on an anchored record.

Collapse
 
alexshev profile image
Alex Shev •

A clean checkout boundary is strong, but I would still treat patches as untrusted inputs. The handoff should carry the diff, command log, and declared files touched, then require a human or policy gate before any merge into the real workspace.

Collapse
 
suirindo profile image
asagiman •

The worktree boundary raises a useful distinction: is “never touch your checkout” enforced by the host's filesystem permissions, or by routing the agent to a separate working directory? A worktree alone doesn't remove the process's access to sibling paths or shared credentials.

A small acceptance test could put a harmless sentinel outside the assigned worktree, ask the agent to modify it, and record both the tool denial and the unchanged sentinel. That would make the enforcement claim independently checkable alongside the spec/merge checks. I haven't run Thinkrail; does its current host enforce that boundary?

Collapse
 
slabb profile image
Sam LABBE •

Checked the repo, since it's open: enforcement is routing, not confinement. The worktree comes from git worktree add (workspaces.ts), which is a separate directory under the same user — sibling paths and shared credentials stay reachable by the process. The only sandbox-exec in the tree is in the test harness, denying the desktop host read of the repo root for e2e isolation — so macOS Seatbelt is already in the building, just not applied to agent sessions. Your sentinel test is the right acceptance check, and run today it fails on the deny half: the tool call would succeed and the sentinel would change.

One distinction your test already contains, worth naming: record both the refusal and the unchanged sentinel. The refusal is a step — a tool can be told to deny; the unchanged sentinel is the sensor — the world has to actually hold still. Anything the agent's report can attest alone, the agent can forge; the sentinel is what makes the claim checkable without trusting the reporter. That's the same law the geometry thread ran: enforcement by permission is the declared vantage, the sentinel is the effective one, and the gap between them is the finding.

Collapse
 
suirindo profile image
asagiman •

Thanks for checking the source and clarifying routing versus confinement. I would treat the predicted sentinel outcome as a source-reading conclusion, not a recorded test result; I haven't run Thinkrail either. For the acceptance check, both the tool denial and an independently verified unchanged sentinel matter.

Thread Thread
 
slabb profile image
Sam LABBE •

Correct, and the correction lands on me: "run today it fails" was a derivation wearing a measurement's clothes. The verified half is the source reading — git worktree add, same user, no confinement in the session path. The failing half is a prediction and gets its label: predicted from source, not executed. Your acceptance formulation is the tight one — tool denial and independently verified unchanged sentinel, both recorded, either both passing or the finding named. The protocol is three lines (sentinel outside the worktree, prompt the agent to modify it, record the denial and the bytes) and it's pre-registered here: whichever way the run lands, the result replaces this prediction.

Thread Thread
 
suirindo profile image
asagiman •

Thanks for making that correction explicit, Sam. Recording both the tool decision and the independently observed sentinel state gives the eventual result a clear basis. The source-derived prediction remains labeled as such until that run supplies the evidence.

Collapse
 
salparvez profile image
Sal Parvez | ML Systems RI •

A SPEC.md beside every module reminds me of as-built drawings. The plans say what was intended, the as-builts say what actually got built, and trouble starts when the same person updates both and nobody checks. A separate sign-off on spec changes seems like the cheap fix. It's how we're thinking about house records at ML Systems.

Collapse
 
slabb profile image
Sam LABBE •

As-builts is the exact analogy, down to the failure you name — the same hand updating both is the second-speaker problem wearing a hard hat. Construction solved it institutionally: the contractor doesn't stamp his own as-builts; a different licensed speaker does, because the two documents serve opposite parties — intent for the designer, reality for whoever maintains the building after. The repo version of the stamp is the path-scoped sign-off: any PR touching both code and spec needs both reviewers, so the as-built can't be amended inside the same approval that changed the building. Cheap fence, and it's the one that doesn't trust anybody's diligence — which, per your house-records point, is the only kind that survives the person who updates both leaving.

Collapse
 
vishisht_choudhary_a12d08 profile image
Vishisht Choudhary •

The worktree-per-agent part makes total sense, but I think the SPEC.md graph is the bigger bet, and you named the catch well: if the agent both follows the spec and edits it, the spec can drift without anyone noticing. Did you see anything in the repo that makes spec edits go through review on their own, kept apart from code changes? Without that, I'd expect someone's SPEC.md to slowly turn into whatever the agent did last Tuesday.

Collapse
 
slabb profile image
Sam LABBE •

Checked the repo, since it's open. The review separation you're asking about doesn't exist — one CODEOWNERS gate for everything (*, five owners, require_code_owner_review on the main ruleset), so a spec edit rides the same review as the code it changed. What does exist is a mechanical drift check one layer down: check:spec-surface compares every enrolled SPEC.md's declared public surface against the module's TypeScript barrel and fails on "Spec surface drift" — which fences the cheap layer in both directions: code that changes the barrel without the spec update fails, and a spec declaring exports that aren't there fails too. What the agent can still do is update both to match whatever it did — the names check out because they were made to.

Your "last Tuesday" drift lives in the layer the check can't see: the spec's narrative — invariants, trade-offs, decisions. That layer has exactly one fence today (the owner gate), and in a mixed PR one review does both jobs at once. The two fences that would actually separate them, cheapest first: a path-scoped CODEOWNERS row (**/SPEC.md owned by a different or additional set — any PR touching spec and code then needs both sign-offs, and a spec-only change gets the spec review alone), and past that, the treatment this series runs on documents the agent follows and writes: the spec sealed at provision, edits arriving as named diffs against the sealed baseline. A spec the agent maintains is a governance file with a compiler attached — the compiler keeps the surface honest, and the seal is what keeps the story honest.

Collapse
 
paullovelace profile image
Paul Lovelace •

For me the worktree idea is almost too obvious in hindsight — I've lost more time to an agent quietly editing the tree I was building in than to any single bad suggestion. Making merges the explicit coordination point feels right, but it also moves the pain somewhere else: what happens when two agents' worktrees touch the same module and both look reasonable? That's the part I'd want to see in practice before I trust a fleet of them, even with SPEC.md sitting beside every module.

Collapse
 
slabb profile image
Sam LABBE •

The honest answer is that the merge stays hard — the isolation just changes what kind of hard. Two worktrees that each pass their own tests and both "look reasonable" produce the nastiest conflict class there is: not textual (git resolves that) but compositional — each diff fine alone, the combination breaking an invariant neither touched. The referee for that can't be either diff; it has to be a third document that states what the module is allowed to mean, which is exactly the seat SPEC.md occupies in this design — the owning spec's invariants are what "both look reasonable" gets checked against, mechanically where the surface is concerned (check:spec-surface) and by the owning review where it isn't.

The deeper half is the record-keeping: in journal terms, a merge is a fan-in — an event binding both consumed heads, so each side's assumptions (which spec version it read, which head it built on) are on the chain, not in the agent's chat history. That's what makes a later "these two changes were each fine and together wrong" derivable instead of archaeological: the conflict propagates to both parents as a precise path set. It won't make two reasonable agents agree — nothing does — but it makes their disagreement derivable: who assumed what, at which head, visible at the merge instead of discovered in production. That's the part I'd want to see in practice too, and it's checkable without trusting anyone's judgment of "reasonable."

Collapse
 
mudassirworks profile image
Mudassir Khan •

the worktree per agent part is the piece i would copy first, merges as the only coordination point beats five agents editing one tree. on the spec drift worry, we let agents propose spec edits but only a human merges them, with CODEOWNERS on the spec files so a bad edit cannot ride along inside a feature branch. do the spec tools in Thinkrail support marking some SPEC.md files read only for agents, or is everything writable?

Collapse
 
slabb profile image
Sam LABBE •

Checked the repo: everything is writable today. spec_update edits frontmatter only (its own docstring says prose goes through the generic write/edit tools), spec_create scaffolds new files, and neither carries a protection flag or deny list. So the read-only marking you're asking about doesn't exist in the tooling; the fence lives where you put yours, at the repo boundary: agents propose, humans merge, CODEOWNERS on the spec paths. Your setup is the load-bearing layer, and per this thread's law it's the only kind that holds: an in-session read-only flag would be advisory unless the harness enforces it, and a fence the session can weigh is a suggestion.

Where a tool-level flag would still earn its keep is earlier in the lifecycle: a bad spec edit caught at write time is cheaper than one caught at review, and protecting, say, the dependency-edge fields (the graph's load-bearing lines) from spec_update would kill the quiet-rewiring class while leaving prose to the merge gate. That's a design suggestion for upstream, not a capability that exists today.

Collapse
 
mudassirworks profile image
Mudassir Khan •

fair, so the fence really is the merge gate and not the tool. the dependency edge fields idea is the one i would push upstream, since a quiet rewire of the graph slips through review easily when the diff looks like a one line frontmatter change.

do you split CODEOWNERS between the spec prose and the edge fields, or is it one owner for the whole spec path?

Thread Thread
 
slabb profile image
Sam LABBE •

One owner for the whole spec path today, and the reason is mechanical: CODEOWNERS works at file granularity, so it cannot split inside a SPEC.md between the prose and the four edge fields. That is worth knowing before designing around it.

Two ways to get the split you want, cheapest first. The CI one: a diff-lint that parses the frontmatter and fails when any edge field (depends-on, references, implements, covers) changed without a matching graph-change label or a second approval. Same repo layout, the rewire stops looking like a one-line prose tweak because a gate says so.

The structural one: hoist the edges out of SPEC.md into their own file, say SPEC.graph.yaml. Now CODEOWNERS can do its job: the prose file gets the team owners, the graph file gets a different set, or a tool-only writer with humans proposing. That is also the version worth pushing upstream alongside your idea, because it matches how Thinkrail already treats structure: the surface check validates barrels mechanically, and the graph is even more machine-shaped than the surface. Edges as data in their own artifact is the same move as the destructive verbs getting their own tools.

One caution from the ossification thread: whichever fence wins, the graph file inherits the staleness problem, so the pair travels with a validator that re-derives it from the code on a schedule.

Collapse
 
sofiicaste01 profile image
sofia castellanos •

The checkout lock is the interesting part. Reviews of agent output fail mostly because they are optional; making the workspace the boundary removes the choice. The open question is how it copes with work that spans several sessions on the same branch.

Collapse
 
slabb profile image
Sam LABBE •

"Reviews fail because they are optional" is the whole argument for structural boundaries in one line — the checkout lock doesn't make reviewers better, it deletes the choice, which is the same reason prompt-level defenses lose: a defense the agent can weigh is a suggestion.

On multi-session work on one branch: the answer that survives this thread's vocabulary is that the branch is a sequence of promoted states, never a shared scratchpad. Each session is a run — it starts from the last promoted (committed) state, and its only path onto the branch is the merge as intentional handoff, binding what it built on. Same-branch-sequential is safe exactly while every session begins committed; the failure mode is sessions sharing uncommitted state, which is chat-RAM with worse observability — the worktree-per-agent design quietly contains it, because a session that dies mid-work leaves a disposable dirty tree, not a poisoned branch. In receipt terms: the branch becomes the chain of run receipts, each one citing the base digest it started from — which is also what makes "which session broke it" derivable instead of argued. (Design answer, labeled as such — the repo's multi-session UX is one of the parts I haven't exercised.)

Collapse
 
unitbuilds profile image
UnitBuilds •

Imo, it runs into the same issue most do. If you have 5 agents working on a codebase, there are shared dependencies they need to edit. That's unfortunately the reality of modern software, right now, that means merge conflicts you need to fix. What they did is essentially 'feature' branches, which isnt really anything new. Getting 5 agents to work on 1 codebase, potentially in the same file, at the same time, without merge conflicts when it's all said and done, that's the tricky part that they didnt solve, which is the exact pain point why people started allowing multiple agents to work on the same live codebase in the first place, because otherwise 1's diff forces structural changes to the other and you spend twice as much fixing mismatches than you do building it right once.

Collapse
 
slabb profile image
Sam LABBE •

You're right on the mechanism, and the post doesn't claim otherwise — worktree-per-agent is feature branches, and fifty years of git say isolation-plus-explicit-merge is the answer to concurrent work. "Same file, same time" was never solved for humans either; pair programming is the only fix and it's social, not mechanical. The claim is narrower than solving conflicts: it makes them explicit and attributable. What's actually new isn't the branching — it's the referee at the merge (the owning SPEC.md's invariants plus a mechanical surface check) and the record: each worktree's history carries which spec version it read and which head it built on, so "one's diff forces structural changes on another" becomes a derivable event at merge time instead of a mismatch discovered after both shipped. The pain point you name is real and unsolved — the honest version of this design's promise is that the same fight costs one merge conflict instead of a week of post-hoc archaeology.

Collapse
 
kartik-nvjk profile image
Kartik N V J K •

Worktree per agent plus per-chat model selection looks like a cheap way to compare models on my own repo. I'd hand the same task to two models in two worktrees and read both diffs next to their token and cost readouts before picking one for that module.

Collapse
 
slabb profile image
Sam LABBE •

That experiment works, and the setup is already halfway instrumented: worktrees give you the same base commit for free, which is the fixture. Two additions make the pick derivable instead of a vibe. First, seal each run's manifest — files changed, tests run, cost — so the token readout prices the attempt and the receipt records the outcome; otherwise the comparison rests on whoever's diff reads better at 2am. Second, grade both diffs against the owning SPEC.md and its surface check, not against each model's own confidence — the fixture is the spec, the model is the variable, and neither diff gets to self-report passing.

One warning from the merge thread: per-module picks compose badly. Two local winners can be the compositional conflict — each fine alone, the seam between them wrong. The A/B that matters is sometimes at the boundary, so run one comparison across a pair of adjacent modules before trusting a fleet of per-module choices.

Collapse
 
rosana_e4663528aeaba0b05b profile image
Info Comment hidden by post author - thread only accessible via permalink
Rosana •

"Moving isolation to the worktree layer instead of fighting prompt drift is the right architectural abstraction."

ThinkRail hits on something most AI IDE wrappers miss: letting an autonomous agent loose directly on your active checkout is an invitation for destructive cross-talk. By spinning up lightweight git worktrees per session, JetBrains is treating multiple concurrent agents more like a team of human contributors working on isolated feature branches rather than a chaotic mob editing the same files in place.

The real test for this architecture will be how the SPEC.md living graph holds up over months of heavy usage. Giving an agent native tools to read and rewrite its own specifications solves the stateless context death problem, but it introduces a fascinating failure mode: if an agent misinterprets a requirement mid-flight and dutifully commits that hallucination back into the spec graph, it effectively gaslights every subsequent agent session built on top of that module.

Still, decoupling the IDE host layer from provider accounts while leaning on the pi coding engine makes this one of the most compelling open-source environments to drop into a local workflow this year.


ThinkRail: JetBrains' Free Agentic IDE Runs 3 Agents at Once

This video provides a quick walkthrough of how ThinkRail handles multiple concurrent agent workspaces and worktree isolation in practice.

Some comments have been hidden by the post's author - find out more