Quarkdown skill
Author Quarkdown (.qd) source files for typeset documents — books, articles, reports, presentations, wikis, and PDFs. Use this skill whenever the user wants to write or edit a Quarkdown document, asks about Quarkdown syntax (functions starting with a dot like `.doctype`, `.box`, `.row`, `.foreach`), needs help producing slides/paged/plain/docs output, wants a programmable Markdown alternative to LaTeX with high-quality typography, asks how to build PDFs from Markdown-like sources, or mentions `.qd` files. Prefer this over plain Markdown whenever the user is working in a `.qd` file or has Quarkdown installed.From its SKILL.md
npx -y skills add uditya-kumar/quarkdown-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
13.8 KB, ~3.4k tokens by cl100k_base, as published. Nobody here has run it
Quarkdown
Quarkdown is a Turing-complete Markdown flavor and typesetting system. Sources are .qd files. The compiler produces HTML, PDF (via Puppeteer), or plain text. Think "Markdown that can do what LaTeX does", with first-class functions, variables, loops, and conditionals.
This skill is the field manual: how to think in Quarkdown, the function call syntax that everything else builds on, the patterns that produce good documents, and the traps that produce broken ones.
When to reach for which feature
Always start by deciding the document type — it changes layout, page behavior, footnote rendering, and which functions even apply.
| User wants… | Use .doctype | Notes |
|---|---|---|
| A note, blog post, README-like page | plain | Continuous flow, no page breaks. Sidenote-style footnotes. |
| A book, article, report, thesis, paper | paged | Page breaks, page numbers, default LaTeX-like numbering. |
| A presentation, lecture, talk | slides | One slide per H1, fragments, transitions. |
| A wiki, knowledge base, technical docs | docs | Sidebar nav, search, multiple subdocument files. |
Then pick a theme combination. Defaults are fine; explicit common picks: paperwhite + latex (academic), darko + minimal (dark, clean), galactic + hyperlegible (highly readable web), beaver + beamer (academic slides).
The one syntax rule that explains everything
Every function call starts with a . and uses curly braces for arguments. Once you internalize this, the rest is vocabulary.
.functionname {arg1} named:{arg2}
Calls come in two flavors that look almost identical but behave very differently:
-
Inline — sits inside a paragraph, output is spliced in.
Hello, .uppercase {world}! -
Block — sits alone on its own line(s) and can take an indented body argument:
.center This whole indented block becomes the body.
The body argument is always the last parameter of the function. Indentation must be at least 2 spaces or 1 tab and consistent across all body lines — inconsistent indentation silently turns part of the body into a code block.
Three more syntactic moves you will use constantly:
- Chaining with
::—.a::bis sugar for.b {.a}. Reads naturally for math and pipelines:.sqrt {10}::round::multiply {2}. - Tight calls with
{...}— wrapping a whole call in braces lets it sit next to word characters:H{.text {2} script:{sub}}O. - Line continuation with
\— split long calls across lines:.container width:{100} \... newline ...padding:{1cm}.
For body arguments, prefer the indented block form whenever possible — it is much more readable than nested inline braces.
Read references/syntax.md when something doesn't parse the way you expect. The most common cause is body indentation or a paragraph that didn't get separated by a blank line.
How to write a Quarkdown document
A complete document has roughly this shape. Put metadata first, content second.
.docname {My Report}
.docauthor {Jane Doe}
.doctype {paged}
.doclang {English}
.theme {paperwhite} layout:{latex}
.pageformat size:{A4} margin:{2.5cm}
.numbering
- headings: 1.1.1
- figures: 1.1
- tables: 1.1
.pagemargin {bottomcenter}
.currentpage / .totalpages
<!-- Visible cover page: required if the user expects to SEE a title -->
.center
#! .docname
*.docauthor*
<<<
.tableofcontents
# Introduction
The first chapter of the report...
# Methods
...
Two things in the boilerplate that matter and aren't obvious:
- The
.centerblock with#! .docnameis what actually puts a visible title on the page..docnamealone only sets metadata.#!is a decorative heading — it renders large but doesn't enter the TOC or the heading-numbering sequence, which is what you want for a cover. <<<is an explicit page break, so the cover gets its own page before the TOC. Without it, the title and the TOC end up on page 1 together.
A few things worth knowing up front, because they catch people:
.doctypedefaults toplain— if the user wants a PDF book or a slide deck, set it explicitly..docnameand.docauthoronly set metadata. They do not render a visible title or byline anywhere in the output. If the user asks for a "report titled X by Y", or otherwise expects the title to appear on the page, you must build a visible title block yourself — typically a centered cover page above the table of contents. See the title-block recipe in the cookbook (and thepaged.qdtemplate). Skipping this is the single most common way to ship a "completed" report that has no title on it.- Heading numbering format strings count nesting levels, not heading levels.
.numberingwithheadings: 1.1.1means up to three nested levels will be numbered as1,1.1,1.1.1. A document with only top-level#chapters will show1,2,3, not1.1.1. To get a1.1.1rendering on a single heading, that heading needs to be three levels deep (### Foounder## Barunder# Baz). - Figures, tables, equations and code only get numbered if they have a caption / cross-ref ID. A bare
is not numbered;is. #triggers an automatic page break inpageddocuments by default. Use.autopagebreak maxdepth:{N}or.noautopagebreakto change this. Use##!(decorative heading) to suppress numbering and TOC entry for a single heading.- Never put
<<<immediately before a#heading in apageddocument. The#already auto-breaks; the explicit<<<adds a second break, which renders as a blank page between every chapter. Reserve<<<for forcing a break in places where one wouldn't otherwise happen — e.g., between a cover (.centerblock) and the TOC, or between two##sections you specifically want on separate pages. If a chapter starts with#, it already gets its own page; do not add<<<above it. - Markdown lazy lines bite hard.
A,B,Con three consecutive lines without blank lines between them is one paragraph, not three list items. Stack functions like.rowsee one block, not three. Always separate items with blank lines, or use.containerto force a fresh layout context. - Writing in code blocks is exempt from text symbol replacement. Outside code,
--becomes—,->becomes→,(C)becomes©, etc. Seereferences/cheatsheet.md.
The cookbook
When the user asks for something concrete, jump to the matching pattern. These are the moves that come up over and over:
| Need | Reach for |
|---|---|
| Side-by-side columns of content | .row (flat) or .grid columns:{N}. Wrap each column in .container if it has its own headings/text. |
| Vertically stacked items with control | .column |
| Centered title or hero text | .center (shorthand for .align {center}) |
| Callout / admonition box | `.box {Title} type:{tip |
| Variable or constant value | .var {name} {value}, then .name to use it |
| Reusable component | .function {name} ... param1 param2: ... body |
| Loop over items | .foreach {iterable} ... item: ... body. .repeat {N} for plain counts. |
| Conditional content | .if {condition} / .ifnot {condition} |
| Math expression inline | $ E = mc^2 $ (whitespace around $ is required) |
| Multi-line math block | $$$ ... $$$ |
| Numbered equation | $ E = mc^2 $ {#energy} then .ref {energy} to cite |
| Image with size | !(50%)[Alt](path.png) or !(300x200)[Alt](path.png) |
| Figure with caption | !(50%)[Logo](logo.png "Caption text") |
| Code block with line numbers | Standard fenced ``` block, or .code lang:{python} for dynamic content |
| Code from file | .code lang:{python} body: .read {snippet.py} |
| Mermaid diagram | .mermaid body: mermaid source. Add caption:{...} to number it. |
| 2D chart | .xychart x:{...} y:{...} body: list of values |
| CSV as a table | .csv {data.csv} (add mode:{markdown} to allow rich cells) |
| Table of contents | .tableofcontents maxdepth:{2} |
| Page counter on every page | .pagemargin {bottomcenter} body: .currentpage / .totalpages |
| Visible title / cover page | .center body: large title (#! .docname) + author (.docauthor) + date, then <<< for an explicit page break before the TOC |
| Slide fragment (reveal piece by piece) | .fragment body: content, optional `behavior:{show |
| Cross-reference | Add {#id} to target, then use .ref {id} to cite |
| Footnote (compact) | text[^: definition] or labeled [^name: definition] then later [^name] |
| Split a big document | .include {chapter1.qd} or .includeall {.listfiles {chapters}} |
| Wide content on a portrait page | .landscape body: content (experimental) |
| Multi-column page | .pageformat columns:{2}, with .fullspan for content that spans all columns |
| Custom font | .font {family-or-path} (supports GoogleFonts:Name, system names, file paths, URLs) |
For deeper recipes — author dictionaries, scoped page formatting, bibliography, subdocuments, persistent headings, custom numbered elements — see references/cookbook.md.
For the comprehensive function list with signatures (math, logical, string, collection, dictionary, optional, layout, document, slides, html), see references/functions.md.
How to actually compile and view it
The user will usually have the quarkdown CLI on PATH after installation.
quarkdown create my-doc # interactive project wizard
quarkdown c main.qd # compile to HTML in ./quarkdown-output/
quarkdown c main.qd --pdf # compile to PDF (needs Chrome/Chromium for Puppeteer)
quarkdown c main.qd -p -w # live preview + watch mode
quarkdown c main.qd --strict --clean # fail on first error, wipe output dir first
Common flags: -o <dir> output directory, --render text for plain text, --allow network if the document fetches remote assets, --allow global-read to read files outside the project, --allow process to read environment variables. Default permissions are project-read and native-content.
When writing for a user, do not assume their project layout. If they have a main.qd, leave includes alone. If they're starting fresh, suggest quarkdown create rather than hand-writing the boilerplate.
What to avoid
These are the mistakes that produce mysterious behavior. Catch them before the user does.
- Don't stack
<<<before a#heading inpagedmode.#already auto-page-breaks, so<<<followed by#produces a blank page. If you want a chapter on a fresh page, just start it with#— nothing else. - Don't put
.rowitems on consecutive lines without blank lines. They merge into one paragraph (one item from the row's perspective). Always blank-line separate, or use.containerfor each item that has internal structure. - Don't use
.center { ... .row ... }with a row inside braces. Inline arguments don't accept block calls. Use the body form:.centernewline indented.row... - Don't expect
.currentpageto be a number..currentpageand.totalpagesare visual nodes, not values — you cannot do.sum {.currentpage} {3}. - Don't mix tabs and spaces in body arguments. Pick one and be consistent inside a single body block.
- Don't forget to escape literal dots that start a line if they would be parsed as a function call. Use a backslash:
\.something. - Don't expect inline
$math$to work without spaces around the$.Let $x$ be...is wrong.Let $ x $ be...is right. - Don't write
.doctype slidesand then use#for slide content without realizing each#becomes a new slide. Use##or##!for headings inside a slide. - Don't use named arguments that come before positional ones. Once you switch to named, all following must be named.
When the user is stuck
Check the obvious things first:
- Is
.doctypeset, and matches what they're trying to do? (Page-counter +plainwon't work.) - Did they forget the blank line between blocks inside a body argument?
- Did they nest a block call inside
{...}instead of using the indented body? - Is
.numberingset if they expect figures/tables/equations to have numbers? - Did they capture an image's caption with
"..."so it becomes a numbered figure? - Did permission issues block file/network access? (
--allow ...)
Then look at references/cookbook.md for a pattern that matches their goal, or references/functions.md for the exact signature of the function that's misbehaving.
Quick orientation files
references/syntax.md— full syntax rules: positional vs named args, body args, chaining, lambdas, destructuring, line continuation, tight calls, escapingreferences/functions.md— categorized reference of stdlib functions with signatures and one-line summariesreferences/cookbook.md— longer recipes: layouts, custom components, slides, paged docs, docs sites, tables, charts, bibliographies, subdocuments, themesreferences/cheatsheet.md— terse one-pager: text symbols, image syntax, footnote syntax, quote types, headings, common gotchasassets/templates/— ready-to-edit starter templates for each.doctype
What ships with it: 9 files
42.9 KB alongside SKILL.md
assets/
- templates/docs.qd325 B
- templates/paged.qd686 B
- templates/plain.qd326 B
- templates/slides.qd606 B
references/
- cheatsheet.md5.5 KB
- cookbook.md9.3 KB
- functions.md15.9 KB
- syntax.md7.5 KB
- README.md2.9 KB