Tutorials 18 min read

The Checkbox Is Just Three Characters: Markdown Task Lists You Own

MMNMNOTE
markdowntask-listscheckboxesplain-textgfmfile-over-appnote-taking

A markdown checkbox is three characters: a left bracket, a space or an x, a right bracket. Write - [ ] for an open task and - [x] for a done one. The box you tick is a render of those bytes — not the task itself. The task is the line of text, and the text is yours.

That much is in every cheat sheet. The part the cheat sheets skip is the consequence. GitHub's own specification says that when a task list renders, "the task list item marker is replaced with a semantic checkbox element."1 Replaced. The box is generated from your characters at display time; it is never the place your work lives. Markdown's creator, John Gruber, set the rule that makes this true in 2004: a Markdown document "should be publishable as-is, as plain text, without looking like it's been marked up with tags or formatting instructions."2 A checkbox honors that rule. The marked-up version and the plain-text version are the same file. This post is about what you gain when you treat the three characters, not the rendered box, as the truth.

What is a markdown task list, exactly?

A task list is an ordinary bulleted list whose items carry a checkbox marker — a normal - list item that happens to start with [ ] or [x]. Nothing more exotic is happening. The GitHub Flavored Markdown spec defines it precisely as a list item whose first paragraph begins with that marker before any other content.1

Read in full, the spec says "a task list item is a list item where the first block in it is a paragraph which begins with a task list item marker and at least one whitespace character before any other content."1 The takeaway is reassuring: you already know how to write a list, so you already know most of the syntax.

The minimal example:

- [ ] Draft the quarterly memo
- [x] Book the room
- [ ] Send the agenda

Three lines. Each is readable aloud without a renderer. The first and third are open; the middle one is done. You could email this, paste it into a terminal, or print it, and every reader — human or machine — would understand it.

What are the exact characters in a markdown checkbox?

The marker is tiny and exact: a left bracket, then either a whitespace character or the letter x, then a right bracket. So the whole menu is [ ], [x], or [X] — three options. The dash and space in front (- ) are the ordinary list-item syntax; the bracket trio is the task part.

The spec spells it out word for word: a task list item marker "consists of an optional number of spaces, a left bracket ([), either a whitespace character or the letter x in either lowercase or uppercase, and then a right bracket (])."1 The rule for which state you get is mechanical. "If the character between the brackets is a whitespace character, the checkbox is unchecked. Otherwise, the checkbox is checked."1 That second sentence is quietly powerful — otherwise means anything that is not a space marks the box as complete. The Markdown Guide gives the everyday version: "To create a task list, add dashes (-) and brackets with a space ([ ]) in front of task list items. To select a checkbox, add an x in between the brackets ([x])."3 Memorize the space-versus-x. Everything else is a list you already know how to write.

The checkbox is a render over bytes you own

Here is the whole idea: the checkbox you see is a view, and the - [x] in the file is your data — two objects, not one. The spec is explicit that on render the marker "is replaced with a semantic checkbox element."1 The box is manufactured from your text. Delete the renderer and it vanishes; the text stays.

In an HTML output, the spec adds, that replacement "would be an <input type="checkbox"> element."1 The implication runs deep. Your task survives a tool change that would orphan a row stored in a vendor's database, because the task was never a row — it was a line of characters all along.

This is the same lesson as a kanban column or a calendar reminder — the structure on screen is a projection of plain characters underneath. Open the file in any text editor and you read your own to-do list with your own eyes: a dash, a bracket, a space, a word. No export, no migration, no account. The renderer is a guest in your file; the file is the host.

Click-to-toggle is a feature of the app, not the file

You can sometimes tick a checkbox with your mouse, and when you do, you are editing the source — clicking flips the character between the brackets from a space to an x. The interaction is real, but it is the app writing to your file on your behalf, not a separate "checkbox object" changing state on its own.

GitHub announced task lists in 2013 with exactly that promise: "If you can modify the Markdown text, you can check or uncheck the boxes and the text will automatically update."4 That distinction matters because clicking is not universal.

On some renderers the box is display-only, and you change a task the way you change any text: open the file, type the x. Visual Studio Code is a clean example. Its own documentation answers whether it adds GitHub's extensions with a flat "No, VS Code targets the CommonMark Markdown specification using the markdown-it library."5 So VS Code shows your tasks but does not let you toggle them by click — and that is fine. Editing [ ] into [x] by hand is editing your file directly, which is the most durable kind of edit there is.

Task lists are a GFM extension, not core Markdown

The honest caveat most cheat sheets omit: checkboxes are not part of standard Markdown. They are a GitHub extension layered on top of CommonMark — the core specification — which GitHub added in 2013 for issues and pull requests.4 You can prove the gap with one command and a search.

Fetch the CommonMark spec and grep it: the phrase "task list" appears zero times, and the words "checkbox," "[x]," and "[ ]" are absent too.6 The primitive simply is not in core. It spread from GitHub outward, which is why one tool treats it as native and another ignores it entirely.

The practical consequence is a clean split. The text- [ ] and - [x] — is plain characters that every Markdown tool will store and display as a list. The interactive checkbox render is an extension feature that a given renderer may or may not implement. A tool that does not support the extension still keeps your line; it just draws the brackets as literal brackets rather than a box. Your data never depends on the extension. Only the visual flourish does.

Where the box renders — and where it toggles

Support for task lists in 2026 is wide but uneven, splitting along two axes: does the tool render the box, and can you click to toggle it. Most popular tools render them. Fewer let you toggle by click; the rest expect you to edit the character by hand.

The table below is a snapshot, anchored on each tool's own documented behavior — read it as "support varies, here is the shape today," not as a permanent law, since renderers change over time.7

Tool / rendererRenders - [ ]?Click to toggle?Note
GitHubYesYesOrigin of the syntax (2013); "the text will automatically update" on click4
GitLabYesYesPer the 2026 platform survey7
ObsidianYesYes"Toggle a task in Reading view by selecting the checkbox"8
TyporaYesYesToggles in the editor7
VS CodeYesNo"Targets the CommonMark … specification using the markdown-it library"5
BitbucketYesNoDisplay-only7
NotionYes (on import)ConvertedBecomes a native to-do block — no longer stored as - [ ]7
PandocYes (with extension)N/AStatic output7

One row deserves a flag. When you import a task list into Notion, it is converted into Notion's native to-do block — after the import it is no longer stored as - [ ] plain text.7 That is precisely the quiet lock-in this post is about: the moment your checkbox stops being three characters and becomes a row in someone's database, you have traded a file you own for a feature you rent. Notion is a capable tool; the caution is about the conversion, not the company.

You decide what goes between the brackets

Because the file stores only the character between two brackets, the meaning of that character is yours to set. The spec's "otherwise, the checkbox is checked" rule1 means a renderer treats anything non-space as done — so your own conventions can be richer than open-or-closed. A character you pick becomes a status you define.

Obsidian leans into this directly: "You can use any character inside the brackets to mark it as complete,"8 so [?], [-], or [/] can stand for blocked, dropped, or in-progress.

- [ ] Not started
- [/] In progress
- [?] Blocked, needs a decision
- [x] Done

A vendor would call that a "custom status field" and gate it behind a settings panel. In plain text it is just a character you chose. The catch is the same one that governs the checkbox itself: a custom marker is your convention, so it renders consistently only where you have taught a tool to read it. The text, again, is portable everywhere; the styling is local. That trade — universal text, local rendering — is the recurring bargain of the whole format, and it is a good one.

Common mistakes

Five errors account for nearly every "my checkbox won't render" question, and all five trace back to the same fact: the marker is exact, and the extension is optional. Get the spacing right and know which tools implement the feature, and the rest follows. Here are the traps, in rough order of how often they bite.

How this works in a Markdown note

The render-versus-bytes split is easiest to feel in a note kept as plain Markdown on your own device. In MNMNOTE, a task list is exactly what the spec describes: you type - [ ], the editor draws a checkbox, and the file still holds the three characters. The box is the view; the - [x] is your data.

Because the note is open Markdown stored locally, you can read it in any other editor, search it with grep '\- \[ \]', or keep it in version control — the checkbox traveled as text, not as a setting trapped in someone's cloud. That is the entire pitch, and it is a quiet one: the tool you use to draw the box should never be the only tool that can read your tasks. A file you can open with your own eyes will still open the day the app that drew the boxes is gone.

Frequently asked questions

How do you make a checkbox in markdown? Start a list item with a dash and a space, then a bracket pair with a space or an x inside: - [ ] for an open task, - [x] for a done one.3 That marker is the whole syntax; the dash-space in front is ordinary list formatting. A renderer that supports the GitHub task-list extension turns the brackets into a checkbox on display.

What is the exact markdown task list syntax? A task list item is a normal list item whose first paragraph begins with a task list item marker: an optional space, a left bracket, a whitespace character or the letter x, and a right bracket.1 In practice you write - [ ] or - [x]. A space between the brackets means unchecked; anything else means checked.

Do markdown checkboxes work everywhere? No. Task lists are a GitHub extension, not part of core CommonMark — the CommonMark spec contains zero occurrences of "task list" or "checkbox."6 Most popular tools render them, but click-to-toggle and even basic rendering vary by tool.7 The plain text always survives; the interactive box does not.

Can I check a markdown checkbox by clicking it? Only on tools that support it, such as GitHub, GitLab, Obsidian, and Typora.7 On GitHub, clicking edits the source directly — "the text will automatically update."4 On display-only renderers like VS Code,5 you toggle a task by editing the character between the brackets yourself.

Why doesn't my markdown checkbox render? Usually a spacing error: [] with no space is not a valid marker, and -[ ] with no space after the dash is not a list item.1 Use - [ ]. If the spacing is correct and you still see literal brackets, your renderer likely does not implement the GFM task-list extension.6

Are markdown task lists part of standard markdown? No. GitHub introduced them in 2013 as part of GitHub Flavored Markdown,4 and they are absent from the core CommonMark specification.6 They are an extension that many tools adopted — which is why their behavior is consistent on GitHub but renderer-dependent elsewhere.

What happens to my task list if I move it to Notion? Notion converts an imported - [ ] task list into its own native to-do block, so it is no longer stored as plain-text Markdown afterward.7 If you want the portable three-character version to persist, keep the canonical copy in a Markdown file you control and treat the Notion version as a derived view.

The checkbox you tick is borrowed from whatever app drew it; the three characters in the file are the only part you actually keep — so write the box, and own the bytes.

If a checkbox marks a task done, the next question is when it is due and how important it is — that lives one layer up, in the open todo.txt conventions covered in Due Dates, Priorities, and Repeats in a Plain Text File. Stack these same checkboxes into status columns and you get the bigger structure: A Kanban Board That's Just Text Files, where a board is a view over the work items, not the work itself. The thread through all three is one claim, worth restating plainly — apps are ephemeral, but your files have a chance to last, as Obsidian's Steph Ango put it; "if you want to create digital artifacts that last, they must be files you can control, in formats that are easy to retrieve and read."9


To keep your checkboxes as the three plain characters you own — readable, greppable, and tied to no single app — write them in a Markdown note that stays on your own device, like the ones in mnmnote.com.

Footnotes

  1. "Task list items (extension)," GitHub Flavored Markdown Spec (Version 0.29-gfm), https://github.github.com/gfm/#task-list-items-extension-, retrieved 2026-06-26. 2 3 4 5 6 7 8 9 10 11

  2. John Gruber, "Markdown: Syntax" (Philosophy), Daring Fireball, https://daringfireball.net/projects/markdown/syntax, retrieved 2026-06-26.

  3. "Extended Syntax — Task Lists," Markdown Guide, https://www.markdownguide.org/extended-syntax/, retrieved 2026-06-26. 2

  4. "Task lists in all markdown documents," The GitHub Blog, 2013-01-09, https://github.blog/news-insights/product-news/task-lists-in-gfm-issues-pulls-comments/, retrieved 2026-06-26. 2 3 4 5

  5. "Markdown and Visual Studio Code" (FAQ), Visual Studio Code Docs, Microsoft, https://code.visualstudio.com/docs/languages/markdown, retrieved 2026-06-26. 2 3 4

  6. CommonMark Spec, Version 0.31.2 (2024-01-28), https://spec.commonmark.org/0.31.2/, retrieved 2026-06-26 (the spec contains zero occurrences of "task list," "checkbox," "[x]," or "[ ]"). 2 3 4 5

  7. "Markdown Checkbox Guide," macmdviewer, 2026-03-25, https://macmdviewer.com/blog/markdown-checkbox-guide, retrieved 2026-06-26. 2 3 4 5 6 7 8 9 10 11

  8. "Basic formatting syntax — Task lists," Obsidian Help, https://help.obsidian.md/Editing+and+formatting/Basic+formatting+syntax, retrieved 2026-06-26. 2

  9. Steph Ango, "File over app," 2023-07-01, https://stephango.com/file-over-app, retrieved 2026-06-26.