SMILES Hover

Select a SMILES string anywhere — Python, JS, JSON, CSV, Markdown, plain text —
press Ctrl+K M, and see the 2D structure rendered with RDKit in
ChemDraw style.
No Python, no pip install, no configuration. RDKit ships inside the
extension as WebAssembly.

Install
VS Code
Open the Extensions view (Ctrl+Shift+X / Cmd+Shift+X), search for
SMILES Hover, and click Install.
Or from a terminal:
code --install-extension adrianm0.smiles-hover
Or open the
Marketplace page
and click Install.
That's everything — there's nothing else to set up. Select a SMILES string and
press Ctrl+K M.
Cursor, VSCodium, Windsurf
These can't reach the Microsoft Marketplace, so install the file directly:
- Download
smiles-hover-<version>.vsix from the
latest release.
- In the editor: Command Palette (
Ctrl+Shift+P) →
Extensions: Install from VSIX… → pick the downloaded file.
Or from a terminal, using whichever CLI your editor installs
(cursor, codium, windsurf):
cursor --install-extension ~/Downloads/smiles-hover-<version>.vsix
The extension only uses stable VS Code API, so it should work on any current
fork — though it's only been tested on VS Code.
Remote SSH, WSL, and containers
Install it on the remote side, where your files are. In the Extensions
view, an extension installed only locally shows an Install in SSH: … (or
Install in WSL, Install in Container) button — click that. From a
terminal, run the install command in the remote session.
Usage
- Select a SMILES string.
- Press
Ctrl+K M (Cmd+K M on macOS), or right-click → SMILES Hover: Show
Molecule for Selection.
- The structure appears in a hover over the selection.
A molecule is remembered for 15 minutes once you've rendered it, and remembered
by its SMILES rather than by where you rendered it — so from then on every
occurrence of that string hovers: further down the file, in other files, and
after edits move it around. Render one cell of a SMILES column and the whole
column comes alive. Matching is on whole delimited tokens, so CCO won't light
up inside CCOCC or inside the word Cocoa.
Selections are cleaned before rendering — surrounding quotes, trailing commas,
and escape sequences like \n or \" are stripped — so grabbing a value
straight out of a JSONL dump works fine.
The first render loads the WASM module (~200 ms); everything after is a few
milliseconds, and results are cached per (smiles, size, preset). Command
Palette → SMILES Hover: Clear Cache to reset.
Configuration
| Setting |
Default |
Description |
smilesHover.autoSize |
true |
Size the canvas to the molecule (see below). |
smilesHover.maxHoverWidth |
460 |
Max displayed width inside the hover, px. |
smilesHover.maxHoverHeight |
240 |
Max displayed height inside the hover, px. |
smilesHover.imageWidth |
500 |
Base render width in px. |
smilesHover.imageHeight |
350 |
Base render height in px. |
smilesHover.colorPreset |
chemdraw |
chemdraw, bright, or mono atom palette. |
smilesHover.retentionMinutes |
15 |
How long a render stays hoverable, minutes. |
With autoSize on (the default), the whole structure is always visible at a
legible scale: the canvas area grows with the atom count, and its aspect ratio
is taken from the generated 2D layout, so a long molecule gets a wide render
rather than a thin band floating in an empty box. imageWidth/imageHeight
set the base size this scales from. Turn autoSize off to pin every render to
exactly those dimensions.
Render size and displayed size are separate. VS Code's hover has a limited
height — roughly a quarter of the editor's — and clips content that overflows
rather than scaling it, which would cut the bottom off a large molecule. So the
image is scaled down to fit maxHoverWidth × maxHoverHeight on display while
the underlying canvas stays large. It's vector, so nothing gets blurry, and the
big canvas is what stops atom labels colliding on dense structures. If you work
in a tall editor, raising maxHoverHeight gets you bigger structures.
Color presets:
- chemdraw — muted, publication-friendly colors on white.
- bright — vivid CPK-like (saturated red O, blue N, yellow S).
- mono — pure black on white, no atom coloring.
How it works
- The command reads your selection and cleans it (src/smiles.ts).
- src/renderer.ts hands it to RDKit's MinimalLib WASM build,
using CoordGen for ChemDraw-like 2D geometry and draw options that
approximate RDKit's ACS 1996 preset — bumped above the ACS print defaults
for bond width and font size, which are calibrated for paper and read as
spidery on screen.
- The SVG is base64-encoded into a
data: URI and embedded in the hover
markdown. No webview, no temp files, no subprocess.
The background is always white, so molecules read the same in light and dark
themes.
Development
npm install
npm run compile # vendors RDKit's WASM into vendor/, then runs tsc
npm test # unit tests for selection cleaning and token matching
Press F5 in VS Code to launch an Extension Development Host.
To build a .vsix locally:
npm run package
The README demo is generated, not screen-recorded —
scripts/make-demo.js composites real renderer output
into a mock editor window and encodes the GIF, so it can never drift from what
the extension actually draws. Regenerate it with npm run demo.
Pushing a v* tag builds the .vsix, attaches it to a GitHub Release, and
publishes to the Marketplace — see
.github/workflows/release.yml.
Limitations
- No InChI, no reaction SMARTS.
- Invalid SMILES surface RDKit's parse error in a notification.
- The
.vsix is ~7 MB, nearly all of it the RDKit WASM binary.
License
MIT — see LICENSE. Bundles
RDKit (BSD-3-Clause) via
@rdkit/rdkit; notice in
THIRD-PARTY-NOTICES.md.