Claude Code on the web vs desktop vs terminal: what actually changes
The same agent has four front doors and they are not equivalent. Cloud sessions clone GitHub rather than your disk, silently ignore two permission modes from your settings files, and drop half a dozen commands. What each surface adds, what each one quietly takes away, and how to pick per task.
Claude Code now has four front doors: the terminal, the VS Code and JetBrains extensions, the desktop app, and Claude Code on the web. People search "terminal vs desktop app" and "terminal vs vscode vs desktop app" because the marketing implies they are the same product with different chrome, and they are not.
The useful split is not graphical versus terminal. It is where the session runs. The terminal, the extensions, and desktop local sessions all execute on your machine, against your files, reading your ~/.claude. Cloud sessions execute on someone else's VM against a fresh clone. Almost every surprise below falls out of that one line.
Where we speak from: we run the terminal all day and use Remote Control to watch it from a phone. The desktop, extension, and cloud specifics here are assembled from the documentation, because a feature matrix nobody has published is more useful than another opinion.
The one that surprises everyone: cloud sessions do not see your disk
claude --cloud "fix the auth bug" does not upload your working directory. The cloud VM clones your current directory's GitHub remote at your current branch. Local commits that you have not pushed are not there. This is the single most common way a cloud task produces confusing results, and it is a one-line fix: push first.
There is a fallback for repositories with no GitHub remote. Claude Code bundles the local repository and uploads it, with real constraints worth knowing before you rely on it:
- Under 100 MB, with degradation steps above that: current branch only, then a squashed snapshot, then failure.
- Untracked files are not included.
git addanything you want the session to see. - On macOS, Linux, and WSL, uncommitted changes to credential-shaped files are left out and named for you:
.env, Terraform*.tfvars,id_rsa,*.pem. The session gets the committed version or nothing. - A session created from a bundle cannot push back unless you have GitHub auth configured separately.
Force the bundle path with CCR_FORCE_BUNDLE=1 when you want it even though GitHub is connected.
What cloud sessions silently drop
This is the part worth printing out, because most of it fails quietly rather than loudly.
Two permission modes are ignored from your settings files. Cloud sessions do not honor defaultMode: "bypassPermissions" or "dontAsk". A repository's checked-in settings cannot start a cloud session in either one. The setting is ignored without a warning and the session starts in whatever the mode dropdown shows. The dropdown itself offers Accept edits, Plan, and Auto only, and Accept edits is what default maps to, because cloud sessions pre-approve file edits regardless of mode. If you have been reasoning about what the bypass flag turns off, none of it applies here.
Commands behave differently or not at all. /clear does not exist; you start a new session from the sidebar. /plugin and /resume are terminal-only. /model, /effort, /fast, /color, and /rename need the value as an argument (/model sonnet) because there is no picker to open. /config opens your settings page and ignores anything you type after it, including key=value.
Plugins need a different install path. Plugins you installed from the desktop app are not available in cloud sessions. Declare them in the repository's .claude/settings.json under enabledPlugins so they install at session start, or enable them for your claude.ai account as synced plugins. The plugin model is the same; the delivery is not.
Compaction fires earlier than you configured. The platform sets CLAUDE_AUTOCOMPACT_PCT_OVERRIDE in cloud sessions itself, and that value overrides one you put in your environment variables. To move the window, use CLAUDE_CODE_AUTO_COMPACT_WINDOW instead. Worth knowing if you have tuned context economics locally and expect it to carry over.
Environments expire. Sessions stop after inactivity and the VM is reclaimed. Reopening provisions a fresh one with conversation history restored, but background work that was running is not restored, including subagents and shell commands.
IP allowlisting breaks it entirely. If your organization allowlists IPs, every Anthropic-hosted cloud session fails with an authentication error, because those sessions call the API from Anthropic's infrastructure rather than your network. The same applies to managed Code Review. Self-hosted environments are the exception.
One more that shapes workflow: handoff from the CLI is one-way. --teleport pulls a cloud session into your terminal. You cannot push an existing terminal session to the web. Only the desktop app's Continue in menu can send a local session to the cloud, and that needs a clean working tree.
What the desktop app adds
The desktop app runs the same engine and reads the same settings files as the CLI, so CLAUDE.md, hooks, skills, MCP servers from ~/.claude.json and .mcp.json, and permission rules all apply. You can run both on the same project simultaneously; they keep separate session history and share configuration.
What it genuinely adds:
- Parallel sessions with git isolation. Each new session gets its own worktree under
<project-root>/.claude/worktrees/, so two tasks cannot step on each other before you commit. Configurable location and branch prefix, with optional auto-archive when a PR merges. - MCP servers from the chat app. The desktop loads
claude_desktop_config.jsoninto local Code tab sessions. The standalone CLI does not read that file at all; useclaude mcp add-from-claude-desktopto copy them across. - Visual diff review, an integrated terminal and editor, PR monitoring, and connectors with a graphical setup flow.
Three asymmetries to keep straight. dontAsk is CLI only. A mode you pick in the selector is remembered per folder and takes precedence over defaultMode, except Plan, which is per session. And when Claude looks across your sessions, it sees only the ones the desktop app runs itself: not cloud sessions, not terminal sessions, not VS Code ones, even in worktrees of the same project.
The Customize configuration is also its own thing. The Cowork tab sources skills, plugins, and connectors from your claude.ai account rather than from the CLI's ~/.claude directory, which is a reasonable design and a confusing one if you assume a single source of truth.
What the extensions do differently
The VS Code extension is the recommended way to use Claude Code inside VS Code, and it adds plan editing before acceptance, @-mentions with line ranges from your selection, and multiple conversations in tabs or windows.
The trap is configuration. Sessions the VS Code extension starts do not read project settings for the starting permission mode. Set claudeCode.initialPermissionMode in your VS Code user settings instead, noting that it accepts default, manual, acceptEdits, plan, and bypassPermissions but not auto. To start in Auto you leave it unset and pick Auto from the mode indicator once. Bypass additionally requires the extension's own Allow dangerously skip permissions toggle, and without it a bypassPermissions value starts the conversation in Manual instead.
How to pick
- Terminal: the reference implementation. Everything exists here first,
dontAskexists only here, and it is the only surface where the full command set and hook lifecycle are guaranteed. Pair it with Remote Control when you want your phone in the loop without giving up any of that. - Desktop: when you want several tasks running in parallel with real git isolation and a diff view, without wiring worktrees yourself. Also the only way to push a local session to the cloud.
- VS Code or JetBrains: when the work is read-heavy and you want the agent next to the code you are already reading. Check the permission mode setting once, because the project-settings gap will bite exactly once and confusingly.
- Web: for work that is genuinely detachable. Something you can describe fully, that runs on a pushed branch, that you want to keep running after the laptop closes. The right shape is plan locally, push, then
claude --cloud "execute the plan in docs/plan.md", which sidesteps the clone-not-your-disk problem by making the plan part of the repository.
The mental model that survives all four: the surface changes what you can see and how many things you can run at once, but only cloud versus local changes what the agent can actually reach. Every quiet failure in this post is a version of forgetting which side of that line you are on.