Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Source CuesNew to Visual Studio Code? Get it now.
Source Cues

Source Cues

Marco Manfredini

|
4 installs
| (0) | Free
Bring project-specific meaning into your editor — encode team conventions, unsafe patterns, and domain terminology as visual cues directly in source.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Source Cues

Bring project-specific meaning into your code editor. Encode team conventions, unsafe patterns, domain terminology, and temporary code states as visual cues — directly in source.

example


Why this exists

Language syntax tells you what the compiler sees. Linters tell you what the language server thinks. But neither encodes what your team knows:

  • Which functions are dangerous despite looking harmless?
  • Which constants are register addresses, not ordinary numbers?
  • Which log calls are debug leftovers that shouldn't reach production?
  • Who owns this TODO and when was it written?

Source Cues fills that gap. You define patterns → the editor surfaces meaning directly in code. It's the layer between syntax highlighting (language-defined) and diagnostics (LSP-defined) — a lightweight, regex-driven way to make tribal knowledge visible.


Real-world use cases

Domain What you'd mark Why
Embedded / firmware REG_[A-Z0-9_]+, 0x400[0-9A-F]+ Register names and memory-mapped addresses look like ordinary constants — cue them so they stand out
Backend / services strcpy, strcat, gets, sprintf Unsafe C functions that should be caught during code review
Security review password, secret, apiKey, token Hardcoded secrets or sensitive variable names that need scrutiny
Legacy codebases DEPRECATED, DO_NOT_USE, LEGACY_API Markers that convey tribal knowledge to new team members
Debug hygiene console\.log, DEBUG_PRINT, print\( Calls that should be removed before merging
TODO tracking TODO\((\w+)\), FIXME, HACK Owner-tagged or untagged temporary markers — with minimap indicators

How it works

Add a :cue: marker anywhere in your source file. When the regex matches, the decoration options are passed to the VS Code Decorator API.

Options can be an inline JSON object, or a #name reference to a style defined in your workspace's .source-cues.json:

// :cue: /\b(REG_[A-Z0-9_]+)\b/ -> { "color": "#d7afff", "outline": "1px solid #d7afff", "fontWeight": "bold" }
// :cue: /\b(strtok|strcat|strcpy)\b/ -> #unsafe
// :cue: /DEBUG_PRINT/ -> { "dark": { "color": "#50fa7b" }, "light": { "color": "#008800" } }

#define REG_CTRL_STAT  0x40021000
#define REG_DATA_BUF   0x40021004

void process_telemetry(const char* packet) {
    char local_copy[256];
    strcpy(local_copy, packet);
    DEBUG_PRINT("Processing new telemetry packet header.\n");
}

More demos are in the demos/ directory.

Quick start

  • "Source Cues: Insert demo rules" — inserts a commented-out block of example inline rules into the active file. Remove the space in : cue: to activate the ones you want.
  • "Source Cues: Open workspace rules" — opens (or creates) the workspace config file (.source-cues.json) for the current project, seeded from a template with working examples.

Both commands are available in the command palette (Ctrl+Shift+P / Cmd+Shift+P).


What you can do with it

  • Spot dangerous patterns instantly — mark unsafe functions, hardcoded secrets, or deprecated APIs with red backgrounds and gutter icons so they're impossible to miss during review.
  • Surface domain terminology — make register names, error codes, or business-logic constants visually distinct from ordinary variables.
  • Track TODO ownership — use capture groups to highlight only the owner name in TODO(maya) so unowned items stand out.
  • See problems in the minimap — overviewRulerColor places markers in the scrollbar so you can navigate issues without scrolling.
  • Inject context after matches — the after option appends virtual text (like ⚠️ UNSAFE or ← owner) without modifying your source file.
  • Work in any language, any project — rules are just regex. No language server, no AST, no configuration UI needed.
  • Stay safe in untrusted workspaces — when you open a workspace you don't trust, both global config files and inline :cue: directives are disabled to prevent malicious patterns from affecting your editor. Standalone files (no workspace) always allow inline rules since you opened them intentionally.

⚡ Performance

Rules are re-evaluated on every keystroke against the full document text to ensure correctness, debounced (configurable via sourceCues.debounceMs, default 200ms, set to 0 to disable) so rapid typing doesn't trigger redundant rescans.

  • There is no incremental/delta matching — each pass is a full rescan.
  • TextEditorDecorationType instances are cached and reused across passes to minimize allocation churn. A type is only disposed when its associated rule is removed.

What to expect

File size With up to 10 rules With 20+ rules
< 2,000 lines Should feel instant on any modern hardware Smooth; rules are cheap
2,000–5,000 lines No noticeable lag Brief pause possible on slower machines
5,000–10,000 lines Scoping rules with include globs recommended Expect visible delay on each keystroke
> 10,000 lines Narrow rules aggressively with include globs May lag noticeably — consider disabling global rules for these files

The extension ships with a sourceCues.maxFileSizeLines setting (default: 5000 lines). Files exceeding this threshold are skipped — a message is logged to the "Source Cues" output channel so you know the limit was hit. Set it to 0 to disable the limit and decorate files of any size.

If you experience slowdown: reduce the number of active rules, narrow their scope with include globs, or scope global rules to specific file patterns so they don't run on every file.

ReDoS protection

Source Cues protects against catastrophic backtracking (ReDoS) with a pre-flight complexity check. Before scanning the full document, each regex is tested against a short prefix of the text. If the test takes longer than 10ms, the pattern is skipped and disabled for the remainder of the session. A warning is logged to the "Source Cues" output channel:

[Warning] Skipping rule /(a+)+$/ — pre-flight regex check took 189ms
(threshold: 10ms). The pattern has been disabled for this session to
prevent catastrophic backtracking (ReDoS).

This catches patterns with nested quantifiers like (a+)+$ or ([a-zA-Z]+)*$ before they can freeze the editor. To re-enable a blocked pattern, fix the regex and reload the VS Code window.


🛠️ Workspace Setup (.source-cues.json)

Create a file named .source-cues.json at the root of your project workspace to apply global rules. The easiest way is to run "Source Cues: Open workspace rules" from the command palette — it creates the file from a template if it doesn't exist yet.

File format

The config file is a JSON object with two sections:

{
  "styles": [
    { "name": "alert", "options": { "color": "#ff5555", "fontWeight": "bold" } }
  ],
  "rules": [
    { "pattern": "CRITICAL", "options": "#alert" },
    { "pattern": "console\\.log", "include": ["**/*.js"], "options": { "textDecoration": "line-through" } }
  ]
}

styles — an array of named, reusable style definitions. Each style has a name and an options object with VS Code decoration properties.

rules — an array of rule objects. Each rule has:

  • pattern — regex pattern (string) or { "source": "...", "flags": "i" }
  • options — either an inline decoration object or a "#name" string referencing a style defined in styles
  • include (optional) — glob or array of globs to limit the rule to matching files

Using #references

When multiple rules share the same styling, define it once in styles and reference it by name:

{
  "styles": [
    {
      "name": "danger",
      "options": {
        "color": "#ffffff",
        "backgroundColor": "#cc0000",
        "fontWeight": "bold",
        "overviewRulerColor": "#ff0000",
        "overviewRulerLane": 4
      }
    },
    {
      "name": "subtle-warn",
      "options": { "color": "#ff9944", "fontStyle": "italic" }
    }
  ],
  "rules": [
    { "pattern": "CRITICAL_ERROR", "options": "#danger" },
    { "pattern": "DEPRECATED_API",  "options": "#danger" },
    { "pattern": "FIXME",          "options": "#subtle-warn" }
  ]
}

Rules can still use inline options objects — references and inline styles can coexist in the same file.


⚙️ Settings

All settings are under the sourceCues.* namespace in VS Code's settings editor or settings.json.

Setting Type Default Description
enableGlobalRules boolean true Load rules from .source-cues.json (requires trusted workspace)
enableInlineRules boolean true Parse :cue: directives in open files (works in Restricted Mode)
highlightDirectiveSyntax boolean true Tint directive lines green (valid) or orange (broken) while editing
configFileName string ".source-cues.json" Custom filename for workspace-level rules
inlineTriggerKeyword string ":cue:" Keyword that triggers an inline rule (e.g. ":cue:", ":highlight:")
maxFileSizeLines number 5000 Skip decoration on files above this line count (0 = no limit)
debounceMs number 200 Delay before re-evaluating after a text change (0 = no debounce)

🧩 Regex Patterns & Quoting

Regex patterns work the same everywhere, but escaping differs between inline rules and the workspace config file — this is the #1 cause of "my rule doesn't match."

Inline :cue: rules

Patterns are written directly in source comments. Backslashes work as in any regex literal — one level of escaping:

// :cue: /\b(TODO|FIXME)\b/ -> { "color": "#ff9944" }

Here \b is a word boundary — one backslash, as you'd write in a regex.

Workspace .source-cues.json

The config file is JSON. JSON strings use backslash escaping, so every regex backslash must be escaped twice — once for JSON and once for the regex engine:

{ "pattern": "\\b(TODO|FIXME)\\b", "options": "#warning" }

\\b in JSON becomes the string \b, which the regex engine sees as a word boundary. A single \b in JSON is the backspace character (ASCII 0x08) — the regex would look for a backspace, not a word boundary.

Quick reference

Pattern Inline :cue: Workspace .source-cues.json
Word boundary /\bword\b/ "\\bword\\b"
Literal dot /\./ "\\."
Digit class /\d+/ "\\d+"
Capture group /TODO\((\w+)\)/ "TODO\\((\\w+)\\)"
Literal backslash /\\\\/ "\\\\\\\\"

Tip: If a workspace rule doesn't match but the same pattern works inline, check your JSON escaping. The "Source Cues" output channel logs the compiled regex — compare it against what you intended.


🎨 Decoration Options Reference

The options field accepts any VS Code DecorationRenderOptions. Below are the most commonly used properties:

Property Type Description
color string Text foreground color (e.g. "#ff5555")
backgroundColor string Text background color (e.g. "#cc0000")
fontWeight string "bold", "normal", or numeric "100"–"900"
fontStyle string "italic" or "normal"
border string CSS border shorthand (e.g. "1px solid red")
borderRadius string Corner rounding (e.g. "3px")
textDecoration string "underline", "line-through", "none"
outline string CSS outline shorthand
opacity string Opacity value (e.g. "0.6")
overviewRulerColor string Minimap scrollbar mark color
overviewRulerLane number Scrollbar lane position (1–6)
before object Virtual text injected before the match
after object Virtual text/content injected after the match
gutterIconPath string or {light, dark} Icon in the editor gutter
dark object Theme-aware overrides for dark themes
light object Theme-aware overrides for light themes

Content injection (before / after)

The before and after properties accept an object that renders as virtual text adjacent to the match:

{
  "after": {
    "contentText": " ⚠️ UNSAFE",
    "color": "#ff5555",
    "fontStyle": "italic",
    "margin": "0 0 0 10px"
  }
}

Gutter icons

Icons are resolved relative to your project, not the extension. Both forms are supported:

// Single icon — workspace-root-relative (leading /) or file-relative
{ "gutterIconPath": "/demos/icons/warning.svg" }

// Theme-aware pair
{ "gutterIconPath": { "light": "/demos/icons/info-light.svg", "dark": "/demos/icons/info-dark.svg" } }

Extension-specific options

Property Type Description
captureGroup number 0-based capture group index to highlight instead of the full match (default: 0). Stripped before passing to VS Code.

Example: Only highlight the owner name inside TODO(maya), not the parentheses or the TODO prefix:

// :cue: /TODO\((\w+)\)/ -> { "captureGroup": 1, "color": "#ff6600", "after": { "contentText": " ← owner", "color": "#888" } }

With captureGroup: 1, only maya is highlighted. With the default 0, the entire TODO(maya) would be styled.

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