Skip to content

No offline mode: client keeps persistent connections to app.warp.dev when logged out with all privacy settings off #15599

Description

@one-kash

Summary

There is no setting to stop Warp's background connections to its servers. Even when logged out, with telemetry, crash reporting, AI, and settings sync all disabled, the client holds two persistent TLS connections open to app.warp.dev. No privacy setting, the Warp Drive toggle, or logging out fully closes them.

Observed behavior

macOS, Stable channel, 2026-08-27. Connections to Warp's backend at 34.117.41.85 (which app.warp.dev, rtc.app.warp.dev, oz.warp.dev, and sessions.app.warp.dev all resolve to) across states, with telemetry_enabled, crash_reporting_enabled, is_any_ai_enabled, and is_settings_sync_enabled all false:

State Persistent connections to app.warp.dev
Logged in, Warp Drive on 3 (including the realtime subscription socket)
warp_drive.enabled set to false (hot-reload) 3 (no change)
Logged out 2 (realtime socket dropped, two remain)

The two remaining connections stayed established and active across repeated samples.

Where

The persistent connection is opened by the cloud-object sync layer, which subscribes over a websocket to the GraphQL endpoint:

/// Starts a websocket connections against the corresponding GraphQL subscription.
/// Messages received over the socket are sent over the `message_sender`.
/// Once the websocket is live, a one-shot message is sent over `stream_ready_sender`
/// to indicate so. This is because this method only returns once the websocket is closed.
async fn get_warp_drive_updates(
&self,
message_sender: Sender<ObjectUpdateMessage>,
stream_ready_sender: Sender<()>,
) -> Result<()> {
// The init payload is how we convey any metadata about
// the subscription to the server (i.e. in lieu of http headers).
// TODO (written by Suraj): we should consider consolidating the places we
// supply this common data. GQL subscriptions use a different
// implementation from our general server requests (which make
// use of [`crate::http`]).
let mut init_payload = HashMap::new();
// Add the bearer token to the init payload when using header-based auth.
// Session-cookie-authenticated clients rely on the websocket handshake cookies instead.
let auth_token = self.get_or_refresh_access_token().await?;
if let Some(token) = auth_token.as_bearer_token() {
let bearer_token = format!("Bearer {token}");
init_payload.insert(http_client::AUTHORIZATION.as_str(), bearer_token);
}
// Add the app version, if available.
if let Some(app_version) = ChannelState::app_version() {
init_payload.insert(
http_client::headers::CLIENT_RELEASE_VERSION_HEADER_KEY,
app_version.to_string(),
);
}
let subscription = GetWarpDriveUpdates::build(());
let result = start_graphql_streaming_operation(
&ChannelState::ws_server_url(),

No offline, network-disable, or work-offline setting exists in the settings definitions (app/src/settings/*, crates/settings). The privacy settings only gate telemetry, crash reporting, and cloud conversation storage.

The onboarding copy states that non-cloud features work offline:

let paragraph_2 = "However, we require users to be online when using Warp for the first time in order to enable Warp's AI and cloud features.";
let paragraph_3 = "We offer cloud features to all users, and so we need an internet connection to meter AI usage, prevent abuse, and associate cloud objects with users. If you opt to use Warp logged-out, a unique ID will be attached to an anonymous user account in order to support these features.";

In practice the client keeps connections open regardless of whether cloud features are in use.

Expected

Provide an offline mode, or a setting to stop background connections to Warp servers when the user has opted out of cloud features and AI. If some connection is required, document what it is and why it cannot be disabled, so the "works offline" statement is accurate.

Caveats for accuracy

Observed live within one running process; logging out tore down one socket in real time, so this is not a cold-start test. The four *.warp.dev hostnames share the GCP load-balancer IP 34.117.41.85, so I did not separate the two remaining connections by hostname without a root-level SNI capture. Read from the open-source client at commit ead591e.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:authAuthentication, login, SSO, session management, and account security.area:settings-keybindingsSettings UI, preferences, keybindings, and keyboard-shortcut management.area:warp-driveWarp Drive objects, sync, sharing, cloud object management, and persisted artifacts.documentationImprovements or additions to documentation.duplicateThis issue or pull request already exists.enhancementNew feature or request.os:macmacOS-specific behavior, regressions, or requests.repro:mediumThe report suggests a plausible repro path, but some uncertainty remains.triagedIssue has received an initial automated triage pass.warp:auto-triage-review

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions