The IDE for AI coding agents
Semantic navigation, resolved types, exact symbol extraction, and usage mapping for coding agents — instead of raw file dumps.
Actual LSP-resolved types from live language servers — not embeddings, not text search, not a static graph. Works on your dependencies too: real APIs from the exact versions in your lockfile, not from model memory or stale docs.
GitHub sign-in · about 30 seconds · no card
recorded session · lsp_manager/operations_queries.rs
Recorded on the engine's own codebase — reproduce the equivalent on yours with a free key. Watch the session below.
Works with Claude Code · Codex · Cursor · any MCP client — two-minute setup.
Agents are still coding from printed source
“35% of my agent sessions had error loops — the agent retrying the same failing approach 3+ times.”
“If i tell it to refactor a API, it never checks if that API is used anywhere else because it only reads in that API code.”
“my MCP tools were consuming 66,000+ tokens of context before I even started a conversation…”
Scott Spence · blog · 2025-09-30
Our 13 tools: 10,011 tokens, measured — audit the raw schema in launch-artifacts.
“Gemini hallucinated a method on a rust crate… That method doesn't exist and has never existed… Eventually it gave up and commented out all the code it was trying to make work.”
A real debugging session, recorded
An error report points at server.rs:114 and the LSP request path is the suspect. Six tool calls trace the call chain through the engine's own 210K-line workspace — from the MCP handler down to the language-server query — outputs shown in full, raw JSON-RPC log published. Run the same trace on your own codebase with a free key.
grep output sifted + every surfaced file read in full exactly once — no re-reads, no wrong-file reads (conservative)
line_context(file: "context-engine-server/src/server.rs", line: 114)Start from the error line. One call returns the complete containing handler - boundaries found automatically - with every type resolved inline by the live language server.
types resolved by the live language server, embedded in place
complete output — raw JSON-RPC in launch-artifacts (replay-debug/raw/step-01.json)
═══ TYPE-ANNOTATED TEXT FROM FILE: /Users/aw/Dev/Rust/context-engine/context-engine-server/src/server.rs ═══
101→#[doc = include_str!("../descriptions/outline.md")]
102→ #[tool]
103→ async fn outline(
104→ &self,
105→ Parameters(request/*: ScanStructureParams*/): Parameters<ScanStructureParams>,
106→ ctx: RequestContext<RoleServer>,
107→ ) -> Result<String, ErrorData> {
108→ let notifier/*: Option<McpProgressNotifier>*/ = self/*: &ContextEngineServer*/
109→ .create_progress_notifier(&ctx, "outline")
110→ .map(|n/*: McpProgressNotifier*/| n as McpProgressNotifier);
111→
112→ let display_without_header/*: bool*/ = request.skip_context;
113→
114→ let result/*: ScanStructureResult*/ = self/*: &ContextEngineServer*/
115→ .api/*: Arc<ContextEngineApi>*/
116→ .scan_structure(
117→ request,
118→ notifier/*: Option<McpProgressNotifier>*/
119→ .as_ref()
120→ .map(|n/*: &McpProgressNotifier*/| n as &dyn context_engine_core::notification_api::ProgressMcpNotifier),
121→ )
122→ .await/*: Result<ScanStructureResult, ContextEngineError>*/
123→ .map_err(|e/*: ContextEngineError*/| self.to_mcp_error(e))?;
124→
125→ if display_without_header {
126→ Ok(result.display_without_header())
127→ } else {
128→ Ok(result.to_string())
129→ }
130→ }The same file, two ways to spend tokens
2,065 vs 5,393 tokens (this file; distribution below)
outline output — recorded session
📊 ~600 tokens (15 symbols across 1 file) vs ~14540 tokens (full file reads) → ~96% savings
/Users/aw/Dev/Rust/context-engine/context-engine-core/src/lsp_manager/manager/operations_queries.rs
│ ▸ Full file content: extract(hashes="0293dd0d09e02dc9418c339") → 727 LOC | ~14540 tokens
│ ▸ Docs only: extract(hashes="0293dd0d09e02e42d5271cd") → 45 LOC | ~900 tokens
│ ▸ File-level context (imports, directives, etc.): extract(hashes="0293dd0d09e02deb347688b") → 18 LOC | ~360 tokens
└─ ⦿ impl LspManager { ... } ─ extract("0293dd0d09e02f783c2298a") 665 loc
├─ ƒ pub async fn text_document_hover( self: &Arc<Self>, uri: &Uri, position: Position, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<crate::types::Hover>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02d34fa09fa9") → 22 LOC | ~440 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e028ab93f0fcf") → 18 LOC | ~360 tokens
├─ ƒ pub async fn text_document_completions( self: &Arc<Self>, uri: &Uri, position: Position, trigger_character: Option<String>, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<crate::types::CompletionResponse>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02d09092a609") → 37 LOC | ~740 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e024dae218d5f") → 33 LOC | ~660 tokens
├─ ƒ pub async fn text_document_definition( self: &Arc<Self>, uri: &Uri, position: Position, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Vec<crate::types::Location>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02ffc1d9e141") → 62 LOC | ~1240 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02a3b20b7108") → 53 LOC | ~1060 tokens
├─ ƒ pub async fn text_document_type_definition( self: &Arc<Self>, uri: &Uri, position: Position, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Vec<crate::types::Location>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e023efa0ecc75") → 66 LOC | ~1320 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02a371007711") → 53 LOC | ~1060 tokens
├─ ƒ pub async fn text_document_references( self: &Arc<Self>, uri: &Uri, position: Position, include_declaration: bool, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<Vec<crate::types::Location>>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02dd8a45e21d") → 34 LOC | ~680 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02f29ef9c4d7") → 30 LOC | ~600 tokens
├─ ƒ pub async fn text_document_document_symbol( self: &Arc<Self>, uri: &Uri, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<crate::types::DocumentSymbolResponse>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e027acba526aa") → 26 LOC | ~520 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02fc22ba5378") → 22 LOC | ~440 tokens
├─ ƒ pub async fn text_document_formatting( self: &Arc<Self>, uri: &Uri, options: crate::types::FormattingOptions, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<Vec<crate::types::TextEdit>>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02c0ebccd0fe") → 27 LOC | ~540 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e028fe5cf66ae") → 23 LOC | ~460 tokens
├─ ƒ pub async fn text_document_range_formatting( self: &Arc<Self>, uri: &Uri, range: crate::types::Range, options: crate::types::FormattingOptions, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<Vec<crate::types::TextEdit>>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e028636fd21be") → 29 LOC | ~580 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02f6d5ded216") → 25 LOC | ~500 tokens
├─ ƒ pub async fn text_document_code_actions( self: &Arc<Self>, uri: &Uri, range: crate::types::Range, context: crate::types::CodeActionContext, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<crate::types::CodeActionResponse>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02373b6882b4") → 30 LOC | ~600 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02a9743396ec") → 26 LOC | ~520 tokens
├─ ƒ pub async fn text_document_rename( self: &Arc<Self>, uri: &Uri, position: Position, new_name: String, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<crate::types::WorkspaceEdit>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e021ddf398b9b") → 24 LOC | ~480 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02f56547a000") → 20 LOC | ~400 tokens
├─ ƒ pub async fn text_document_type_hierarchy( self: &Arc<Self>, uri: &Uri, position: Position, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result< Vec<( crate::types::TypeHierarchyItem, Vec<crate::types::TypeHierarchyItem>, Vec<crate::types::TypeHierarchyItem>, )>, > { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e02101f4071a4") → 120 LOC | ~2400 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e024f5922b0cd") → 82 LOC | ~1640 tokens
├─ ƒ pub async fn text_document_implementation( self: &Arc<Self>, uri: &Uri, position: Position, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Vec<crate::types::Location>> { ... }
│ ▸ Full (docs + code): extract(hashes="0293dd0d09e0255aca2cab8") → 100 LOC | ~2000 tokens
│ ▸ Code only: extract(hashes="0293dd0d09e02ca4a703ad9") → 53 LOC | ~1060 tokens
└─ ƒ pub async fn text_document_inlay_hint( self: &Arc<Self>, uri: &Uri, range: crate::types::Range, retry_config: Option<crate::lsp_manager::LspRetryConfig>, ) -> Result<Option<Vec<crate::types::InlayHint>>> { ... }
▸ Full (docs + code): extract(hashes="0293dd0d09e029922d59b85") → 74 LOC | ~1480 tokens
▸ Code only: extract(hashes="0293dd0d09e02d74fbdc899") → 49 LOC | ~980 tokens
raw context-engine-core/src/lsp_manager/manager/operations_queries.rs — excerpt, lines 1–40 of 727
//! Document query LSP operations. //! //! This module provides high-level LSP operations for querying document //! information at specific positions or ranges. These are the core operations //! that power IDE features like "go to definition", "find references", //! "show hover information", etc. //! //! # Navigation Operations //! //! - **text_document_definition** - Jump to where a symbol is defined //! - **text_document_type_definition** - Jump to where a symbol's type is //! defined //! - **text_document_implementation** - Find trait implementations or vice //! versa //! - **text_document_references** - Find all usages of a symbol //! //! # Hierarchy Operations //! //! - **text_document_type_hierarchy** - Get complete type hierarchy (supertypes //! and subtypes for each item) //! //! # Information Operations //! //! - **text_document_hover** - Get documentation and type info at a position //! - **text_document_document_symbol** - Get all symbols in a document //! - **text_document_inlay_hint** - Get inlay hints (inferred types, parameter //! names) //! //! # Code Intelligence Operations //! //! - **text_document_completions** - Get completion suggestions //! - **text_document_code_actions** - Get available code actions (refactorings, //! fixes) //! //! # Editing Operations //! //! - **text_document_formatting** - Format entire document //! - **text_document_range_formatting** - Format specific range //! - **text_document_rename** - Rename symbol across workspace //!
The “~N tokens” header inside the recorded output is the tool's own byte-based estimate; the badge above is tokenizer-measured.
Not a best case — the whole distribution
Outline size as a fraction of the raw file, measured across all 895Rust files of the engine's own repository. Left of 1.0 means the outline is smaller.
Honest tail: 206 of 895 files have outlines that are not smaller than the file — overwhelmingly tiny ones (median 400raw tokens; this repository keeps one type per file). When the structural view wouldn't be smaller, the tool returns the file content instead. Distribution and raw per-file data published in launch-artifacts.
What leaves your machine
This is the entire license-verification request. Source analysis stays on your machine.
POST /v1/license/verify
{
"api_key": "ce_xxx",
"machine_id": "persisted-random-device-uuid",
"cli_version": "0.1.0",
"os": "darwin",
"os_version": "14.5",
"telemetry": {
"tool_calls": {},
"tokens_saved_estimate": 0,
"languages_used": []
}
}- Analysis is 100% local. Your files are read by your machine's language servers and never uploaded.
- License verification is one short request. At most daily, against a 3-day signed offline lease.
- The payload is what you see on the left. Key, device UUID, version, OS, and aggregate telemetry counts — never code, paths, repository names, or symbols. Server-side we store that verification event and those counters, keyed to your license — nothing else arrives to store.
- OAuth scopes are identity-only. Sign-in never requests access to your repositories.
- Telemetry changes are announced first. Any change to these fields lands in the changelog before it ships.
Verify it yourself
Cut the network after one successful verification — analysis keeps working for the lease window, offline. Or watch the wire: run lsof -i (or Little Snitch) during a session and inspect each destination and payload. Details in the FAQ.
Why it matters
The goal is not just fewer tokens. The goal is fewer wrong assumptions.
Source-of-truth APIs
Outlines, jumps, and extracts read from live language servers and the dependency sources actually resolved in your lockfile. The agent verifies against the source before writing — fewer wrong assumptions about what an API looks like.
First-time-right code
Code written against verified signatures compiles against reality, not against a guess. Whether that reduces retry loops across real tasks is a hypothesis we are measuring: a multi-task benchmark with published per-task results is planned, and the first recorded artifacts are already public.
Lower cost
Surgical context replaces full-file dumps, and wasted iterations are where token bills actually explode. 23% of tech leaders already report paying $200–500 per developer per month for AI coding tokens.¹
¹ Gartner press release, June 24, 2026: 23% of surveyed tech leaders spend $200–500 per developer per month on AI coding tokens; 6% spend over $2,000.
Built with itself
Context Engine is developed with Context Engine wired into the assistant that writes it — 210K lines of Rust. In our own sessions, compile-error chasing became rare: the assistant checks a signature before using it instead of guessing and rebuilding.
That is testimony from a closed repository, not a benchmark — treat it accordingly. The measurable claims on this page live in the launch-artifacts repository, limitations stated in its methodology.
What the Community Preview covers
Languages
Rust, TypeScript, and Markdown are validated end-to-end. The rest of the 323 bundled Tree-sitter grammars ship as experimental — bundled and working, less battle-tested.
Platforms
Tagged releases publish separate archives for macOS x64, macOS arm64, Linux x64, and Windows x64.
Pricing
Free during Community Preview. If paid tiers arrive, preview users get 30 days' notice.
- 5,300+ tests
- ~1,300 doctests
- 323 bundled Tree-sitter grammars(macOS- and Windows-verified)
- 142 default LSP configurations
- ~450 files/sec (outline) outline throughput2
² criterion, 500-file scans, 23,716 symbols; LSP server initialized once (as in real sessions); result cache disabled. Raw artifacts in the launch-artifacts repository. Audit it.
Give your agent the source of truth
GitHub sign-in · about 30 seconds · no card
Verify every claim yourself — the artifacts repo has the raw JSON.