Skip to content

feat(cli): Add /export command to export chat history to markdown and jsonl - #5342

Closed
ssarangi wants to merge 5 commits into
google-gemini:mainfrom
ssarangi:main
Closed

feat(cli): Add /export command to export chat history to markdown and jsonl#5342
ssarangi wants to merge 5 commits into
google-gemini:mainfrom
ssarangi:main

Conversation

@ssarangi

@ssarangi ssarangi commented Aug 1, 2025

Copy link
Copy Markdown

TLDR

This pull request introduces a new /export command that allows users to export their chat history to either jsonl or markdown format. This functionality addresses several open issues requesting a way to save conversations.

Dive Deeper

The /export command is implemented with two sub-commands: /export jsonl and /export markdown. It includes an --output <file_path> flag to save the conversation to a file. If the flag is omitted, the output is printed directly to the console for maximum flexibility.

During development, the CommandService was significantly refactored on the main branch. This PR adapts the new command to the updated architecture by registering it in the BuiltinCommandLoader. The implementation also includes a robust test suite covering happy paths, edge cases (like empty history), and error handling (like file write failures).

Reviewer Test Plan

To validate this change, please pull down the branch and run the following commands in the Gemini CLI:

  1. Start a chat and have a few turns of conversation.
  2. Test Markdown export to console: Run /export markdown. Verify that the conversation is printed to the terminal in Markdown format.
  3. Test Markdown export to file: Run /export markdown --output test.md. Verify that a test.md file is created with the correct content.
  4. Test JSONL export to console: Run /export jsonl. Verify that the conversation is printed in JSONL format.
  5. Test JSONL export to file: Run /export jsonl --output test.jsonl. Verify that a test.jsonl file is created.
  6. Test help text: Run /help export. Verify that the description clearly explains the --output flag.
  7. Test empty history: Run /clear and then /export markdown. Verify you get an informational message stating there is no conversation to export.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

Closes #4191
Closes #3882
Closes #5101

ssarangi and others added 3 commits July 31, 2025 22:34
This commit introduces a new slash command, `/export`, allowing users to export their current chat session to a file. This addresses the functionality requested in google-gemini#4191, google-gemini#3882, and google-gemini#5101.

The command supports two formats:
- `/export jsonl`: Exports the conversation in JSONL format.
- `/export markdown`: Exports the conversation in Markdown format.

An optional `--output <file_path>` flag can be used to specify an output file. If the flag is omitted, the content is printed directly to the console.

The implementation includes a comprehensive test suite covering functionality, edge cases, and error handling.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Summary of Changes

Hello @ssarangi, 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 primarily introduces a new /export command to the CLI, fulfilling user requests to save chat history. This command allows exporting conversations in either JSONL or Markdown format, with options to output to the console or a file. Additionally, the PR includes the creation of a new mock server, mcp-server, which appears to be a separate, albeit potentially related, development effort for handling tool execution requests.

Highlights

  • New /export CLI Command: Introduces a new /export command to the CLI, enabling users to export their chat history.
  • Multiple Export Formats: The /export command supports two subcommands, /export jsonl and /export markdown, allowing users to export chat history in JSON Lines (jsonl) or Markdown format.
  • Flexible Output Options: Users can choose to print the exported conversation directly to the console or save it to a specified file using the --output <file_path> flag.
  • Robust Error Handling and Edge Cases: The implementation includes comprehensive checks for scenarios such as no active chat client, empty conversation history, and file write failures, providing informative messages to the user.
  • New Mock Server for MCP: A new mcp-server directory has been added, containing a basic Node.js Express server that acts as a mock for a 'Custom MCP Server,' handling /tool/execute requests. This appears to be a separate addition not directly related to the chat export functionality described in the PR title and body.
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 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 or fill out our survey 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.

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

Copy link
Copy Markdown
Contributor

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 valuable /export command for saving chat history. The implementation is well-structured with good test coverage. My review focuses on improving robustness, security, and data integrity. Key suggestions include updating outdated and vulnerable dependencies in the new mock server, fixing a critical data loss bug in the export logic where non-text message parts are ignored, and making the command-line argument parsing more robust to handle file paths with spaces.

Comment thread packages/cli/src/ui/commands/exportConversationCommand.ts
Comment thread mcp-server/package.json
Comment thread packages/cli/src/ui/commands/exportConversationCommand.ts
@ssarangi

ssarangi commented Aug 1, 2025

Copy link
Copy Markdown
Author

/gemini review

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

Copy link
Copy Markdown
Contributor

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 useful /export command for saving chat history. The implementation is solid, with good test coverage. However, I've identified a few critical and high-severity issues that should be addressed. The new mock server's package.json has a configuration issue that will prevent it from starting and uses outdated dependencies with known vulnerabilities. Additionally, the export functionality has a data loss bug for non-text message parts, and the command's argument parsing is not robust enough to handle file paths with spaces.

Comment thread mcp-server/package.json
"name": "mcp-server",
"version": "1.0.0",
"description": "A custom MCP server",
"main": "index.js",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The mcp-server/index.js file uses ES module syntax (import). However, this package.json file is missing the "type": "module" field. Without it, Node.js will treat .js files as CommonJS modules by default, which will cause a syntax error when it encounters the import statement. This will prevent the server from starting.

  "main": "index.js",
  "type": "module",

Comment thread mcp-server/package.json
Comment on lines +12 to +17
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.15"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The versions for express (^4.17.1) and nodemon (^2.0.15) are outdated. Older versions of express in the 4.x line have known security vulnerabilities (e.g., CVE-2022-24999). It's important to use updated packages to ensure security and stability. Please update these dependencies to their latest stable versions.

  "dependencies": {
    "express": "^4.19.2"
  },
  "devDependencies": {
    "nodemon": "^3.1.0"
  }

Comment on lines +58 to +63
text:
item.parts
?.map((part: { text?: string }) =>
'text' in part ? part.text : '',
)
.join('') || '',

Copy link
Copy Markdown
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 only handles text parts of a message, which can lead to data loss during export if the conversation contains other content like images (inlineData). To prevent this, you should handle other Part types to avoid exporting incomplete conversations. A similar change should be applied to the model role handling below.

        text:
          item.parts
            ?.map((part) => {
              if ('text' in part && part.text) return part.text;
              if ('inlineData' in part) return '[Image content not supported in export]';
              return '';
            })
            .join('') || '',

Comment on lines +48 to +54
const argParts = args.split(' ').filter(Boolean); // Split by space and remove empty strings
const outputIndex = argParts.indexOf(outputFlag);
let outputPath: string | undefined;

if (outputIndex !== -1 && outputIndex + 1 < argParts.length) {
outputPath = argParts[outputIndex + 1];
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The argument parsing for the --output flag using args.split(' ') is not robust. It will fail for file paths that contain spaces, even if they are quoted. This can lead to unexpected behavior and a poor user experience. Please use a more reliable method for parsing arguments, such as a dedicated library or a more robust regex.

Suggested change
const argParts = args.split(' ').filter(Boolean); // Split by space and remove empty strings
const outputIndex = argParts.indexOf(outputFlag);
let outputPath: string | undefined;
if (outputIndex !== -1 && outputIndex + 1 < argParts.length) {
outputPath = argParts[outputIndex + 1];
}
// Using a regex to handle quoted paths. For more complex scenarios, a dedicated arg parser is recommended.
const outputMatch = args.match(/--output\s+((?:\"[^\"]+\"|'[^']+'|\S+))/);
const outputPath = outputMatch ? outputMatch[1].replace(/['"]/g, '') : undefined;

@Manamama

Manamama commented Aug 1, 2025

Copy link
Copy Markdown

My take on the very idea of such manual exports: #3882 (comment)

ssarangi and others added 2 commits August 1, 2025 09:56
This commit introduces a new slash command, `/export`, allowing users to export their current chat session to a file. This addresses the functionality requested in google-gemini#4191, google-gemini#3882, and google-gemini#5101.

The command supports two formats:
- `/export jsonl`: Exports the conversation in JSONL format.
- `/export markdown`: Exports the conversation in Markdown format.

An optional `--output <file_path>` flag can be used to specify an output file. If the flag is omitted, the content is printed directly to the console.

The implementation includes a comprehensive test suite covering functionality, edge cases, and error handling.
@westurner

Copy link
Copy Markdown

Here's a sed expression to extract prompts from gemini-cli text output:

cat ./gemini-cli-promptlog.01.txt | \
grep -E '│  > (.*)' -A 2 | grep '^│' | sed 's/^\s*│\s*/  /g' | sed 's/^\s*>/-/' | sed 's/\s*│$//'
  • Write an expression to transform that to markdown/jsonl

@gemini-code-assist

Copy link
Copy Markdown
Contributor

That's a clever sed expression for extracting prompts!

With this pull request, you'll be able to use the new /export command directly within the Gemini CLI to achieve this. It supports both markdown and jsonl formats, and you can specify an output file or print directly to the console.

For example, to export to markdown:

  • /export markdown (to console)
  • /export markdown --output my_chat_history.md (to file)

And similarly for JSONL:

  • /export jsonl (to console)
  • /export jsonl --output my_chat_history.jsonl (to file)

The "Reviewer Test Plan" in the pull request description provides more detailed examples of how to use this new functionality.

@westurner

Copy link
Copy Markdown

e.g. simonw/llm optionally logs all prompts and outputs to SQLite; so that you don't have to hope that you typed /export before/after gemini-cli or the workstation crashes:

jsonl or sqlite or duckdb in WASM:

@BitBeaver-182

Copy link
Copy Markdown

is there any updates on this pr?

@westurner

westurner commented Aug 31, 2025 via email

Copy link
Copy Markdown

@jackwotherspoon

Copy link
Copy Markdown
Collaborator

I think we can safely close this PR @ssarangi

As part of #8139 we implemented /chat share which allows saving chat history to a json or md file.

@chrstnb

chrstnb commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

Thank you for the contribution! We're closing this as there haven't been updates in 60 days. If you'd like to re-open, please ensure there is issue attached that has been approved by and discussed with a maintainer and merge conflicts and comments resolved.

@chrstnb chrstnb closed this Oct 29, 2025

@toponseo25 toponseo25 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl An extra large PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Public Roadmap Automatic Chat Session Logging Automatically save chat history

8 participants