Skip to content

Comments

feat(commands): make daily cost clickable in cc statusline#215

Merged
AnnatarHe merged 1 commit intomainfrom
feat/cc-statusline-clickable-daily-cost
Feb 6, 2026
Merged

feat(commands): make daily cost clickable in cc statusline#215
AnnatarHe merged 1 commit intomainfrom
feat/cc-statusline-clickable-daily-cost

Conversation

@AnnatarHe
Copy link
Contributor

@AnnatarHe AnnatarHe commented Feb 6, 2026

Summary

  • Add model/user_profile_service.go with GraphQL query to fetch current user's login
  • Cache user login in daemon timer service (fetched once per daemon lifetime, never re-fetched)
  • Pass UserLogin through CCInfoResponse from daemon to CLI
  • Wrap daily cost section in cc statusline with OSC8 clickable link to {webEndpoint}/users/{login}/coding-agent/claude-code
  • Fallback path (no daemon) keeps daily cost as plain text

Test plan

  • go build ./... compiles successfully
  • go test ./daemon/... ./model/... pass
  • go test -run TestCCStatuslineTestSuite ./commands/ pass
  • Manual: run daemon, verify daily cost section has OSC8 link in terminal

🤖 Generated with Claude Code


Open with Devin

Add user profile GraphQL service to fetch current user's login, cache it
in the daemon timer (once per lifetime), and use it to wrap the daily
cost section with an OSC8 clickable link pointing to the coding agent
page at {webEndpoint}/users/{login}/coding-agent/claude-code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AnnatarHe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the cc statusline functionality by making the daily cost display interactive. It introduces the capability to fetch and cache the current user's login, which is then used to construct a clickable link within the terminal statusline. This allows users to quickly navigate to their coding agent usage page directly from the statusline, improving usability and access to relevant information.

Highlights

  • User Profile Service: A new service model/user_profile_service.go has been introduced to fetch the current user's login via a GraphQL query.
  • User Login Caching: The user's login is now cached within the daemon's timer service, fetched only once per daemon lifetime to minimize API calls.
  • Daemon to CLI Communication: The fetched UserLogin is passed from the daemon to the CLI through the CCInfoResponse.
  • Clickable Daily Cost: The daily cost displayed in the cc statusline is now wrapped with an OSC8 clickable link. This link directs users to their coding agent usage page ({webEndpoint}/users/{login}/coding-agent/claude-code).
  • Fallback Mechanism: If the daemon is not running or user login information is unavailable, the daily cost will gracefully fall back to being displayed as plain text.
Changelog
  • commands/cc_statusline.go
    • Added UserLogin and WebEndpoint fields to ccStatuslineResult struct to carry user-specific and endpoint information.
    • Modified commandCCStatusline and formatStatuslineOutput functions to accept and process the new UserLogin and WebEndpoint parameters.
    • Implemented logic within formatStatuslineOutput to conditionally wrap the daily cost string with an OSC8 terminal escape code, creating a clickable link to the user's coding agent page if UserLogin and WebEndpoint are provided.
    • Updated getDaemonInfoWithFallback to populate UserLogin from the daemon response and WebEndpoint from the configuration.
  • commands/cc_statusline_test.go
    • Updated calls to formatStatuslineOutput in various test cases to include the newly added userLogin and webEndpoint parameters, typically passing empty strings to maintain existing test behavior.
  • daemon/cc_info_timer.go
    • Introduced userLogin and userLoginFetched fields to CCInfoTimerService to cache the user's login status and value.
    • Added a new fetchUserProfile method responsible for fetching the current user's login via GraphQL and caching it for the daemon's lifetime.
    • Integrated fetchUserProfile into the timerLoop to ensure the user profile is fetched when the daemon starts.
    • Provided a GetCachedUserLogin method to safely retrieve the cached user login.
  • daemon/socket.go
    • Added a UserLogin field to the CCInfoResponse struct to include the user's login in the daemon's response to CLI requests.
    • Modified handleCCInfo to populate the UserLogin field in the response by calling p.ccInfoTimer.GetCachedUserLogin().
  • model/user_profile_service.go
    • New file: Defines FetchCurrentUserProfileQuery, a GraphQL query to retrieve the current user's ID and login.
    • New file: Defines UserProfileResponse struct for deserializing the GraphQL response.
    • New file: Implements FetchCurrentUserProfile function, which sends a GraphQL request to fetch the current user's profile based on the provided configuration.
Activity
  • The author has added a new GraphQL query and service to fetch user profile information.
  • User login information is now cached in the daemon for efficiency.
  • The daemon now passes user login and web endpoint details to the CLI.
  • The cc statusline command has been updated to render the daily cost as a clickable link.
  • The author has confirmed successful compilation with go build ./....
  • Unit tests for daemon and model packages (go test ./daemon/... ./model/...) have passed.
  • Unit tests for commands package (go test -run TestCCStatuslineTestSuite ./commands/) have passed.
  • Manual verification is pending to confirm the OSC8 link functionality in the terminal.
  • The pull request was generated using Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Feb 6, 2026

Codecov Report

❌ Patch coverage is 44.68085% with 26 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
model/user_profile_service.go 0.00% 17 Missing ⚠️
daemon/cc_info_timer.go 77.27% 3 Missing and 2 partials ⚠️
commands/cc_statusline.go 42.85% 3 Missing and 1 partial ⚠️
Flag Coverage Δ
unittests 37.82% <44.68%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
daemon/socket.go 65.85% <100.00%> (+0.27%) ⬆️
commands/cc_statusline.go 66.66% <42.85%> (-0.99%) ⬇️
daemon/cc_info_timer.go 84.89% <77.27%> (-0.76%) ⬇️
model/user_profile_service.go 0.00% <0.00%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully adds a clickable link to the daily cost in the cc statusline, which improves user experience by providing a quick link to the coding agent page. The implementation is well-structured, involving changes in the daemon to fetch and cache user data, and in the CLI to construct and display the link.

My review includes a couple of suggestions:

  • In daemon/cc_info_timer.go, I've identified a potential race condition in how the user profile is fetched and suggested a more robust implementation using sync.Once.
  • In commands/cc_statusline_test.go, I've noted that while existing tests were updated, new tests covering the link generation logic would improve coverage for this new feature.

Comment on lines +429 to +454
func (s *CCInfoTimerService) fetchUserProfile(ctx context.Context) {
if s.config.Token == "" {
return
}

s.mu.RLock()
fetched := s.userLoginFetched
s.mu.RUnlock()

if fetched {
return
}

profile, err := model.FetchCurrentUserProfile(ctx, *s.config)
if err != nil {
slog.Warn("Failed to fetch user profile", slog.Any("err", err))
return
}

s.mu.Lock()
s.userLogin = profile.FetchUser.Login
s.userLoginFetched = true
s.mu.Unlock()

slog.Debug("User profile fetched", slog.String("login", profile.FetchUser.Login))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The current implementation of fetchUserProfile has a potential race condition. If it were ever called concurrently, multiple goroutines could pass the if fetched check and perform the network request, which is inefficient. Using sync.Once is the idiomatic Go way to ensure a piece of code is executed exactly once.

To apply this suggestion, you'll also need to modify the CCInfoTimerService struct by replacing userLoginFetched bool with userProfileOnce sync.Once.

func (s *CCInfoTimerService) fetchUserProfile(ctx context.Context) {
	s.userProfileOnce.Do(func() {
		if s.config.Token == "" {
			return
		}

		profile, err := model.FetchCurrentUserProfile(ctx, *s.config)
		if err != nil {
			slog.Warn("Failed to fetch user profile", slog.Any("err", err))
			return
		}

		s.mu.Lock()
		s.userLogin = profile.FetchUser.Login
		s.mu.Unlock()

		slog.Debug("User profile fetched", slog.String("login", profile.FetchUser.Login))
	})
}


func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_AllValues() {
output := formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil)
output := formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil, "", "")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

While the existing tests for formatStatuslineOutput have been updated to compile, they don't yet cover the new clickable link functionality. Adding a dedicated test case would ensure the OSC8 link is generated correctly when userLogin and webEndpoint are provided.

For example, you could add a new test like this:

func (s *CCStatuslineTestSuite) TestFormatStatuslineOutput_WithClickableLink() {
	output := formatStatuslineOutput("claude-opus-4", 1.23, 4.56, 3661, 75.0, "main", false, nil, nil, "testuser", "https://example.com")

	expectedURL := "https://example.com/users/testuser/coding-agent/claude-code"
	dailyStr := color.Yellow.Sprintf("📊 $%.2f", 4.56)
	expectedLink := wrapOSC8Link(expectedURL, dailyStr)

	assert.Contains(s.T(), output, expectedLink)
}

Since a code suggestion can't add a new function, you could also adapt an existing test to include these assertions.

Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 4 additional findings in Devin Review.

Open in Devin Review

if dailyCost > 0 {
dailyStr := color.Yellow.Sprintf("📊 $%.2f", dailyCost)
if userLogin != "" && webEndpoint != "" {
url := fmt.Sprintf("%s/users/%s/coding-agent/claude-code", webEndpoint, userLogin)

Choose a reason for hiding this comment

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

🟡 User login not URL-encoded when constructing clickable link URL

The userLogin string is directly interpolated into the URL path without URL encoding. If a user's login contains special characters (spaces, @, #, %, or non-ASCII characters), the generated URL would be malformed.

Root Cause

At commands/cc_statusline.go:155, the URL is constructed as:

url := fmt.Sprintf("%s/users/%s/coding-agent/claude-code", webEndpoint, userLogin)

The userLogin value comes directly from the GraphQL API response (model/user_profile_service.go:21) and is used without sanitization. While most login systems restrict usernames to safe characters, this is not guaranteed, and URL path segments should be properly encoded using url.PathEscape() to handle edge cases.

Impact: Users with special characters in their login would see broken clickable links in their terminal statusline, leading to 404 errors or incorrect navigation when clicked.

Suggested change
url := fmt.Sprintf("%s/users/%s/coding-agent/claude-code", webEndpoint, userLogin)
url := fmt.Sprintf("%s/users/%s/coding-agent/claude-code", webEndpoint, url.PathEscape(userLogin))
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@AnnatarHe AnnatarHe merged commit 17031dd into main Feb 6, 2026
8 checks passed
@AnnatarHe AnnatarHe deleted the feat/cc-statusline-clickable-daily-cost branch February 6, 2026 14:59
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