From c81ac40d4c0447a459b5e429518a410121da8bd2 Mon Sep 17 00:00:00 2001
From: Rafael Audibert <32079912+rafaeelaudibert@users.noreply.github.com>
Date: Thu, 28 May 2026 17:48:03 -0300
Subject: [PATCH] Add PR badge to sidebar task list
Tasks in the sidebar with a linked pull request now show a small clickable badge on the right side of the row. The badge displays the PR number (e.g. `#123`) when it can be extracted from the URL and falls back to `PR` otherwise; clicking it opens the PR in the user's browser via `openUrlInBrowser`. The URL is sourced from the existing `TaskData.cloudPrUrl` field (populated from `task.latest_run.output.pr_url`), so no new data plumbing is needed.
Generated-By: PostHog Code
Task-Id: ba55cf1b-c69e-4b32-b689-9a00d3831b64
---
.../sidebar/components/TaskListView.tsx | 1 +
.../sidebar/components/items/TaskItem.tsx | 50 ++++++++++++++++++-
2 files changed, 49 insertions(+), 2 deletions(-)
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}
>