SCDOC(5)

πŸ’– SCDOC(5) β€” the manual page about writing manual pages πŸ’–

ok so bestie, this is the SCDOC(5) page from the File Formats Manual, and it's literally the spec for scdoc β€” the document format for writing manual pages. you do NOT have to hand-write roff like some kind of gremlin, you just write cute little text files and scdoc handles the rest. it's giving ✨main character energy✨ and I'm gonna walk you through every single bit of it. no cap. πŸŽ€


🌸 NAME

scdoc β€” the document format for writing manual pages. periodt. πŸ’…


πŸ¦‹ SYNTAX

first things first, and this is a hard requirement: input files must use the UTF-8 encoding. that's not a suggestion, that's the law. πŸ™ˆ

🫢 Preamble

every scdoc file has to open with this exact preamble, no skipping:

NAME(section) ["left_footer" ["center_header"]]

so NAME is the name of the man page you're writing, and section is the section you're writing for β€” go read man(1) if you need the whole lore on manual sections, iykyk.

left_footer and center_header are optional arguments that set the text sitting at those exact spots in the generated man page. and they must be surrounded with double quotes, okay? don't come for me, that's just how it is. 🌸

πŸ‘‘ Section headers

each section of your man page should start with something like this:

# HEADER NAME

subsection headers are also understood β€” just use two hashes. and the one thing you cannot mess up: each header must have an empty line on either side. every time. it's a vibe check for your headers. ✨

πŸ’¬ Paragraphs

begin a new paragraph with an empty line. that's it. that's the whole trick. 🫢

πŸ“ Line breaks

insert a line break by ending a line with ++.

the result looks like this.

(and yeah, that rendering above is the point β€” the ++ gives you the break without starting a whole new paragraph.)

πŸ’œ Formatting

text can be made bold or _underlined_ with asterisks and underscores: *bold* or _underlined_. and bestie, don't worry β€” underscores the_middle_of_words will be disregarded. so you can be cute with snake_case names and nothing breaks. πŸ”₯

🌈 Indentation

you may indent lines with tab characters (\t) to indent them by 4 spaces in the output. indented lines may not contain headers, though β€” that's the one rule.

The result looks something like this.

You may use multiple lines and most formatting.

deindent to return to normal, or indent again to increase your indentation depth. nest it like russian dolls, queen. πŸŽ€

⭐ Lists

you may start bulleted lists with dashes (-), like so:

- Item 1
- Item 2
     - Subitem 1
     - Subitem 2
- Item 3

the result looks like this:

β€’   Item 1
β€’   Item 2
    β€’   Subitem 1
    β€’   Subitem 2
β€’   Item 3

you may also extend long entries onto another line by giving it the same indent level, plus two spaces. they'll be rendered as a single list entry β€” so your long-winded item stays one item, iconically. πŸ’…

- Item 1 is pretty long so let's
  break it up onto two lines
- Item 2 is shorter
     - But its children can go on
       for a while
β€’   Item 1 is pretty long so let's break it up onto two lines
β€’   Item 2 is shorter
    β€’   But its children can go on for a while

🧚 Numbered lists

numbered lists are similar to normal lists, but they begin with periods (.) instead of dashes (-), like so:

. Item 1
. Item 2
. Item 3,
  with multiple lines
1.  Item 1
2.  Item 2
3.  Item 3, with multiple lines

see? the numbers happen automatically. slay. πŸ”₯

πŸ¦‹ Tables

to begin a table, add an empty line followed by any number of rows.

ok here's the anatomy, and yes every bit of this matters:

  • each line of a table should start with | or : to start a new row or column respectively (or a space to continue the previous cell on multiple lines)
  • then comes [ or - or ] to align the contents to the left, center, or right
  • then a space, then the contents of that cell
  • you may use a space instead of an alignment specifier to inherit the alignment of the same column in the previous row
  • each row must have the same number of columns; empty columns are permitted

and the very first character of the first row is not limited to | β€” it has special meaning:

  • [ will produce a table with borders around each cell
  • | will produce a table with no borders
  • ] will produce a table with one border around the whole table

to conclude your table, add an empty line after the last row. don't forget it or the table just keeps going like a group chat at 2am. 😭

[[ *Foo*
:- _Bar_
:-
|  *Row 1*
:  Hello
:] world!
|  *Row 2*
:  こんにけは
:  δΈ–η•Œ
   !
β”Œβ”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Foo   β”‚    Bar     β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Row 1 β”‚   Hello    β”‚ world! β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Row 2 β”‚ こんにけは β”‚ δΈ–η•Œ ! β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

you may also cause columns to expand to fill the available space with < (left align), = (center align), and > (right align), like so:

[[ *Normal column*
:< Expanded column
|  *Foo*
:  Bar
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Normal column β”‚ Expanded column                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Foo           β”‚ Bar                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

look at that stretch. πŸ’…

πŸ’– Literal text

you may turn off scdoc formatting and output literal text with escape codes and literal blocks.

inserting a \ into your source will cause the subsequent symbol to be treated as a literal and copied directly to the output. you may also make blocks of literal syntax like so β€” you wrap the text in a line of three backticks above and below:

_This formatting_ will *not* be interpreted by scdoc.

these blocks will be indented one level. now listen, important caveat: literal text is shown literally in the man viewer β€” that is, it's not a means for inserting your own roff macros into the output. so don't try it. πŸ™ˆ

also note that \ is still interpreted within literal blocks, which for example can be useful to output three backticks inside of a literal block. cute recursive moment, no cap. πŸŒ€

πŸŽ€ Comments

lines beginning with ; and a space are ignored.

; This is a comment

poof, gone, never happened. 🌸


🌟 CONVENTIONS

by convention, all scdoc documents should be hard wrapped at 80 columns. it's not enforced by the universe, but it is enforced by everyone's eyeballs. do it for the culture. 🫢


πŸ”— SEE ALSO

  • scdoc(1) β€” the actual tool that eats these files

πŸ‘‘ AUTHORS

maintained by Drew DeVault <sir@cmpwn.com>. up-to-date sources can be found at https://git.sr.ht/~sircmpwn/scdoc and bugs/patches can be submitted by email to ~sircmpwn/public-inbox@lists.sr.ht. support the ecosystem bestie, file those patches. πŸ’œ


and that's the whole page, omg we ate. this was SCDOC(5) from the File Formats Manual, dated 2026-07-07 at the bottom of the original β€” consider this your signed, sealed, adorable sign-off. now go write a man page that actually slaps. πŸ¦‹βœ¨πŸŽ€

πŸ“¦ where this page comes from