paddleboard_ai_dock: Introduce the AI Dock - #38
Merged
Merged
Conversation
Adds a new `paddleboard_ai_dock` crate that ships a single browse-surface for the three things agents talk to. Replaces the hardcoded 5-card "Agent Setup" row on the Welcome screen and absorbs the standalone MCP Servers pane into one of its tabs. What lands: - `paddleboard_ai_dock` crate with a `ModalView`-implementing `AiDock` exposing three tabs (Agents / Skills / MCP Servers), backed by a static in-repo catalog at `assets/ai_dock/catalog.json` (5 agents, 6 skills, 5 MCP servers). - `crates/agent_ui/src/mcp_servers_ui.rs`: `McpServersPage` → `McpServersView`. Dropped the `Item` + `EventEmitter<ItemEvent>` impls and tab-metadata methods; kept `Render` + `Focusable`. Re-exported publicly via `pub use crate::mcp_servers_ui::McpServersView` in `agent_ui.rs`. The dock hosts an `Entity<McpServersView>` constructed lazily on first MCP-tab activation, so the view keeps using the private `agent_configuration::*` modals without lifting them. - Action wiring: new `paddleboard_actions::ai_dock::Open` (Agents tab); legacy `paddleboard_actions::McpServers` keeps working but now routes to the dock on the MCP tab. The old pane-item handler in `agent_ui.rs:575-593` was removed in favor of a divergence comment. - `crates/onboarding/src/basics_page.rs::render_ai_section` collapsed from a 5-card grid to a single "Open the AI Dock" button. The now-dead `render_zed_agent_button` / `render_registry_agent_button` helpers and ~6 unused imports removed. `FEATURED_AGENT_IDS` retained for `onboarding.rs:245` telemetry. - Detection is per-tab rather than a generic strategy: agents check `project::agent_server_store::AllAgentServersSettings`; skills check `<cwd>/.claude/commands/<id>.md` and `~/.claude/commands/<id>.md`; MCP defers entirely to the absorbed view. Originally scaffolded as "Store"; renamed to "AI Dock" mid-session because nothing is being purchased and the nautical metaphor fits the PaddleBoard theme. The rename is total — crate, action namespace, types, asset path, UI strings. The dock renders as a `ModalView` despite the name; the "Dock" framing is the paddleboard metaphor, not the GPUI dock concept. Verification: `./script/clippy` (release, all targets, deny warnings) clean; `cargo build -p paddleboard` clean. UI smoke test deferred — binary launches without crash but Screen Recording permission blocked screenshot evidence in this session. WELCOME.md and the in-app tour (`crates/workspace/src/tour.md`) updated; RECAPS 2026-05-21 entry documents the build + the rename. Release Notes: - Added the AI Dock — a single modal for browsing and installing agents, skills, and MCP servers. Replaces the old Welcome-screen "Agent Setup" row and absorbs the MCP Servers page (the `zed: Mcp Servers` action now opens the dock on the MCP tab). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`humanize_action_name` now strips a leading `zed::` and replaces it with
`paddleboard::` before applying the existing humanization. Propagates to
every caller of the helper — command palette, which_key, keymap_editor,
and the paddleboard binary's menu builder — so the visible action prefix
matches the rest of the fork's branding.
Display-only. `Action::name()` still returns `zed::Foo`, so every binding
in `assets/keymaps/` keeps resolving without edits. The alternative
(rewriting 17 `#[action(namespace = zed)]` declarations plus 23 keymap
references) would have been a maintenance trap on every upstream merge.
Tagged with a `// PaddleBoard:` divergence comment and a regression-locking
test asserting `humanize_action_name("zed::OpenOnboarding") ==
"paddleboard: open onboarding"`.
Release Notes:
- Improved command palette labels to read `paddleboard: <name>` instead of `zed: <name>` (cosmetic; existing keybindings unchanged).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ip, drop /simplify Followup polish on the 2026-05-21 AI Dock landing. What lands: - **Skills tab install path.** When a catalog skill has bundled markdown content AND is not yet installed, the row now renders two buttons — **Add to project** and **Add to user** — that write the file into `<workspace>/.claude/commands/<id>.md` or `~/.claude/commands/<id>.md` and `cx.notify()` so the badge flips to "Installed". Errors surface via `Workspace::show_error`. Sync IO inside the click handler is intentional: a few-KB write completes in microseconds, and backgrounding would have required threading a `WeakEntity<AiDock>` for no real win. - **Bundled content** via `bundled_skill_content(id)` in `catalog.rs`, using `include_str!` directly against `.claude/commands/<id>.md`. The slash command this repo uses and the install copy are physically the same bytes — zero drift, and renaming the source file would break the build. - **`project_skills_dir` fix.** Previously fell back to `std::env::current_dir()`, which is the launch directory, not the active workspace. Now reads `workspace.project().visible_worktrees(cx).next()` and joins `.claude/commands/`, with the CWD path only as a last-resort fallback. Both detection and install honor this — picking the wrong project root for a write would have been a silent data hazard. - **Welcome Featured strip.** Below the existing "Open the AI Dock" button, the onboarding screen now shows a small "Featured" label plus four outlined pills — **Claude**, **Codex**, **Copilot**, **Cursor**. Each pill dispatches the same `ai_dock::Open` action; the editorial value is the names being visible to first-run users, not a per-pill action. A parallel `WELCOME_FEATURED_AGENT_LABELS` constant lives next to the existing `FEATURED_AGENT_IDS` so the upstream-shaped `onboarding.rs:245` telemetry call site stays zero-touch. - **Catalog cleanup.** Dropped the phantom `/simplify` entry — its description was copy-pasted from `/review` and no real `/simplify` skill exists anywhere. Skills count: 6 → 5; the dock subtitle auto-updates. Also fixed `$schema_note` that still referenced the pre-rename "Store" naming and the deleted `paddleboard_store` crate path. - **Docs sync.** `WELCOME.md` and `crates/workspace/src/tour.md` now mention the Featured strip and the new Skills install buttons. Stale `zed: Mcp Servers` palette references in both files updated to `paddleboard: Mcp Servers` to match the namespace display rename. - **`.gitignore`** excludes `aidock-*.png` so future smoke-test screenshots stay local instead of cluttering `git status`. Tests added in `paddleboard_ai_dock::catalog::tests`: - `bundled_skill_content_returns_known_skills` - `bundled_skill_content_returns_none_for_unbundled` - `every_bundled_id_is_in_catalog` (structural — catches an orphan bundled id whose catalog entry was deleted, which would leave install buttons that never render) Verified: `cargo check -p paddleboard_ai_dock -p onboarding`, `./script/clippy -p paddleboard_ai_dock -p onboarding` (release, all targets, deny warnings), `cargo test -p paddleboard_ai_dock` (3/3 pass), `cargo build -p paddleboard`. UI smoke test confirmed the Featured strip renders and the modal header now reads "5 agents · 5 skills · 5 MCP servers" with `/simplify` gone from the Skills list. Open follow-ups (deferred): - `/verify`, `/review`, `/security-review` are still in the catalog without bundled content; render as "Not installed" with no install path. These are claude-code harness-bundled skills — decide whether to drop them from the catalog (harness owns discovery) or ship our own copies. - MCP tab still ignores the catalog: header counts 5, tab shows 0 installed and never lists the 5 entries (filesystem, fetch, git, github, puppeteer). The three tabs have asymmetric browse behavior — catalog-driven for Agents/Skills, installed-only for MCP. Release Notes: - Added install buttons (Add to project / Add to user) for bundled skills in the AI Dock and a Welcome-screen Featured strip surfacing Claude, Codex, Copilot, and Cursor. The `/build` and `/update-tour` skills now have install paths instead of routing to a homepage link. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Today's session: AI Dock smoke test (no code), Skills tab install path, Welcome Featured strip + docs/tour sync, and a command-palette display rename from "zed:" to "paddleboard:". Notes on the commit split, the gitignore entry for smoke-test PNGs, and the open follow-ups left for next session. Release Notes: - N/A Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Upstream drift reportComparing PaddleBoard
Generated by |
jasonsmithio
added a commit
that referenced
this pull request
May 22, 2026
Fixes the gap called out in PR #38's known follow-ups: the dock header counted "5 MCP servers" but the MCP tab itself only embedded McpServersView (installed-only) and never rendered the 5 catalog entries. First-run users would click MCP, see "No MCP servers installed yet", and have no way to discover what was available without going elsewhere. What lands: - Compact "Available" section rendered at the top of the MCP tab, above the absorbed McpServersView. One row per catalog entry, with icon, name, description (truncated to the row width), and an Install / Installed button. - Install button writes a ContextServerSettingsContent::Stdio entry into settings.project.context_servers keyed by the catalog id, using the catalog entry's command + args. update_settings_file does the write; the absorbed McpServersView picks up the new server through its existing context_server_store subscription. cx.notify() also fires after the write so the catalog row flips to "Installed" without waiting for the settings cascade. - Install state is read each render from ProjectSettings::get_global(cx).context_servers.keys(); any matching catalog id shows the disabled "Installed" badge regardless of which variant (Stdio, SandboxedStdio, Extension, Http) the user actually has, so a server added via a different path doesn't get double-listed. Intentionally preserved: - crates/agent_ui/src/mcp_servers_ui.rs is untouched. The catalog section sits above the absorbed view in a v_flex().size_full() with the view as flex_1().min_h_0() below — every keymap binding, search filter, "+ Add Server" popover, status indicator, etc. that ships with the absorbed view continues to work without divergence. - Default install variant is Stdio (unsandboxed) rather than SandboxedStdio, because SandboxedStdio requires a container image field and the catalog doesn't currently specify one. Users can flip to sandboxed after install. Extending McpEntry with an optional image field to enable SandboxedStdio-by-default is a worthwhile followup (aligns with PB's sandboxing emphasis) but out of scope. Verified: - cargo check -p paddleboard_ai_dock clean - ./script/clippy -p paddleboard_ai_dock (release, all targets, deny warnings) clean - UI smoke test: clicked Install on the Filesystem catalog entry from the running app. The catalog row flipped to "Installed", the MCP Servers header re-rendered to "1/1 running", a new filesystem card appeared in the absorbed view with Running status, the server process actually spawned (npx -y @modelcontextprotocol/server-filesystem .), and ~/.config/paddleboard/settings.json gained the exact Stdio block the catalog described. Release Notes: - Added an "Available" catalog section to the AI Dock's MCP Servers tab. The 5 bundled MCP server entries (filesystem, fetch, git, github, puppeteer) are now visible above the installed-servers manager, each with a one-click Install button that writes the right settings entry and spawns the server. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jasonsmithio
added a commit
that referenced
this pull request
May 22, 2026
Adds a maximize/minimize toggle in the modal header so users can grow the dock when there's more catalog or install content to scan than the default size comfortably fits. What lands: - New `expanded: bool` field on `AiDock`, default `false`, plus a `toggle_expanded` method that flips it and calls `cx.notify()`. - New `IconButton` in `render_header` placed left of the close button. Icon swaps between `IconName::Maximize` (when collapsed) and `IconName::Minimize` (when expanded); tooltip swaps between "Expand" and "Collapse". Both buttons live in the same `h_flex().gap_1()` cluster so the header layout doesn't shift across toggles. - `render()` picks size based on `self.expanded` — normal is `56rem x 36rem` (unchanged), expanded is `80rem x 54rem` (~2.1x the area). Each tab's render path is size-agnostic — rows are full-width and the embedded `McpServersView` has its own internal scroll — so growing the modal just gives the content more room. Intentionally preserved: - State is per-modal-instance, not persisted. Closing and reopening the dock starts collapsed. Persisting modal layout across reopens is the kind of small-but-controversial UX call worth deferring until someone explicitly wants it. - Two-state preset rather than free drag-to-resize. GPUI doesn't have a built-in resizable-modal primitive and rolling one would be a much bigger lift than the "minor change" framing implied. Also: removes the stray `paddleboard-5.png` sketch image that got committed at the repo root in the initial AI Dock commit (3d22299). Was already called out as a known follow-up in PR #38; closing it here. Verified: - cargo check -p paddleboard_ai_dock clean - ./script/clippy -p paddleboard_ai_dock (release, all targets, deny warnings) clean - UI verification: clicked the new Maximize button in the modal header, the modal grew to the expanded size, the icon swapped to Minimize and tooltip flipped to "Collapse". Close button stayed in place. Release Notes: - Added an Expand / Collapse toggle to the AI Dock modal header so users can grow the dock to roughly 2x the area when browsing longer catalog or install lists. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 22, 2026
jasonsmithio
added a commit
that referenced
this pull request
May 31, 2026
paddleboard_ai_dock: Introduce the AI Dock
jasonsmithio
added a commit
that referenced
this pull request
May 31, 2026
Fixes the gap called out in PR #38's known follow-ups: the dock header counted "5 MCP servers" but the MCP tab itself only embedded McpServersView (installed-only) and never rendered the 5 catalog entries. First-run users would click MCP, see "No MCP servers installed yet", and have no way to discover what was available without going elsewhere. What lands: - Compact "Available" section rendered at the top of the MCP tab, above the absorbed McpServersView. One row per catalog entry, with icon, name, description (truncated to the row width), and an Install / Installed button. - Install button writes a ContextServerSettingsContent::Stdio entry into settings.project.context_servers keyed by the catalog id, using the catalog entry's command + args. update_settings_file does the write; the absorbed McpServersView picks up the new server through its existing context_server_store subscription. cx.notify() also fires after the write so the catalog row flips to "Installed" without waiting for the settings cascade. - Install state is read each render from ProjectSettings::get_global(cx).context_servers.keys(); any matching catalog id shows the disabled "Installed" badge regardless of which variant (Stdio, SandboxedStdio, Extension, Http) the user actually has, so a server added via a different path doesn't get double-listed. Intentionally preserved: - crates/agent_ui/src/mcp_servers_ui.rs is untouched. The catalog section sits above the absorbed view in a v_flex().size_full() with the view as flex_1().min_h_0() below — every keymap binding, search filter, "+ Add Server" popover, status indicator, etc. that ships with the absorbed view continues to work without divergence. - Default install variant is Stdio (unsandboxed) rather than SandboxedStdio, because SandboxedStdio requires a container image field and the catalog doesn't currently specify one. Users can flip to sandboxed after install. Extending McpEntry with an optional image field to enable SandboxedStdio-by-default is a worthwhile followup (aligns with PB's sandboxing emphasis) but out of scope. Verified: - cargo check -p paddleboard_ai_dock clean - ./script/clippy -p paddleboard_ai_dock (release, all targets, deny warnings) clean - UI smoke test: clicked Install on the Filesystem catalog entry from the running app. The catalog row flipped to "Installed", the MCP Servers header re-rendered to "1/1 running", a new filesystem card appeared in the absorbed view with Running status, the server process actually spawned (npx -y @modelcontextprotocol/server-filesystem .), and ~/.config/paddleboard/settings.json gained the exact Stdio block the catalog described. Release Notes: - Added an "Available" catalog section to the AI Dock's MCP Servers tab. The 5 bundled MCP server entries (filesystem, fetch, git, github, puppeteer) are now visible above the installed-servers manager, each with a one-click Install button that writes the right settings entry and spawns the server. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jasonsmithio
added a commit
that referenced
this pull request
May 31, 2026
Adds a maximize/minimize toggle in the modal header so users can grow the dock when there's more catalog or install content to scan than the default size comfortably fits. What lands: - New `expanded: bool` field on `AiDock`, default `false`, plus a `toggle_expanded` method that flips it and calls `cx.notify()`. - New `IconButton` in `render_header` placed left of the close button. Icon swaps between `IconName::Maximize` (when collapsed) and `IconName::Minimize` (when expanded); tooltip swaps between "Expand" and "Collapse". Both buttons live in the same `h_flex().gap_1()` cluster so the header layout doesn't shift across toggles. - `render()` picks size based on `self.expanded` — normal is `56rem x 36rem` (unchanged), expanded is `80rem x 54rem` (~2.1x the area). Each tab's render path is size-agnostic — rows are full-width and the embedded `McpServersView` has its own internal scroll — so growing the modal just gives the content more room. Intentionally preserved: - State is per-modal-instance, not persisted. Closing and reopening the dock starts collapsed. Persisting modal layout across reopens is the kind of small-but-controversial UX call worth deferring until someone explicitly wants it. - Two-state preset rather than free drag-to-resize. GPUI doesn't have a built-in resizable-modal primitive and rolling one would be a much bigger lift than the "minor change" framing implied. Also: removes the stray `paddleboard-5.png` sketch image that got committed at the repo root in the initial AI Dock commit (064a04c). Was already called out as a known follow-up in PR #38; closing it here. Verified: - cargo check -p paddleboard_ai_dock clean - ./script/clippy -p paddleboard_ai_dock (release, all targets, deny warnings) clean - UI verification: clicked the new Maximize button in the modal header, the modal grew to the expanded size, the icon swapped to Minimize and tooltip flipped to "Collapse". Close button stayed in place. Release Notes: - Added an Expand / Collapse toggle to the AI Dock modal header so users can grow the dock to roughly 2x the area when browsing longer catalog or install lists. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
paddleboard_ai_dock) — a modal with three tabs (Agents / Skills / MCP Servers) backed by a static in-repo catalog atassets/ai_dock/catalog.json. Replaces the hardcoded 5-card "Agent Setup" row on the Welcome screen with an "Open the AI Dock" button plus a small Featured strip (Claude / Codex / Copilot / Cursor pills), and absorbs the standalone MCP Servers page into the MCP tab. The legacypaddleboard_actions::McpServersaction keeps working — it now opens the dock on the MCP tab.AllAgentServersSettingsand writeCustomAgentServerSettings::Registry { … }on install. Bundled skills (/buildand/update-tour) have their markdown embedded viainclude_str!and install with Add to project / Add to user buttons that drop a file into.claude/commands/. MCP servers render in an Available section above the absorbed view, each with an Install button that writes aContextServerSettingsContent::Stdioentry intocontext_serversand spawns the server.56rem × 36remto80rem × 54rem(~2.1× the area) for browsing longer catalog or install lists. State is per-modal-instance.zed:→paddleboard:in the command palette (display-only) viahumanize_action_name. Keymaps and action declarations untouched — the underlyingAction::name()still returnszed::Foo, so every binding inassets/keymaps/keeps resolving without edits.What's in the six commits
3d222998979669d4b587zed:→paddleboard:rename in command palette + which_key + keymap editor + PB menua8fd95efe4/build+/update-tour, workspace-aware project dir resolution, Welcome Featured strip,/simplifycatalog cleanup, WELCOME.md + tour.md sync41e1a370317b7327b6648b94177cbdpaddleboard-5.pngsketch imageTest plan
cargo checkclean acrosspaddleboard,paddleboard_ai_dock,onboarding,command_palette./script/clippy(release, all targets, deny warnings) clean forpaddleboard_ai_dock,onboarding,command_palettecargo test -p paddleboard_ai_dock— 3/3 catalog tests pass (bundled_skill_content_returns_known_skills,bundled_skill_content_returns_none_for_unbundled,every_bundled_id_is_in_catalog)cargo test -p command_palette test_humanize_action_name— regression-locking test passesaidock-1.png…aidock-10.pngcaptured locally, gitignored): Welcome screen shows the "Open the AI Dock" button + Featured strip; the dock modal opens on Agents tab with header "5 agents · 5 skills · 5 MCP servers"; all 3 tabs switch cleanly; agent install detection works (Zed Agent shows Installed/Sign In, others show Install); skills filesystem detection works (/build+/update-tourshow Installed (Project), others show Not installed); MCP tab renders the Available catalog (5 entries) above the absorbed view; legacyzed::McpServersaction correctly routes to the MCP tab; the Maximize button grows the modal to ~2.1× the area and the icon swaps to Minimizefilesystemcard appeared with Running status, thenpx -y @modelcontextprotocol/server-filesystem .process actually spawned, and~/.config/paddleboard/settings.jsongained the exact Stdio block the catalog described..claude/commands/. To exercise:mv .claude/commands/build.md /tmp/, open the dock → install buttons should appear for/build, click "Add to user" → verify~/.claude/commands/build.mdis created, restore the backup.Known follow-ups (deferred, captured in RECAPS)
/verify,/review,/security-revieware in the catalog without bundled content; they render as "Not installed" with no install path. These are claude-code harness-bundled skills — decide whether to drop them from the catalog (harness owns discovery) or ship our own copies.McpEntryshould grow an optionalimagefield so the catalog can describe SandboxedStdio-capable servers (e.g.ghcr.io/github/github-mcp-server:latestforgithub). Then the install default could flip to sandboxed for entries that have an image, aligning with PB's sandboxing emphasis.workspace.rs:785/paddleboard/src/main.rs:1494only writePaddleBoard_Tour.mdwhen it doesn't already exist. Fresh installs pick it up automatically. Worth fixing eventually so docs actually reach users.Release Notes:
paddleboard: Mcp Serversaction now opens the dock on the MCP tab), ships install paths for the/buildand/update-tourskills, surfaces a 5-entry MCP server catalog with one-click install, adds an Expand / Collapse toggle for browsing larger lists, and adds a Featured strip on the Welcome screen for first-run discoverability. Command palette labels also now readpaddleboard:instead ofzed:(cosmetic; existing keybindings unchanged).