# Windsurf IDE Observability Schema

**Cross-validated against actual data from ~/.windsurf and ~/Library/Application Support/Windsurf**

---

## Overview

Windsurf stores data across multiple locations (similar to VS Code/Cursor but with key differences):

1. **`~/Library/Application Support/Windsurf/`** - Main app data
2. **`~/.windsurf/`** - Extensions and argv config (minimal)
3. **`<workspace>/.windsurf/`** - Per-project rules (if created)

**Key Finding:** Unlike Cursor, Windsurf does NOT store chat transcripts in SQLite. Session data is stored in **LevelDB** (`Local Storage/leveldb/`).

---

## 1. Storage Locations

### 1.1 Global State Database

**Path:** `~/Library/Application Support/Windsurf/User/globalStorage/state.vscdb`

**Schema:**
```sql
CREATE TABLE ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB);
```

**Note:** Unlike Cursor, there is NO `cursorDiskKV` table.

#### Key Patterns (Verified)

| Key | Description | Value Type |
|-----|-------------|------------|
| `codeium.windsurf` | Installation ID, API server | JSON |
| `windsurfConfigurations` | Model configs (base64 protobuf) | Binary |
| `windsurfAuthStatus` | Auth state | JSON |
| `windsurf_auth-<username>` | User auth info | JSON array |
| `windsurf_auth-<username>-usages` | Usage tracking | JSON array |
| `windsurfOnboarding` | Onboarding complete flag | boolean |
| `windsurfProductEducation` | Feature education state | JSON |
| `chat.ChatSessionStore.index` | Chat session index | JSON |
| `interactive.sessions` | VS Code interactive sessions | JSON array |

**Sample Values:**

**`codeium.windsurf`:**
```json
{
  "codeium.installationId": "uuid",
  "apiServerUrl": "https://server.self-serve.windsurf.com"
}
```

**`chat.ChatSessionStore.index`:**
```json
{
  "version": 1,
  "entries": {}
}
```

**`windsurfProductEducation`:**
```json
{
  "onboardingState": 1,
  "onboardingItems": [
    {
      "id": "windsurf.prioritized.chat.open",
      "title": "Code with Cascade",
      "completed": true,
      "command": "windsurf.prioritized.chat.open",
      "tooltip": "...",
      "displayName": "Toggle Cascade",
      "alwaysShow": true
    }
  ]
}
```

---

### 1.2 Workspace State Database

**Path:** `~/Library/Application Support/Windsurf/User/workspaceStorage/<hash>/state.vscdb`

**Mapping:** `workspace.json` in each folder:
```json
{
  "folder": "file:///path/to/workspace"
}
```

#### Key Patterns

| Key | Description |
|-----|-------------|
| `chat.ChatSessionStore.index` | Per-workspace chat index |
| `chat.customModes` | Custom chat modes |
| `windsurf.cascadeViewContainerId.state` | Cascade panel state |
| `windsurf.cascadeViewContainerId.numberOfVisibleViews` | UI state |

---

### 1.3 LevelDB Storage (Primary Cascade Data)

**Path:** `~/Library/Application Support/Windsurf/Local Storage/leveldb/`

This is where **Cascade chat sessions are stored**, NOT in SQLite.

**Files:**
```
000005.ldb
000137.ldb
000139.ldb
000140.log
000141.ldb
CURRENT
LOCK
LOG
MANIFEST-000001
```

#### Discovered Keys (from string extraction)

| Key Pattern | Description |
|-------------|-------------|
| `cascade-last-viewed-at` | Timestamps of last viewed sessions |
| `open-sessions-by-workspace` | Session mappings per workspace |
| `unleash:repos` | Feature flag configs |
| Various model configs | `CHAT_GPT_4O_MINI_*`, `CASCADE_*` |

**Sample Data Structure:**

**`cascade-last-viewed-at`:**
```json
{
  "3d6be327-9db0-49c2-beaa-e37ac15c1644": "2026-02-05T04:04:46.509Z",
  "5bdeec62-2363-42fe-b6ac-828e45c032b4": "2026-02-05T04:05:06.509Z"
}
```

**`open-sessions-by-workspace`:**
```json
{
  "/Users/sagar/temp/lorem-ipsum-projects/windsurf-proj": {
    "tabs": [
      {
        "type": "c",
        "id": "..."
      }
    ],
    "activeTabId": "..."
  }
}
```

---

## 2. File-Based Storage

### 2.1 Extensions

**Path:** `~/.windsurf/extensions/`

Standard VS Code extension format.

### 2.2 User Settings

**Path:** `~/Library/Application Support/Windsurf/User/settings.json`

Standard VS Code settings format.

### 2.3 File History

**Path:** `~/Library/Application Support/Windsurf/User/History/<hash>/`

Contains:
- `entries.json` - Edit history metadata
- `<id>.<ext>` - Historical file versions

### 2.4 Logs

**Path:** `~/Library/Application Support/Windsurf/logs/<timestamp>/`

Structure:
```
20260205T092104/
├── window1/
│   ├── exthost/
│   │   └── codeium.windsurf/
│   │       ├── Windsurf.log
│   │       └── Windsurf (Lifeguard).log
│   ├── network.log
│   ├── renderer.log
│   └── views.log
├── main.log
├── terminal.log
└── telemetry.log
```

**Windsurf.log sample:**
```
2026-02-05 09:19:24.029 [info] I0205 09:19:24.029398 21931 main.go:819] Starting language server process with pid 21931
2026-02-05 09:19:24.030 [info] I0205 09:19:24.030382 21931 server.go:369] Language server listening on random port at 63131
```

### 2.5 Per-Project Rules (if created)

**Path:** `<workspace>/.windsurf/rules/*.md`

Markdown files with custom rules for Cascade.

---

## 3. Cache and Supporting Data

### 3.1 URL Cache

**Path:** `~/Library/Caches/com.exafunction.windsurf/Cache.db`

SQLite database for HTTP caching (not chat data).

### 3.2 Web Storage

**Path:** `~/Library/Application Support/Windsurf/WebStorage/`

Contains CacheStorage for web resources.

---

## 4. Key Differences from Cursor

| Aspect | Cursor | Windsurf |
|--------|--------|----------|
| Chat storage | SQLite (`cursorDiskKV`) | LevelDB (`Local Storage/leveldb/`) |
| Transcript files | `~/.cursor/projects/*/agent-transcripts/*.txt` | **Not found** (stored in LevelDB only) |
| AI code tracking | `~/.cursor/ai-tracking/ai-code-tracking.db` | **Not present** |
| Terminal captures | `~/.cursor/projects/*/terminals/*.txt` | **Not found** |
| MCP tool cache | `~/.cursor/projects/*/mcps/` | **Not found** |
| Memories | `cursor/pendingMemories` in ItemTable | **Not found** |

---

## 5. Extraction Strategy

### For Cascade Sessions (LevelDB)

LevelDB is not directly queryable like SQLite. Options:

1. **Node.js levelup/leveldown:**
```javascript
const level = require('level');
const db = level('~/Library/Application Support/Windsurf/Local Storage/leveldb');

db.get('open-sessions-by-workspace', (err, value) => {
  console.log(JSON.parse(value));
});
```

2. **Python plyvel:**
```python
import plyvel
import json

db = plyvel.DB('~/Library/Application Support/Windsurf/Local Storage/leveldb', create_if_missing=False)
for key, value in db:
    if b'cascade' in key or b'session' in key:
        print(key.decode(), json.loads(value.decode()))
```

3. **strings extraction (basic):**
```bash
strings /path/to/leveldb/*.ldb | grep -E 'cascade|session|tabs'
```

### For Configuration (SQLite)

```bash
sqlite3 "~/Library/Application Support/Windsurf/User/globalStorage/state.vscdb" \
  "SELECT key, value FROM ItemTable WHERE key LIKE '%windsurf%'"
```

---

## 6. Observability Schema Summary

### Available Data Sources

| Source | Type | Data |
|--------|------|------|
| `globalStorage/state.vscdb:ItemTable` | SQLite | Settings, auth, feature flags |
| `workspaceStorage/*/state.vscdb:ItemTable` | SQLite | Per-workspace UI state |
| `Local Storage/leveldb/` | LevelDB | **Cascade sessions, chat history** |
| `logs/*/window1/exthost/codeium.windsurf/` | Text | Debug logs |
| `User/History/*/entries.json` | JSON | File edit history |

### Key Identifiers

- **Session UUID:** e.g., `3d6be327-9db0-49c2-beaa-e37ac15c1644`
- **Workspace path:** Used as key in `open-sessions-by-workspace`
- **Installation ID:** In `codeium.windsurf`

---

## 7. Verified LevelDB Extraction (Node.js)

Successfully extracted data using `classic-level`:

```javascript
import { ClassicLevel } from 'classic-level';

const db = new ClassicLevel('/path/to/leveldb-copy', { 
  createIfMissing: false,
  keyEncoding: 'utf8',
  valueEncoding: 'utf8'
});

await db.open();

for await (const [key, value] of db.iterator()) {
  const cleanKey = key.toString()
    .replace('_vscode-file://vscode-app', '')
    .replace(/\x00\x01/g, '');
  // Process...
}
```

**Note:** Copy the LevelDB folder first and remove LOCK file since Windsurf holds a lock when running.

### Extracted Cascade Keys

| Key | Content |
|-----|---------|
| `cascade-last-viewed-at` | Session UUIDs → ISO timestamps |
| `cascade-open-sessions-by-workspace` | Workspace path → tabs array with session IDs |
| `cascade-tab-editor-state` | Session ID → Lexical editor state (empty paragraphs) |

### Sample Extracted Data

**`cascade-open-sessions-by-workspace`:**
```json
{
  "file:///Users/sagar/temp/lorem-ipsum-projects/windsurf-proj": {
    "tabs": [
      { "type": "cascade", "id": "3d6be327-9db0-49c2-beaa-e37ac15c1644" },
      { "type": "cascade", "id": "5bdeec62-2363-42fe-b6ac-828e45c032b4" }
    ],
    "activeTabId": "5bdeec62-2363-42fe-b6ac-828e45c032b4"
  }
}
```

**`cascade-last-viewed-at`:**
```json
{
  "3d6be327-9db0-49c2-beaa-e37ac15c1644": "2026-02-05T04:04:46.509Z",
  "5bdeec62-2363-42fe-b6ac-828e45c032b4": "2026-02-05T04:29:06.511Z"
}
```

---

## 8. Critical Finding: Chat Content is Server-Side (VERIFIED)

**The actual conversation content (user messages, AI responses) is NOT stored locally.**

### Verification Test

Searched for keywords from an actual Cascade prompt:
```
"Build a blog app in Python Flask with SQLite..."
"dummy posts", "SQLAlchemy models", "uv venv"
```

**Results:**

| Search Target | Found? | Location |
|---------------|--------|----------|
| Prompt text "Build a blog app..." | ❌ NOT FOUND | - |
| Keywords "dummy posts", "SQLAlchemy" | ❌ NOT FOUND | - |
| Generated code (`app.py` content) | ✅ FOUND | `History/281549fa/kYb8.py` |
| Session IDs | ✅ FOUND | LevelDB `cascade-*` keys |

### What's Stored Locally

| Data Type | Stored? | Location |
|-----------|---------|----------|
| Session IDs (UUIDs) | ✅ | LevelDB: `cascade-open-sessions-by-workspace` |
| Session timestamps | ✅ | LevelDB: `cascade-last-viewed-at` |
| Workspace mappings | ✅ | LevelDB: `cascade-open-sessions-by-workspace` |
| Generated file versions | ✅ | `User/History/<hash>/<id>.<ext>` |
| Feature flags/config | ✅ | LevelDB: `unleash:repository:repo` |
| Editor UI state | ✅ | LevelDB: `cascade-tab-editor-state` (empty paragraphs) |

### What's NOT Stored Locally

| Data Type | Stored Locally? |
|-----------|-----------------|
| User prompts | ❌ Server-side |
| AI responses | ❌ Server-side |
| Tool calls and results | ❌ Server-side |
| Thinking/reasoning content | ❌ Server-side |
| Conversation history | ❌ Server-side |

### File History (What IS Local)

Windsurf stores **file versions** (the output of AI edits) in:
```
~/Library/Application Support/Windsurf/User/History/<hash>/
├── entries.json      # Metadata
└── <id>.<ext>        # Actual file content at that point in time
```

Example: The Flask app code generated by Cascade was found in `kYb8.py`:
```python
from flask import Flask, render_template, request, redirect, url_for, flash
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
```

But the **prompt that generated it** is nowhere on disk.

---

## 9. Limitations

1. **Chat content is server-synced:** Cannot extract conversation text from local storage
2. **No plain-text transcripts:** Unlike Cursor's `agent-transcripts/*.txt`
3. **Binary protobuf:** `windsurfConfigurations` uses binary encoding
4. **No AI code tracking:** No equivalent to Cursor's `ai-code-tracking.db`
5. **Session metadata only:** Local LevelDB only has session IDs and timestamps
6. **No local prompt history:** User prompts are not persisted locally

---

## 10. Recommendations

For Windsurf observability, options are limited:

1. **Session metadata:** Extract session IDs, timestamps, workspace mappings from LevelDB
2. **File history:** Monitor `User/History/` for generated code versions
3. **Logs:** Monitor `~/Library/Application Support/Windsurf/logs/` for activity traces
4. **API interception:** Consider network-level monitoring (complex, may violate ToS)
5. **Export feature:** Use "Download Windsurf Logs File" from Command Palette (diagnostic only)
6. **Request from Codeium:** Check if they offer a chat export API or local storage option

### Comparison with Cursor

| Aspect | Cursor | Windsurf |
|--------|--------|----------|
| Chat content location | Local SQLite/text files | **Server-side (Codeium)** |
| User prompts stored locally | ✅ Yes | ❌ No |
| AI responses stored locally | ✅ Yes | ❌ No |
| Session metadata | Local SQLite | Local LevelDB |
| Full transcript export | ✅ Possible | ❌ Not possible locally |
| AI code tracking | ✅ `ai-code-tracking.db` | ❌ None |
| Generated file history | ✅ In transcripts | ✅ In `User/History/` |

---

## 11. LevelDB Summary

Only **9 keys** in the entire LevelDB:

| Key | Purpose | Size |
|-----|---------|------|
| `META:vscode-file://vscode-app` | Internal metadata | 13 bytes |
| `METAACCESS:vscode-file://vscode-app` | Access metadata | 9 bytes |
| `VERSION` | DB version | 1 byte |
| `DefaultOverridesCacheExists` | Cache flag | 4 bytes |
| `cascade-last-viewed-at` | Session timestamps | 134 bytes |
| `cascade-open-sessions-by-workspace` | Session-workspace mapping | 254 bytes |
| `cascade-tab-editor-state` | Empty editor states | 2,162 bytes |
| `unleash:repository:repo` | Feature flags (huge) | 63,264 bytes |
| `unleash:repository:sessionId` | Unleash session | 12 bytes |

**Total chat-related data: ~2.5 KB** (just metadata, no content)
