Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>C/C++ BlitzNew to Visual Studio Code? Get it now.
C/C++ Blitz

C/C++ Blitz

tsj

|
61 installs
| (0) | Free
C/C++ code navigation powered by tree-sitter. Built for embedded code where IntelliSense struggles.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

C/C++ Blitz

Marketplace Open VSX Downloads License: MIT

Source Insight–inspired C/C++ code navigation for VS Code, built for embedded codebases where the Microsoft C/C++ extension's IntelliSense struggles — heavy macros, non-standard ARM-family compilers, code that doesn't compile in a standard toolchain.

  • Navigation that works on code no compiler will accept. tree-sitter gets as close to a compiler's understanding as possible without a compiler or preprocessor, and a name-based (grep) index takes over only where the parse is defeated.
  • Nothing to build, anywhere. No native modules — one platform-independent .vsix that also works on Remote-SSH as-is.
  • Scales to huge trees. A multi-hundred-thousand-file checkout indexes in the background across worker threads into on-disk SQLite; tens of millions of references never touch the UI thread.
  • A real context window. The Code Insight view follows your cursor with the symbol's kind, type, signature, callers, callees, and references — optionally mirrored into one dedicated read-only preview pane.

Tip: For the best experience, disable the Microsoft C/C++ extension's IntelliSense ("C_Cpp.intelliSenseEngine": "disabled"). VS Code merges results from every definition provider, so leaving it on mixes its answers with ours and slows navigation.

Open a C/C++ folder and indexing starts on its own — there is no project file, no compile database, and nothing to configure. cBlitz.exclude and .gitignore are all you use to keep build output out.

Features

Feature Reach it with What you get
Go to Definition F12, Ctrl+Click, Peek Role-aware jump — a type tag and a same-named variable never resolve to each other
Search Symbols F10 Fuzzy search over every symbol in the index, ranked off the UI thread
Code Insight Activity bar Symbol / Definition / Declaration / Called by / Calls / References for the symbol under the cursor, following it live
Preview pane codeInsight.previewPane Every result click mirrored into one dedicated read-only pane — Source Insight's context window
External macros Automatic -D-injected and built-in macros become real, searchable symbols instead of "not found"
Background indexing Automatic Live progress and a real percentage in the status bar; cancelable, incremental, git-aware

Go to Definition — F12

Jump to a symbol's definition through our index. The built-in F12 / Ctrl+Click / Peek / right-click → Go to Definition all resolve through it, because the extension registers a normal VS Code definition provider. Multiple definitions give you a picker or a native peek.

Resolution is structural first: the token's syntactic role decides which kinds of symbol may match, so in struct buffer *buffer the type tag and the variable never resolve to each other — at any scope. Parameters and locals resolve within their own function, and obj->field is narrowed by walking the declared-type chain.

A dedicated C/C++ Blitz: Go to Definition command in the Command Palette returns only our results, if you ever want to bypass provider merging.

Search Symbols — F10

Fuzzy search over every symbol in the index: functions, prototypes, variables, macros, typedefs, struct/union/enum, enum constants, goto labels, and C++ classes, namespaces, and member functions.

Search runs on a dedicated worker off the UI thread, so typing never stutters on a multi-million-symbol index. Needs at least 2 characters; results are capped by cBlitz.fuzzy.maxResults.

F10 is also VS Code's debug Step Over. Our binding excludes debug sessions, and you can rebind it freely in Keyboard Shortcuts (cBlitz.fuzzySymbolSearch).

Code Insight — the context window

An activity-bar panel that follows the cursor and shows everything known about the symbol under it, in seven categories: Symbol / Definition / Declaration / Called by / Calls / References (plus Type, nested inside Symbol).

  • Symbol is a rich summary — humanized kind, declared Type (which jumps to the underlying struct and expands when the type is ambiguous), function Signature, and Storage class. When a set of candidates stays genuinely ambiguous, every distinct value is listed rather than one being picked at random; the tooltip carries the full, untruncated list.
  • Definition / Declaration rows read <kind> <declared type> in <directory> and hover the absolute path — what tells fourteen same-named typedefs apart is where each lives and what each one aliases.
  • Called by / Calls are recursive call trees. Expand any caller or callee to see its own, following the chain as deep as you like; a node that loops back to an ancestor is marked and stops.
  • References are grouped per file with a code-line snippet, like Find All References, read lazily when you expand a group.
  • Look Up Symbol points the view at any symbol without moving the editor, so you can ask "what calls this?" about code you are not in. It uses the same search as F10, and the symbol it finds is pinned automatically.
  • Pin freezes the view on the current symbol so it stops following the cursor; Refresh re-derives it from the live cursor even while pinned. A pinned view says so the moment it ignores a cursor move, so it never looks stale by accident.
  • Opening a result keeps the focus on the list, so the next one is a single arrow key away; Alt+Enter opens a result and takes you there. Either way your cursor in the editor you came from is left where it was. cBlitz.codeInsight.focusAfterOpen switches this to the classic behavior (focus returns to that editor) or to always landing in the opened code.
  • Show as Text turns the whole result into one read-only document — every category in full, reference snippets included — so you can search it with Ctrl+F, fold it by heading and copy it. It is Source Insight's Search Results window in text form: a heading per category with its match count, and each line carrying the file, line number, source text and enclosing function. Ctrl+Click any path:line:column to jump there (paths are workspace-relative; the hover shows the full one). Called by / Calls name each function and quote the call site's own line beneath it. Empty categories are left out, following the same hideEmptyCategories setting. One tab per symbol: dumping the same symbol again refreshes it, a different symbol opens its own so two results can sit side by side.
  • Empty categories are hidden by default (cBlitz.codeInsight.hideEmptyCategories), and each category can be toggled live via cBlitz.codeInsight.show.*.
  • While a lookup is slow (over 0.2 s), the view title ticks the elapsed seconds (Code Insight — 2.3) and then holds the final duration. Fast lookups say nothing.
  • Diff and file-history views are left alone. They show a different version of a file under that file's own path, so the index does not describe what you are looking at; rather than answer from the wrong coordinates, the view keeps whatever symbol it was showing.

Preview pane

Set cBlitz.codeInsight.previewPane to bottom or right and every result click opens in one dedicated read-only pane — Source Insight's context window. Tabs replace each other instead of piling up, focus stays where you were, and the pane never steals your working editors.

The pane is identified by the tabs it holds, so you can drag it anywhere — including into a separate window — and previews follow it. Its tab reads Preview while the breadcrumb bar shows the real file's path, and the Open the Real File button (editor title bar) opens the editable file at the same position in your working area.

When the preview pane is off, cBlitz.codeInsight.splitDirection decides how the editor is split if a click has to create a group: vertical (default, side by side), horizontal (stacked below), or followLayout (continue the grid's current orientation). Opening into an existing group never re-splits.

External macros

Identifiers tested in #if / #ifdef but #defined nowhere in the indexed tree — compile-time-injected macros from -D flags, compiler built-ins, or out-of-tree generated config — are synthesized as first-class external macro symbols anchored at their first use.

They become searchable in F10 and resolve in the Code Insight Symbol summary (showing their Origin and jumping to the first use) instead of reading "not found". Annotate their Origin with the values your build actually injects via cBlitz.externalMacros.predefined (-D style) or cBlitz.externalMacros.file (a JSON map, re-read live with no re-index).

Indexing you can watch and control

A persistent status-bar item shows the index state at a glance and opens a command menu on click:

State Status bar
Idle C/C++ Blitz: 3,262,118 symbols — click for Search / Rebuild / Show log
Indexing C/C++ Blitz: 42% · parsing 12,043/32,114 files · 1m 12s — click to Stop indexing
Not yet indexed C/C++ Blitz: no index

Every step of a run reports in the same shape — <percent>% · <what is happening> <counts> · <elapsed> — on both the notification and the status bar, and the percentage is derived from the actual size of the work and re-calibrated on every run, so after one run the estimate fits your machine and your codebase. It never runs backwards.

Stop indexing keeps the partial index and pauses automatic indexing until you say so — an unpacking archive or a long checkout can't restart a scan behind your back. A Resume indexing entry then appears in the menu; it finishes the job incrementally and re-enables automatic indexing.

Rebuild index clears the index and parses every file again, so it starts from the same state as a fresh install. It asks first: until it finishes, symbol search and Go to Definition find nothing. You rarely need it — new, changed and deleted files are picked up automatically as you work, on checkout, and at startup.

When one file behaves oddly — Show Index Info

Navigation is only as good as the parse behind it, and when a file defeats tree-sitter the symptoms are indirect: a local variable reads not found, or resolves to a same-named field from a file you have never opened. C/C++ Blitz: Show Index Info for This File (Command Palette) explains why, for the file you are in:

  • which parser produced its rows — tree-sitter or the grep fallback — and, if it fell back, the rule that fired with its measured value (errorRatio 0.412 > 0.25);
  • what the index holds at your cursor, so a stale position is never mistaken for a missing symbol;
  • how the workspace as a whole parsed, which separates one awkward file from a shared cause;
  • and a plain-language verdict for all of it.

It re-parses the file as it runs (nothing is written) and compares that against the stored rows, so an index written before an update says so. The report goes to the output channel with a Copy report button — paste it into an issue and the whole picture travels with it.

Commands

All commands are prefixed C/C++ Blitz in the Command Palette.

Command How you normally reach it
Go to Definition F12 / Ctrl+Click / Peek (via the provider); the command itself is Palette-only and never merges with other providers
Search Symbols F10
Find All References Native Shift+F12 / right-click → Find All References resolve through our index; this command opens the References view directly
Look Up Symbol in Code Insight Code Insight title bar 🔍 — points the view at a symbol without moving the editor
Refresh Code Insight Code Insight title bar ↻
Pin / Unpin Code Insight Code Insight title bar toggle
Show Code Insight as Text Code Insight title bar
Open Code Insight Result and Focus It Alt+Enter on a Code Insight row (view-only, not in the Palette)
Open the Real File Editor title bar, shown only on a preview-pane tab
Show Index Info for This File Palette-only — why the open file indexed the way it did, ready to paste into an issue
Rebuild Index from Scratch Status-bar menu → Rebuild index
Stop Indexing Status-bar menu → Stop indexing (only while a run is active)

Settings

Indexing scope

Setting Notes Default
cBlitz.fileExtensions File extensions to index .c .h .cpp .cc .cxx .hpp .hh .hxx .hl
cBlitz.exclude Glob patterns to exclude, applied gitignore-style **/.git/**, **/out/**, **/_out/**
cBlitz.include Exceptions that re-admit paths an exclude removed — not a whitelist (everything is indexed by default) []
cBlitz.respectGitignore Also exclude what the workspace's .gitignore files ignore (root + nested, git's rules). exclude/include are applied after and win true

Indexing behavior

Setting Notes Default
cBlitz.indexing.workerCount Parallel worker threads for bulk indexing 8
cBlitz.indexing.deferQueriesMs How long F12/F10/Code Insight wait for an in-flight reindex before querying (0 = off) 1500
cBlitz.indexing.verifyContentHash When a file's mtime changes, re-hash and skip re-parsing if byte-identical (e.g. after git checkout), at the cost of reading each changed file false
cBlitz.db.location Database directory; an absolute path is allowed (e.g. a fast or large disk). On Remote-SSH this resolves on the remote host workspace storage

Parsing

Setting Notes Default
cBlitz.parse.maxFileSizeKB Larger files fall back to grep 2048
cBlitz.parse.errorRatioThreshold ERROR-byte ratio threshold for grep fallback 0.25
cBlitz.parse.timeoutMs Per-file parse timeout before grep fallback 5000

Code Insight & search

Setting Notes Default
cBlitz.codeInsight.previewPane off / bottom / right — route every result click into one dedicated read-only pane. Overrides Split Direction off
cBlitz.codeInsight.splitDirection vertical / horizontal / followLayout — how a click creates an editor group. Ignored while Preview Pane is on vertical
cBlitz.codeInsight.focusAfterOpen Where focus goes after opening a result: view (stay on the list), editor (back to the editor you came from), target (into the opened code). Alt+Enter always goes to the code view
cBlitz.codeInsight.debounceMs Cursor-follow delay 200
cBlitz.codeInsight.hideEmptyCategories Hide categories with no entries for the current symbol true
cBlitz.codeInsight.show.* Per-category visibility (symbol/type/definition/declaration/calledBy/calls/references) true
cBlitz.fuzzy.maxResults F10 result cap 200

External macros

Setting Notes Default
cBlitz.externalMacros.enabled Synthesize external macro symbols for #if/#ifdef names not #defined in-tree. Toggling forces a rescan true
cBlitz.externalMacros.predefined Names your build injects ("NAME" or "NAME=value", -D style) — annotates Origin only; does not create symbols []
cBlitz.externalMacros.file Path (or list of paths) to a JSON file mapping injected macro names to values — annotates Origin; re-read live (no re-index needed) ""

How it works

  • A pool of background worker threads (default 8, cBlitz.indexing.workerCount) parses files with tree-sitter in parallel and writes to an on-disk SQLite database via Node's built-in node:sqlite (WAL mode — no native module to build or rebuild). The extension host only reads. References for a ~300 MB codebase can reach tens of millions of rows — far too much for memory — so everything lives in SQLite and is fetched with indexed point queries. There is no parallel in-memory copy: even F10 queries SQLite directly, on its own worker, ranking a bounded candidate set per keystroke.
  • The index is the cache. On restart only changed or new files are re-parsed (mtime diff) and deleted files are dropped.
  • Reconciling after a git checkout costs what the change costs, not what the repo costs. Scanning a large workspace to discover what moved is O(total files) — many seconds on a 100k-file tree, at every launch and every branch switch. Since the trigger is almost always a git operation, and git already computed the exact delta, automatic reconciliation asks git (diff --name-status ∪ status --porcelain) and stats only those paths. Non-git folders, git errors, or an unknown prior revision fall back to the full scan, which remains the correctness backstop and always owns Resume / Rebuild / filter changes.
  • Headers pick their grammar by content, not just extension. A .h defaults to C but is parsed as C++ when the text contains a decisive C++ marker (namespace X {, template <, enum class, an access specifier, …) — so Chromium-style trees that spell C++ headers .h index correctly. A markerless plain C header keeps the C grammar.
  • Fallback: if tree-sitter fails or produces low-confidence results (parse error, unsupported file, timeout, very large file, or too many ERROR nodes), the file is indexed with a regex (grep) scanner instead — symbols are still found, refs and calls on a best-effort basis. Two common shapes that used to force this fallback are handled before parsing: a whole-file include guard is neutralized (one misparse deep in a guarded header could otherwise collapse the entire file to grep), as are C++ export macros in a class head (class BASE_EXPORT Foo : public Bar {).
  • Macros in declaration position are resolved from facts, not guesses. A macro where a declaration is expected is genuinely ambiguous without a preprocessor, so the workspace is swept once up front to learn which names are function-like macros and which are typedefs; those facts then recover the swallowed declaration, and only when doing so demonstrably recovers a declaration without losing any. That sweep is the "reading macro definitions" phase, roughly 10% of parse time, and it survives restarts by being reconstructed from the index itself.
  • External macros are synthesized (cBlitz.externalMacros.enabled, default on): a table-wide pass inserts one definition-less symbol per #if/#ifdef name with no definition of any kind in the tree, anchored at its first use. It is maintained incrementally — an external macro appears or disappears live as edits add or remove its uses — and covers grep-parsed heavy-macro files too.
  • Comments are never indexed. #if 0 … #endif blocks are indexed (a known, intentional limitation — there is no preprocessor).
  • Bulk indexing is cancelable and never overlaps itself. Bulk runs are serialized (latest wins). Files added, changed, or removed reindex in the background behind a single coalesced notification, and navigation queries briefly wait for an in-flight reindex to settle (bounded by cBlitz.indexing.deferQueriesMs) so they reflect your latest edits.

Requirements

  • VS Code 1.106+. The hard technical floor is 1.99 (Electron 35+ / Node 22.13+ for node:sqlite); the marketplace minimum is pinned higher on purpose, so a future update that adopts a newer VS Code API won't break old installs.
  • No native modules — the .vsix is platform-independent and works on Remote-SSH with nothing to rebuild.

Limitations

  • No compiler, preprocessor, macro expansion, or real type system — symbol resolution is best-effort by design. Parameters and locals resolve within their function, and member access (a->x) is type-narrowed by walking the declared-type chain, but when a type cannot be resolved it falls back to every struct field named x. When a set stays ambiguous, Code Insight lists every candidate rather than picking one.
  • C++ is supported structurally but not semantically. Qualified names (Widget::kWidth), member functions, and implicit-this member lookup resolve; overload resolution is name + arity only, and base-class member lookup (inheritance) is not modeled — an inherited member use stays best-effort.
  • A macro in a declaration position is handled well, not perfectly. A decorator-stacked function (several macro prefixes) or a multi-line macro invocation may still not be recovered, and after a restart with no reindexing a live single-file edit sees only that file's own macros until the next full scan. In both cases the declaration is simply absent, never wrong, and the next automatic scan resolves it.
  • A very large source file is indexed by name only. Past a size limit the structural parse is skipped, so the file is still searchable and its definitions are still found — but without scope, locals, or the finer resolution those give; past a much larger limit it also stops contributing its macros to the rest of the workspace. Generated blobs and amalgamated sources are the usual cases. Every indexing run lists such files in the log with their sizes, so nothing about it has to be guessed at.
  • Unsaved-buffer edits re-index on a short debounce; saving always triggers re-indexing.

Install

C/C++ Blitz is published to both extension registries — both get the same platform-independent .vsix:

  • VS Code Marketplace — https://marketplace.visualstudio.com/items?itemName=tsj.sintra
  • Open VSX (VSCodium, Cursor, Gitpod, Eclipse Theia, …) — https://open-vsx.org/extension/tsj/sintra

Support

If C/C++ Blitz put a smile on your face, consider buying me a coffee — Buy Me a Coffee (global) or Fairy (KRW, for Korean supporters).

Thanks

C/C++ Blitz is shaped by the people who actually navigate embedded code all day and told us what was in the way. Thanks for the feedback to:

  • Dong Hoon Lee
  • Austin Lee
  • Eric Jung
  • Donghyun Min
  • Morris Ju

License

MIT © tsj — see the LICENSE file in the extension package.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft