Skip to main content

Local Cursor chat summary indexer and search tool

Project description

Curlens

PyPI version Python 3.12+ License: MIT Cursor CLI

Search and resume your Cursor CLI chat sessions by description.

Curlens Demo

The Problem

You use Cursor CLI across multiple projects. After a few days, you have dozens of chats scattered across different workspaces. You remember discussing "flink job optimization" somewhere, but:

  • Which folder was it in?
  • What was the chat called?
  • How do you resume it?

Cursor stores all chats internally like this:

~/.cursor/chats/
├── a14702e33628716ed.../   # MD5 hash of workspace path (not human-readable!)
│   ├── 8616c508-cbce.../   # Chat UUID
│   │   └── store.db        # Messages stored in SQLite
│   └── 2134a03e-7cdb.../
├── 1dd0fd26bc4627ee.../    # Another workspace hash
│   └── ...
└── (dozens more)

This is Cursor's internal structure—not your project folders. The hash a14702e33628... is actually MD5("/Users/you/workspace/myproject"). There's no easy way to:

  1. Know which workspace a hash folder belongs to
  2. Search chat contents without opening each store.db
  3. Find the right chat to resume with cursor agent --resume <id>

The Solution

Curlens indexes your chats with AI-generated summaries and lets you search by description:

$ curlens -d "flink optimization"

Found 2 matching chat(s):

[1] Flink Job Tuning
    Dir: /Users/you/workspace/data-pipeline
    Optimized Flink checkpointing and parallelism settings for better throughput...

[2] Stream Processing Debug  
    Dir: /Users/you/workspace/analytics
    Fixed watermark issues in Flink streaming job...

Select chat [1-2]: 1
→ Resuming: Flink Job Tuning
→ Directory: /Users/you/workspace/data-pipeline

How It Works

┌─────────────────────────────────────────────────────────────────┐
│                        CURSOR CLI                               │
│  cursor agent (shell commands, file edits, MCP calls)          │
└─────────────────────┬───────────────────────────────────────────┘
                      │ hooks fire
                      ▼
┌─────────────────────────────────────────────────────────────────┐
│                     CURLENS HOOK                                │
│  1. Read chat messages from ~/.cursor/chats/<hash>/<id>/        │
│  2. Extract user queries + assistant responses                  │
│  3. Generate summary via LLM (cursor agent -p)                  │
│  4. Store in ~/.cursor/curlens/summary.db                       │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                     CURLENS SEARCH                              │
│  curlens -d "your query"                                        │
│  1. Load summaries from SQLite                                  │
│  2. Rank by keyword match (or LLM with --smart)                 │
│  3. Display top results                                         │
│  4. Resume selected chat with cursor agent --resume             │
└─────────────────────────────────────────────────────────────────┘

Cursor's Internal Structure

Curlens reads from Cursor's internal storage:

~/.cursor/
├── chats/
│   └── <md5(workspace_path)>/      # Hash of workspace path
│       └── <conversation_id>/
│           └── store.db            # SQLite with chat messages
├── projects/
│   └── Users-you-workspace-myproject/  # Encoded workspace path
│       └── worker.log              # Contains workspace mapping
└── curlens/                        # Created by curlens
    ├── config.json
    ├── summary.db
    └── hook.log

The hash folders in chats/ are MD5 hashes of workspace paths. Curlens maps them back using the projects/ folder names.

Install

pip install curlens

Or from source:

git clone https://github.com/cnighut/curlens
cd curlens
pip install -e .

Quick Start

1. Backfill Existing Chats (Do This First)

Index your existing chats before setting up hooks:

# Preview what will be processed
curlens --backfill --dry-run

# Process all chats (creates DB automatically)
curlens --backfill

# Or process in batches
curlens --backfill --limit 50

This scans ~/.cursor/chats/, generates summaries, and stores them. Chats with unknown workspace paths are skipped.

⚠️ Backfill is slow - Each chat requires an LLM call (~10-30 seconds). For 100+ chats, expect 30-60 minutes. Use --limit to process in batches. Already-processed chats are skipped on re-runs.

2. Setup Hooks (For Auto-Indexing)

Hooks automatically update summaries as you chat. Without hooks, you'd need to re-run backfill manually.

Create/edit ~/.cursor/hooks.json:

{
  "version": 1,
  "hooks": {
    "afterShellExecution": [
      {"command": "python3 /path/to/curlens/curlens/hooks/session_end.py"}
    ],
    "afterMCPExecution": [
      {"command": "python3 /path/to/curlens/curlens/hooks/session_end.py"}
    ],
    "afterFileEdit": [
      {"command": "python3 /path/to/curlens/curlens/hooks/session_end.py"}
    ]
  }
}

Important: Replace /path/to/curlens with your actual install path.

Why these hooks?

  • afterShellExecution - Fires after terminal commands
  • afterMCPExecution - Fires after MCP tool calls
  • afterFileEdit - Fires after file modifications

These are the only hooks that work reliably with Cursor CLI.

3. Search & Resume

# Basic search (fast, keyword-based)
curlens -d "configuring nvim"

# Smart search (LLM-ranked, slower but smarter)
curlens -d "kubernetes deployment issue" --smart

Config

~/.cursor/curlens/config.json (created automatically):

{
  "summary_model": "grok",
  "search_model": "grok",
  "summary_max_words": 70,
  "search_window_days": 20,
  "hooks_enabled": true,
  "debug": false
}
Key Description
summary_model Model for generating summaries
search_model Model for --smart ranking
summary_max_words Max words per summary
search_window_days How far back to search
hooks_enabled Enable/disable hook processing
debug Log to ~/.cursor/curlens/hook.log

Cost Considerations

Curlens uses cursor agent -p to generate summaries, which consumes API tokens from your Cursor subscription.

Estimated usage per chat:

  • Summary generation: ~500-1000 tokens
  • Smart search (optional): ~200 tokens per search

To minimize costs:

  1. Use a cheaper/faster model in config:

    {"summary_model": "grok", "search_model": "grok"}
    
  2. Skip smart search - Default search uses keyword matching (free):

    curlens -d "query"        # Free (keyword match)
    curlens -d "query" --smart  # Uses LLM tokens
    
  3. Use self-hosted models - If you have Ollama or similar:

    {"summary_model": "ollama/llama3", "search_model": "ollama/llama3"}
    

    (Requires Cursor to be configured with your local model endpoint)

  4. Backfill in batches to control spend:

    curlens --backfill --limit 20  # Process 20 at a time
    

Note: Hooks fire frequently during active chats. Each hook only processes new messages incrementally, so repeated summaries for the same chat are efficient updates, not full regenerations.

CLI-Only

This tool is designed for Cursor CLI (cursor agent). IDE-originated chats are automatically skipped.

Tested on: Cursor CLI version 2026.01.23-6b6776e

cursor agent --version  # Check your version

Troubleshooting

No chats found?

  • Run curlens --backfill --dry-run to check discovery
  • Ensure hooks are configured correctly

Debug mode:

{"debug": true}

Check ~/.cursor/curlens/hook.log for hook events.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

curlens-0.1.1.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

curlens-0.1.1-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file curlens-0.1.1.tar.gz.

File metadata

  • Download URL: curlens-0.1.1.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for curlens-0.1.1.tar.gz
Algorithm Hash digest
SHA256 725a31ca54bcd53729b827b4680f364a0645e8dd49e9783872208a6366f1511d
MD5 d6c14005d5a08f3dcb37b05210ec4e35
BLAKE2b-256 544d0b5e316a22c67bb4b088d4d996c430ad8cf9936797f61e67a8380d33d0f2

See more details on using hashes here.

File details

Details for the file curlens-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: curlens-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for curlens-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5be3eb2a52de84e1fcf6819a0a40753876e8690b4dbf479060e433ba3086500
MD5 0bea938b2e6402814ae171da555d0f95
BLAKE2b-256 5fa3a242411083a38013f98bd5aaef834a92522198b1f0daed69a1eefa3d2227

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page