Skip to content

Conversation

@JayadityaGit
Copy link
Contributor

@JayadityaGit JayadityaGit commented Nov 12, 2025

Summary

This PR enhances the onboarding experience by displaying an informative tip during the first request in the CLI. It also refactors the witty loading phrases and informative tips into dedicated constant files, improving code organization, readability, and maintainability.


Details

  • Updated the usePhraseCycler hook to differentiate between first and subsequent requests:

    • On the first request, a tip is always displayed.

    • On subsequent requests, the existing behavior is preserved — showing either a witty phrase or a tip (with a 1/6 probability).

  • Extracted WITTY_LOADING_PHRASES and INFORMATIVE_TIPS from usePhraseCycler.ts into separate files located under
    packages/cli/src/ui/constants/.

  • Updated and expanded test coverage:

    • Adjusted test suites for usePhraseCycler and useLoadingIndicator to align with the new logic.

    • Added a dedicated test case to verify that a tip is shown on the first activation.


Related Issues

None.


How to Validate

  1. Run the CLI application.

  2. Trigger an action that shows a loading spinner (e.g., sending a prompt).
    Expected: The first spinner displays an informative tip.

  3. Trigger another spinner.
    Expected: Subsequent spinners show either a witty phrase or a tip (with 1/6 probability).

  4. Run the test suite to confirm all checks pass:

    npm run preflight
    

Pre-Merge Checklist

  • Updated relevant documentation and README (if applicable)

  • Added/updated tests

  • Noted breaking changes (if any)

  • Validated on required platforms:

Platform npm run npx Docker Podman Seatbelt
macOS
Windows
Linux    

#12953

- Shows an informative tip on the first request to help new users.
- Refactors witty phrases and tips into separate constant files for better organization.
- Updates tests to reflect the new behavior and improve robustness.
@JayadityaGit JayadityaGit requested a review from a team as a code owner November 12, 2025 18:02
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @JayadityaGit, 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 refines the CLI's loading experience by introducing a dedicated informative tip for the user's first interaction, making the onboarding process more guided. Concurrently, it significantly improves code structure by externalizing loading phrases and tips into separate constant files, which enhances modularity and simplifies future updates. The changes are supported by updated and expanded test coverage to ensure the new behavior is correctly implemented.

Highlights

  • Enhanced Onboarding Experience: The CLI now displays an informative tip specifically during the very first request, providing a more guided initial user experience.
  • Code Organization and Maintainability: Witty loading phrases and informative tips have been extracted from the usePhraseCycler.ts hook into dedicated constant files (tips.ts and wittyPhrases.ts), significantly improving code structure, readability, and ease of maintenance.
  • Improved Test Coverage: Test suites for usePhraseCycler and useLoadingIndicator have been updated and expanded to accurately reflect the new logic, including a specific test case to verify the display of a tip on the first activation.
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.

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 PR does a great job of refactoring the loading phrases and tips into separate constants, which significantly improves code organization and maintainability. The new feature to display a tip on the first request is a nice enhancement to the user experience. My main feedback is a critical architectural concern regarding the use of a module-level variable to manage the 'first request' state. This introduces global state outside of React's control, which is an anti-pattern. I've left specific comments detailing the issue and suggesting a more idiomatic solution using React's Context API. Addressing this will make the implementation much more robust and aligned with React best practices.

];

// Track if it's the very first activation globally across the app
let hasShownFirstRequestTip = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

Using a module-level mutable variable (hasShownFirstRequestTip) to manage state across hook instances is an architectural anti-pattern in React. It introduces global state outside of React's control, which can lead to unpredictable behavior and makes testing more complex (as evidenced by the need for __resetFirstRequestFlagForTesting).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks !

Copy link
Contributor

Choose a reason for hiding this comment

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

To my eye the best solution is having a ref inside of the usePhraseCycler hook.

Having a React context is complete overkill b/c we already have uiState

Copy link
Collaborator

Choose a reason for hiding this comment

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

agreed

Comment on lines 58 to 71
let phraseList;
// Show a tip on the first request after startup, then continue with 1/6 chance
if (!hasShownFirstRequestTip) {
// Show a tip during the first request
phraseList = INFORMATIVE_TIPS;
hasShownFirstRequestTip = true; // Mark that we've shown the first request tip
} else {
// Roughly 1 in 6 chance to show a tip after the first request
const showTip = Math.random() < 1 / 6;
phraseList = showTip ? INFORMATIVE_TIPS : WITTY_LOADING_PHRASES;
}
const randomIndex = Math.floor(Math.random() * phraseList.length);
setCurrentLoadingPhrase(phraseList[randomIndex]);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This logic relies on the module-level hasShownFirstRequestTip variable. A more robust and idiomatic React solution would be to manage this application-wide state using a React Context. This would keep the state management within React's lifecycle, making it more predictable and maintainable.

I recommend creating a FirstRequestTipContext to provide and update this state, and then consuming it within this hook.

Copy link
Contributor

@psinha40898 psinha40898 left a comment

Choose a reason for hiding this comment

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

Gemini is correct that this module level variable is a React anti pattern

I'm surprised that it recommended creating a new React context as the solution.

A ref works fine here to my eye

The difference is when you declare a module level variable React has no idea about its existence.

With useRef(false) that means when the hook is called by a component the flag is set to False and then modified within that component's lifecycle.

So when it mounts the flag is set to false by default, and the flag is modified within the component's (that calls the hook) lifecycle.
uiState already stores and exposes this to any component in the tree that would need it.

the tldr is that:
with useRef React has full knowledge of this flag or ref and before it did not even know that it existed.

];

// Track if it's the very first activation globally across the app
let hasShownFirstRequestTip = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

To my eye the best solution is having a ref inside of the usePhraseCycler hook.

Having a React context is complete overkill b/c we already have uiState

describe('usePhraseCycler', () => {
beforeEach(() => {
vi.useFakeTimers();
__resetFirstRequestFlagForTesting();
Copy link
Contributor

Choose a reason for hiding this comment

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

with useRef inside of usePhraseCycler you would be able to safely remove this from your PR

describe('useLoadingIndicator', () => {
beforeEach(() => {
vi.useFakeTimers();
__resetFirstRequestFlagForTesting();
Copy link
Contributor

Choose a reason for hiding this comment

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

with useRef inside of usePhraseCycler you would be able to safely remove this from your PR

loadingPhrases[0],
);
const phraseIntervalRef = useRef<NodeJS.Timeout | null>(null);

Copy link
Contributor

@psinha40898 psinha40898 Nov 12, 2025

Choose a reason for hiding this comment

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

here add const hasShownFirstTipRef = useRef(false);

const showTip = Math.random() < 1 / 6;
const phraseList = showTip ? INFORMATIVE_TIPS : WITTY_LOADING_PHRASES;
let phraseList;
// Show a tip on the first request after startup, then continue with 1/6 chance
Copy link
Contributor

Choose a reason for hiding this comment

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

remove unnecessary llm generated comments

Fun fact: LLMs generate better code when leaving these types of comments, but neither LLMs nor humans need them to understand clear code such as this so they become quite unnecessary

@JayadityaGit
Copy link
Contributor Author

Gemini is correct that this module level variable is a React anti pattern

I'm surprised that it recommended creating a new React context as the solution.

A ref works fine here to my eye

The difference is when you declare a module level variable React has no idea about its existence.

With useRef(false) that means when the hook is called by a component the flag is set to False and then modified within that component's lifecycle.

So when it mounts the flag is set to false by default, and the flag is modified within the component's (that calls the hook) lifecycle. uiState already stores and exposes this to any component in the tree that would need it.

the tldr is that: with useRef React has full knowledge of this flag or ref and before it did not even know that it existed.

Thank you @psinha40898 !

Copy link
Collaborator

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

Looks great! Will be good to get users started off with a tip. Now I need to go ahead and add some tips about how to get the most of the custom scrolling and sticky headers.

@jacob314 jacob314 enabled auto-merge November 18, 2025 06:54
@jacob314 jacob314 added this pull request to the merge queue Nov 18, 2025
Merged via the queue into google-gemini:main with commit ecf8fba Nov 18, 2025
21 checks passed
thacio added a commit to thacio/auditaria that referenced this pull request Nov 18, 2025
jackwotherspoon pushed a commit that referenced this pull request Nov 19, 2025
Co-authored-by: Jacob Richman <jacob314@gmail.com>
danpalmer pushed a commit to danpalmer/gemini-cli that referenced this pull request Nov 29, 2025
@JayadityaGit JayadityaGit deleted the feature/separate-tips-file-and-first-request-tip branch December 17, 2025 05:03
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.

3 participants