Skip to content

perf(core): cache loadApiKey to reduce redundant keychain access#21520

Merged
sehoon38 merged 2 commits intomainfrom
perf/cache-load-api-key
Mar 9, 2026
Merged

perf(core): cache loadApiKey to reduce redundant keychain access#21520
sehoon38 merged 2 commits intomainfrom
perf/cache-load-api-key

Conversation

@sehoon38
Copy link
Contributor

@sehoon38 sehoon38 commented Mar 7, 2026

Summary

This PR caches the results of loadApiKey to avoid redundant keychain access during CLI startup and context refreshes. Accessing the system keychain involves IPC overhead, so caching this for a short duration (30 seconds) improves startup performance while still allowing for near-instant updates if the key is changed interactively.

Details

  • Implemented an in-memory cache with a 30-second TTL for loadApiKey in packages/core/src/core/apiKeyCredentialStorage.ts using the core createCache utility.
  • Added resetApiKeyCacheForTesting to allow proper test isolation.
  • Updated saveApiKey and clearApiKey to explicitly delete the cached entry to ensure changes take effect instantly.
  • Updated tests in apiKeyCredentialStorage.test.ts to assert that fs and storage read methods are only called the expected number of times, validating the cache behavior.

Related Issues

Related to #21519

How to Validate

  1. Run the core tests for apiKeyCredentialStorage:
    npm test -w @google/gemini-cli-core -- src/core/apiKeyCredentialStorage.test.ts
  2. Start the CLI normally and ensure there are no keychain prompts or delays. The API key should be correctly loaded and utilized.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

The `loadApiKey` function accesses the system keychain to retrieve
the API key, which involves inter-process communication (IPC) overhead.
Since this function can be called repeatedly during startup or context
refreshes, this commit wraps it in a short-lived memory cache to
improve startup performance and avoid unnecessary OS prompts.
@sehoon38 sehoon38 requested a review from a team as a code owner March 7, 2026 03:58
@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 7, 2026

Hi there! Thank you for your contribution to Gemini CLI.

To improve our contribution process and better track changes, we now require all pull requests to be associated with an existing issue, as announced in our recent discussion and as detailed in our CONTRIBUTING.md.

This pull request is being closed because it is not currently linked to an issue. Once you have updated the description of this PR to link an issue (e.g., by adding Fixes #123 or Related to #123), it will be automatically reopened.

How to link an issue:
Add a keyword followed by the issue number (e.g., Fixes #123) in the description of your pull request. For more details on supported keywords and how linking works, please refer to the GitHub Documentation on linking pull requests to issues.

Thank you for your understanding and for being a part of our community!

@gemini-cli gemini-cli bot closed this Mar 7, 2026
@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 7, 2026

Hi @sehoon38, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: Improving Our Contribution Process & Introducing New Guidelines.

Key Update: Starting January 26, 2026, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

Thank you for your understanding and for being a part of our community!

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 introduces a caching layer for API key retrieval, significantly enhancing the performance of the CLI. By storing the API key in a short-lived in-memory cache, the system avoids repeated, costly interactions with the underlying keychain, leading to faster startup times and more efficient context refreshes. The design ensures that while performance is boosted, the system remains responsive to real-time changes in the API key.

Highlights

  • Performance Improvement: Implemented caching for the loadApiKey function to reduce redundant and expensive keychain access during CLI startup and context refreshes.
  • Cache Mechanism: The cache uses an in-memory map with a 30-second Time-To-Live (TTL) to balance performance gains with the need for near-instant updates when the API key is changed interactively.
  • Cache Invalidation: Modified saveApiKey and clearApiKey functions to explicitly delete the cached API key entry, ensuring that any changes to the key are immediately reflected.
  • Testability: Added resetApiKeyCacheForTesting to facilitate proper test isolation and ensure reliable testing of the caching logic.
  • Test Coverage: Updated existing tests and added new ones in apiKeyCredentialStorage.test.ts to assert that storage read methods are called the expected number of times, validating the cache's effectiveness.
Changelog
  • packages/core/src/core/apiKeyCredentialStorage.test.ts
    • Imported and utilized resetApiKeyCacheForTesting in beforeEach to ensure test isolation.
    • Renamed and updated test cases to explicitly verify caching behavior for loadApiKey when an API key is present or null.
    • Modified tests for saveApiKey and clearApiKey to include assertions that the cache is correctly invalidated, leading to subsequent re-fetches from storage.
  • packages/core/src/core/apiKeyCredentialStorage.ts
    • Imported the createCache utility.
    • Initialized apiKeyCache with a 30-second default TTL for storing API key promises.
    • Exported resetApiKeyCacheForTesting to allow external resetting of the cache for testing purposes.
    • Refactored loadApiKey to use apiKeyCache.getOrCreate, enabling caching of the API key retrieval process.
    • Added apiKeyCache.delete(DEFAULT_API_KEY_ENTRY) calls within saveApiKey and clearApiKey to invalidate the cache upon key modification or removal.
Activity
  • Added/updated tests.
  • Validated on MacOS using 'npm run'.
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.

@gemini-cli gemini-cli bot reopened this Mar 7, 2026
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 introduces caching for loadApiKey to improve performance, which is a good optimization. However, the implementation of the cache reset mechanism for tests introduces shared mutable state at the module level, which can lead to flaky tests. I've suggested a safer alternative using the existing cache API, aligning with the rule for using existing cache dependencies. Additionally, the test refactoring has inadvertently removed coverage for important edge cases related to clearing the API key and error handling, which should be restored.

@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 7, 2026

Thank you for linking an issue! This pull request has been automatically reopened.

@github-actions
Copy link

github-actions bot commented Mar 7, 2026

Size Change: +446 B (0%)

Total Size: 26 MB

ℹ️ View Unchanged
Filename Size Change
./bundle/gemini.js 25.5 MB +446 B (0%)
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B

compressed-size-action

@gemini-cli gemini-cli bot added area/core Issues related to User Interface, OS Support, Core Functionality area/platform Issues related to Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Mar 7, 2026
@sehoon38 sehoon38 added this pull request to the merge queue Mar 9, 2026
Merged via the queue into main with commit 0f12583 Mar 9, 2026
27 checks passed
@sehoon38 sehoon38 deleted the perf/cache-load-api-key branch March 9, 2026 17:06
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality area/platform Issues related to Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants