Turn a source file into a syntax-highlighted PNG or JPG, styled like a code-screenshot card (macOS-style title bar, gradient background, soft shadow), straight from the terminal.
The dark theme with --footer, rendered by snapcode docs/examples/sample.ts.
snapcode src/snap.js → snapshot.png
- Node.js 22.12 or newer.
- Git on
PATHis optional; it is only used for--footer. - Not on the npm registry yet, install from source.
npm install # from the repo root
npm link # optional: puts `snapcode` on your PATH# Dark theme (default), writes ./snapshot.png
snapcode ./index.js
# Light theme, custom output, copy the image to the clipboard, add the git footer
snapcode ./index.js -t light -o shots/index.png --clipboard image --footer
# JPG with line numbers and lines 3 and 5-8 highlighted, writes ./snapshot.jpg
snapcode ./index.js -f jpg --line-numbers --highlight 3,5-8
# Without linking
npm start -- ./index.js -o index.png
node src/snap.js ./index.jsOn success it prints Saved PNG: <absolute path> (or Saved JPG:).
Every image here was made from docs/examples/sample.ts.
![]() |
![]() |
-t dark (default) |
-t light |
snapcode serve: paste code on the left, the preview on the right is the PNG the CLI would write.
$ snapcode --help
Usage: snapcode [options] [command] <filepath>
Generate syntax-highlighted PNG or JPG snapshots from source code files.
Arguments:
filepath Path to the source code file
Options:
-V, --version output the version number
-t, --theme <theme> Theme variant (choices: "dark", "light", default:
"dark")
-f, --format <format> Image format (choices: "png", "jpg", default: "png")
-o, --output <file> Output file name (default: snapshot.<format>)
--clipboard <mode> Copy the image to the clipboard (choices: "image",
"none", default: "none")
--footer Add a footer with the last git commit's author and date
--tab-width <n> Columns per tab stop (1-16) (default: 4)
--max-lines <n> Render at most this many lines, 0 for all (default:
100)
--line-numbers Show line numbers
--highlight <lines> Highlight lines, e.g. 3,5-8
-h, --help display help for command
Commands:
serve [options] Open the web UI, served on 127.0.0.1 only$ snapcode docs/examples/sample.ts -t light -o docs/images/theme-light.png
Saved PNG: D:\Projects\SnapCodeCLI\docs\images\theme-light.pngOutput captured from the CLI; the path on your machine will differ.
| Flag | Default | Description |
|---|---|---|
<filepath> |
required | Source file to render (exactly one) |
-t, --theme <dark|light> |
dark |
dark = Shiki dracula, light = github-light |
-f, --format <png|jpg> |
png |
Image format. JPG is written at quality 90 |
-o, --output <file> |
snapshot.<format> |
Output path; must end in .png, or .jpg/.jpeg with -f jpg; missing folders are created; an existing file is overwritten |
--clipboard <image|none> |
none |
image copies the image itself to the clipboard. A clipboard failure only prints a warning |
--footer |
off | Add Last edited by <author> on <date> from the last git commit touching the file |
--tab-width <n> |
4 |
Columns per tab stop, 1 to 16 |
--max-lines <n> |
100 |
Render only the first n lines and warn on stderr; 0 renders everything |
--line-numbers |
off | Show right-aligned line numbers in a gutter |
--highlight <lines> |
none | Highlight lines, e.g. 3,5-8. Lines past the end are ignored |
-V, --version |
Print the version | |
-h, --help |
Show help |
See docs/COMMANDS.md for details and exit codes.
snapcode serve # http://127.0.0.1:3333, opens your browser
snapcode serve -p 8080 --no-openPaste code or drop a file, pick a language and theme, and download the PNG. The preview updates as you type and is the same PNG the CLI would make. The server listens on 127.0.0.1 only and renders up to 256 KB, 100 lines and 300 characters per line.
The SVG renderer has no filesystem or rasteriser dependency, so it also runs in a browser:
import { renderSvg } from "snapcode-cli";
const svg = await renderSvg(code, { fileName: "app.ts", theme: "dark", footer: null, tabWidth: 4 });
// Options also take language (a Shiki id; detected from fileName when omitted), lineNumbers and highlight.- Language comes from Shiki's own language ids and aliases (so
.lua,.vue,.ps1,Dockerfile,Makefileall work), plus a short override map for names Shiki does not alias. Anything else renders as plain text. - Tabs advance to the next tab stop (every 4 columns unless
--tab-widthsays otherwise). A final newline does not add a blank row. - Only the grammar and theme the file needs are loaded: a one-line file renders in about 0.5 s.
- Columns line up on every OS: each character sits on a fixed 14.4 px grid, and CJK, fullwidth and emoji take two cells. The font is not bundled (the SVG asks for
JetBrains Mono, Menlo, Consolas, monospace), so glyph shapes differ per OS. CJK and emoji need a system font that has them, and joined emoji such as 👨👩👧 render as separate glyphs in the PNG because librsvg does not join them. - Long files are clipped to 100 lines by default (
--max-lines). Width is not capped, so minified one-liners still make very wide images.
npm test # node --test
npm run dev # web UI server, restarts when src/ changesCI runs the tests on Windows, macOS and Linux with Node 22 and 24.
- docs/COMMANDS.md: full reference
- docs/ARCHITECTURE.md: how it works
- CONTRIBUTING.md: dev setup
- AUDIT_REPORT.md: known issues and roadmap
MIT. See LICENSE.



