Keybinding Note: This extension uses Emacs-style keybindings where Ctrl is used on all platforms (not Cmd on Mac), except where explicitly noted.
Markdown Compatibility
Scimax VS Code provides first-class support for org-mode files, and most of its
structural editing, navigation, task and code block commands also work in
Markdown files. In a Markdown file the commands write Markdown syntax: **bold**,
[text](target) links, # TODO headings with org-style SCHEDULED / DEADLINE
lines, and results that
render in the Markdown preview. This chapter documents which features work in
Markdown files and how they differ from org.
Design Philosophy
Commands that make sense in Markdown write Markdown. TODO keywords, priorities, SCHEDULED/DEADLINE lines and hashtags use the same syntax as org (see Tasks, Planning and Hashtags in Markdown). Features that only exist in org syntax (clocking, property drawers, tangling) stay org-only rather than writing org text that Markdown renderers show literally.
| Category | Markdown Support | Notes |
|---|---|---|
| Structural editing | Full | Headings, subtrees, refile, archive |
| Navigation | Full | Jump, outline, breadcrumbs, links and anchors |
| Speed commands | Most | Clocking and property keys are org-only |
| Text markup | Full | Writes **bold**, *italic*, `code`, ~~strike~~ |
| Tables | Full (GFM) | Alignment colons kept; formulas are org-only |
| Code block execution | Most | Header arguments on the fence; shared session |
| TODO states | Full | ## TODO Title or ## [TODO] Title |
| Priorities | Full | ## TODO [#A] Title |
| Scheduling/Deadlines | Full | SCHEDULED / DEADLINE line under the heading |
| Agenda | Full | Database and current-file agendas |
| Tags | Full | #tags or :a:b: ending a heading |
| Hashtags | Full | Coloured, hover, click, completion |
| Clocking | None | Org-specific syntax |
| Properties | None | Org-specific syntax |
Supported Features
What Counts as a Heading
A heading is a line that starts with one to six # characters followed by a
space. Every heading command, speed key, fold, outline entry and refile target
ignores # lines in these places, because they are not headings there:
inside fenced code blocks (
```or~~~), such as a# commentin Pythonin YAML front matter at the top of the file (between
---lines)inside HTML comments (
<!-- ... -->)
So a speed key pressed at the start of # install deps inside a ```bash block
types the letter instead of acting on a section, and moving or demoting a
section moves its code blocks with it untouched.
Setext headings (a title underlined with ==== or ---) are not recognized;
use # headings. A trailing ## sequence or a Pandoc {#id} attribute is not
part of the heading title.
Heading Manipulation
Change heading levels and move subtrees:
| Key | Command | Description |
|---|---|---|
| M- | Promote Heading | Decrease level (## -> #) |
| M- | Demote Heading | Increase level (# -> ##) |
| M-S- | Promote Subtree | Promote heading and all children |
| M-S- | Demote Subtree | Demote heading and all children |
| M- | Move Subtree Up | Swap with previous sibling |
| M- | Move Subtree Down | Swap with next sibling |
Markdown has six heading levels, so demoting stops at ######.
Insert Headings
| Key | Command | Description |
|---|---|---|
| C- | Insert Heading | Insert new heading at same level |
| - | Insert Subheading | Insert heading one level deeper |
The extension uses # characters for Markdown (not * like org), and a
subheading under a ###### heading stays at level 6.
Subtree Operations
All subtree operations work in Markdown:
| Command | Speed Key | Description |
|---|---|---|
| scimax.org.markSubtree | m, @ | Select entire subtree |
| scimax.org.killSubtree | k | Cut subtree to clipboard |
| scimax.org.cloneSubtree | W | Duplicate subtree below |
| scimax.speed.yankSubtree | y | Paste subtree from clipboard |
| scimax.org.refile | w | Move subtree under a heading |
| scimax.org.narrowToSubtree | Focus on subtree (fold others) | |
| scimax.org.widen | Unfold all (undo narrow) |
Refile and archive (speed key a) adjust heading levels the same way yank
does.
Yank Subtree Level Adjustment
When yanking (pasting) a subtree, the extension adjusts heading levels to
match the context. Only real headings change: # comments inside code blocks
in the subtree are left alone, and no heading goes past level 6.
## Target Section
<!-- Yank a subtree that was cut from a different level -->
<!-- Headings are automatically adjusted to match ## level -->
Speed Commands
Speed commands work at the beginning of Markdown headings (column 0 of a heading line, see What Counts as a Heading).
| Keys | Action |
|---|---|
| n p f b u j g | Navigate: next, previous, sibling, parent, jump, go to |
| c C o Tab | Visibility: cycle, show children, overview, fold |
| U D | Move subtree up / down |
| l r L R | Promote / demote heading, promote / demote subtree |
| m @ k W y w a | Mark, kill, clone, yank, refile, archive subtree |
| t | Cycle TODO state (# TODO, # DONE) |
| s d | Add a SCHEDULED / DEADLINE line under the heading |
| ? | Speed command help |
The keys 1 2 3 0 (priority), : (tags), e (effort), P (property)
and I O (clock in/out) are for org headings; see
Features Not Available in Markdown.
✅ Folding
Markdown headings support folding via the standard VS Code folding mechanism:
Press
Tabon a heading to cycle fold statePress
Shift+Tabanywhere for global fold cyclingUse the fold icons in the gutter
Fenced code blocks and Pandoc fenced divs (::: {.callout-note} ... :::,
nested to any depth, and MyST :::{note} fences) fold as well.
✅ Text Markup and Comments
The markup commands write Markdown syntax in Markdown files:
| Key | Command | Org | Markdown |
|---|---|---|---|
| M-b, C-c b | scimax.markup.bold | *text* | **text** |
| M-i, C-c i | scimax.markup.italic | /text/ | *text* |
| M-u, C-c _ | scimax.markup.underline | _text_ | <u>text</u> |
| M-c, C-c ` | scimax.markup.code | ~text~ | `text` |
| M-v, C-c = | scimax.markup.verbatim | =text= | `text` |
| M-s, C-c + | scimax.markup.strikethrough | +text+ | ~~text~~ |
| M-- | scimax.markup.subscript | _{text} | <sub>text</sub> |
| M-= | scimax.markup.superscript | ^{text} | <sup>text</sup> |
| scimax.markup.latexDisplayMath | \[text\] | $$text$$ |
M-; (scimax.org.dwimComment) comments lines with HTML comments
(<!-- ... -->), using VS Code's Toggle Line Comment. In org it adds =# =,
which in Markdown would make the line a heading.
Lists and Return
Return (DWIM return) in a Markdown file:
On a list item (
-,+,*or1.), starts the next item; on an empty item, removes it.*at column 0 is a list bullet in Markdown, not a heading.On a checkbox item (
- [ ] ...), starts a new checkbox item.In a table, moves to the next row.
Inside a fenced code block, front matter or an HTML comment, inserts a plain newline, so
- key: valuein a YAML block and| pipesin code are left alone.
C-c C-c on a checkbox (scimax.markdown.toggleCheckbox) toggles it in
Markdown and Quarto files.
Links
| Key | Command | In Markdown |
|---|---|---|
| C-c C-o | scimax.org.openLink | Follows [text](target) and  links |
| C-c l | scimax.org.storeLink | On a heading, stores a link to it |
| C-c C-l | scimax.org.insertLink | Inserts [description](target); edits the link at point |
C-c C-o follows:
URLs:
[docs](https://example.com)other files, relative to the current file:
[notes](../notes.md)headings in this file:
[Methods](#methods)headings in another file:
[setup](install.md#setup); in an org file the anchor is aCUSTOM_ID
Heading anchors are GitHub-style: lower case, punctuation removed, spaces
replaced by hyphens, so ## Results & Discussion is #results--discussion. A
Pandoc attribute such as # Intro {#sec-intro} also works as #sec-intro.
To link to a heading, put the cursor on it and press C-c l, then press
C-c C-l where the link should go. In the same file this inserts
[Methods](#methods); in another Markdown file, [Methods](notes.md#methods).
Org-style [[...]] links in Markdown files still work with C-c C-o.
Tables
Org table editing works on GitHub-flavored Markdown pipe tables:
| Name | Count | Price |
|:-----|:-----:|------:|
| a | 1 | 2.50 |
Tab/S-Tabmove between cells and realign the table.Alignment colons in the delimiter row are kept:
:---left,:---:center,---:right. Cells are padded to match, and the alignment moves with its column when you move, insert or delete columns.The header row and the delimiter row stay at the top. Inserting a row below the header puts it under the delimiter row, moving rows skips over the delimiter, and deleting the header or the delimiter is refused.
C-c -(insert separator) creates the delimiter row when the table has none, and otherwise does nothing, since GFM tables have only one.
Rows must start with |. Tables written without the outer pipes
(a | b / --|--) are not recognized. Table formulas (#+TBLFM:) are org-only.
Code Block Support
Markdown fenced code blocks support:
Detection and navigation
Execution via Babel/Jupyter
Block manipulation (split, merge, clone, kill, move)
Fenced Block Syntax
Both backtick and tilde fences are supported, with the language as a single word or in braces:
```python
print("Hello from Python")
```
~~~javascript
console.log("Hello from JS");
~~~
```{python}
print("Quarto/Pandoc chunk form")
```
The fence must start at column 0. Org header arguments may follow the language
(```python :results output, ```jupyter-python :session s). Other text after
the language (```python title"x"=) means the fence is not treated as a code
block. Markdown renderers use only the first word as the language, so header
arguments do not change how the preview, GitHub or Marp show the block.
Code Block Execution
Press C-c C-c inside a fenced code block to execute it. Results go below the
block, between two HTML comments that the Markdown preview and Pandoc hide:
```python
print(6 * 7)
```
<!-- results -->
```
42
```
<!-- /results -->
Running the block again replaces these results instead of adding a second
copy. Images from Jupyter kernels are written as ,
so they show in the preview. Table results become GFM tables.
Supported languages include Python, JavaScript, TypeScript, Shell, and any
language with a Jupyter kernel installed. A ▶ Run button above each runnable
block runs it, and ✕ Clear removes its results. Turn the buttons off with
scimax.babel.markdownCodeLens (Configuration).
Most Markdown code blocks have no header arguments, so a Markdown file has defaults that make it work like a notebook:
Its blocks share one session per file, so a variable set in one Python block is there in the next.
As in a Jupyter cell, a Python block shows its printed output and then the value of its last line, unless that value is
Noneor the line ends with;. A block ending inmath.pi * r**2shows the area without aprint.
Header arguments on the fence change this for one block, as in org (any
:results turns off the last-line value):
```python
data = [3, 1, 4, 1, 5]
```
```python
print(sorted(data))
```
```python
sorted(data)[-1]
```
```python :session none
print("a fresh Python, without data")
```
```python :results value
sum(data)
```
The precedence is the block's header arguments, then a file-wide
#+PROPERTY: header-args ... line, then the Markdown defaults. Execute-all,
tangle and noweb references are org-only.
In a Marp deck, C-c C-c on a ```python block with no header arguments runs
it in the deck's Python panel instead, and nothing is written into the deck
(results would show on the slide). Give the block a header argument (for
example ```python :results output) to write its results into the file. See
Running cells in VS Code.
Code Block Manipulation
| Command | Description |
|---|---|
| scimax.ob.splitBlock | Split block at cursor |
| scimax.ob.mergeWithPrevious | Merge with previous block |
| scimax.ob.mergeWithNext | Merge with next block |
| scimax.ob.insertBlockAbove | Insert new block above |
| scimax.ob.insertBlockBelow | Insert new block below |
| scimax.ob.insertBlockBelowSame | Insert block with same language |
| scimax.ob.cloneBlock | Duplicate current block |
| scimax.ob.killBlock | Delete block and results |
The extension preserves the fence style (``` or ~~~) when manipulating
blocks. Kill and move take the block's results with it. Merging puts the
merged block where the first one was, drops both blocks' results and keeps any
text between the blocks. Split, clone and insert keep the fence's header
arguments. The header-argument commands (scimax.ob.editHeader) add them after
the language; Quarto chunks (```{python}) keep their options in the braces
instead.
Tasks and Planning
Markdown files have two kinds of task: TODO headings and checkbox tasks.
Checkbox tasks carry their dates as @due(...) / @scheduled(...) tags, and
C-c C-s / C-c C-d above the first heading insert those tags.
Headings
A heading whose first word is a TODO keyword is a task, with org-style SCHEDULED / DEADLINE lines under it. See Tasks, Planning and Hashtags in Markdown for the syntax, commands and agenda.
Checkbox Tasks
- [ ] Email reviewers @due(2026-01-22) @project(paper) #urgent
- [x] Upload data @closed(2026-01-10)
| Command | Description |
|---|---|
| scimax.markdown.insertTask | Insert a new checkbox task |
| scimax.markdown.toggleCheckbox | Toggle the checkbox (C-c C-c) |
| scimax.markdown.insertPriority | Add @priority(A) |
| scimax.markdown.showAgenda | Tasks grouped by date |
| scimax.markdown.showTodaysTasks | Tasks due or scheduled today, or overdue |
| scimax.markdown.showTasksByTag | Filter tasks by #tag |
| scimax.markdown.showTasksByProject | Filter tasks by @project(...) |
A task is overdue when its due date, or its scheduled date if it has no due
date, is in the past. A tag is a #word that starts with a letter and follows
a space or the start of the line, so #123 and the #section part of a URL
are not tags. Invalid dates such as @due(2026-02-30) are ignored.
Export
C-c C-e (scimax.markdown.exportMenu) exports the Markdown file with Pandoc
to HTML, PDF, LaTeX or Word, writing the output next to the source with the
new extension. This works for .md, .markdown and other Markdown
extensions; the export never writes over the source file. Code blocks are not
executed during export.
Markdown Preview
VS Code's Markdown preview (Cmd+Shift+V, Cmd+K V to the side) gets these
additions from Scimax:
MyST directives and roles (Jupyter Book) render as callouts, figures and highlighted code instead of raw
:::{...}text. See MyST Preview.Reveal Cursor in Markdown Preview (
scimax.marp.revealInPreview) scrolls the preview so the element on the cursor line is at its top, opening a preview to the side if none is showing. It relies onmarkdown.preview.scrollPreviewWithEditor(on by default).Export to PDF: the export button in the preview's title bar (
scimax.markdown.preview.exportPdf, also in the Command Palette while the preview has focus) saves the previewed file asname.pdfnext to it and opens it. It uses Pandoc and LaTeX, like Markdown → PDF (see Markdown File Export), so the PDF is typeset rather than a copy of the preview's look; unsaved changes are included. A Marp deck exports its slides with Marp instead, aspin the Marp export menu does. The other markdown export commands and the export menu also work from the preview.
Files with marp: true in their front matter are previewed as slides, with
citations rendered; see Marp Slides.
Equation Hover
Hovering LaTeX math in a Markdown or Quarto file shows it typeset, as in org
files: $...$, \(...\), $$...$$ and \[...\] (on one line or
across lines), and math environments such as \begin{equation}. Math in
code fences, inline code, front matter and HTML comments is skipped. The hover
uses the org LaTeX renderer, so it needs latex and dvisvgm (or
dvipng), and scimax.latexPreview.enabled turns it off. Equations are
shown without numbers. See LaTeX Preview.
Quarto Documents
Quarto files (.qmd) are Pandoc Markdown with executable code chunks. Scimax
works alongside the official Quarto extension (quarto.quarto), which gives
.qmd files their language (quarto). Each extension does its own part:
| Feature | Provided by |
|---|---|
| Syntax highlighting, YAML header completion | Quarto |
| Outline view, cross-reference completion | Quarto |
Render and preview (Cmd+Shift+K, Cmd+Shift+V) | Quarto |
| Running chunks in a Jupyter session | Quarto |
| Heading navigation, promote/demote, move | Scimax |
| Subtree kill, copy, yank, refile | Scimax |
| Speed commands at a heading | Scimax |
Folding cycles (Tab, Shift+Tab) | Scimax |
| Tables, citations, timestamps, jump | Scimax |
| Code block split, clone, move, navigation | Scimax |
Everything in Supported Features above works the same way in a .qmd
file as in a .md file.
Code chunks
Scimax recognizes Quarto's chunk fences (```{python}, ```{r, echo=FALSE})
as code blocks, along with plain fences, ```{.python} display blocks and
```{=html} raw blocks. Blocks that scimax inserts in a .qmd file use the
chunk form, so Quarto executes them; splitting, cloning and merging keep it.
C-c C-c in a chunk runs it with Quarto's Run Cell (quarto.runCurrentCell)
rather than scimax's own execution, because chunk output belongs in the
rendered page, not in the source. Quarto's own keys stay in charge in .qmd
files: Cmd+Enter (run line or selection), Shift+Enter (run and advance) and
Cmd+Shift+K (preview). In a .md file those keys keep their scimax
meanings, and Cmd+Shift+K on a citation still deletes it there.
Cmd+Shift+V (Ctrl+Shift+V) in a .qmd file also runs Quarto's Preview
(quarto.preview), so the preview key matches org and Markdown files.
Callouts and other divs
Fenced divs (callouts, ::: {.columns}, panels, ::: {#fig-x} figure divs)
fold from the opening ::: to its matching close, including nested divs.
Features Not Available in Markdown
These org-mode features have no Markdown form and stay org-only. Their commands either do nothing in Markdown files or work only in org files.
Time and Metadata
| Feature | Reason |
|---|---|
| Clocking | Org syntax: CLOCK: [timestamp]--[timestamp] |
| Properties | Org syntax: :PROPERTIES: drawer |
| LOGBOOK | Org syntax: :LOGBOOK: drawer |
The speed keys I (clock in), e (effort) and P (set property) insert org
drawers even in Markdown files, where nothing reads them back. Avoid them in
Markdown.
Special Elements
| Feature | Reason |
|---|---|
| Inline tasks | Org syntax: 15+ stars |
| Dynamic blocks | Org syntax: #+BEGIN: |
| Special blocks | Org syntax: #+BEGIN_QUOTE, etc. |
| Table formulas | Org syntax: #+TBLFM: |
| Tangle, noweb | Need org header arguments |
| LaTeX preview | Inline previews are drawn for org files |
| Image overlays | Inline images are drawn for org files |
| Capture into a file | Capture templates write org headings |
| Backlinks | Links in Markdown files are not indexed |
Tips for Markdown Users
Maximizing Compatibility
To get the most out of Scimax VS Code with Markdown:
Use speed commands - Position cursor at column 0 of headings for rapid single-key operations
Use fenced code blocks - The extension supports
```languageblocks for execution and manipulationUse the outline view - Provides visual navigation similar to org's sparse tree features
Use jump commands -
C-c C-jfor headings,C-c C-v gfor code blocksUse
# TODOheadings with SCHEDULED / DEADLINE lines - they show up in the org agenda next to your org tasks
When to Use Org-Mode Instead
Consider using org-mode files when you need:
Time tracking with clocking
Inherited properties and tags
Per-block header arguments, tangling and noweb
Table formulas
Advanced export features
Org files can be exported to Markdown when sharing with others who don't use org-mode.