richlander/dotnet-package-skills/markout

Claude Code and agent skill by richlander/dotnet-package-skills

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when generating Markdown or other structured output (plain text, ANSI, pretty tables, TSV/JSONL) from C# objects instead of hand-built strings — CLIs, tools, reports, agent output. Markout is a source-generated .NET serializer: it looks like System.Text.Json source-gen but the rules differ (NO reflection fallback), so it needs a generated MarkoutSerializerContext and Markout-specific attributes. Start here for the required pattern; branch to the domain skills for conditional reports, multi-view/verbosity, output formats, built-in shapes, and composite cells/cards. Don't decompile the Markout assembly or web-search its API — every idiom you need is in these skills.

Install

npx vskill@latest install richlander/dotnet-package-skills/markout

SKILL.md

Markout — structured output from objects

Package Markout (the source generator ships in it — no extra package). Default output is Markdown. Reach for Markout whenever a tool would otherwise build strings with Console.WriteLine / StringBuilder.

Everything you need is in these skills. Do NOT web_search / web_fetch for Markout usage —
this base skill plus the domain skills below are authoritative and version-matched to the package.
If an idiom isn't here, pull the matching domain skill (listed at the end); don't go to the web.

The required pattern (3 parts — all mandatory)

csharp
using Markout;
// 1. Annotate every model type. List<T> -> table, scalar -> field.
[MarkoutSerializable(TitleProperty = nameof(Title))] // TitleProperty -> the H1 heading
public class Report
{
public string Title { get; set; } = "";
public int Count { get; set; } // scalar -> "Count | 3" field row
[MarkoutSection(Name = "Items")] // -> "## Items" heading
public List<Row>? Items { get; set; } // List<T> -> a table
}
[MarkoutSerializable]
public class Row { public string Name { get; set; } = ""; public string Value { get; set; } = ""; }
// 2. Register EVERY type on a partial context (the source generator fills it in).
[MarkoutContext(typeof(Report))]
[MarkoutContext(typeof(Row))]
public partial class ReportContext : MarkoutSerializerContext { }
// 3. Serialize THROUGH the context.
MarkoutSerializer.Serialize(report, Console.Out, ReportContext.Default);

Scalar field shaping (title, description, per-value formatting)

Shape scalar properties with attributes — never pre-format strings in the model or hand-write rows:

csharp
[MarkoutSerializable(
TitleProperty = nameof(Name), // -> the H1 heading
DescriptionProperty = nameof(Summary), // -> a paragraph under the H1 (NOT a Field | Value row)
FieldLayout = FieldLayout.Inline)] // Table (default) | Inline | Bulleted | Numbered | Plain
public class Component
{
public string Name { get; set; } = "";
public string Summary { get; set; } = "";
[MarkoutDisplayFormat("{0:N0} downloads")] // 5100000 -> "5,100,000 downloads"
public long Downloads { get; set; }
[MarkoutDisplayFormat("{0:yyyy-MM-dd}")] // DateTime -> "2024-06-01"
public DateTime Published { get; set; }
[MarkoutBoolFormat("Yes", "No")] // true -> "Yes", false -> "No"
public bool Verified { get; set; }
}
  • DescriptionProperty renders a property as a description paragraph, not a table row.
  • FieldLayout.Inline puts the scalar fields on one line (Owner: … | Status: …) instead of a table.
  • [MarkoutDisplayFormat("{0:…}")] / [MarkoutBoolFormat(t,f)] format a value in place — do not bake

the formatting into the getter or build the cell string yourself.

Gotchas (where System.Text.Json intuition is wrong)

  • No reflection fallback. There is no Serialize(obj) overload. EVERY Serialize call takes a

MarkoutSerializerContext. Omitting it does not compile — the #1 mistake.

  • Register every type. A model missing [MarkoutSerializable] + [MarkoutContext(typeof(T))]

won't serialize. The context class MUST be partial.

  • Markout attributes, not Json: [MarkoutSerializable] (not [JsonSerializable]),

[MarkoutContext], [MarkoutSection(Name=...)], [MarkoutPropertyName], [MarkoutIgnore].

  • Type drives rendering, not markup: List<T> -> table; scalar -> Field | Value row;

[MarkoutSection(Name="X")] -> a ## X heading above the property.

  • `[MarkoutIgnoreInTable]` on non-tabular list properties (List<Metric>, List<Breakdown>,

List<TreeNode>, List<Description>, Callout) or they get mistreated as table columns.

Most common workflow: JSON API → model → report

Fetch JSON, project to a Markout model (a plain data model is fine — no separate visual layer), serialize. Keep the JSON DTO and the Markout model separate; project between them with LINQ.

Which skill for what

Author declaratively — describe the data, let the type/attributes drive output. Do NOT hand-roll if/StringBuilder for things below. Pull the matching skill:

  • conditional-composition — show/hide sections & columns from the data; filter to sections;

one model, many shapes (ShowWhenProperty, IgnoreColumnWhen, IncludeSections, same-name sections).

  • output-formats — plain text, ANSI/Spectre, pretty tables, TSV/JSONL, multi-format dispatch.
  • built-in-shapes — Metric, Breakdown, Callout, TreeNode, Description, CodeSection.
  • composite-cells-cards — dense-Markdown-cell ↔ decomposed-column data (Change<V>, Fraction,

Share, Percent, Segments, Delta/Goal) and metric/role/verdict cards.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/richlander/dotnet-package-skills/markout/badge)](https://verified-skill.com/skills/richlander/dotnet-package-skills/markout)

Something wrong with this skill or its page? Tell us.