Skip to content

feat(desktop): add Open in workspace button to task detail - #1473

Merged
saddlepaddle merged 1 commit into
mainfrom
feat/task-open-in-workspace
Feb 13, 2026
Merged

saddlepaddle merged 1 commit into
mainfrom
feat/task-open-in-workspace

Conversation

@saddlepaddle

@saddlepaddle saddlepaddle commented Feb 13, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Adds an "Open in workspace" control to the task detail properties sidebar — a project dropdown (defaults to most recent, shows project icons) plus a go button that creates a workspace and launches an autonomous Claude session with full task context
  • Consolidates the Claude command prompt template into @superset/shared/claude-command so both the MCP server and desktop renderer share a single source of truth instead of duplicated copies

Test plan

  • Open desktop app, navigate to a task detail page
  • Verify the "Open in workspace" section appears in the properties sidebar with a project dropdown defaulting to the most recent project
  • Select a different project from the dropdown, verify project icons render
  • Click the arrow button — verify a workspace is created, the app navigates to it, and Claude starts in the terminal with task context
  • Verify bun run typecheck passes for both @superset/mcp and @superset/desktop

Summary by CodeRabbit

  • New Features
    • Added "Open in Workspace" functionality in the task sidebar with project selection and workspace creation capabilities
    • Integrated Claude command execution support for task automation
    • Automatic branch name generation from task information
    • Enhanced workspace handling with success and error notifications

@coderabbitai

coderabbitai Bot commented Feb 13, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces workspace integration for tasks. It adds a new buildClaudeCommand utility to the shared packages for constructing Claude command strings, refactors MCP to use this shared utility instead of duplicating logic, creates an OpenInWorkspace React component for selecting projects and opening/creating workspaces, and adds supporting utilities for branch name derivation.

Changes

Cohort / File(s) Summary
Build Claude Command Infrastructure
packages/shared/src/claude-command.ts, packages/shared/package.json, apps/desktop/.../utils/buildClaudeCommand.ts
New shared utility exporting buildClaudeCommand function and TaskInput interface for constructing Claude shell commands; configured as a public export in shared package.
MCP Refactoring
packages/mcp/src/tools/devices/start-claude-session/start-claude-session.ts, packages/mcp/package.json
Replaced internal buildCommand logic with calls to the shared buildClaudeCommand utility; added @superset/shared dependency to packages/mcp.
OpenInWorkspace Component
apps/desktop/.../components/OpenInWorkspace/OpenInWorkspace.tsx, apps/desktop/.../components/OpenInWorkspace/index.ts
New React component enabling project selection via dropdown, workspace creation/opening, and Claude command registration with error/success notifications.
PropertiesSidebar Integration
apps/desktop/.../PropertiesSidebar/PropertiesSidebar.tsx
Integrated OpenInWorkspace component into the task properties sidebar after the Labels section.
Branch Naming Utility
apps/desktop/.../utils/deriveBranchName.ts
New utility that constructs sanitized Git branch names from task slug and title using a shared sanitization function.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through workspaces with glee,
Claude commands now shared for all to see,
Branch names trimmed neat, projects all lined up,
Opening workspaces—a feature cooked up! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The provided description covers the summary of changes and test plan, but lacks required template sections: Related Issues, Type of Change, Testing, Screenshots, and Additional Notes are missing or incomplete. Add missing template sections: specify related issues (if any), mark 'New feature' under Type of Change, provide detailed testing steps, and complete other template fields for consistency.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main feature addition: an 'Open in workspace' button added to the task detail view, which is the primary user-facing change in this PR.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/task-open-in-workspace

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/`$taskId/components/WorkOnTaskButton/WorkOnTaskButton.tsx:
- Around line 89-93: In the catch block inside the WorkOnTaskButton component
(the error handler that currently calls toast.error), add a console.error call
before showing the toast to log the full error and contextual info (e.g.,
"WorkOnTaskButton: failed to create workspace" plus the caught err and err.stack
when available) so the error is not swallowed; keep the toast behavior unchanged
after logging.
🧹 Nitpick comments (2)
packages/shared/src/claude-command.ts (1)

1-9: Export TaskInput so consumers can reference the type.

The buildClaudeCommand function accepts task: TaskInput, but TaskInput is not exported. Consumers (e.g., WorkOnTaskButton, MCP tools) cannot type-check their task objects against this interface without relying on structural compatibility alone.

Proposed fix
-interface TaskInput {
+export interface TaskInput {
apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/WorkOnTaskButton/WorkOnTaskButton.tsx (1)

158-165: Consider showing a loading indicator while workspace creation is pending.

The button is correctly disabled during createWorkspace.isPending, but users have no visual feedback that an action is in progress. A spinner or similar indicator would improve the experience, especially if workspace creation takes a noticeable amount of time.

Suggested change
 				<Button
 					size="icon"
 					className="h-8 w-8 shrink-0"
 					disabled={!effectiveProjectId || createWorkspace.isPending}
 					onClick={handleOpen}
 				>
-					<HiArrowRight className="w-3.5 h-3.5" />
+					{createWorkspace.isPending ? (
+						<span className="animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full" />
+					) : (
+						<HiArrowRight className="w-3.5 h-3.5" />
+					)}
 				</Button>

Comment on lines +89 to +93
} catch (err) {
toast.error(
err instanceof Error ? err.message : "Failed to create workspace",
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add console.error logging before the toast.

The catch block displays a user-facing toast but doesn't log the error. This makes debugging harder in production. Per the project guidelines: "Never swallow errors silently; at minimum log errors with context before rethrowing or handling them explicitly."

Proposed fix
 		} catch (err) {
+			console.error("[WorkOnTaskButton/handleSelectProject]", err);
 			toast.error(
 				err instanceof Error ? err.message : "Failed to create workspace",
 			);
 		}
🤖 Prompt for AI Agents
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/`$taskId/components/WorkOnTaskButton/WorkOnTaskButton.tsx
around lines 89 - 93, In the catch block inside the WorkOnTaskButton component
(the error handler that currently calls toast.error), add a console.error call
before showing the toast to log the full error and contextual info (e.g.,
"WorkOnTaskButton: failed to create workspace" plus the caught err and err.stack
when available) so the error is not swallowed; keep the toast behavior unchanged
after logging.

@github-actions

github-actions Bot commented Feb 13, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app
  • ✅ Streams Fly.io app

Thank you for your contribution! 🎉

Adds a project selector + go button in the task detail properties sidebar
that creates a workspace and launches an autonomous Claude session with
full task context. Consolidates the Claude command prompt template into
@superset/shared so MCP and desktop share a single source of truth.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/shared/src/claude-command.ts`:
- Around line 1-9: The TaskInput interface is not exported, so callers cannot
import the primary input type for buildClaudeCommand; update the module to
export TaskInput (e.g., change the declaration to export interface TaskInput or
export type TaskInput = { ... }) so consumers can import TaskInput alongside
buildClaudeCommand and get explicit type safety when constructing task objects.
🧹 Nitpick comments (4)
packages/shared/src/claude-command.ts (1)

48-48: Minor: consider validating that randomId produces a safe shell delimiter.

replaceAll("-", "") on a UUID is fine for the expected input, but if a non-UUID string were passed (e.g., containing newlines or quotes), it could break the heredoc. Since callers currently use crypto.randomUUID(), this is low risk — just worth a defensive note or a doc comment on the expected format.

apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/PropertiesSidebar/components/OpenInWorkspace/OpenInWorkspace.tsx (3)

37-42: The useEffect is redundant given the effectiveProjectId fallback on line 32.

Line 32 already computes effectiveProjectId as the fallback to the first recent project. The useEffect on lines 38–42 then sets selectedProjectId to the same value, causing a needless re-render. Since effectiveProjectId already handles the "no selection yet" case, the effect adds no user-visible value — it only triggers an extra render cycle.

Consider removing it unless there's a downstream need for selectedProjectId to be explicitly set in state (e.g., for controlled form submission).


44-47: handleOpen triggers workspace creation immediately — is this intentional UX?

Clicking the arrow button calls handleSelectProject, which both selects and creates/opens a workspace. But clicking a project in the dropdown only updates the selection (line 140). The asymmetry seems intentional (dropdown = pick, arrow = go), but the function name handleSelectProject is misleading since it actually creates a workspace. A rename to something like handleCreateOrOpenWorkspace would reduce confusion.


15-17: Use path aliases instead of deep relative imports.

Lines 11–14 use the renderer/ alias, but these three imports use relative paths with deep ../../../../ traversals. This is inconsistent and fragile.

Proposed fix
-import type { TaskWithStatus } from "../../../../../components/TasksView/hooks/useTasksTable";
-import { buildClaudeCommand } from "../../../../utils/buildClaudeCommand";
-import { deriveBranchName } from "../../../../utils/deriveBranchName";
+import type { TaskWithStatus } from "renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/hooks/useTasksTable";
+import { buildClaudeCommand } from "renderer/routes/_authenticated/_dashboard/tasks/$taskId/utils/buildClaudeCommand";
+import { deriveBranchName } from "renderer/routes/_authenticated/_dashboard/tasks/$taskId/utils/deriveBranchName";

As per coding guidelines: "Use alias as defined in tsconfig.json when possible."

Comment on lines +1 to +9
interface TaskInput {
id: string;
slug: string;
title: string;
description: string | null;
priority: string;
statusName: string | null;
labels: string[] | null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n packages/shared/src/claude-command.ts

Repository: superset-sh/superset

Length of output: 1997


🏁 Script executed:

rg "import.*TaskInput|from.*claude-command" --type=ts --type=tsx

Repository: superset-sh/superset

Length of output: 91


🏁 Script executed:

rg "TaskInput" --type=ts --type=tsx -B 2 -A 2

Repository: superset-sh/superset

Length of output: 91


🏁 Script executed:

rg "TaskInput" --type=ts -B 2 -A 2

Repository: superset-sh/superset

Length of output: 1317


🏁 Script executed:

fd "\.ts$|\.tsx$" packages/mcp packages/desktop-app 2>/dev/null | head -20

Repository: superset-sh/superset

Length of output: 1171


🏁 Script executed:

rg "import.*from.*claude-command" --type=ts

Repository: superset-sh/superset

Length of output: 209


🏁 Script executed:

cat -n packages/mcp/src/tools/devices/start-claude-session/start-claude-session.ts

Repository: superset-sh/superset

Length of output: 5510


🏁 Script executed:

cat -n packages/mcp/src/tools/tasks/create-task/create-task.ts | head -40

Repository: superset-sh/superset

Length of output: 1699


Export TaskInput from the claude-command module.

buildClaudeCommand is exported, but TaskInput — its primary input type — is not. Consumers in packages/mcp and elsewhere must construct the task object without importing the type, relying on structural typing instead of explicit type safety.

Proposed fix
-interface TaskInput {
+export interface TaskInput {
	id: string;
	slug: string;
	title: string;
	description: string | null;
	priority: string;
	statusName: string | null;
	labels: string[] | null;
}
🤖 Prompt for AI Agents
In `@packages/shared/src/claude-command.ts` around lines 1 - 9, The TaskInput
interface is not exported, so callers cannot import the primary input type for
buildClaudeCommand; update the module to export TaskInput (e.g., change the
declaration to export interface TaskInput or export type TaskInput = { ... }) so
consumers can import TaskInput alongside buildClaudeCommand and get explicit
type safety when constructing task objects.

@saddlepaddle
saddlepaddle merged commit 588ecce into main Feb 13, 2026
14 of 15 checks passed

This branch was previously deployed

1 inactive deployment
preview — f8d143e9 Deployed Feb 13, 2026 by saddlepaddle via Deploy Marketing #1900
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant