Liqpil392 downloadsHandwrite inside your markdown notes with pressure-aware ink, a searchable text layer, inline sketches, and Apple Pencil support.
Handwriting that lives inside your notes — pressure-aware ink, fused with markdown, searchable and graphable like everything else in your vault.
Write by hand, hit recognize, and the transcription lands in the note's searchable text layer — full demo on inkedmark.com.
InkedMark makes handwriting a first-class block inside ordinary markdown notes. You write by hand where handwriting is better (diagrams, math, marginalia, fast capture) and type where typing is better — in the same note — and Obsidian's search and graph see all of it through a first-class text layer.
*.ink.md files open in a pen-first canvas view, yet
stay plain markdown files that sync, diff, and link like any other note.[[links]], #tags) that Obsidian's core
search, graph, backlinks, and Quick Switcher index with no extra work.![[Sketch.ink.md]], or
drop a small ```inkedmark block right inside any note.*.ink.md note opens in the canvas view.| Tool | Key | Notes |
|---|---|---|
| Pen | P |
Pressure-sensitive ink |
| Highlighter | H |
Translucent, multiply-blended |
| Eraser | E |
Drag across strokes; one undo step per gesture |
| Select | V |
Drag a box to select; drag inside it to move; Delete removes |
Plus: color swatches (add your own in settings), stroke sizes, a pressure
toggle, undo/redo (Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z), clear, and zoom
out / fit / in. The right side of the toolbar shows version, build, stroke
count, and zoom.
*.ink.md in the current folder.```inkedmark block.Three providers (Settings → Handwriting recognition):
Manual (default) — you type the transcription in the text-layer panel. Never uses the network.
Cloud AI (bring your own key) — renders the note's ink to an image and
asks a vision model for a markdown transcription, which lands in a clearly
marked section of the text layer for you to review and edit. Supports
Anthropic (Claude), OpenAI (GPT), and Google (Gemini); you pick the vendor
and model and paste your own API key. Typical cost is a fraction of a
cent per page. The OpenRouter vendor lets you try any vision model on
the market (e.g. google/gemini-3.5-flash, anthropic/claude-haiku-4.5)
with a single key — and its Connect OpenRouter button sets the key up
for you in one click (you approve it in your browser; no copy/paste).
The Custom endpoint vendor points recognition at any self-hosted
OpenAI-compatible server (Ollama, LM Studio, llama.cpp, vLLM, LocalAI) so
your ink never leaves your own network — see
SELF_HOSTING.md for setup guides and honest quality
expectations.
On-device (experimental, desktop only) — an offline TrOCR model transcribes the ink line-by-line, entirely on your machine. Enable it under On-device recognition (experimental) in settings. First run downloads the model from Hugging Face (~250 MB Fast / ~1.3 GB Accurate; cached afterwards). English handwriting only, and noticeably less accurate than Cloud AI — treat it as the privacy/offline fallback, not the quality path. Mobile webviews can't run the models, so it is desktop only.
Run it from the toolbar's scan button, the command palette, or turn on Recognize automatically in settings to have it run in the background ~30 seconds after you stop writing. Recognition is skipped when the ink hasn't changed since the last run, and clearing the page clears the transcription section too (your own prose in the text layer is never touched).
InkedMark makes network requests only for recognition, and only in three
cases: (1) Cloud AI sends a rendered PNG of the current note's ink to your
chosen vendor (Anthropic, OpenAI, Google, or OpenRouter) — or to the custom
endpoint URL you configured — using your API key, after a one-time
confirmation; (2) clicking Connect OpenRouter opens openrouter.ai in your
browser and exchanges a one-time code with openrouter.ai/api/v1/auth/keys —
nothing is sent until you approve in the browser; (3) the experimental
on-device provider downloads its model from the Hugging Face CDN (and the
ONNX runtime from jsDelivr) on first use — your ink never leaves the
device with that provider. Nothing else is ever transmitted — no telemetry,
no analytics, and the manual provider works fully offline. Your API key is
stored locally in the vault's plugin data (data.json).
Open the text-layer panel (toolbar 📄 button or command) and type a
transcription, key points, [[links]], and #tags. That text is stored as the
note's markdown body, so handwritten notes show up in search, the graph,
backlinks, and the Quick Switcher — find a sketch by its transcription, and
its links become real graph edges.
![[Sketch.ink.md]] renders the sketch inside any note (reading mode and
live preview).```inkedmark blocks hold a small drawing in place, with an optional
caption: line that doubles as its searchable text. Editing ink inline
happens in the dedicated note; inline blocks render read-only.An ink note is a single markdown file: frontmatter (inkedmark: true), your
text layer as the body, and the stroke data in a trailing
%%inkedmark … %% comment (quantized, compressed, invisible in reading view).
No sidecar files; atomic sync and version control.
pcrausaz/obsidian-inkedmark.main.js, manifest.json, and styles.css from a
release into
<vault>/.obsidian/plugins/inkedmark/, then enable it.What changed between versions is documented in the changelog; each GitHub release carries the matching section as its release notes.
Turn off iPadOS Scribble: Settings → Apple Pencil → Scribble (off).
iPadOS “Scribble” (the system handwriting-to-text feature) intercepts fast Apple Pencil strokes at the OS level, before they reach Obsidian's web view — so with it on, quick handwriting drops strokes. This is an iPadOS/WebKit behavior no plugin can disable or detect. With Scribble off, capture is smooth (verified on an iPad Pro 12.9″ 4th-gen, Apple Pencil 2). InkedMark shows a one-time reminder and a settings note on iPad.
npm install
npm run dev # esbuild watch (inline sourcemap)
npm run test # vitest (pure modules)
npm run lint # eslint, zero-warning gate
npm run typecheck # tsc --noEmit
npm run build # typecheck + production bundle
The build emits main.js; together with manifest.json and styles.css it
forms the Obsidian plugin. See SPECIFICATION.md for the
technical brief, QA.md for the on-device test pass,
GitHub issues for tracked bugs, and
RELEASE.md for the release flow.
Point the build at a vault's plugin folder by creating a gitignored
.deploy-target file at the repo root containing that path, e.g.
/Users/you/Library/Mobile Documents/iCloud~md~obsidian/Documents/MyVault/.obsidian/plugins/inkedmark
(or set OBSIDIAN_PLUGIN_DIR in the environment). Then:
npm run dev — watch build; auto-copies the three artifacts into the
target on every rebuild.npm run deploy — copy the current artifacts without rebuilding.A .hotreload marker is written alongside so the desktop
Hot-Reload plugin reloads on change.
iPad note: point
.deploy-targetat an iCloud-stored vault — iCloud syncs the copied files to the iPad (symlinks do not sync, which is why the build copies real files). After a deploy, wait for iCloud to sync, then reload the plugin on the iPad.
MIT © 2026 liqpil.com