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.

CategoryMarkdown SupportNotes
Structural editingFullHeadings, subtrees, refile, archive
NavigationFullJump, outline, breadcrumbs, links and anchors
Speed commandsMostClocking and property keys are org-only
Text markupFullWrites **bold**, *italic*, `code`, ~~strike~~
TablesFull (GFM)Alignment colons kept; formulas are org-only
Code block executionMostHeader arguments on the fence; shared session
TODO statesFull## TODO Title or ## [TODO] Title
PrioritiesFull## TODO [#A] Title
Scheduling/DeadlinesFullSCHEDULED / DEADLINE line under the heading
AgendaFullDatabase and current-file agendas
TagsFull#tags or :a:b: ending a heading
HashtagsFullColoured, hover, click, completion
ClockingNoneOrg-specific syntax
PropertiesNoneOrg-specific syntax

Supported Features

✅ Document Outline and Navigation

Markdown files have full support for the VS Code outline view and breadcrumb navigation.

Outline View

The extension provides a DocumentSymbolProvider for Markdown that recognizes:

  • ATX headings (lines starting with # to ######)

  • Fenced code blocks (```language or ~~~language)

  • YAML frontmatter title

Open the Outline view in the Explorer sidebar or press Ctrl+Shift+O to see the document structure.

✅ Breadcrumbs

Breadcrumbs show the current heading hierarchy in the editor title bar. This works automatically for Markdown files.

✅ Jump to Heading

Press C-c C-j to open a quick-pick menu of all headings in the current file. Type to filter and press Enter to jump. Cmd-C/Shift-o also works.

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 # comment in Python

  • in 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 Navigation

All heading navigation commands work in Markdown:

KeyCommandDescription
C-c C-nNext HeadingMove to next heading (any level)
C-c C-pPrevious HeadingMove to previous heading
C-c C-uParent HeadingMove to parent (higher level)
C-c C-jJump to HeadingQuick-pick menu of all headings

Speed commands (when cursor is at column 0 of a heading line):

KeyAction
nNext heading (any level)
pPrevious heading (any level)
fNext heading (same level - forward)
bPrevious heading (same level - back)
uUp to parent heading
jJump to heading (opens menu)

Heading Manipulation

Change heading levels and move subtrees:

KeyCommandDescription
M-Promote HeadingDecrease level (## -> #)
M-Demote HeadingIncrease level (# -> ##)
M-S-Promote SubtreePromote heading and all children
M-S-Demote SubtreeDemote heading and all children
M-Move Subtree UpSwap with previous sibling
M-Move Subtree DownSwap with next sibling

Markdown has six heading levels, so demoting stops at ######.

Insert Headings

KeyCommandDescription
C-Insert HeadingInsert new heading at same level
-Insert SubheadingInsert 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:

CommandSpeed KeyDescription
scimax.org.markSubtreem, @Select entire subtree
scimax.org.killSubtreekCut subtree to clipboard
scimax.org.cloneSubtreeWDuplicate subtree below
scimax.speed.yankSubtreeyPaste subtree from clipboard
scimax.org.refilewMove subtree under a heading
scimax.org.narrowToSubtreeFocus on subtree (fold others)
scimax.org.widenUnfold 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).

KeysAction
n p f b u j gNavigate: next, previous, sibling, parent, jump, go to
c C o TabVisibility: cycle, show children, overview, fold
U DMove subtree up / down
l r L RPromote / demote heading, promote / demote subtree
m @ k W y w aMark, kill, clone, yank, refile, archive subtree
tCycle TODO state (# TODO, # DONE)
s dAdd 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 Tab on a heading to cycle fold state

  • Press Shift+Tab anywhere for global fold cycling

  • Use 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:

KeyCommandOrgMarkdown
M-b, C-c bscimax.markup.bold*text***text**
M-i, C-c iscimax.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 (-, +, * or 1.), 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: value in a YAML block and | pipes in code are left alone.

C-c C-c on a checkbox (scimax.markdown.toggleCheckbox) toggles it in Markdown and Quarto files.

Tables

Org table editing works on GitHub-flavored Markdown pipe tables:

| Name | Count | Price |
|:-----|:-----:|------:|
| a    |   1   |  2.50 |
  • Tab / S-Tab move 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 Navigation

KeyCommandDescription
C-c C-v nNext Source BlockJump to next fenced block
C-c C-v pPrevious Source BlockJump to previous fenced block
C-c C-v gJump to Source BlockQuick-pick menu of all blocks

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 ![](.ob-jupyter/plot.png), 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 None or the line ends with ;. A block ending in math.pi * r**2 shows the area without a print.

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

CommandDescription
scimax.ob.splitBlockSplit block at cursor
scimax.ob.mergeWithPreviousMerge with previous block
scimax.ob.mergeWithNextMerge with next block
scimax.ob.insertBlockAboveInsert new block above
scimax.ob.insertBlockBelowInsert new block below
scimax.ob.insertBlockBelowSameInsert block with same language
scimax.ob.cloneBlockDuplicate current block
scimax.ob.killBlockDelete 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)
CommandDescription
scimax.markdown.insertTaskInsert a new checkbox task
scimax.markdown.toggleCheckboxToggle the checkbox (C-c C-c)
scimax.markdown.insertPriorityAdd @priority(A)
scimax.markdown.showAgendaTasks grouped by date
scimax.markdown.showTodaysTasksTasks due or scheduled today, or overdue
scimax.markdown.showTasksByTagFilter tasks by #tag
scimax.markdown.showTasksByProjectFilter 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 on markdown.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 as name.pdf next 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, as p in 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:

FeatureProvided by
Syntax highlighting, YAML header completionQuarto
Outline view, cross-reference completionQuarto
Render and preview (Cmd+Shift+K, Cmd+Shift+V)Quarto
Running chunks in a Jupyter sessionQuarto
Heading navigation, promote/demote, moveScimax
Subtree kill, copy, yank, refileScimax
Speed commands at a headingScimax
Folding cycles (Tab, Shift+Tab)Scimax
Tables, citations, timestamps, jumpScimax
Code block split, clone, move, navigationScimax

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.

Tasks, Planning and Hashtags in Markdown

Markdown headings can be org tasks. A heading may start with a TODO keyword (bare, or in brackets as [TODO] so it renders visibly), then a priority cookie; tags are #tag words or an org :a:b: group at the end of the title. A planning line with SCHEDULED, DEADLINE and CLOSED timestamps may follow the heading directly:

## TODO [#A] Write the introduction #paper #writing
SCHEDULED: <2026-11-03 Tue> DEADLINE: <2026-11-07 Fri>

## [NEXT] Send the draft to coauthors

## DONE Collect the data
CLOSED: [2026-10-30 Fri 14:12]

Highlighting

Task headings are coloured as in org: TODO keywords red, done keywords green, and the priority, :tags: and the SCHEDULED / DEADLINE / CLOSED line with its timestamps in the theme's org colours. They are semantic tokens (orgTodo, orgDone, orgPriority, orgTag, orgPlanning, orgTimestamp), so editor.semanticTokenColorCustomizations can change them.

Keywords

The default keywords are TODO NEXT WAIT WAITING HOLD SOMEDAY IN-PROGRESS (active) and DONE CANCELLED CANCELED (done). Declare others with a #+TODO: line, inside an HTML comment so it does not render:

<!-- #+TODO: TODO REVIEW | DONE REJECTED -->

Put the declaration somewhere other than the first line when the first line is a heading.

Commands

KeySpeed keyAction
C-c C-ttCycle the heading's TODO keyword
S-<right> / S-<left>Next / previous TODO keyword
C-c ,,Set the priority
C-c C-ssSchedule the heading the cursor is under
C-c C-ddSet a deadline on the heading the cursor is under
C-c C-cToggle a checkbox; recount a [n/m] cookie
C-c a < aAgenda view for the current file
C-c a < tTODO list for the current file

C-c C-s and C-c C-d work anywhere in a heading's section, as in org: they open the calendar date picker, write the SCHEDULED / DEADLINE line under the heading, and add TODO to a heading without a keyword, so the task shows in the agenda. Above the first heading they insert @scheduled(...) / @due(...) at the cursor, as before. Cycling a [TODO] heading writes the keyword bare (TODO).

C-c C-t, t and S-<right> / S-<left> work as in org. A done keyword adds a CLOSED: [...] timestamp to the planning line (or a new line under the heading), and leaving it removes it. On a task with a repeater (SCHEDULED: <2026-11-03 Tue +1w>) the date moves on and the heading goes back to TODO instead. The planning line must come right after the heading, with no blank line in between.

Checkbox Statistics

A [n/m] or [n%] cookie on a heading counts the checkboxes in its section; on a list item, its direct child checkboxes. Toggling a checkbox (C-c C-c or a click) updates the cookies above it, and C-c C-c on a line with a cookie recounts it. As in org, a heading's cookie also counts its direct subheadings with TODO keywords when you change one with C-c C-t.

## Checkboxes [2/3]
- [x] task 1
- [x] task 2
- [ ] task 3

Agenda

Indexed Markdown files take part in the database agenda and TODO lists (C-c a), with priority, tags and planning dates. The first database sync after updating re-indexes Markdown files. The agenda view for the current file (C-c a < a) works on a Markdown file; agendas limited to a project read only its org files.

Hashtags

#tags in Markdown are drawn in blue, hover and click like in org (see Hashtags in the Editor), and are indexed. A heading's own # marks are not hashtags, but #tags in its title are.

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

FeatureReason
ClockingOrg syntax: CLOCK: [timestamp]--[timestamp]
PropertiesOrg syntax: :PROPERTIES: drawer
LOGBOOKOrg 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

FeatureReason
Inline tasksOrg syntax: 15+ stars
Dynamic blocksOrg syntax: #+BEGIN:
Special blocksOrg syntax: #+BEGIN_QUOTE, etc.
Table formulasOrg syntax: #+TBLFM:
Tangle, nowebNeed org header arguments
LaTeX previewInline previews are drawn for org files
Image overlaysInline images are drawn for org files
Capture into a fileCapture templates write org headings
BacklinksLinks in Markdown files are not indexed

Tips for Markdown Users

Maximizing Compatibility

To get the most out of Scimax VS Code with Markdown:

  1. Use speed commands - Position cursor at column 0 of headings for rapid single-key operations

  2. Use fenced code blocks - The extension supports ```language blocks for execution and manipulation

  3. Use the outline view - Provides visual navigation similar to org's sparse tree features

  4. Use jump commands - C-c C-j for headings, C-c C-v g for code blocks

  5. Use # TODO headings 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.

✅ Navigation