DEV Community

Cover image for How to Migrate Your Conversation History to the New Antigravity IDE (macOS)
Mohammad Awwaad
Mohammad Awwaad

Posted on

How to Migrate Your Conversation History to the New Antigravity IDE (macOS)

If you've recently upgraded from the classic Antigravity App to the new, standalone Antigravity IDE, you might have noticed a frustrating quirk: your "Past Conversations" sidebar is completely empty.

Google recently separated the Antigravity IDE into its own application. As a result, the application data path changed from ~/.gemini/antigravity to ~/.gemini/antigravity-ide. Because the IDE is built on top of VS Code's core architecture, its internal SQLite databases (state.vscdb) contain hardcoded absolute paths pointing to the old directory structure.

In this guide, I'll show you how to safely migrate your old workspaces, conversation history, and artifact links to the new IDE using a quick Python script.

The Problem

When you switch to the new IDE, your conversation history files (stored as .pb Protobuf files) are left behind in the old directory. Furthermore, even if you copy them over manually, the IDE's internal state.vscdb databases won't register them because the trajectory summaries and recently opened workspaces use hardcoded legacy paths.

The Solution: A Python Migration Script

To fix this, we need to:

  1. Copy the latest .pb conversation files to the new IDE folder.
  2. Connect to the VS Code SQLite databases (state.vscdb) in both global and workspace storage.
  3. Merge the Base64-encoded Protobuf trajectory summaries so both old and new histories are combined.
  4. Intelligently find and replace the legacy paths (antigravityantigravity-ide) without causing double-suffixes.

⚠️ Crucial Note: The IDE flushes its database state to disk when it closes. You must completely quit the IDE (Cmd + Q) before running this script. If the IDE is open, it will overwrite the database the moment you close it, erasing the migration!

Step 1: Save the Migration Script

Create a new file called migrate_antigravity.py and paste the following Python code into it:

import os
import sqlite3
import shutil
import base64
import json
import re

def log(msg):
    print(f"[*] {msg}")

def replace_paths(val):
    if not isinstance(val, str):
        return val
    # Intelligently replace legacy paths without creating double suffixes (e.g., antigravity-ide-ide)
    val = re.sub(r'/Users/([^/]+)/\.gemini/antigravity(?!-ide)', r'/Users/\1/.gemini/antigravity-ide', val)
    val = re.sub(r'Application Support/Antigravity(?! IDE)', r'Application Support/Antigravity IDE', val)
    return val

def parse_summaries(data):
    # Parses the repeated protobuf messages for trajectory summaries
    summaries = []
    i = 0
    while i < len(data):
        if data[i] != 0x0a:
            i += 1
            continue
        i += 1
        length, shift = 0, 0
        while i < len(data):
            b = data[i]
            i += 1
            length |= (b & 0x7f) << shift
            if not (b & 0x80): break
            shift += 7
        summaries.append(data[i:i+length])
        i += length
    return summaries

def encode_varint(value):
    out = []
    while value >= 0x80:
        out.append((value & 0x7f) | 0x80)
        value >>= 7
    out.append(value)
    return bytes(out)

def get_trajectory_id(msg_bytes):
    if len(msg_bytes) >= 38 and msg_bytes[0] == 0x0a and msg_bytes[1] == 0x24:
        return msg_bytes[2:38].decode('utf-8', errors='ignore')
    return None

def merge_trajectory_summaries(old_val_b64, new_val_b64):
    old_data = base64.b64decode(old_val_b64) if old_val_b64 else b""
    new_data = base64.b64decode(new_val_b64) if new_val_b64 else b""

    merged_dict = {}
    for s in parse_summaries(old_data):
        if tid := get_trajectory_id(s): merged_dict[tid] = s
    for s in parse_summaries(new_data):
        if tid := get_trajectory_id(s): merged_dict[tid] = s

    out = bytearray()
    for s in merged_dict.values():
        out.append(0x0a)
        out.extend(encode_varint(len(s)))
        out.extend(s)
    return base64.b64encode(out).decode('ascii')

def main():
    home = os.path.expanduser("~")
    old_global_db = os.path.join(home, "Library/Application Support/Antigravity/User/globalStorage/state.vscdb")
    new_global_db = os.path.join(home, "Library/Application Support/Antigravity IDE/User/globalStorage/state.vscdb")

    old_ws_dir = os.path.join(home, "Library/Application Support/Antigravity/User/workspaceStorage")
    new_ws_dir = os.path.join(home, "Library/Application Support/Antigravity IDE/User/workspaceStorage")

    # 1. Global Storage Migration
    log("Migrating Global Storage...")
    if os.path.exists(new_global_db):
        shutil.copy2(new_global_db, new_global_db + ".backup")

    old_g_conn = sqlite3.connect(old_global_db)
    new_g_conn = sqlite3.connect(new_global_db)

    old_items = {row[0]: row[1] for row in old_g_conn.execute("SELECT key, value FROM ItemTable WHERE key LIKE 'antigravity%' OR key LIKE 'google.antigravity%' OR key = 'history.recentlyOpenedPathsList'")}
    new_items = {row[0]: row[1] for row in new_g_conn.execute("SELECT key, value FROM ItemTable")}

    for key, old_val in old_items.items():
        if "notification" in key: continue

        if key == "antigravityUnifiedStateSync.trajectorySummaries":
            merged = merge_trajectory_summaries(old_val, new_items.get(key))
            new_g_conn.execute("INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?)", (key, merged))
        elif key == "history.recentlyOpenedPathsList":
            # Simple JSON merge (implementation omitted for brevity, fallback to replace_paths)
            new_g_conn.execute("INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?)", (key, replace_paths(old_val)))
        else:
            if key not in new_items or "Preferences" in key:
                new_g_conn.execute("INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?)", (key, replace_paths(old_val)))

    new_g_conn.commit()
    old_g_conn.close(); new_g_conn.close()

    # 2. Workspace Storage Migration
    log("Migrating Workspace Storage...")
    os.makedirs(new_ws_dir, exist_ok=True)
    if os.path.exists(old_ws_dir):
        for folder in os.listdir(old_ws_dir):
            old_db = os.path.join(old_ws_dir, folder, "state.vscdb")
            if not os.path.exists(old_db): continue

            new_folder_path = os.path.join(new_ws_dir, folder)
            os.makedirs(new_folder_path, exist_ok=True)
            new_db = os.path.join(new_folder_path, "state.vscdb")

            new_conn = sqlite3.connect(new_db)
            new_conn.execute("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value TEXT)")

            for row in sqlite3.connect(old_db).execute("SELECT key, value FROM ItemTable").fetchall():
                new_conn.execute("INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?)", (row[0], replace_paths(row[1])))

            new_conn.commit()
            new_conn.close()

    # 3. Copy Conversation files
    log("Copying Conversation Protobufs...")
    old_conv_dir = os.path.join(home, ".gemini/antigravity/conversations")
    new_conv_dir = os.path.join(home, ".gemini/antigravity-ide/conversations")
    os.makedirs(new_conv_dir, exist_ok=True)

    if os.path.exists(old_conv_dir):
        for filename in os.listdir(old_conv_dir):
            if filename.endswith(".pb"):
                shutil.copy2(os.path.join(old_conv_dir, filename), os.path.join(new_conv_dir, filename))

    log("Migration completed successfully!")

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

Step 2: Run the Migration

  1. Fully Quit the Antigravity IDE (Cmd + Q). This is critical.
  2. Open macOS Terminal.
  3. Run the script:
   python3 migrate_antigravity.py
Enter fullscreen mode Exit fullscreen mode
  1. Look for the [*] Migration completed successfully! message.
  2. Reopen the Antigravity IDE.

That's it!

All your previously stored artifacts, active workspaces, and past conversational history will be flawlessly restored in the sidebar of the new IDE app. Happy coding!

Top comments (0)