Follow Discord
Sweep 22 Oct 2026 · 04:32Z Build v2.1.308 527 read Stable v2.1.308 Latest v2.1.308 Next v2.1.308 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-docs

SSH remote sessions in Claude Desktop on 3P changedthird-party/claude-desktop/ssh-remote-sessions

Nearest release: v2.1.302, published under an hour before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 16 Oct 2026 17:34 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 16 Oct 2026 17:37 UTC.

Upstream edited
Recorded here
Lines+82added
Lines−6removed
From line 15 where the diff opens
First seen 28 Aug 2026 this site's first read of the page
Recorded edits14to this page, all time

### Alert the user with hooks on the host

The whole hunk

from line 15, old and new numbered
/
lines
from line 15
15153. **Run.** The remote server starts the engine on the host with the inference credential and policy from your managed configuration. Every file read, edit, shell command, and git operation runs on the host, in the working directory the user chose there. Claude Desktop connects to [managed MCP servers](/docs/third-party/claude-desktop/extensions#managed-mcp-servers-admin) from the device and exposes them to the engine as tools.
16164. **Stream.** Claude's responses and tool output stream back to Claude Desktop. Permission prompts appear in Claude Desktop, and the engine waits on the host until the user answers.
1717 
18The engine keeps running on the host through a dropped SSH link, device sleep, or the user quitting Claude Desktop. It finishes the current turn, or stops at a permission prompt, then idles until the user reopens the session. Reopening starts a fresh engine from the transcript stored on the host, so a turn that finished while the app was closed is shown in full; a turn still running at that moment is cut short and not continued automatically. While Claude Desktop is closed, no new turns run and the inference credential is not refreshed, so a turn that outlives the credential fails with an authentication error.
18The engine keeps running on the host through a dropped SSH link, device sleep, or the user quitting Claude Desktop. It finishes the current turn, or stops at a permission prompt, then idles until the user reopens the session. While Claude Desktop is closed, no new turns run and the inference credential is not refreshed, so a turn that outlives the credential fails with an authentication error. A restart of the app for an update counts as a quit.
1919 
20When the user reopens the session after a quit, Claude Desktop rejoins the engine or replaces it, unless it refuses to start the session:
21 
22* **Rejoins**: on a macOS or Linux device, Claude Desktop 2.42304.0 or later tries to rejoin an engine that 2.42304.0 or later started. If it rejoins, a turn still running goes on. It can fail to rejoin, for example after some Claude Desktop updates or after a change to the managed configuration since the engine started. After a quit it never rejoins on a Windows device, and never rejoins an engine that an earlier version started.
23* **Replaces**: otherwise, Claude Desktop ends the engine and starts a fresh one from the transcript stored on the host. A turn that finished while the app was closed is shown in full, and a turn that still runs is cut short. If the turn stays stopped, the user sends a message to continue it.
24 
2025On a host that ends a user's processes at logout, the remote server and the engine end with the SSH connection that started them, so a turn in progress doesn't survive a disconnect. Linux hosts where systemd-logind's `KillUserProcesses` setting is `yes` and applies to the SSH user behave this way. To keep remote sessions running through a disconnect on such a host, ask the host's administrator to exempt the SSH user, for example by listing the user under `KillExcludeUsers` in the systemd-logind configuration.
2126 
2227An idle engine stays on the host, with the credential in its environment, until one of these happens:
2328 
24* The user reopens, archives, or deletes the session.
29* The user archives or deletes the session.
30* The user reopens the session and Claude Desktop ends the engine to start a fresh one.
2531* The host restarts.
26* A Claude Desktop update replaces the remote server on the host (deferred while a session on that host was active in the last 24 hours, for up to 7 days).
32* After an update that includes a new remote server, Claude Desktop replaces the host's remote server at a later connection. This ends the engines under the old server. Claude Desktop can put the replacement off while it believes that work is running on that host.
2733* On a Linux or macOS host, 30 days pass without a connection from Claude Desktop to the remote server. The remote server then stops and ends its engines. Requires Claude Desktop 1.52386.0 or later.
2834 
2935While Claude Desktop is disconnected, the remote server keeps the most recent output of each running engine in a 16 MiB buffer. It drops older output, and the engine keeps running.
from line 36
3036 
3137On a Linux or macOS host, if Claude Desktop stayed open, it rejoins the running engine when it reconnects after device sleep or a dropped SSH link. It catches up from the buffer, and loads the part of the conversation that the buffer has dropped from the transcript stored on the host. If it can't load all of it, the session shows "Some output produced while you were disconnected may be missing here."
3238 
39Some tool calls wait for an answer from Claude Desktop, and fail while it is disconnected:
40 
41* **File tools under a folder restriction**: if you set [`allowedWorkspaceFolders`](/docs/third-party/claude-desktop/configuration#allowedworkspacefolders), Claude Desktop checks each file read, search, and edit before it happens. While Claude Desktop is disconnected, each of these calls waits up to 10 minutes and then fails.
42* **Tools that your policy sets to ask**: if [`builtinToolPolicy`](/docs/third-party/claude-desktop/configuration#builtintoolpolicy) sets a bare tool name, such as `Bash`, to `ask`, Claude Desktop is consulted before each call to that tool. While Claude Desktop is disconnected, each call waits up to 10 minutes and then fails.
43* **Tools from MCP servers that run on the device**: these include your managed MCP servers (see [Where MCP servers run in a remote session](#where-mcp-servers-run-in-a-remote-session)). While Claude Desktop is disconnected, each call to one of their tools fails after about 30 seconds. The 30-second limit requires Claude Desktop 2.2553.0 or later.
44 
45For a task that uses these tools, have the user keep the device awake and connected. For other limits, see [Limits while Desktop is disconnected](https://code.claude.com/docs/en/desktop#limits-while-desktop-is-disconnected).
46 
47### Alert the user with hooks on the host
48 
49A [hook](https://code.claude.com/docs/en/hooks) is a command of yours that the engine runs on the host at a set point in a session. With hooks, the host can tell the user that a turn is waiting at a permission prompt, has finished, or has failed with an API error, including while Claude Desktop is disconnected. To set them up, add this `hooks` key to `~/.claude/settings.json` in the SSH user's home directory on the host before the user starts the session.
50 
51```json ~/.claude/settings.json theme={null}
52{
53 "hooks": {
54 "Notification": [
55 {
56 "matcher": "permission_prompt",
57 "hooks": [{ "type": "command", "command": "/path/to/alert-user.sh" }]
58 }
59 ],
60 "Stop": [
61 { "hooks": [{ "type": "command", "command": "/path/to/alert-user.sh" }] }
62 ],
63 "StopFailure": [
64 { "hooks": [{ "type": "command", "command": "/path/to/alert-user.sh" }] }
65 ]
66 }
67}
68```
69 
70Replace `/path/to/alert-user.sh` with a script that you write and place on the host, for example one that posts to a messaging service that the host can reach. The engine runs the script as the SSH user and passes it the event as JSON on standard input, with fields such as `hook_event_name`, `session_id`, and `cwd`. The `Stop` event also carries Claude's last message, so forward only the fields that the alert needs.
71 
72Have the script print nothing and exit with code 0, because a `Stop` hook's output and exit code can keep the turn going (see [Stop decision control](https://code.claude.com/docs/en/hooks#stop-decision-control)). To confirm the setup, have the user start a remote session on the host and send a message. The script runs when Claude finishes responding.
73 
74The hooks run in these cases:
75 
76* **A permission prompt waits for the user's answer**: the [`Notification`](https://code.claude.com/docs/en/hooks#notification) hook runs once the prompt has waited about six seconds
77* **Claude finishes responding**: the [`Stop`](https://code.claude.com/docs/en/hooks#stop) hook runs
78* **An API error, such as an authentication error, ends the turn**: the [`StopFailure`](https://code.claude.com/docs/en/hooks#stopfailure) hook runs in place of `Stop`
79 
80The `Notification` hook doesn't run for a tool call that is waiting for Claude Desktop's own check. That check comes before any permission prompt for the call. Calls that wait for that check include these:
81 
82* Each file read, search, and edit, if you set [`allowedWorkspaceFolders`](/docs/third-party/claude-desktop/configuration#allowedworkspacefolders)
83* Each call to a tool that [`builtinToolPolicy`](/docs/third-party/claude-desktop/configuration#builtintoolpolicy) sets to `ask` by its bare name, such as `Bash`
84* Each call to a tool from an MCP server that runs on the device
85 
86While Claude Desktop is disconnected, each of these calls waits and then fails, after up to 10 minutes for file tools and tools set to `ask` (for each limit, see [How a remote session works](#how-a-remote-session-works)). Claude receives the failure as the call's result, and a further call of the same kind waits again, which delays the `Stop` hook. For a task that makes these calls, have the user keep the device awake and connected.
87 
88To cover every user of a host, put the hooks in [Claude Code managed settings](https://code.claude.com/docs/en/settings#settings-files) on the host instead, which on a Linux host is the file `/etc/claude-code/managed-settings.json`. If the host already has Claude Code managed settings, add the hooks to those and leave [`parentSettingsBehavior`](https://code.claude.com/docs/en/settings-reference#parentsettingsbehavior) as it is, set or unset. Changing it changes how those settings combine with the policy that Claude Desktop supplies. If the host has none yet, also set `parentSettingsBehavior` to `"merge"` in the managed settings that you create.
89 
90<Warning>
91 By default, Claude Code managed settings on the host replace the policy that Claude Desktop supplies, even if they hold only hooks (see [Managed configuration on the remote host](#managed-configuration-on-the-remote-host)). With `parentSettingsBehavior` set to `"merge"`, the policy that Claude Desktop supplies still applies, layered under the host's own policy.
92</Warning>
93 
3394### Where MCP servers run in a remote session
3495 
3596An MCP server in a remote session runs on the device or on the host, depending on how it was added.
from line 148
87148 
88149On devices where users applied the configuration locally, deploy `sshHostAllowlist` in Claude Code's managed settings. That restricts SSH without an MDM profile taking ownership of the whole configuration (see [Update keys and managed precedence](/docs/third-party/claude-desktop/mdm#update-keys-and-managed-precedence)).
89150 
151To turn off Code sessions that run on the device, so that users work in SSH remote sessions, set [`disableDesktopLocalSessions`](https://code.claude.com/docs/en/settings-reference#disabledesktoplocalsessions) to `true` in a [Claude Code managed-settings file](https://code.claude.com/docs/en/settings#settings-files) or OS policy on the device. Claude Desktop then refuses to start or resume a Code session that runs on the device. If the device already has Claude Code managed settings, add the key to those and leave `parentSettingsBehavior` as it is, set or unset. Changing it changes how those settings combine with the policy that Claude Desktop supplies. If the device has none yet, also set `parentSettingsBehavior` to `"merge"` in the managed settings that you create. Without `"merge"`, the new managed settings replace the policy that Claude Desktop supplies to Claude Code on the device (see [Interaction with Claude Code's own managed settings](/docs/third-party/claude-desktop/code#interaction-with-claude-code%E2%80%99s-own-managed-settings) on the Code page).
152 
153Before you deploy `disableDesktopLocalSessions`, make sure that the `sshHostAllowlist` that applies on the device, by [the order of its sources](#interaction-with-claude-code-managed-settings-on-the-device), allows the hosts that users need. While SSH remote sessions are off, a device that has `disableDesktopLocalSessions` set can start neither a local Code session nor an SSH remote session.
154 
90155### Devices that move to an admin console organization
91156 
92157A device that gets its SSH keys from a managed profile, a registry policy, or the profile's bootstrap server moves to the configuration from the [Enterprise Admin Console](/docs/third-party/claude-desktop/admin-console) when its user signs in to an organization that uses the console and chooses that organization in the dialog that follows. The app then restarts. A device that used such an organization before its profile arrived, and whose user hasn't signed out of the app since, moves back at its first launch on Claude Desktop 2.37337.0 or later, with no new sign-in and without asking the user, even if the stored sign-in has expired. To prevent that, add `disableDeploymentModeChooser` to the profile before devices update. `forceLoginOrgUUID` prevents it only for organizations it leaves out. Before Claude Desktop 2.37337.0, a device with such a profile ignores the admin console.
from line 219
154219Where the rules apply, they cover the following:
155220 
156221* **Claude's file tools**: they refuse to create or change a file under the path, even in bypass permissions mode. A writable entry listed inside a read-only one is read-only for them too.
157* **Shell commands that Claude runs**: Claude Code's sandbox keeps them from writing under the path on a host where it runs, which on Linux needs Claude Code's [sandbox dependencies](https://code.claude.com/docs/en/sandboxing). The sandbox doesn't cover commands listed in Claude Code's `sandbox.excludedCommands`, or a path that contains one of `* ? [ ] ( ) { } | +` or a double quote. It may not stop commands in a folder that is listed through a symbolic link, so list each read-only folder by its real path, and keep it outside writable entries. On a host where the sandbox doesn't run, shell commands can still change the folder. For how the app reports that, see [Sandbox status on the remote host](#sandbox-status-on-the-remote-host).
222* **Shell commands that Claude runs with its Bash tool**: Claude Code's sandbox keeps them from writing under the path on a host where it runs, which on Linux needs Claude Code's [sandbox dependencies](https://code.claude.com/docs/en/sandboxing). The sandbox doesn't cover commands listed in Claude Code's `sandbox.excludedCommands`, or a path that contains one of `* ? [ ] ( ) { } | +` or a double quote. It may not stop commands in a folder that is listed through a symbolic link, so list each read-only folder by its real path, and keep it outside writable entries. On a host where the sandbox doesn't run, shell commands can still change the folder. For how the app reports that, see [Sandbox status on the remote host](#sandbox-status-on-the-remote-host).
158223 
159The rules don't bind the SSH user, or other programs that run under that account. MCP servers on the host, hooks from Claude Code's configuration on the host, and the session's terminal can change the folder, and Claude Desktop and Claude Code can create git worktrees inside it.
224The rules don't bind the SSH user, or other programs that run under that account. MCP servers on the host, hooks from Claude Code's configuration on the host, and the session's terminal (including commands that Claude runs there) can change the folder, and Claude Desktop and Claude Code can create git worktrees inside it.
160225 
161226### Sandbox status on the remote host
162227 
from line 238
173238| Your organization's sandbox policy isn't fully applied on `<host>`, so shell commands there may run outside it | `overridden` | Claude Code managed settings on the host replace your policy, even when they say nothing about the sandbox, or they turn the sandbox off or loosen it | Set `parentSettingsBehavior` to `"merge"` in the host's managed settings, and remove `sandbox` values there that conflict with your policy |
174239| No message | `unknown` | Claude Code gives no answer that Claude Desktop can read | In a session on that host, ask Claude to run the two commands under [Confirm commands run inside the sandbox](https://code.claude.com/docs/en/sandboxing#confirm-commands-run-inside-the-sandbox) |
175240 
241To check one session, have the user open it, wait until Claude has finished replying, and enter `/status` in the message box. Where your policy includes the sandbox, the **Session info** card shows what Claude Desktop last learned in a **Sandbox** row. Requires Claude Desktop 2.31226.0 or later. Find the value's `reason` in the table of messages and reasons for the cause and the fix:
242 
243* **On · Strict**: no reason. Claude Code reports the sandbox from your policy turned on and running.
244* **Off · can't start**: `cannot_start` or `unsupported`
245* **Off**: `overridden`, and Claude Code reports no sandbox running
246* **On · not fully applied**: `overridden`, and Claude Code reports a sandbox that Claude Desktop can't match to your policy
247* **Couldn't check**: `unknown`
248 
249If the card has no **Sandbox** row, have the user send a message, and enter `/status` again after Claude's reply.
250 
176251With [`otlpEndpoint`](/docs/third-party/claude-desktop/configuration#otlpendpoint) set, your collector receives a `desktop_ssh_sandbox_check_failed` event under the `service.name` value `claude-desktop`, unless [`otlpDesktopLogLevel`](/docs/third-party/claude-desktop/configuration#otlpdesktoploglevel) is `off`. A session can send the event more than once, for example when the reason changes or after Claude Desktop restarts, so count distinct `session_id` values rather than events. The event carries these attributes:
177252 
178253* **`reason`**: `cannot_start`, `unsupported`, `overridden`, or `unknown`
from line 300
225300 
226301* For hosts behind a bastion, configure a `ProxyJump` or `ProxyCommand`. `ProxyJump` works only when the device's OpenSSH client carries the connection (the default on macOS and Linux). The built-in client refuses it. For the card that the user sees, see [Ask your IT administrator to set sshTransport to system-openssh](#ask-your-it-administrator-to-set-sshtransport-to-system-openssh).
227302* With the device's OpenSSH client, OpenSSH's own host key checking applies. For a host whose key isn't on record yet, where the app can show a prompt, it shows the key's fingerprint, asks the user whether to trust it, and records a trusted key in the user's `known_hosts` file, unless the user's own SSH configuration accepts new keys without asking. The app can't show a prompt on every connection, for example when it reconnects in the background. Distribute the host keys or a host certificate authority to the devices, so that each host's key is on record before users connect. `@cert-authority` entries are honored. A key that differs from the one on record for the host is refused, whatever the entry's `StrictHostKeyChecking` says, unless another setting in the SSH configuration that applies to the host takes that check away, such as `NoHostAuthenticationForLocalhost yes` for a host on a loopback address.
303* With the device's OpenSSH client, you can keep the app from asking users to trust the key of a host that isn't on record yet. Distribute the host keys in the client's system-wide `known_hosts` file, such as `/etc/ssh/ssh_known_hosts`, or distribute a host certificate authority. Then set `StrictHostKeyChecking yes`, for example under `Host *`, in the client's system-wide configuration file, such as `/etc/ssh/ssh_config`, which also governs other uses of that client, such as `git` over SSH. Where the SSH configuration that applies to a host has `StrictHostKeyChecking yes`, Claude Desktop doesn't ask the user to trust such a key, and `ssh` refuses the host if it can't verify the key. A key that differs from the one on record is handled the same way with or without this setting. The setting doesn't bind the user. By OpenSSH's own rules, `ssh` reads the user's `~/.ssh/config` before the system-wide file and keeps the first value it finds for a setting, so a `StrictHostKeyChecking` line there applies in place of yours. `ssh` also accepts a key that the user adds to their own `known_hosts` file, but under `yes` a connection from a terminal doesn't record the key.
228304* With the built-in client, the host's key must already be in the device's `~/.ssh/known_hosts` as a plain entry. The app does not prompt to accept a new key and does not evaluate `@cert-authority` entries, so have users connect once from a terminal before adding the host in the app.
229305* With the built-in client, an identity file protected by a passphrase is skipped, not prompted for. Load it into the SSH agent, or use an unencrypted key. With the device's OpenSSH client, the app asks for the passphrase once the host's key is verified, and skips the key if the user cancels.
230306* With the built-in client, a host reached through a `ProxyCommand` gets the same host key check as a host reached directly. Before Claude Desktop 2.9939.0, the built-in client skipped host key verification for such a host.
Feedback