lens for cursor
Cortex Lens is a paid commercial product. This extension is the client component and requires an active Cortex Lens tenant to operate. See LICENSE for terms.
vs-code-style extension for cursor that ships token, cost, and tool-call telemetry into the multi-tenant cortex-lens dashboard. it lives next to connectors/claude-code-hook and connectors/lens-cli and uses the same env contract so a workspace can adopt all three with one token.
status: 0.1.0, scaffold only. the mcp transport binding and full editor-activity capture land in pc-1b.
what it looks like
once activated, the extension surfaces a status bar widget at the bottom-right of the cursor window showing live session savings (lens: $0.00 saved). click the widget to open the configured dashboard at <lens.baseUrl> in the browser, where the SavingsCounter, Brain Advisor whisper card, and Improvements drill-down chart aggregate every tool call captured by this extension and its sibling connectors.
screenshots: three banner-style placeholder mockups live in images/: status-bar.png (1200x300, the bottom-of-IDE widget), dashboard-preview.png (1200x600, the Lens dashboard top nav with the savings counter), and command-palette.png (1200x400, the three lens: commands the extension registers). these are composed placeholders, not real captures from a running install; they ship with the Marketplace listing and are replaced with real screenshots once the first design-partner is on the dashboard.
install
pnpm --filter @cortex/lens-cursor-extension build
pnpm --filter @cortex/lens-cursor-extension package
cursor --install-extension questo.lens-cursor-extension-0.1.0.vsix
configuration
set both values in Cursor > Settings > Extensions > Lens for Cursor or in your workspace .vscode/settings.json:
| setting |
required |
purpose |
lens.baseUrl |
yes |
lens dashboard origin. the extension posts events to <lens.baseUrl>/api/ingest/ide. falls back to LENS_BASE_URL. |
lens.tenantToken |
yes |
per-tenant bearer token of shape <tenant_uuid>:<secret>. sent only on the authorization header. falls back to LENS_TENANT_TOKEN. |
lens.enabled |
no |
toggle capture on or off without uninstalling. default true. |
what it captures
- mcp tool calls forwarded from cursor's internal mcp layer (pre and post phases). args are redacted client-side via
lib/redact for obvious credentials; the receiver applies the full removal catalog server-side.
- status bar widget bottom-right showing current session savings. click opens the configured dashboard.
- claude-code-in-terminal detector: polls integrated terminals every 30 seconds. when claude code is running in the same workspace, the de-dup adapter in
packages/adapters uses this signal to drop duplicate events.
commands
| id |
description |
lens.openDashboard |
open <lens.baseUrl> in the default browser |
lens.toggleEnabled |
pause or resume capture for the current workspace |
lens.viewSavings |
quick-pick recent session savings |
privacy
- the tenant token never lands in logs, stdout, stderr, or the post body. only the authorization header carries it.
- arg values matching common credential patterns are replaced with
[redacted] before they leave the workstation. server-side, the removal catalog applies again over the message text and tool args.
- the extension only reads files cursor already has open or terminals already running. it does not read arbitrary disk.
carry-forwards (pc-1b future scope)
the following are documented as out of scope for this scaffold and land in the pc-1b follow-on:
- editor activity capture: cursor moves, file opens, selection changes. requires
vscode.workspace.onDidOpenTextDocument + vscode.window.onDidChangeTextEditorSelection wiring with a sampling cap.
- completion telemetry: cursor tab token usage. requires hooking cursor's internal completion api (still in flux as of 2026-05).
- inline chat capture: cursor's inline chat panel events. depends on cursor exposing a public event api.
- real mcp transport binding: this scaffold uses a no-op mcp source. pc-1b wires the actual cursor mcp event stream into
MCPProxy.
layout
connectors/cursor-extension/
package.json
tsconfig.json
vitest.config.ts
README.md
src/
extension.ts activate/deactivate, status bar wire, command registration
index.ts public re-exports for tests
status-bar.ts LensStatusBar widget
mcp-proxy.ts MCPProxy + MCPEventSource interface
claude-code-detector.ts ClaudeCodeDetector poll
lib/
redact.ts client-side credential redactor stub
ingest-client.ts batched HTTP transport
tests/
vscode-mock.ts vscode runtime mock for vitest
extension.test.ts 4 cases
mcp-proxy.test.ts 3 cases
claude-code-detector.test.ts 4 cases
status-bar.test.ts 2 cases
ingest-client.test.ts 4 cases
connectors/claude-code-hook ships hook events for claude code itself (python).
connectors/lens-cli wraps coding-agent cli invocations from the outside (node).
packages/adapters/src/claude-code-to-agent-trace.ts is the receiver-side adapter for the hook source. the cursor adapter lands in pc-2.
apps/enterprise/app/api/ingest/ide/route.ts is the receiver this extension posts to (the ide path).
verifying that lens is actually loaded inside cursor
cursor 3.5.x sometimes hides side-loaded vsix entries from the search filter inside the extensions panel even when the extension is fully activated and running. the activation log is the source of truth, not the panel search box. follow this procedure to verify in under one minute.
1. confirm activation in the log
open the most recent log session under %APPDATA%/Cursor/logs/<TIMESTAMP>/window1/exthost/exthost.log and search for questo.lens-cursor-extension. you should see two lines per cursor restart:
ExtensionService#_doActivateExtension questo.lens-cursor-extension, startup: false, activationEvent: 'onStartupFinished'
Extension activated success: questo.lens-cursor-extension - 10ms (code loading: 8ms, activate call: 2ms, activate resolved: 0ms)
if those two lines are present, the extension is loaded and running. visibility in the extensions panel is a separate ui concern and does not gate functionality.
after activation, the extension calls vscode.window.createStatusBarItem(...).show(). look at the bottom-right of the cursor status bar. you will see one of two texts:
lens: $0.00 saved when capture is enabled
lens: paused when capture is paused
if the widget is visible, lens is alive end-to-end. clicking the widget runs lens.openDashboard.
3. confirm command registration
open the command palette with ctrl+shift+p and type lens:. three commands should appear:
Lens: open dashboard
Lens: toggle capture
Lens: view recent session savings
if the palette finds them, the extension is registered correctly. command palette lookup is independent of the extensions panel filter and is the second most reliable signal after the activation log.
this is the known cursor 3.5.x ui state: side-loaded vsix entries can disappear from the installed-tab search filter when cursor's publisher registry sync fails. functionality is unaffected. options:
- ignore it: the extension is running. the panel entry is only needed to uninstall via the gui.
- restart cursor with
--reload-extensions: forces cursor to rebuild the panel state from ~/.cursor/extensions/extensions.json.
- uninstall via cli if needed:
cursor --uninstall-extension questo.lens-cursor-extension. the entry comes back on the next reinstall in some cases.
5. if the activation log does not show the two lines
then the extension truly failed to load. likely causes and fixes, in order of probability:
| cause |
how to detect |
fix |
| engines mismatch |
log line Cannot activate ... engines.vscode '^A.B.C' incompatible with cursor |
edit package.json in the install dir to lower engines.vscode (current shipped value: ^1.80.0). |
| out/extension.js syntax error |
log line with stack trace at activate call |
rebuild via pnpm --filter @cortex/lens-cursor-extension build and replace the out/ dir. |
| publisher rejected |
extension absent from ~/.cursor/extensions/extensions.json after install |
publisher in package.json is questo. if cursor rejects it, change to local or omit the publisher, then repackage with vsce package --no-dependencies and reinstall. |
| extension registry file corrupted |
extensions.json is missing the cortex.lens entry but the install dir exists |
delete the install dir, then cursor --install-extension <path-to-vsix>. |
6. quick repackage and reinstall procedure
if you need to rebuild and reinstall from source after editing the manifest:
cd C:/Intel/questo/projects/cortex-lens/connectors/cursor-extension
pnpm --filter @cortex/lens-cursor-extension build
pnpm --filter @cortex/lens-cursor-extension package
cursor --install-extension lens-cursor-extension-0.1.0.vsix
then fully quit cursor (taskkill any leftover Cursor.exe) and reopen. re-verify steps 1 through 3 above.