One Agent, Many Surfaces: They Share a Model and Nothing Else
Two sessions on two surfaces, same repository, same moment. They are two independent agents that happen to share a login.
The surfaces share a model, not a context
The same agent is now reachable from a terminal, from inside an editor, from a desktop application, from a browser, and from a hosted runner triggered by a pull request. It is natural to think of these as views onto one thing, because the underlying model and your account are common to all of them.
Almost nothing else is. Each surface has its own conversation, its own idea of what files are relevant, its own permission configuration, its own environment, and its own notion of what "the project" means. Two sessions on two surfaces working on the same repository at the same time are two independent agents that happen to share a login.
Once you hold that clearly, a whole category of confusion resolves — including the most common complaint about multi-surface tooling, which is that the same request produces different results depending on where you made it.
What differs, concretely
The environment. A terminal session has your shell, your running services, your authenticated CLIs. A hosted runner has none of them and a clean checkout instead. Identical instructions produce different behaviour because the machine is different.
The implicit context. An editor integration knows what file you have open, what you have selected, and what your language server is complaining about. A terminal session knows the working directory. That implicit context is why "fix this" works in one place and is meaningless in another.
The permissions. Configuration for what an agent may do is per-surface more often than people realise, and the assumption that a rule set in one place applies everywhere is a documented source of bugs rather than a theoretical concern.
The session. Conversations do not follow you. What you established in the terminal — corrections, decisions, context you built up — is not present when you continue in the editor.
The repository is the only shared substrate
This is the practical conclusion and it is worth stating plainly: if you want consistent behaviour across surfaces, it has to come from files in the repository, because the repository is the only thing all of them see.
Instructions in a checked-in file apply everywhere. Instructions given in a conversation apply to that conversation. The same is true of permission configuration committed to the project, of hooks kept in the repository, and of the one canonical test command — each of them is a way of moving behaviour from a surface into the substrate.
Which means the multi-surface question has the same answer as most other questions in this area: put it in the repository. The layered structure for doing that well is in layered instruction design.
"It worked in the CLI"
The characteristic bug report. A task succeeds in one surface and fails in another, and the natural conclusion is that one of them is broken.
Usually neither is. The terminal session had a running database, an authenticated cloud CLI and a virtual environment active; the hosted runner had a clean checkout and no network. Both agents behaved correctly given what they could see. The difference is environment, and it is the same undeclared-state problem as local execution and reproducibility, arriving through a different door.
The diagnostic is to ask what each surface could reach, not what each was told.
Permission configuration is the one to check
Of the differences, this is the one with security consequences rather than merely confusing ones. If you have carefully denied reads of your environment files, it is worth verifying that the denial holds in every surface you use rather than in the one where you configured it.
The check is trivial — ask each surface to read a file that should be denied — and it is worth doing after any tooling update, because this is precisely the class of behaviour that changes quietly between versions. A control you have verified in one surface is not a control you have.
Editor integrations in particular have a history of attaching context by mechanisms that predate or bypass the agent's own file-access rules. Do not assume a rule configured for the terminal governs what an editor sends.
Choose the surface by the shape of the task
Once you stop expecting uniformity, the surfaces become a menu rather than a redundancy, and each has work it is best at.
The terminal is for anything needing your real environment: debugging against live services, host work, anything involving your authenticated tooling. The editor is for focused changes where the file you are looking at is the context, and where seeing diffs inline matters. A hosted runner is for work that should happen in a clean, declared environment against a pull request. The browser and mobile surfaces are for reading, reviewing and directing — not for authoring, because the feedback loop is too slow to correct a wrong turn cheaply.
Do not author on a surface you cannot interrupt quickly
Following from that. The value of watching an agent's opening moves depends on being able to stop it within seconds, and that is a property of the surface: a terminal gives it to you, a phone does not.
So the surfaces with slow interaction loops should be used for work that is already bounded — approving a plan, reading a result, kicking off a task with a machine-checkable done condition. Starting an open-ended task from a surface where correction is expensive combines the worst properties of both models.
Handing off between surfaces
Since sessions do not travel, moving work from one surface to another means recreating context deliberately. The mechanism that works is writing it down: a plan file, a scratch document in the repository, or a well-written pull request description.
This sounds like overhead and it is mostly a good discipline anyway, because the same artefact is what a colleague needs and what your future self needs after a weekend. Context that exists only in a conversation is context that is one surface switch away from being lost.
Two surfaces on one repository at once
Worth being careful about. An editor session and a terminal session working in the same checkout are two agents editing the same files with no knowledge of each other, and the result is exactly what you would expect: one overwrites the other's work, or both read a file mid-edit by the other.
If you want genuine concurrency, use separate working trees so the file systems are disjoint, which is the mechanism covered in orchestrating parallel agent sessions. Sharing one checkout between surfaces is not concurrency, it is a race.
What this means for a team
Two implications. First, standardise on the repository-level configuration and be relaxed about which surface people use — that is where consistency can actually be enforced, and personal preference about interface is not worth legislating.
Second, when someone reports different behaviour, ask which surface before anything else. It is the first question and it is almost never the first question asked, so a lot of time gets spent debugging a discrepancy that is fully explained by one person using an editor and the other a terminal.
The genuine benefit of many surfaces
Having been sceptical throughout, the upside is real: work can start where the trigger is. A failing build gets a response from a runner. A code review comment gets addressed from the browser. A thought on the way home becomes a task from a phone. A focused change happens in the editor where the file is already open.
That is a genuine reduction in friction, and it works well as long as nobody expects the surfaces to behave identically. They are different tools sharing a model, and treating them as one tool with several front doors is what produces the confusion.
Onboarding is where the differences bite hardest
Someone new to a team picks a surface, usually the one a colleague recommended, and their first weeks are shaped by it. If your repository configuration is thin and behaviour comes mostly from per-surface settings, that person's experience is essentially unrelated to the one the team describes.
The symptom is a new joiner who cannot get an agent to behave the way everyone says it does. Nobody can reproduce the problem because nobody else is on that surface. The answer is not to standardise the surface but to move enough into the repository that the surface stops mattering, which benefits everyone rather than only the new person.
The hosted runner is a different kind of surface
Worth calling out separately because it is the one people misjudge. A runner is not a remote version of your terminal — it is an unattended execution environment with credentials, running against a pull request, usually with no human watching.
Everything about it should be more constrained than an interactive session: tighter permissions, narrower egress, no interactive approvals to lean on, and a machine-checkable objective, because nothing else will catch a wrong turn. Treating it as "the same agent, elsewhere" imports habits from a supervised context into an unsupervised one, which is the wrong direction of travel.
Pick one surface for the work that matters
A closing suggestion. Variety is fine for exploration and worse for the work you depend on. For your team's main flow, pick one surface, configure it properly, verify its controls, and write down what it is. Use the others freely for what they are good at.
That gives you one arrangement you have actually checked, rather than five you have assumed, and it makes every subsequent question — about a permission, an environment difference, a surprising behaviour — answerable rather than dependent on who is asking.
If you take one operational habit from this: when anything surprising happens, the first question is which surface, and the second is what that surface could reach. Those two answers resolve most of the confusion in this area, and asking them takes ten seconds against the twenty minutes usually spent assuming the tool is inconsistent.
And a small thing that saves a lot of confusion: when you write down a procedure for your team, say which surface it assumes. Half the instructions circulating in most organisations are surface-specific and presented as general, which is why they work for the person who wrote them and not for the person who followed them.
Sessions do not merge, and neither do their conclusions
A last consequence worth drawing out. Because each surface holds its own conversation, corrections you make in one do not propagate. Explaining a convention in the terminal on Monday does nothing for the editor session on Tuesday, and the agent will make the same mistake with the same confidence.
People experience this as the agent not learning, and it is not a memory failure — it is that the correction was made in a place that does not persist. The fix is the same as everything else here: when a correction is worth keeping, it goes in a file rather than in a reply. That is the only mechanism by which anything you say survives the session it was said in.
The compact version, for a team wiki: consistency lives in the repository, because that is the only thing every surface reads. Everything you configure in a surface applies to that surface. Everything you say in a conversation applies to that conversation. Anything you want to be true everywhere goes in a file and gets committed, and that rule alone resolves most of the confusion people have about why the same agent behaves differently in two places.
The surfaces share a model and an account, and almost nothing else — not the conversation, not the environment, not the implicit context, and often not the permission rules. So consistency has to live in the repository, which is the only substrate all of them read. Verify file-access denials separately in every surface you use, choose the surface by the shape of the task, do not author from one you cannot interrupt within seconds, and never run two surfaces against one checkout.