Remove Claude upsell (#52831)

Self-Review Checklist:

- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

Release Notes:

- Removed the (broken) Claude ACP upsell dialogue
This commit is contained in:
Conrad Irwin 2026-03-31 20:10:05 -06:00 committed by GitHub
parent 3b6252ca80
commit 4087d9f2ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 23 additions and 300 deletions

View file

@ -21,8 +21,8 @@ use settings::{LanguageModelProviderSetting, LanguageModelSelection};
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use zed_actions::agent::{
AddSelectionToThread, ConflictContent, OpenClaudeAgentOnboardingModal, ReauthenticateAgent,
ResolveConflictedFilesWithAgent, ResolveConflictsWithAgent, ReviewBranchDiff,
AddSelectionToThread, ConflictContent, ReauthenticateAgent, ResolveConflictedFilesWithAgent,
ResolveConflictsWithAgent, ReviewBranchDiff,
};
use crate::{
@ -40,7 +40,7 @@ use crate::{
};
use crate::{
DEFAULT_THREAD_TITLE,
ui::{AcpOnboardingModal, ClaudeCodeOnboardingModal, HoldForDefault},
ui::{AcpOnboardingModal, HoldForDefault},
};
use crate::{ExpandMessageEditor, ThreadHistoryView};
use crate::{ManageProfiles, ThreadHistoryViewEvent};
@ -245,11 +245,6 @@ pub fn init(cx: &mut App) {
.register_action(|workspace, _: &OpenAcpOnboardingModal, window, cx| {
AcpOnboardingModal::toggle(workspace, window, cx)
})
.register_action(
|workspace, _: &OpenClaudeAgentOnboardingModal, window, cx| {
ClaudeCodeOnboardingModal::toggle(workspace, window, cx)
},
)
.register_action(|_workspace, _: &ResetOnboarding, window, cx| {
window.dispatch_action(workspace::RestoreBanner.boxed_clone(), cx);
window.refresh();

View file

@ -1,6 +1,5 @@
mod acp_onboarding_modal;
mod agent_notification;
mod claude_agent_onboarding_modal;
mod end_trial_upsell;
mod hold_for_default;
mod mention_crease;
@ -9,7 +8,6 @@ mod undo_reject_toast;
pub use acp_onboarding_modal::*;
pub use agent_notification::*;
pub use claude_agent_onboarding_modal::*;
pub use end_trial_upsell::*;
pub use hold_for_default::*;
pub use mention_crease::*;

View file

@ -1,261 +0,0 @@
use agent_servers::CLAUDE_AGENT_ID;
use gpui::{
ClickEvent, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, MouseDownEvent, Render,
linear_color_stop, linear_gradient,
};
use ui::{TintColor, Vector, VectorName, prelude::*};
use workspace::{ModalView, Workspace};
use crate::{Agent, agent_panel::AgentPanel};
macro_rules! claude_agent_onboarding_event {
($name:expr) => {
telemetry::event!($name, source = "ACP Claude Code Onboarding");
};
($name:expr, $($key:ident $(= $value:expr)?),+ $(,)?) => {
telemetry::event!($name, source = "ACP Claude Code Onboarding", $($key $(= $value)?),+);
};
}
pub struct ClaudeCodeOnboardingModal {
focus_handle: FocusHandle,
workspace: Entity<Workspace>,
}
impl ClaudeCodeOnboardingModal {
pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context<Workspace>) {
let workspace_entity = cx.entity();
workspace.toggle_modal(window, cx, |_window, cx| Self {
workspace: workspace_entity,
focus_handle: cx.focus_handle(),
});
}
fn open_panel(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
self.workspace.update(cx, |workspace, cx| {
workspace.focus_panel::<AgentPanel>(window, cx);
if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
panel.update(cx, |panel, cx| {
panel.new_agent_thread(
Agent::Custom {
id: CLAUDE_AGENT_ID.into(),
},
window,
cx,
);
});
}
});
cx.emit(DismissEvent);
claude_agent_onboarding_event!("Open Panel Clicked");
}
fn view_docs(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
window.dispatch_action(Box::new(zed_actions::AcpRegistry), cx);
cx.notify();
claude_agent_onboarding_event!("Documentation Link Clicked");
}
fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
}
impl EventEmitter<DismissEvent> for ClaudeCodeOnboardingModal {}
impl Focusable for ClaudeCodeOnboardingModal {
fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl ModalView for ClaudeCodeOnboardingModal {}
impl Render for ClaudeCodeOnboardingModal {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let illustration_element = |icon: IconName, label: Option<SharedString>, opacity: f32| {
h_flex()
.px_1()
.py_0p5()
.gap_1()
.rounded_sm()
.bg(cx.theme().colors().element_active.opacity(0.05))
.border_1()
.border_color(cx.theme().colors().border)
.border_dashed()
.child(
Icon::new(icon)
.size(IconSize::Small)
.color(Color::Custom(cx.theme().colors().text_muted.opacity(0.15))),
)
.map(|this| {
if let Some(label_text) = label {
this.child(
Label::new(label_text)
.size(LabelSize::Small)
.color(Color::Muted),
)
} else {
this.child(
div().w_16().h_1().rounded_full().bg(cx
.theme()
.colors()
.element_active
.opacity(0.6)),
)
}
})
.opacity(opacity)
};
let illustration = h_flex()
.relative()
.h(rems_from_px(126.))
.bg(cx.theme().colors().editor_background)
.border_b_1()
.border_color(cx.theme().colors().border_variant)
.justify_center()
.gap_8()
.rounded_t_md()
.overflow_hidden()
.child(
div().absolute().inset_0().w(px(515.)).h(px(126.)).child(
Vector::new(VectorName::AcpGrid, rems_from_px(515.), rems_from_px(126.))
.color(ui::Color::Custom(cx.theme().colors().text.opacity(0.02))),
),
)
.child(div().absolute().inset_0().size_full().bg(linear_gradient(
0.,
linear_color_stop(
cx.theme().colors().elevated_surface_background.opacity(0.1),
0.9,
),
linear_color_stop(
cx.theme().colors().elevated_surface_background.opacity(0.),
0.,
),
)))
.child(
div()
.absolute()
.inset_0()
.size_full()
.bg(gpui::black().opacity(0.15)),
)
.child(
Vector::new(
VectorName::AcpLogoSerif,
rems_from_px(257.),
rems_from_px(47.),
)
.color(ui::Color::Custom(cx.theme().colors().text.opacity(0.8))),
)
.child(
v_flex()
.gap_1p5()
.child(illustration_element(IconName::Stop, None, 0.15))
.child(illustration_element(
IconName::AiGemini,
Some("New Gemini CLI Thread".into()),
0.3,
))
.child(
h_flex()
.pl_1()
.pr_2()
.py_0p5()
.gap_1()
.rounded_sm()
.bg(cx.theme().colors().element_active.opacity(0.2))
.border_1()
.border_color(cx.theme().colors().border)
.child(
Icon::new(IconName::AiClaude)
.size(IconSize::Small)
.color(Color::Muted),
)
.child(Label::new("New Claude Agent Thread").size(LabelSize::Small)),
)
.child(illustration_element(
IconName::Stop,
Some("Your Agent Here".into()),
0.3,
))
.child(illustration_element(IconName::Stop, None, 0.15)),
);
let heading = v_flex()
.w_full()
.gap_1()
.child(
Label::new("Beta Release")
.size(LabelSize::Small)
.color(Color::Muted),
)
.child(Headline::new("Claude Agent: Natively in Zed").size(HeadlineSize::Large));
let copy = "Powered by the Agent Client Protocol, you can now run Claude Agent as\na first-class citizen in Zed's agent panel.";
let open_panel_button = Button::new("open-panel", "Start with Claude Agent")
.style(ButtonStyle::Tinted(TintColor::Accent))
.full_width()
.on_click(cx.listener(Self::open_panel));
let docs_button = Button::new("add-other-agents", "Add Other Agents")
.end_icon(
Icon::new(IconName::ArrowUpRight)
.size(IconSize::Indicator)
.color(Color::Muted),
)
.full_width()
.on_click(cx.listener(Self::view_docs));
let close_button = h_flex().absolute().top_2().right_2().child(
IconButton::new("cancel", IconName::Close).on_click(cx.listener(
|_, _: &ClickEvent, _window, cx| {
claude_agent_onboarding_event!("Canceled", trigger = "X click");
cx.emit(DismissEvent);
},
)),
);
v_flex()
.id("acp-onboarding")
.key_context("AcpOnboardingModal")
.relative()
.w(rems(34.))
.h_full()
.elevation_3(cx)
.track_focus(&self.focus_handle(cx))
.overflow_hidden()
.on_action(cx.listener(Self::cancel))
.on_action(cx.listener(|_, _: &menu::Cancel, _window, cx| {
claude_agent_onboarding_event!("Canceled", trigger = "Action");
cx.emit(DismissEvent);
}))
.on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, window, cx| {
this.focus_handle.focus(window, cx);
}))
.child(illustration)
.child(
v_flex()
.p_4()
.gap_2()
.child(heading)
.child(Label::new(copy).color(Color::Muted))
.child(
v_flex()
.w_full()
.mt_2()
.gap_1()
.child(open_panel_button)
.child(docs_button),
),
)
.child(close_button)
}
}

View file

@ -1,3 +1,7 @@
// This module provides infrastructure for showing onboarding banners in the title bar.
// It's currently not in use but is kept for future feature announcements.
#![allow(dead_code)]
use gpui::{Action, Entity, Global, Render, SharedString};
use ui::{ButtonLike, Tooltip, prelude::*};
use util::ResultExt;
@ -94,21 +98,21 @@ fn persist_dismissed(source: &str, cx: &mut App) {
}
pub fn restore_banner(cx: &mut App) {
cx.defer(|cx| {
cx.global::<BannerGlobal>()
.entity
.clone()
.update(cx, |this, cx| {
if let Some(banner_global) = cx.try_global::<BannerGlobal>() {
let entity = banner_global.entity.clone();
cx.defer(move |cx| {
entity.update(cx, |this, cx| {
this.dismissed = false;
cx.notify();
});
});
});
let source = &cx.global::<BannerGlobal>().entity.read(cx).source;
let dismissed_at = dismissed_at_key(source);
let kvp = db::kvp::KeyValueStore::global(cx);
cx.spawn(async move |_| kvp.delete_kvp(dismissed_at).await)
.detach_and_log_err(cx);
let source = &cx.global::<BannerGlobal>().entity.read(cx).source;
let dismissed_at = dismissed_at_key(source);
let kvp = db::kvp::KeyValueStore::global(cx);
cx.spawn(async move |_| kvp.delete_kvp(dismissed_at).await)
.detach_and_log_err(cx);
}
}
impl Render for OnboardingBanner {

View file

@ -155,7 +155,7 @@ pub struct TitleBar {
multi_workspace: Option<WeakEntity<MultiWorkspace>>,
application_menu: Option<Entity<ApplicationMenu>>,
_subscriptions: Vec<Subscription>,
banner: Entity<OnboardingBanner>,
banner: Option<Entity<OnboardingBanner>>,
update_version: Entity<UpdateVersion>,
screen_share_popover_handle: PopoverMenuHandle<ContextMenu>,
_diagnostics_subscription: Option<gpui::Subscription>,
@ -246,7 +246,9 @@ impl Render for TitleBar {
children.push(self.render_collaborator_list(window, cx).into_any_element());
if title_bar_settings.show_onboarding_banner {
children.push(self.banner.clone().into_any_element())
if let Some(banner) = &self.banner {
children.push(banner.clone().into_any_element())
}
}
let status = self.client.status();
@ -385,19 +387,6 @@ impl TitleBar {
}));
}
let banner = cx.new(|cx| {
OnboardingBanner::new(
"ACP Claude Code Onboarding",
IconName::AiClaude,
"Claude Agent",
Some("Introducing:".into()),
zed_actions::agent::OpenClaudeAgentOnboardingModal.boxed_clone(),
cx,
)
// When updating this to a non-AI feature release, remove this line.
.visible_when(|cx| !project::DisableAiSettings::get_global(cx).disable_ai)
});
let update_version = cx.new(|cx| UpdateVersion::new(cx));
let platform_titlebar = cx.new(|cx| {
let mut titlebar = PlatformTitleBar::new(id, cx);
@ -416,7 +405,7 @@ impl TitleBar {
user_store,
client,
_subscriptions: subscriptions,
banner,
banner: None,
update_version,
screen_share_popover_handle: PopoverMenuHandle::default(),
_diagnostics_subscription: None,

View file

@ -450,8 +450,6 @@ pub mod agent {
OpenOnboardingModal,
/// Opens the ACP onboarding modal.
OpenAcpOnboardingModal,
/// Opens the Claude Agent onboarding modal.
OpenClaudeAgentOnboardingModal,
/// Resets the agent onboarding state.
ResetOnboarding,
/// Starts a chat conversation with the agent.