[ANN] SciCodeNotes 1.0.0—external Markdown notes and LaTeX previews for source code (vsc extension)

Hi everyone,

I’m happy to announce the first release of SciCodeNotes, a VS Code extension for attaching external Markdown notes to precise ranges of source code.

SciCodeNotes was originally designed for scientific computing, where formulas, derivations, assumptions, references, and implementation rationale often need more space than ordinary source comments can provide. However, it is not restricted to scientific code—it can be used with any programming language or source file.

Instead of adding large comment blocks to the source, SciCodeNotes stores notes separately and presents them beside the relevant implementation. LaTeX formulas can be rendered directly in the editor and in rich hover content.

Demo

SciCodeNotes workflow demo

The source-side preview can render formulas beside their implementation:

Hovering the preview reveals the complete Markdown note:

Why external notes

In production code, you usually do not want long explanations, unfinished ideas, internal derivations, or implementation notes exposed as source comments. At the same time, removing that context entirely can make complex code difficult to understand and maintain.

SciCodeNotes provides a sidecar annotation layer for this information. Select a source range and attach a separate Markdown note without modifying the code itself. The note can contain formulas, derivations, references, tables, or anything else supported by Markdown. Its first line appears beside the relevant code, while hovering reveals the complete note with rendered LaTeX.

The attachment follows ordinary code changes whenever possible. Notes can be stored with the repository or in an external location, and portable links can connect related notes and source ranges.

Install

SciCodeNotes is released under the MIT License. Feedback, bug reports, and suggestions are welcome.

Hey, this looks super cool, and is definitely something that could fit my use case—I have a number of programs with huge comment blocks explaining my the formula being implemented, where it comes from, stuff I plan to do and so on. That said, I’m curious about what differentiates this from ordinary documentation, since that’s already attached to specific source code, contains Markdown and LaTeX formulas, etc. Is the difference simply that the SciCodeNotes are meant to be more internal? Relatedly, is there a convenient way to convert the notes to more public-facing documentation? It could save a lot of repeated work if you could just clean up and organize your internal notes and turn them into docs, for example.

Glad you’re interested in this, and that’s a really good point. The way I see it, there are two main differences between ordinary documentation and SciCodeNotes: how private/internal information is handled, and what the information is organized around.

The first difference is privacy and publication.

With ordinary documentation, you could of course organize a project like this:

src/
├── file1.jl
├── file1.md
├── file2.jl
└── file2.md

In a typical documentation workflow, though, those Markdown files would usually end up in version control together with the source code, and would therefore be shared or published with the repository. You can certainly add them to .gitignore, or keep them somewhere outside the repository, but that is something you have to arrange yourself.

SciCodeNotes treats private sidecar notes as a normal use case. You can keep the notes under .scicodenotes/ and exclude that directory with .gitignore, or store the entire note database outside the repository. This makes it easy to keep internal derivations, unfinished ideas, implementation details, and similar material close to the source code without putting them into the public repository.

The second difference is what the information is organized around.

Ordinary documentation is usually document-centric: you start with a document and then refer to or describe the code from there. If you want to point to a specific piece of implementation, you usually have to record the file, function, or line manually, and that reference normally does not move when the source code changes.

SciCodeNotes is source-code-centric instead: you start with the source code and attach knowledge directly to a precise source range. That attachment is part of the note itself, and SciCodeNotes tries to keep it attached to the corresponding code as the source changes. So, you will be working with the source code.

In principle, yes. But SciCodeNotes notes may naturally contain things like:

  • half-finished derivations
  • reasons why a particular approach was rejected
  • benchmark observations
  • temporary assumptions
  • TODOs

Simply concatenating all of those notes would not produce very good public documentation.

On the other hand, if your workflow is more structured–for example, if you carefully maintain one SciCodeNote for each function–then I can definitely imagine exporting them into something closer to Julia’s documentation:

function → explanation → related source location

In that kind of workflow, SciCodeNotes could become an public documentation and reduce the amount of duplicated writing.

I do not yet know what your actual workflow looks like, though. If this is something you would genuinely like to use, I would be very interested in seeing a concrete example of how you imagine organizing and exporting the notes. Please feel free to open an issue in the repository and describe the workflow you have in mind. That would give me a much better basis for designing the feature around a real use case.

This looks very useful, thanks.

I am probably doing something wrong as for some reason the VS Code hovering window failed to render the formulas:

(for the formulas to display I need to open the preview window)

The full note is provided here.
# Wyllie Time-Average Equation

Relates sonic transit time to porosity in a fluid-saturated rock, assuming
a simple mixing law between matrix and fluid travel times.

## Assumptions
- Rock is a stack of alternating matrix and fluid layers, sonic wave travels
  through both in series (no bypassing).
- Only valid for clean, consolidated, fully saturated formations.
- Breaks down in unconsolidated or gas-bearing zones (velocity underestimated).

## Formula

$$
\frac{1}{V} = \frac{\phi}{V_f} + \frac{1 - \phi}{V_{ma}}
$$

Equivalently, in terms of transit time $\Delta t$ (µs/ft), since $\Delta t = 1/V$:

$$
\Delta t = \phi \, \Delta t_f + (1 - \phi)\, \Delta t_{ma}
$$

Solving for porosity:

$$
\phi = \frac{\Delta t - \Delta t_{ma}}{\Delta t_f - \Delta t_{ma}}
$$

## Variables
| Symbol | Meaning | Typical value |
|---|---|---|
| $\Delta t$ | Measured sonic transit time | from log |
| $\Delta t_{ma}$ | Matrix transit time | 55.5 µs/ft (sandstone) |
| $\Delta t_f$ | Fluid transit time | 189 µs/ft (freshwater mud) |
| $\phi$ | Sonic-derived porosity | — |

## References
Wyllie, M.R.J., Gregory, A.R., and Gardner, L.W. (1956), "Elastic wave
velocities in heterogeneous and porous media," *Geophysics*, 21(1), 41–70.

Hmm… I can’t reproduce this issue on my machine. So I plan to focus on adding debug log output when Mathjax initialization fails in the next version. By then, you’ll know what happened to Mathjax on your machine. I’ll get it done as soon as possible.

Hi, I just released SciCodeNotes 1.0.1 with improved MathJax diagnostics.

Could you please update to 1.0.1, reload or restart VS Code, reproduce the formula-rendering issue, and then open:

Toggle Panel → Output → SciCodeNotes

If there is any diagnostic output there, could you send it to me? That should help me identify what is failing in your environment.

Hi karei,
Thanks for the 1.0.1 diagnostics update.
Here’s what showed up in the SciCodeNotes Output channel after reproducing the issue:

SciCodeNotes diagnostic
[2026-09-07T09:26:37.623Z] Math rendering failed.
Phase: tex2svg
Formula: inline; length=4; fingerprint=10ce0200b450
Error type: TypeError
Error message fingerprint: d03a0f993daf
Stack:
    at HoverMathRenderer.renderSvg (c:\Users\jrafa\.vscode\extensions\shakirachristian.scicodenotes-1.0.1\out\hoverMath.js:276:34)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at processTimers (node:internal/timers:538:9)

And in case it helps:

About VS Code
Version: 1.136.1 (user setup)
Commit: a44adf7f53e00964ab890f9f8758a334f1fc15bc
Date: 2026-09-03T05:06:41Z
Electron: 42.10.0
ElectronBuildId: 15109253
Chromium: 148.0.7778.280
Node.js: 24.18.1
V8: 14.8.178.38-electron.0
@github/copilot: 1.0.81-0
@github/copilot-sdk: 1.0.11
OS: Windows_NT x64 10.0.26200

Hi rafael.guerra,
Thank you for the detailed feedback. I was able to reproduce the issue on a Windows virtual machine, identify the cause, and fix it in SciCodeNotes 1.0.2.

If you would like to know the reason, please read on. Otherwise, you can stop reading here. :wink:

Details

The problem turned out to be related to how MathJax 4.1.3 loads its components on Windows.

SciCodeNotes initializes MathJax through its Node API. During initialization, MathJax eventually resolves these components to absolute paths and passes them to its loader.

On Linux, an absolute path such as

/home/user/.../input/tex.js

can be passed directly to JavaScript’s dynamic import().

On Windows, however, the equivalent path is something like

C:/Users/.../input/tex.js

and Node’s ECMAScript Module (ESM) loader does not accept a Windows absolute filesystem path in that form. It expects a file:// URL instead, such as

file:///C:/Users/.../input/tex.js.

This is closely related to a previous MathJax Windows issue, MathJax #3481, which reported the same Node error:

On Windows, absolute paths must be valid file:// URLs.

MathJax fixed that issue by converting Windows paths to file:// URLs. There was later another related CommonJS/ESM path-handling issue, MathJax #3585, because CommonJS require() and ESM import() require different path representations on Windows.

In MathJax 4.1.3’s Node loader, there is a problematic combination: the resolved component path could remain a Windows filesystem path such as C:/..., while the component loader was still implemented using dynamic import(). As a result, component loading failed before MathJax had completed its initialization.

The underlying loading error was not propagated to SciCodeNotes, so it only surfaced later during formula rendering.

In 1.0.2, I changed the MathJax loader so that Windows absolute paths are converted to file:// URLs before import(). Other paths are left as-is. I also verified on the same Windows virtual machine, and math rendering now works normally.

Thanks again for reporting this. It was helpful in tracking the problem down.

Thanks, karei, confirmed that the hover math rendering works correctly now, appreciate the quick turnaround on this!

Very cool extension.

How fast is the manual latex->svg pipeline? If it’s reasonably snappy we should probably put something similar into the Julia extension too (for docstrings), ideally as a factored out JS library.

Yes, very snappy :smiling_face_with_sunglasses:

I benchmarked the current MathJax 4.1.3 pipeline locally. On Linux/x64 with Node 26.3.1 and an Intel Core i7-10875H, MathJax initialization takes about 110 ms and only happens once. The first render after initialization is about 21 ms, and after warm-up TeX-to-serialized-SVG is roughly 2.1 ms median per formula, with 95% of renders under about 3.1 ms.

If you’d like, I can also factor this out into a small shared JS library.

That would be great, yes!

I factored out the TeX-to-SVG rendering part you mentioned into a standalone repository: mathjax-svg. It has no VS Code dependency and provides the MathJax runtime layer.

The npm package is also published as mathjax-svg.

Version 1.1.0 is out!

A really cool new feature has been added: you can now attach notes directly to any location within your source code! (No longer limited to faint text at the end of a line.)
Example image

Honestly this feels like a game-changer

The times I have realised that I have forgotten how I have defined a variable and that let to bugs down the line is much more than I care to admit. And no, standard documentation does not make it this easy, despite heavily commenting my code.

I don’t know if this is the place notes did not survive a cut and paste of the code. Should I open an issue on codeberg?

You mean, after you cut and pasted the code, the comments were lost?
That’s normal, because it’s difficult to make comments track the code itself, and I only did the tracking function to a certain extent.

Yes, exactly.

But your question reminded me. Since you have this need, I will find a way to expand the tracking scope of the comments to the original code.
Could you tell me if it’s convenient, do you often use cross-file cut and paste, or just the same file?

Thanks for the time!

I would say that I have done both but rarely. What I did in the above case was copy and pasting across files. While I am developing my code, I wrote the notes of what is what and then I decided to move the function to another file for better organization. I would say this is the more likely case than moving functions around in a large file.