Skip to content

Draft: Automatically record chat history in interactive and non-interactive mode; add interactive and non-interactive conversation resuming and a session browser#4401

Closed
bl-ue wants to merge 55 commits intogoogle-gemini:mainfrom
Piebald-AI:auto-record-chat-history-071725
Closed

Draft: Automatically record chat history in interactive and non-interactive mode; add interactive and non-interactive conversation resuming and a session browser#4401
bl-ue wants to merge 55 commits intogoogle-gemini:mainfrom
Piebald-AI:auto-record-chat-history-071725

Conversation

@bl-ue
Copy link
Copy Markdown
Contributor

@bl-ue bl-ue commented Jul 17, 2025

⚠️ This PR has been broken up into 8 smaller PRs:

  1. feat(sessions): Introduce core ChatRecordingService for automatic conversation saving #5221 (MERGED)
  2. feat(sessions): Integrate chat recording into GeminiChat #6721 (MERGED)
  3. feat(sessions): Add automatic session cleanup and retention policy #7662 (MERGED)
  4. feat(sessions): add resuming to geminiChat and add CLI flags for session management #10719 (MERGED)
    a. Followup from #10719 #13243 (MERGED)
    b. fix(resume): allow passing a prompt via stdin while resuming using --resume #13520
  5. feat(sessions): record interactive-only errors and warnings to chat recording JSON files #13300 (MERGED)
  6. feat(ui): build interactive session browser component #13351 (MERGED)
  7. feat(sessions): add /resume slash command to open the session browser #13621
  8. docs(sessions): add documentation for chat recording and session management #13667

The original description, still completely relevant, is below.


Important

All the functionality from this MR is now merged into main.


In this PR, I—

  • added automatic conversation recording to JSON files for interactive and non-interactive sessions (see below for details);
  • created an interactive session browser with sorting, searching/filters, deleting, and resuming capabilities;
  • implemented both interactive and non-interactive session resuming via the command line with --resume <session_id> (for a specific session) and --resume (for the latest one);
  • configured a retention feature that automatically removes sessions based on age (older than a specific date) or quantity (when the total count of sessions exceeds a specific number),
  • made /clear start a new session recording; and
  • updated the documentation (commands.md, and added chat-recording.md).

Resuming modifies the session file in place. It would not be difficult to make a configuration option to make it duplicate the session file instead.

What's Done

In this PR I've added automatic chat history recording. Starting with the first user message, we record:

  • All user messages, with the timestamp and a UUID
  • All Gemini messages, with
    • Timestamp
    • UUID
    • Thoughts (subject, description, timestamp)
    • Tool calls (ID, name, input, output, state, timestamp)
    • Token usage (input, output, cached, thoughts, tools)
    • Session ID
    • Project hash
    • Session start time
    • Model

Tool calls in all states are recorded, even while they're waiting to be confirmed. API errors and info messages such as context compression notifications are also recorded, so the whole conversation log is preserved. Each message is stored immediately; thus, if the CLI crashes or is killed, no messages are lost.

In the JSON, Gemini's thoughts are attached to their corresponding message object, and so, since they're generated before the message itself be it a normal text message or tool calls, they're queued, not being flushed to the JSON until after the corresponding message is finished generating and then flushed.

I replaced the current /chat {list|save|resume} functionality with a new interactive session browser available with /resume. It'll list all your saved conversations, along with the date and number of messages, as well as the first user message for context. You can search through their content with /. When you select a chat, it will be resumed, and subsequent messages will be appended to it.

The retention feature automatically deletes either all sessions older than currentDate - maxAge—where maxAge is defined in ~/.gemini/settings.json—or enough sessions to get the total number of them down to a specific count—maxCount, also defined in the global or per-workspace settings—or both, if both are defined.

{
  "sessionRetention": {
    "enabled": true,
    // Either or, or both.
    "maxAge": "7d", // minimum: 1h
    "maxCount": 50 // minimum: 1
  }
}

A quick demo of the session browser and resuming:

auto-record-and-resume-demo.mp4

(This functionality also enables Gemini CLI to be supported in Splitrail.)

Recorded chat sample

Below I've pasted a sample of a recorded chat session.

Click to expand
{
  "sessionId": "6577c6cc-dfe2-42f1-a861-ff475f3dc692",
  "projectHash": "7bf1664fd227f3ccca27efcaffc3225990adc35edcf3ffcb8c5b2624c3749ced",
  "startTime": "2025-07-25T14:27:05.262Z",
  "lastUpdated": "2025-07-25T14:28:10.713Z",
  "messages": [
    {
      "id": "89d02136-a4fa-489d-9efa-b17af3edaa69",
      "timestamp": "2025-07-25T14:27:08.141Z",
      "type": "user",
      "content": "Hello"
    },
    {
      "id": "c325c8dc-a69a-4134-ae15-5626361c71c0",
      "timestamp": "2025-07-25T14:27:12.766Z",
      "type": "gemini",
      "content": "Hi there! How can I help you today?",
      "thoughts": [
        {
          "subject": "Formulating a Response",
          "description": "I'm crafting a friendly greeting right now. My current strategy is to use a simple \"Hello\" followed by a question to offer assistance. It's all about being welcoming and helpful, setting the stage for a productive interaction.",
          "timestamp": "2025-07-25T14:27:10.687Z"
        }
      ],
      "tokens": {
        "input": 12823,
        "output": 10,
        "cached": 0,
        "thoughts": 22,
        "tool": 0,
        "total": 12855
      },
      "model": "gemini-2.5-pro"
    },
    {
      "id": "5ec6dcb0-45b1-461d-af7a-9330f84704ff",
      "timestamp": "2025-07-25T14:27:18.782Z",
      "type": "user",
      "content": "Create a.txt with the contents \"Hello\""
    },
    {
      "id": "41e51247-f6a3-4d2c-bc85-a91acab31abe",
      "timestamp": "2025-07-25T14:27:25.135Z",
      "type": "gemini",
      "content": "",
      "toolCalls": [
        {
          "id": "write_file-1752848843973-5d6bfd5ae1bed",
          "name": "write_file",
          "args": {
            "file_path": "C:\\dev\\gemini-cli\\a.txt",
            "content": "Hello"
          },
          "result": [
            {
              "functionResponse": {
                "id": "write_file-1752848843973-5d6bfd5ae1bed",
                "name": "write_file",
                "response": {
                   "output": "Successfully overwrote file: C:\\dev\\gemini-cli\\a.txt."
                }
              }
            ]
          },
          "status": "success",
          "timestamp": "2025-07-25T14:28:05.209Z"
        }
      ],
      "thoughts": [
        {
          "subject": "Analyzing File Operations",
          "description": "I've identified the user's objective: to generate `a.txt` containing \" Hello\". My next move involves the `write_file` tool. I'm currently strategizing how to correctly construct the `file_path` parameter, noting the importance of an absolute path and the current working directory to achieve the desired file creation.",
          "timestamp": "2025-07-25T14:27:22.986Z"
        },
        {
          "subject": "Defining the Tool Call",
          "description": "I'm now finalizing the tool call parameters. After confirming the absolute path is crucial, I'm focused on formatting the `write_file` call. Ensuring proper escaping of backslashes within the `file_path` is paramount to avoid any errors during file creation. I'm confident in this approach now.",
          "timestamp": "2025-07-25T14:27:23.923Z"
        }
      ],
      "tokens": {
        "input": 12843,
        "output": 19,
        "cached": 0,
        "thoughts": 146,
        "tool": 0,
        "total": 13008
      },
      "model": "gemini-2.5-pro"
    },
    {
      "id": "cf0fe414-770c-44ea-afd3-59c9209a59ec",
      "timestamp": "2025-07-25T14:28:10.713Z",
      "type": "gemini",
      "content": "Done.\n",
      "thoughts": [],
      "tokens": {
        "input": 12883,
        "output": 3,
        "cached": 0,
        "thoughts": 0,
        "tool": 0,
        "total": 12886
      },
      "model": "gemini-2.5-pro"
    }
  ]
}

Reviewer test plan

Run the CLI and chat with Gemini. Then use /resume to see chats saved and ready to be resumed. Also run gemini with --list-sessions, --delete-session, --resume, and --resume <session index> to try out the non-interactive mode support.

How to building locally

If you'd like to temporarily use this PR's implementation of automatic recording and resuming, first uninstall your existing Gemini CLI (npm uninstall -g @google/gemini-cli), and then run the following commands to clone, build, and install it from source:

npm uninstall -g @google/gemini-cli
git clone https://github.com/Piebald-AI/gemini-cli.git
cd gemini-cli
git checkout auto-record-chat-history-071725
npm run build

Important

All the functionality from this MR is now merged into main.

@bl-ue bl-ue requested a review from a team as a code owner July 17, 2025 19:06
@google-cla
Copy link
Copy Markdown

google-cla Bot commented Jul 17, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@bl-ue bl-ue marked this pull request as draft July 17, 2025 19:07
Copy link
Copy Markdown
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.

Summary of Changes

Hello @bl-ue, 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 robust automatic chat history recording system for the Gemini CLI. It ensures that all conversations, including user prompts, AI responses, internal thoughts, and tool executions, are persistently saved to local files. Concurrently, it refactors the command-line interface by repurposing the /chat command for managing these auto-saved sessions and creating a new /fork command for manual conversation checkpointing.

Highlights

  • Automatic Conversation Recording: A new ChatRecordingService is implemented to automatically save comprehensive chat history (user/Gemini messages, AI thoughts, tool calls, token usage) to JSON files in a project-specific temporary directory.
  • Refactored /chat Command: The /chat command is now dedicated to managing auto-saved conversations, providing subcommands to list available sessions, resume a previous conversation by ID, and search conversation content.
  • New /fork Command for Manual Checkpoints: The previous manual conversation checkpointing functionality (saving and loading conversations by a user-defined tag) has been moved from the /chat command to a new /fork command.
  • Enhanced History Detail: The recorded history now includes richer details such as the AI's internal thoughts during generation and the full lifecycle (requests, results, status) of tool calls.
  • Dedicated Documentation: A new docs/chat-recording.md file has been added, providing clear instructions and details on how the automatic chat recording works and how to interact with it via the updated /chat command.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 is currently in preview and 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 to provide feedback.

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
Copy Markdown
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 a comprehensive automatic chat recording feature. Conversations are now saved to disk, and a new /chat command allows users to list, resume, and search their history. The previous functionality of the /chat command (manual checkpointing) has been moved to a new /fork command. The implementation is well-integrated throughout the UI and core services. I've identified a critical data loss bug in the tool call recording logic and a high-severity issue with un-guarded console logs that should be addressed.

Comment thread packages/core/src/services/chatRecordingService.ts Outdated
Comment thread packages/core/src/services/chatRecordingService.ts
@bl-ue bl-ue changed the title Auto record chat history 071725 Automatically record chat history Jul 17, 2025
This was referenced Jul 17, 2025
+ Remove /fork
+ Add interactive resuming
bl-ue added 4 commits July 19, 2025 20:02
* Now we don't copy the session file when resuming it--it's too confusing
* We do show the current session in the session browser, but its disabled
* Replace /chat * with just /resume
* There was a bug making an empty Gemini message before tool calls
* The resuming wasn't refreshing the statics, so unpredictable the resume didn't appear to work
@ShuangLiu1992
Copy link
Copy Markdown

Dear @bl-ue, Excellent work! I understand it might take some time for your changes to be fully merged. In the meantime, I’m particularly interested in testing the CLI with the --save and --resume options in a non-interactive way. Is there a specific commit in your branch that you could point me to for this?

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Aug 21, 2025

Hi @ShuangLiu1992! The very latest commit has all the functionality in it, including the --resume CLI flag. --save doesn't exist because now all chats, both interactive and non-interactive, are automatically saved; there's no need to manually save specific ones anymore.

To get this PR's version of Gemini CLI running, first you need to uninstall your existing gemini-cli. Then run these commands:

npm uninstall -g @google/gemini-cli
git clone https://github.com/bl-ue/gemini-cli.git
cd gemini-cli
git checkout auto-record-chat-history-071725
npm run build

And then run npm link to install your local version globally:

npm link

Then when you run gemini it should point to your local version.

@ShuangLiu1992
Copy link
Copy Markdown

@bl-ue Automatic saving is fantastic!
If manual saving isn’t on the roadmap, it would be incredibly helpful to have access to the unique session ID for each saved conversation. For instance, Claude Code includes the session ID in its JSON output, which seems like it would be extremely useful for Splitrail and many others.

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Aug 21, 2025

Hi @ShuangLiu1992, you can actually resume specific sessions by index, for example

PS C:\dev\gemini-cli> gemini --list-sessions

Available sessions for this project (8):

  1. How can you detect light/dark mode in a Windows app? (1 day ago)
  2. Where do we store saved sessions in this app? (2 days ago)
  3. Find config.ts (20 hours ago)
  4. Hi (2 days ago)
  5. Empty conversation (1 day ago)
  6. Empty conversation (20 hours ago)
  7. Empty conversation (20 hours ago)
  8. Hi there. (20 hours ago)

For example, to resume the third session, where the first message I sent was Find config.ts, I'd run

gemini --resume 3

Session number 1 is the oldest session, and session 8 is the newest. A subsequent new session would be assigned index 9, and then 10, and so on. So the indices will never change unless you delete a session, in which case the indices after the one you deleted will be shifted back.

Is that what you're thinking, or are you envisioning something else?

@ShuangLiu1992
Copy link
Copy Markdown

ShuangLiu1992 commented Aug 21, 2025

@bl-ue
For example with claude, if you run claude -p "hello" --output-format=json
It will output something like:
{"type":"result","subtype":"success","is_error":false,"duration_ms":4555,"duration_api_ms":4530,"num_turns":1,"result":"Hello! How can I help you today?","session_id":"a97a5671-7e3f-47f6-b6b4-e1e36b037dd0","total_cost_usd":0.047189999999999996,"usage":{"input_tokens":15670,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12,"server_tool_use":{"web_search_requests":0},"service_tier":"standard"},"permission_denials":[]}

In automated, non-interactive environments, using the unique session IDs is typically more reliable than relying on the sequential order of conversations.

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Aug 21, 2025

That's a good point @ShuangLiu1992. I'll add the ability to resume/delete sessions by an ID in addition to by an index.

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Aug 22, 2025

@ShuangLiu1992 Done! Now running --list-sessions will show the UUIDs for each session, and you can specify the UUIDs with --resume:

PS C:\dev\gemini-cli-4401> npm run start -- --list-sessions
...
Available sessions for this project (2):

  1. Write "Hi" to "abc.txt" (22 hours ago) [5cc38062-0914-406a-8e92-e0fa0c4c8aae]
  2. Hello (1 hour ago) [0b34cb6a-dfe3-44a3-b7c3-4d7d7412cc7f]

PS C:\dev\gemini-cli-4401> npm run start -- --resume 5cc38062-0914-406a-8e92-e0fa0c4c8aae
...
Loaded cached credentials.
I attempted to write "Hi" to the file `C:\dev\gemini-cli-4401\abc.txt`, but the operation was cancelled.

The UUIDs were already being assigned to each session; I just added the ability to use --resume with the UUID as well.

@ShuangLiu1992
Copy link
Copy Markdown

@bl-ue Amaizng! Look forward to more awesome stuff coming out of Piebald-AI!

@kundeng
Copy link
Copy Markdown

kundeng commented Aug 25, 2025

So this is not in the major release and needs to be manually pulled and built?

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Aug 25, 2025

Hi @kundeng, yes, currently it's not in the main branch yet; we're working on splitting up into smaller PRs. I'm currently working on the second one, #6721. For the present, you can run the commands listed above to get it. I'll let you know when it's all merged in.

bl-ue added a commit to Piebald-AI/gemini-cli that referenced this pull request Aug 29, 2025
It was made mutable in google-gemini#5221 as part of this google-gemini#4401 branch, but that was too
early, and so was reverted in google-gemini#7219.  We need it mutable as part of the setup
but we'll not bring it to main until it's needed.
@Finndersen
Copy link
Copy Markdown

Would love to get this feature implemented!!

@bl-ue
Copy link
Copy Markdown
Contributor Author

bl-ue commented Sep 8, 2025

@Finndersen #7662

@mercmobily
Copy link
Copy Markdown

I can't resist... I know this is just noise, but I just can't resist... THANK YOU!!! THANK YOU!!! And THANK YOU!!!

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.

10 participants