Usage guide

Back up your own account

Grok Bots, with attachments, and regular Grok chats. One command, two directories, on the computer where Chrome is already logged in.

Fully local, no API key. Progress lines from the exporter are in Chinese. Markdown source: docs/guide.md.

Contents

  1. Before you start 01
  2. Install 02
  3. Export 03
  4. Where the files go 04
  5. Reading the archive 05
  6. MCP server 06
  7. Troubleshooting 07
  8. Safety 08

1. Before you start

  1. macOS, Windows, or Linux. macOS uses the Keychain. Windows can use DPAPI. Linux is best-effort. Any platform can pass --cookie.
  2. Google Chrome, logged in at grok.com as the account you want to back up. Safari, Firefox, Arc, and Chromium are not read.
  3. That login lives in the Chrome profile Default, Profile 1, or Profile 2. Other profiles are ignored.
  4. Python 3.9 or newer (python3 --version).
  5. The account is yours.

--mode bot (the default) exports Grok Bots: an agent with an id, a roster entry, and a transcript. --mode chat exports regular grok.com conversations. --mode all exports both, into two directories.

Sign in before you run anything. The tool reuses that session. It does not open a login window. macOS will ask once for Keychain access; that step is under Troubleshooting.

2. Install

git clone https://github.com/LofiSu/grok-export-tool.git
cd grok-export-tool
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt

requirements.txt installs websocket-client and cryptography. Both modes decrypt Chrome’s cookie database first, so both need them. Chat requests themselves use the Python standard library.

Keep the virtualenv active in the terminal where you run the exporter. The MCP server has no third-party imports, so its command can be system python3.

python3 grok-bot-export.py --help

You should see --mode {bot,chat,all}, --skip-attachments / --messages-only, and --workers.

3. Export

Run these from the repository root, with the virtualenv active. The first successful cookie read triggers a macOS dialog for the Keychain item Chrome Safe Storage. Choose Allow.

Grok Bots, full archive

Messages, events, voice-call records, and attachment files.

python3 grok-bot-export.py
# or
./export.sh

Default directory: ~/Downloads/grok-bot-export-YYYYMMDD/.

Grok Bots, messages only

The transcript is still complete. Attachment bytes are not downloaded. messages.jsonl still records localFile when the transcript names a file, so a later full run knows where to put it.

python3 grok-bot-export.py --messages-only
# --skip-attachments is the same flag
# ./export-messages.sh wraps it

Regular Grok chats

python3 grok-bot-export.py --mode chat
# or
./export-chat.sh

Default directory: ~/Downloads/grok-chat-export-YYYYMMDD/. This writes conversation text and raw response JSON. It does not download attachment files. --messages-only has no effect here.

Both

python3 grok-bot-export.py --mode all

With no directory argument, Bots go to ~/Downloads/grok-bot-export-YYYYMMDD/ and chats go to ~/Downloads/grok-chat-export-YYYYMMDD/. There is no export-all.sh. --messages-only together with --mode all skips Bot attachments and still writes chats.

Choose a directory

python3 grok-bot-export.py ~/Backups/grok-bots
python3 grok-bot-export.py --messages-only ~/Backups/grok-bots
python3 grok-bot-export.py --mode chat ~/Backups/grok-chats
python3 grok-bot-export.py --mode all ~/Backups/grok-bots

The last command writes Bots to ~/Backups/grok-bots and chats to ~/Backups/grok-bots-chat. The -chat suffix is added only when --mode all and a directory are both set. A chat-only run uses the directory you passed, with no suffix.

Attachment workers

Bot downloads use 6 threads unless you change it. --workers must be from 1 to 32. Each chunk is 4 MB, which is the request size the exporter sends.

python3 grok-bot-export.py --workers 4

A file that already exists and is non-empty is left in place. An empty file is downloaded again. Re-running a full Bot export retries failures.

Each mode walks the whole list the session returns. There is no flag for a single Bot or a single chat. Afterward, open one folder, or ask the MCP server for one Bot by name.

4. Where the files go

Defaults sit under ~/Downloads/, outside the git repository. An export can contain full transcripts and files, and it should not be committed.

A cookie failure exits before any directory is created. If the Bot WebSocket fails after cookies succeed, the Bot export may already have created an empty output directory.

5. Reading the archive

Grok Bots

grok-bot-export-YYYYMMDD/
  AGENTS.md            short map for an agent
  _index.md            one link per Bot
  roster.json          the roster, under "agents"
  01_<name>/
    meta.json          roster record for that Bot
    messages.jsonl     one JSON object per line
    conversation.md    the same transcript, for reading
    transcript.json    decoded entries
    attachments/       downloaded files

Folder numbers are at least two digits. The name is sanitized: path characters are replaced, and it is trimmed to 60 characters. Open _index.md, then a conversation.md. For scripts or an agent, prefer messages.jsonl.

FieldMeaning
seqOrder from the transcript
typemessage, send-message, user-attachment, event, voice-call, or another entry kind
roleuser or assistant on message entries. send-message is stored as assistant. user-attachment is stored as user
contentText. Empty for a bare user attachment
timestamp, timestampMsLocal time string, and the original millisecond value
attachmentFile name and path fields when this entry has a file
localFilePath relative to the Bot folder, such as attachments/0007_name
event, callPayload for those entry kinds
entryId, fromAgent, replyTo, messageType, rawPresent when the transcript has them

meta.json is the roster object. name, agentId, status, and lastTurnAt are the fields the MCP server displays.

Regular chats

grok-chat-export-YYYYMMDD/
  _index.md
  conversations.jsonl       every message, one object per line
  conversations/
    0001_<title>.md         readable transcript
    0001_<title>.json       id, title, times, raw responses

Numbers are at least four digits. Titles are sanitized the same way as Bot names. When the API omits a title, the file uses 未命名对话.

FieldMeaning
conversationIdgrok.com conversation id
titleConversation title
roleuser when the sender is human, otherwise assistant
senderSender string from the API
contentMessage text. When the body is not a string, the JSON text of that body
timestamp, timestampMsLocal time string, and createTime

The per-conversation JSON keeps the raw messages array plus createTime and modifyTime. A chat export has no AGENTS.md, and the MCP server does not index it.

6. MCP server for OpenCode

The server is grok-bot-mcp.py. Point it at the Bot folder from the previous section, the one that contains roster.json and numbered Bot directories.

python3 /absolute/path/to/grok-export-tool/grok-bot-mcp.py \
  /absolute/path/to/grok-bot-export-YYYYMMDD

It speaks JSON-RPC on stdin and stdout and waits. The agent client starts it; you do not leave that line running yourself. The script expands ~ in the directory argument. Prefer an absolute path, because some clients do not run the command through a shell.

If you leave the directory out, the server selects the newest ~/Downloads/grok-bot-export-* by modification time. It does not look at grok-chat-export-*. Pass the Bot path explicitly.

OpenCode

The current schema at https://opencode.ai/config.json uses mcp.servers. Edit ~/.config/opencode/opencode.json, or create opencode.json in a project.

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "grok-bot": {
        "type": "local",
        "command": [
          "python3",
          "/absolute/path/to/grok-export-tool/grok-bot-mcp.py",
          "/absolute/path/to/grok-bot-export-YYYYMMDD"
        ],
        "enabled": true
      }
    }
  }
}

Replace both paths. System python3 is enough, because the MCP file does not import websocket or cryptography. To use the exporter’s virtualenv instead, put .venv/bin/python first in command.

Start a new OpenCode session so it reloads config. Ask it to use the grok-bot tools: list the bots, then open one by the name you see.

ToolArgumentsBehavior
list_botsnoneName, agentId, message count, last active time. The wording is Chinese
get_botbot (required), limit (default 200)Matches a folder prefix such as 01, then a substring of the name or agentId
searchquery (required), context (default 2)Case-sensitive substring of content. Up to 10 hits, with neighboring messages

If OpenCode rejects servers

Some older builds want the server directly under mcp. The current schema marks that shape deprecated. Use it only when the servers form is rejected:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "grok-bot": {
      "type": "local",
      "command": [
        "python3",
        "/absolute/path/to/grok-export-tool/grok-bot-mcp.py",
        "/absolute/path/to/grok-bot-export-YYYYMMDD"
      ]
    }
  }
}

OpenCode skill

The skill file is .claude/skills/grok-export/SKILL.md. Claude Code and OpenCode read .claude/skills/ in the project. The skill name is grok-export. Ask, in ordinary language, to export or to look something up in the Bot archive.

Other agents

Any stdio MCP client can launch the same program.

Claude Code, project scope, is .mcp.json at the project root. Approve it when Claude Code asks. User scope lives in ~/.claude.json. The mcpServers object is the same either way:

{
  "mcpServers": {
    "grok-bot": {
      "type": "stdio",
      "command": "python3",
      "args": [
        "/absolute/path/to/grok-export-tool/grok-bot-mcp.py",
        "/absolute/path/to/grok-bot-export-YYYYMMDD"
      ]
    }
  }
}

Codex reads ~/.codex/config.toml, and .codex/config.toml in a trusted project:

[mcp_servers.grok-bot]
command = "python3"
args = [
  "/absolute/path/to/grok-export-tool/grok-bot-mcp.py",
  "/absolute/path/to/grok-bot-export-YYYYMMDD",
]

Cursor uses .cursor/mcp.json or ~/.cursor/mcp.json:

{
  "mcpServers": {
    "grok-bot": {
      "command": "python3",
      "args": [
        "/absolute/path/to/grok-export-tool/grok-bot-mcp.py",
        "/absolute/path/to/grok-bot-export-YYYYMMDD"
      ]
    }
  }
}

If a key is rejected, that client’s MCP page is the authority. The process to launch does not change.

list_bots looks for subfolders that contain meta.json. A chat directory has none, and the reply says, in Chinese, that no export was found.

7. Troubleshooting

Keychain prompt

The exporter runs security find-generic-password for the item Chrome Safe Storage, account Chrome. Choose Allow, or Always Allow so later runs stay quiet. The password stays on the machine and decrypts Chrome’s cookie database. Do not paste it into an issue, a chat, or a commit. SECURITY.md lists what a report must leave out.

If you choose Deny, the script exits with 未能从 Chrome 解密出 grok.com 登录态. In Keychain Access, allow the terminal app you are using, then run the export again. A headless SSH session may be unable to answer the dialog; run it once in a graphical session.

Chrome is not logged in

The same exit line covers three causes:

  • grok.com is not logged in inside Google Chrome.
  • The login is in a profile other than Default, Profile 1, or Profile 2. Sign in inside one of those three. This tool does not scan any further profile.
  • Keychain access was denied, so the cookies could not be decrypted.

The tool needs both cookie names sso and sso-rw. If none of the three profile databases exist, the log also includes 未找到 Chrome 的 Default、Profile 1 或 Profile 2 Cookies 文件. Log in, confirm the profile, allow Keychain, and run again. Quitting Chrome is necessary only when the cookie database itself cannot be copied.

Empty Bot roster

The log line 找到 0 个 bot means the WebSocket roster returned no agents. The directory is still written: AGENTS.md, _index.md, and roster.json.

Regular chats show up under --mode chat or --mode all, in the chat directory. An account that only uses the main grok.com chat will have an empty Bot roster. A login in another Chrome profile is invisible unless that profile is Default, Profile 1, or Profile 2.

Empty chat list

找到 0 个普通会话 means the chat list was empty or the list request failed. Look for 会话列表请求失败(HTTP …) just above it. HTTP 429 and HTTP 5xx are retried up to five times. A warning 拉取失败 on one title means that conversation was saved with whatever messages had already arrived. Other conversations in the same run are unaffected.

Cookie database error

If Python prints a traceback while copying Chrome’s Cookies file, quit Chrome completely, including background processes, and run the export again. The tool copies the database to a temp file, reads it, and deletes the copy. It does not print cookie values.

Attachments missing

--messages-only skips downloads on purpose. On a full run, the summary line reports how many attachment jobs succeeded. A file is kept only when its download finishes. Re-run the full Bot export to retry files that are missing. Files larger than 2 GB are skipped. Chat mode never writes an attachments/ folder.

MCP says there are no bots

Pass the Bot directory, not the repository root and not the chat directory. The folder should contain subfolders with meta.json. Restart the agent client after changing the path.

The run dies on the WebSocket or mid-list

grok.com can change these interfaces without notice. Pull the latest main and try again. If it still fails, open an issue with the error text and the commit you ran. Leave out cookies, the Keychain password, agent ids, and transcript text. Security reports go through SECURITY.md, not a public issue.

8. Safety

  • Back up an account you own.
  • Keep ~/Downloads/grok-bot-export-* and ~/Downloads/grok-chat-export-* private.
  • Do not commit exports, Chrome’s cookie database, or Keychain material.
  • grok-bot-mcp.py does not open a network connection. The exporter does open connections to grok.com, using your existing session, to read history.
  • The tool does not send a new chat message and does not delete bots or conversations.
  • The exporter sets umask 077 and then marks the export tree so directories are mode 0700 and files are mode 0600. Logs do not include cookie values.
  • The project is not affiliated with xAI. Follow grok.com’s terms. Interfaces can break.

Home · 中文教程. Contact and GitHub Sponsors are in the footer, and also on GitHub, X / @su_lofi, and at lofisuchat@gmail.com.