diff --git a/apps/code/src/renderer/features/sidebar/components/TaskListView.tsx b/apps/code/src/renderer/features/sidebar/components/TaskListView.tsx
index 7fea8db2c5..82487858cd 100644
--- a/apps/code/src/renderer/features/sidebar/components/TaskListView.tsx
+++ b/apps/code/src/renderer/features/sidebar/components/TaskListView.tsx
@@ -131,6 +131,7 @@ function TaskRow({
slackThreadUrl={task.slackThreadUrl}
prState={prState}
hasDiff={hasDiff}
+ prUrl={task.cloudPrUrl}
timestamp={timestamp}
onClick={onClick}
onDoubleClick={onDoubleClick}
diff --git a/apps/code/src/renderer/features/sidebar/components/items/TaskItem.tsx b/apps/code/src/renderer/features/sidebar/components/items/TaskItem.tsx
index a5ee2a5b49..3c5b2c66db 100644
--- a/apps/code/src/renderer/features/sidebar/components/items/TaskItem.tsx
+++ b/apps/code/src/renderer/features/sidebar/components/items/TaskItem.tsx
@@ -1,13 +1,54 @@
import { Tooltip } from "@components/ui/Tooltip";
import type { SidebarPrState } from "@features/sidebar/hooks/useTaskPrStatus";
import type { WorkspaceMode } from "@main/services/workspace/schemas";
-import { Archive, PushPin } from "@phosphor-icons/react";
+import { Archive, GitPullRequest, PushPin } from "@phosphor-icons/react";
import type { TaskRunStatus } from "@shared/types";
+import { openUrlInBrowser } from "@utils/browser";
import { formatRelativeTimeShort } from "@utils/time";
import { useCallback, useEffect, useRef, useState } from "react";
import { SidebarItem } from "../SidebarItem";
import { TaskIcon } from "./TaskIcon";
+function extractPrNumber(url: string): string | null {
+ const match = url.match(
+ /\/(?:pull|pulls|merge_requests|pull-requests)\/(\d+)/,
+ );
+ return match ? match[1] : null;
+}
+
+function PrBadge({ url }: { url: string }) {
+ const number = extractPrNumber(url);
+ const open = () => {
+ void openUrlInBrowser(url);
+ };
+ return (
+
+ {/* biome-ignore lint/a11y/useSemanticElements: nested clickable inside SidebarItem button */}
+ {
+ e.stopPropagation();
+ open();
+ }}
+ onDoubleClick={(e) => e.stopPropagation()}
+ onKeyDown={(e) => {
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ e.stopPropagation();
+ open();
+ }
+ }}
+ >
+
+ {number ? `#${number}` : "PR"}
+
+
+ );
+}
+
interface TaskItemProps {
depth?: number;
taskId: string;
@@ -27,6 +68,7 @@ interface TaskItemProps {
slackThreadUrl?: string;
prState?: SidebarPrState;
hasDiff?: boolean;
+ prUrl?: string | null;
timestamp?: number;
isEditing?: boolean;
onClick: (e: React.MouseEvent) => void;
@@ -123,6 +165,7 @@ export function TaskItem({
slackThreadUrl,
prState,
hasDiff,
+ prUrl,
timestamp,
isEditing = false,
onClick,
@@ -149,6 +192,8 @@ export function TaskItem({
/>
);
+ const prBadge = prUrl ? : null;
+
const timestampNode = timestamp ? (
{formatRelativeTimeShort(timestamp)}
@@ -165,8 +210,9 @@ export function TaskItem({
) : null;
const endContent =
- timestampNode || toolbar ? (
+ prBadge || timestampNode || toolbar ? (
<>
+ {prBadge}
{timestampNode}
{toolbar}
>