From dfe53465b70965750ca953afe3352cb4ae79eec3 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Feb 2026 12:32:34 +0000 Subject: [PATCH] feat(cli): add clickable profile link to time section in cc statusline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap the ⏱️ time section with an OSC8 link to the user's profile page at {webEndpoint}/users/{userLogin}, allowing users to click the time display to view their status on shelltime.xyz. https://claude.ai/code/session_01GihLQR12WQ9guABhJT59ts --- commands/cc_statusline.go | 6 +++++- commands/cc_statusline_test.go | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/commands/cc_statusline.go b/commands/cc_statusline.go index 9834e24..fefb8fb 100644 --- a/commands/cc_statusline.go +++ b/commands/cc_statusline.go @@ -167,9 +167,13 @@ func formatStatuslineOutput(modelName string, sessionCost, dailyCost float64, se // Quota utilization parts = append(parts, formatQuotaPart(fiveHourUtil, sevenDayUtil)) - // AI agent time (magenta) + // AI agent time (magenta) - clickable link to user profile if sessionSeconds > 0 { timeStr := color.Magenta.Sprintf("⏱️ %s", formatSessionDuration(sessionSeconds)) + if userLogin != "" && webEndpoint != "" { + url := fmt.Sprintf("%s/users/%s", webEndpoint, userLogin) + timeStr = wrapOSC8Link(url, timeStr) + } parts = append(parts, timeStr) } else { parts = append(parts, color.Gray.Sprint("⏱️ -")) diff --git a/commands/cc_statusline_test.go b/commands/cc_statusline_test.go index fa52e08..45aacae 100644 --- a/commands/cc_statusline_test.go +++ b/commands/cc_statusline_test.go @@ -354,6 +354,27 @@ func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_SessionCostWithoutLin assert.NotContains(s.T(), output, "coding-agent/session/") } +func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_TimeWithProfileLink() { + output := formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil, "testuser", "https://shelltime.xyz", "session-abc123") + + // Should contain OSC8 link wrapping time section to user profile + assert.Contains(s.T(), output, "shelltime.xyz/users/testuser") + assert.Contains(s.T(), output, "1h1m") +} + +func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_TimeWithoutProfileLink() { + // No userLogin - should not have profile link on time + output := formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil, "", "https://shelltime.xyz", "session-abc123") + assert.Contains(s.T(), output, "1h1m") + // The time section should not contain a link to users/ profile + // Count occurrences of "shelltime.xyz/users/" - should only be in session cost and daily cost links + assert.NotContains(s.T(), output, "shelltime.xyz/users//") + + // No webEndpoint - should not have profile link on time + output = formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil, "testuser", "", "session-abc123") + assert.Contains(s.T(), output, "1h1m") +} + func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_WithQuota() { fh := 45.0 sd := 23.0