Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Sidecar CommentsNew to Visual Studio Code? Get it now.
Sidecar Comments

Sidecar Comments

shapled

|
1 install
| (0) | Free
Show extra comments as CodeLens rows anchored above lines. Comment text lives in .sidecar-comments/ and never touches your source files until you convert it.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Sidecar Comments logo

Sidecar Comments

English · 简体中文

A VSCode extension that adds sidecar comment lines to your files. The comment text lives completely detached from the document — stored under .sidecar-comments/ at the workspace root (mirroring each file's relative path) — and is rendered as a CodeLens row above the anchor line.

CodeLens rows are view-zone virtual lines, so a comment row takes no line number, never enters the buffer, and cannot be typed into: zero dirty dots, zero save flicker, completely invisible to the LSP.

Shortcuts and interactions

Action Behavior
Ctrl+Cmd+/ One-way extraction: a plain/comment line → content goes into the sidecar and the line is deleted (line numbers below contract; the lens lands exactly in the old line's visual slot). No reverse: if the cursor line is an anchor line it prompts "The current line is an anchor line and cannot be converted"; if the next line is an anchor line it prompts "The anchor line already has a codelens; cannot convert" (prevents materializing and prevents two comments colliding on one anchor). Converting back to the document is always done with Up/Down.
Ctrl+Cmd+Up Directional toggle (line ⇄ codelens): if the cursor line has an anchored comment → release it (insert a real // sc\| content line at the anchor); otherwise → extract the line above (the anchor lands on the current line; press again to release). Prompts at the top line / on empty lines / anchor collisions; never grabs remote comments.
Ctrl+Cmd+Down Same directional toggle downward: anchored on the line below → release; otherwise → extract the line below (press again to release). End-of-document / empty / collision prompts likewise.
Ctrl+Cmd+Enter Add above: create a side comment via input box, anchor = current line (first line of a multi-line selection); sidecar-only, zero buffer, zero dot; refuses when the line already has an anchor.
Click lens text Edit the comment in a quick input (writes only the sidecar, never the buffer, zero dot)
Editor context menu A dedicated group (8_sidecar) sitting directly above the Copy/Paste group: two prominent items, "Sidecar: Toggle Comment Above" (the Ctrl+Cmd+Up command) and "Sidecar: Export Merged File"
Sidecar: Export Merged File Export a merged file: source buffer + every comment inserted as a // sc\| … line above its anchor → sibling <name>.merged.<ext>; zero dot, no comments → prompts and writes nothing (same name in the Command Palette)
Sidecar Comments: Show Sidecar File Open the sidecar JSON for the current file

Conversion commands do "line insert/delete + sidecar write + silent save" (TextDocument.save) in one shot; buffer and disk match immediately, and the dirty dot exists only for the instant of conversion.

Multi-line selection rules: Ctrl+Cmd+/ refuses a cross-line selection with a prompt (single lines only); Ctrl+Cmd+Up acts on the selection's first line (extract target / release check); Ctrl+Cmd+Down on the last line; Ctrl+Cmd+Enter anchors at the first line.

Display (CodeLens)

  • The lens row renders above the anchor line as a view-zone virtual line: no line number, consumes no document line, unreachable by cursor or editing.
  • Styled as small clickable text (color/size: editorCodeLens.foreground, editor.codeLensFontSize, follows your theme); no full-line background (view zones have no background API).
  • Comments are single-line (that's the lens; click the lens to edit longer text in an input box).
  • Coexists with other extensions' CodeLens (e.g. TS references); editor.codeLens: false disables the display globally (on by default).
  • If the sidecar file is edited by hand (external JSON changes), a file watcher refreshes the lens immediately.

State model

Every comment lives in exactly one of two forms; they are mutually exclusive and no content is ever lost:

sidecar (shown as lens)            document (real marked comment line)
┌───────────────────────┐  Ctrl+Cmd+/ extract  ┌───────────────────────────┐
│ lens row above anchor │ ←─────────────────── │ // sc| content (real line)│
│ (not in buffer, no #) │ ───────────────────→ │ editable, saved normally  │
└───────────────────────┘  Ctrl+Cmd+Up/Down    └───────────────────────────┘
  • Lens form: content lives only in the sidecar + lens; the buffer has no such line.
  • Real comment line form: // sc| content is an ordinary source line — edit, diff, and commit flows are unaffected; when converting back to the sidecar, the line's content is the source of truth.
  • Clicking a lens to edit only updates the sidecar; it never modifies the buffer.
  • Up/Down are state toggles: an adjacent anchor on that side → release (back to a real comment line); otherwise → extract the adjacent line on that side (the toggle's other half; the two directions are strict inverses).

File moves and export

  • Mirrors follow file moves: renaming/moving a file or folder in the Explorer moves its mirror under .sidecar-comments/ (the file's <relative-path>.json, or a folder's whole <relative-path>/ directory) to the new location — comments stay attached. Moving outside any workspace root leaves the old mirror in place (non-destructive).
  • Export merged file: reads the current buffer plus all comments, inserts each comment as a // sc| … line above its anchor, and writes a sibling <name>.merged.<ext> (extension kept for syntax highlighting). Reads the buffer, writes only the new file: zero dot, source untouched; an existing export is overwritten (idempotent); legacy hidden entries (content already in the document) are skipped to avoid duplication.

sidecar JSON

{
  "version": 2,
  "comments": [{ "line": 3, "text": "a = b" }]
}
  • line: anchor line number; text: comment content (single line)
  • hidden: leftover field from the legacy host-line model; ignored on read and cleaned up by any conversion command

Content cleaning and generation

Extraction (Ctrl+Cmd+/, line → sidecar):

  • Plain line var a = 1 → comment content var a = 1 (verbatim)
  • Plain comment // a = b → content a = b (comment token stripped)
  • Marked comment // sc| a = b → content a = b (token and marker stripped)
  • Block comment <!-- sc| a = b --> → a = b (open/close and marker stripped)
  • Empty lines cannot be converted (a prompt is shown)
  • Anchor guards: when the line to extract is an anchor line it prompts "The current line is an anchor line and cannot be converted" (cursor line) or "The line to extract is an anchor line and cannot be converted" (line above/below); when the line after it is an anchor it prompts "The anchor line already has a codelens; cannot convert" (see Shortcuts)

Generation (Ctrl+Cmd+Up/Down, sidecar → line):

  • Line-comment languages: a = b → // sc| a = b
  • Block-comment languages: a = b → <!-- sc| a = b -->
  • Languages without a comment token: a = b → sc| a = b

Settings

  • sidecarComments.enabled (default true)
  • sidecarComments.marker (default " sc| ", used to recognize and generate permanent comment lines; matched literally, no regex)
  • sidecarComments.languageTokens (language → comment template map overriding the built-in table; used for cleaning and generation)

Known limitations

  • Single-line lens text, no full-line background: the CodeLens capability boundary (single line, no view-zone background); position is always above the anchor line.
  • Extraction really deletes the line: line numbers below contract and a silent save happens; if the extracted line was code, the language service may briefly complain (e.g. a function missing its return) — converting back restores it.
  • Anchor clamp: after its anchor line is deleted, the lens clamps to the document's last line; line numbers may drift if the file is heavily rewritten outside VSCode (git rebase, etc.).
  • Silent save saves the whole file: other unsaved modifications are saved together with a conversion (same semantics as files.autoSave).
  • Multi-root workspaces keep an independent .sidecar-comments/ per root; files outside any root are not processed.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft