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.
Resources
14Install
npx skillscat add markup-carve/carve-skill Install via the SkillsCat registry.
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.
- Emphasis is swapped.
/italic/is italic (slashes lean),*bold*is bold._underline_is underline, not italic. Bold-italic is/*text*/. **bold**and~~strike~~are NOT Carve. Double delimiters render with literal characters. Bold is a single*; strikethrough is a single~(~strike~).- Superscript/subscript are braced-only.
{^text^}and{,text,}. Bare^x^and,x,are literal text. (~x~is strikethrough here, not subscript.) - Highlight is
=text=(single equals). - Heading attributes go on the line ABOVE, not trailing: write
{#id .class}then# Heading. A trailing{#id}on a heading line is literal text. +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.+ textis a paragraph.- A list marker needs content. A lone
-(or-) is paragraph text, not an empty list item. - Cross-references are
</#id>— the link text is auto-filled from the target heading. Implicit heading links:[Heading][]. - 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). - Comments are
%%to end of line (or a%%%fenced block), not{% %}or<!-- -->. - Definition lists use explicit markers:
:: termthen: 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>[^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 (alsoa.A.i.I.),- [ ]/- [x]tasks.+continues an item. - Tables:
|= Header |header cells,|=>/|=</|=~alignment,^rowspan,<colspan,+ cellmulti-line,^ Captionafter 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:
>;^ Attributioncaption; a lone+at column 0 attaches the next block. - Math: inline
$`e^{i\pi}+1=0`, display$$`\int_0^1 x\,dx`. - Captions: a
^ Captionline 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/---jsonfor 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-djotonly 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.