markup-carve

carve-authoring

Use when writing or editing Carve markup (`.crv` / `.carve` files), or when the user asks to author Carve. Carve is a post-Markdown lightweight markup language that deliberately diverges from Markdown/Djot — the emphasis delimiters are swapped (`/italic/`, `*bold*`), sup/sub are braced-only, and several Markdown habits produce wrong output. This skill front-loads the correct syntax and the traps so the output is valid Carve the first time.

markup-carve 0 Updated 1mo ago

Resources

14
GitHub

Install

npx skillscat add markup-carve/carve-skill

Install via the SkillsCat registry.

SKILL.md

Authoring Carve

Carve's mnemonic: the markup looks like its output. It starts from Djot but breaks source-compatibility in a few places to remove footguns. If you write Carve with Markdown habits, it silently mis-renders — so read the traps below before writing.

Files use the .crv extension (.carve also accepted).

The rules you will get wrong (read first)

These are the Markdown/Djot habits that break in Carve. Full list with rationale in references/traps.md.

  1. Emphasis is swapped. /italic/ is italic (slashes lean), *bold* is bold. _underline_ is underline, not italic. Bold-italic is /*text*/.
  2. **bold** and ~~strike~~ are NOT Carve. Double delimiters render with literal characters. Bold is a single *; strikethrough is a single ~ (~strike~).
  3. Superscript/subscript are braced-only. {^text^} and {,text,}. Bare ^x^ and ,x, are literal text. (~x~ is strikethrough here, not subscript.)
  4. Highlight is =text= (single equals).
  5. Heading attributes go on the line ABOVE, not trailing: write {#id .class} then # Heading. A trailing {#id} on a heading line is literal text.
  6. + is the list-continuation marker, not a bullet. Bullets are - and * only. A lone + on its own line attaches the next flush-left block to the current item. + text is a paragraph.
  7. A list marker needs content. A lone - (or - ) is paragraph text, not an empty list item.
  8. Cross-references are </#id> — the link text is auto-filled from the target heading. Implicit heading links: [Heading][].
  9. Block markers interrupt paragraphs (Markdown-like): a #/>/fence/table line directly under prose starts a block. Exception: list markers do NOT interrupt (a list still needs a blank line before it).
  10. Comments are %% to end of line (or a %%% fenced block), not {% %} or <!-- -->.
  11. Definition lists use explicit markers: :: term then : definition (single colon + two spaces). Djot's : term + indented body does not work.

Core syntax (quick)

Full card in references/syntax.md.

  • Inline: /italic/ *bold* _underline_ ~strike~ =highlight= `code` {^sup^} {,sub,} [text](url) <https://auto> </#section-id> ![alt](img.jpg) [^1] reference footnote / ^[inline note] [span]{.class} @user #tag. Escape with \. Force an intraword delimiter with the brace form: H{,2,}O, mc{^2^}.
  • Headings: #..######; attributes on the line above ({#id .class}).
  • Lists: -/* unordered, 1./1) ordered (also a. A. i. I.), - [ ]/- [x] tasks. + continues an item.
  • Tables: |= Header | header cells, |=>/|=</|=~ alignment, ^ rowspan, < colspan, + cell multi-line, ^ Caption after the table. A GFM |---| separator row is accepted as an alias.
  • Code: ```language "Header" [Label] (no space after the backticks; "Header"<pre title>, [Label]→code-group tab). Raw pass-through: ```=html.
  • Divs / admonitions: ::: note "Title"::: (types: note tip warning danger info success example quote; any other word → generic <div>). Longer fences (::::) nest shorter ones. Titles must be straight-quoted.
  • Blockquotes: >; ^ Attribution caption; a lone + at column 0 attaches the next block.
  • Math: inline $`e^{i\pi}+1=0`, display $$`\int_0^1 x\,dx`.
  • Captions: a ^ Caption line after an image/table/code/$$-math block; ^ Figure #: auto-numbers, referenced by </#id>.
  • Attributes: {#id .class key=value} on the line above/below the target; bare words are boolean attributes ({.note open}).
  • Frontmatter: a leading --- block (add ---toml / ---json for other formats).
  • Editorial (CriticMarkup): {+inserted+} {-deleted-} {~old~>new~} {#a comment#}.

Extensions (opt-in)

Some constructs are Tier-2/Tier-3 extensions, enabled per-processor and host-dependent — do not assume they render everywhere. Details in references/extensions.md: citations [@key], glossary/index/bibliography, table of contents, symbols :name:, :type[content]{attrs} inline extensions, mermaid/chart/math fences.

Always validate before finishing

Carve ships a linter that catches constructs that parse but render wrong. After authoring or editing a .crv, run it and fix every finding:

carve lint file.crv
  • Default lint targets hand-written Carve (flags **bold**, ~~strike~~, ^sup^, + bullets, broken </#id>, duplicate ids, trailing heading attributes, etc.).
  • Add --from-djot only when checking a document migrated from Djot (it also flags _x_/~x~/{=x=}, which are valid in hand-written Carve).

The round-trip you are aiming for: author using several constructs → carve lint is clean with no --from-djot. See references/validation.md.