Technical Writer
finos/morphir
Assists with writing and maintaining Morphir technical documentation.
Guidelines for producing accurate and maintainable documentation for the Hex1b TUI library.
$ npx skills add mitchdenny/hex1b --skill doc-writer -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install mitchdenny/hex1b doc-writer --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.github/skills/doc-writer .claude/skills/doc-writer && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .claude/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writerType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add mitchdenny/hex1b --skill doc-writer -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install mitchdenny/hex1b doc-writer --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.github/skills/doc-writer .agents/skills/doc-writer && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .agents/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add mitchdenny/hex1b --skill doc-writer -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install mitchdenny/hex1b doc-writer --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.github/skills/doc-writer .cursor/skills/doc-writer && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .cursor/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/mitchdenny/hex1b.git --path .github/skills/doc-writer--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add mitchdenny/hex1b --skill doc-writer -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install mitchdenny/hex1b doc-writer --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.github/skills/doc-writer .gemini/skills/doc-writer && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .gemini/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install mitchdenny/hex1b doc-writerInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add mitchdenny/hex1b --skill doc-writer -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .github/skills && cp -r skills-src/.github/skills/doc-writer .github/skills/doc-writer && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .github/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add mitchdenny/hex1b --skill doc-writer -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install mitchdenny/hex1b doc-writer --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mitchdenny/hex1b.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.github/skills/doc-writer .opencode/skills/doc-writer && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "doc-writer" agent skill from https://github.com/mitchdenny/hex1b/tree/main/.github/skills/doc-writer into .opencode/skills/doc-writer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "doc-writer", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
doc-writerGuidelines for producing accurate and maintainable documentation for the Hex1b TUI library.
Doc Writer is an agent skill from mitchdenny/hex1b. Guidelines for producing accurate and maintainable documentation for the Hex1b TUI library. Use when writing XML API documentation comments, creating end-user guides, or updating existing documentation.
Its SKILL.md is about 8.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files (for example `ansi-generator/README.md` and `static-generator/README.md`).
It sits in Development, covering Technical documentation and Technical writing. It works with C#. The repository describes itself as: The .NET Terminal Application Stack. The licence is MIT.
2 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e2335bd. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (C#), which the agent can run.
Shell commands in SKILL.md call:
dotnetnpmFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
learn.microsoft.comvitepress.devFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Doc Writer loads about 8.7k tokens when it runs. Until then it costs about 53 tokens; SKILL.md has 2,551 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from mitchdenny/hex1b at commit e2335bd, republished under its MIT licence (© mitchdenny). 2,551 words, ~8,678 tokens.
.claude/skills/doc-writer/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.This skill provides guidelines for AI coding agents to help maintainers produce accurate and easy-to-maintain documentation for the Hex1b project. The repository contains two primary types of documentation, each serving different audiences and following different conventions.
Location: C# source files in src/Hex1b/
Audience: Library consumers, API reference generators, IDE intellisense users
Format: XML doc comments (///)
Build Setting: GenerateDocumentationFile is enabled in src/Hex1b/Hex1b.csproj
XML documentation comments provide:
Required for:
Example:
/// <summary>
/// Represents a color that can be used in the terminal.
/// </summary>
public readonly struct Hex1bColor
{
/// <summary>
/// Creates a color from RGB values.
/// </summary>
/// <param name="r">Red component (0-255)</param>
/// <param name="g">Green component (0-255)</param>
/// <param name="b">Blue component (0-255)</param>
/// <returns>A new Hex1bColor instance with the specified RGB values.</returns>
public static Hex1bColor FromRgb(byte r, byte g, byte b) => new(r, g, b);
}Good:
/// <summary>
/// Creates a Layout that wraps a single child widget with clipping enabled.
/// </summary>Bad:
/// <summary>
/// This method will take the child widget and wrap it in a layout.
/// The layout uses the clipMode parameter which defaults to Clip.
/// </summary>Always document:
<param> for each parameter<returns> for non-void methods<exception> for thrown exceptions (when applicable)<typeparam> for generic type parametersExample:
/// <summary>
/// Arranges child widgets vertically within the given constraints.
/// </summary>
/// <param name="constraints">The size constraints for layout.</param>
/// <param name="children">The child widgets to arrange.</param>
/// <returns>The total size required for all children.</returns>
/// <exception cref="ArgumentNullException">Thrown when children is null.</exception>
public Size ArrangeVertical(Constraints constraints, Hex1bWidget[] children)Use <example> and <code> tags for key APIs within the Hex1b framework. Examples should be consise yet contain sufficient context to help developers understand how they are used. For examples that use Hex1bApp to create sample applications favor the use of the fluent API since that is the intended usage pattern.
/// <summary>
/// The main entry point for building terminal UI applications.
/// </summary>
/// <example>
/// <para>Create a minimal Hex1b application:</para>
/// <code>
/// using Hex1b;
///
/// var app = new Hex1bApp(ctx =>
/// ctx.VStack(v => [
/// v.Text("Hello, Hex1b!"),
/// v.Button("Quit", e => e.Context.RequestStop())
/// ])
/// );
///
/// await app.RunAsync();
/// </code>
/// </example>Note: HTML-encode special characters in code examples:
< becomes <> becomes >& becomes &Use <remarks> for:
/// <summary>
/// The main entry point for building terminal UI applications.
/// </summary>
/// <remarks>
/// Hex1bApp manages the render loop, input handling, focus management, and reconciliation
/// between widgets (immutable declarations) and nodes (mutable render state).
///
/// State management is handled via closures - simply capture your state variables
/// in the widget builder callback.
/// </remarks>
public class Hex1bApp : IDisposable, IAsyncDisposableUse <see> and <seealso> to link to related types:
/// <summary>
/// Theme elements for Scroll widgets.
/// </summary>
/// <seealso cref="ScrollPanelWidget"/>
/// <seealso cref="Hex1bTheme"/>
public static class ScrollThemeInternal APIs (marked with internal) should still be documented but can be less formal:
<NoWarn>$(NoWarn);CS1591</NoWarn>Review existing XML documentation in the codebase to match:
Location: src/content/
Audience: Hex1b library users (developers building TUI applications)
Format: Markdown with VitePress components
Build System: VitePress (static site generator)
This is the curernt documentation structure. As the documentation structure evolves, this should be updated to assist future agent development efforts.
src/content/
├── index.md # Landing page
├── api/
│ └── index.md # API reference overview
├── guide/
│ ├── getting-started.md # Tutorial walkthrough
│ ├── first-app.md # Quick start
│ ├── widgets-and-nodes.md # Core concepts
│ ├── layout.md # Layout system
│ ├── input.md # Input handling
│ ├── testing.md # Testing guide
│ ├── theming.md # Theming guide
│ └── widgets/ # Per-widget documentation
│ ├── text.md
│ ├── button.md
│ ├── textbox.md
│ ├── list.md
│ ├── stacks.md
│ ├── containers.md
│ └── navigator.md
├── deep-dives/ # Advanced topics
└── gallery.md # Examples showcaseStructure documentation from simple to complex:
Example: The getting-started.md file walks through building a todo app in 5 progressive steps, each adding new concepts.
Every code example should:
Good:
using Hex1b;
var state = new CounterState();
var app = new Hex1bApp(ctx =>
ctx.Border(b => [
b.Text($"Button pressed {state.Count} times"),
b.Button("Click me!").OnClick(_ => state.Count++)
], title: "Counter Demo")
);
await app.RunAsync();
class CounterState
{
public int Count { get; set; }
}Bad (incomplete, won't compile):
var button = new Button();
button.Click = () => count++;The site uses custom VitePress components for rich content:
<TerminalCommand command="..." /> - Show CLI commands<CodeBlock lang="csharp" :code="variable" /> - Code with syntax highlighting<TerminalDemo example="..." title="..." /> - Interactive terminal demos::: tip / ::: warning / ::: danger - Callout boxesExample:
::: tip Generating Full API Docs
Full API documentation can be generated from XML doc comments using tools like DocFX or xmldocmd.
```bash
dotnet build /p:GenerateDocumentationFile=true
xmldocmd src/Hex1b/bin/Release/net10.0/Hex1b.dll docs/api:::
##### 4. Live Terminal Demos
The documentation site includes a WebSocket-based terminal that can run live code examples. This gives developers an interactive preview of how their code will behave when run locally.
**Location**: `src/Hex1b.Website/Examples/`
**Component**: `<TerminalDemo example="..." title="..." />`
###### How It Works
1. The Hex1b.Website project hosts WebSocket endpoints that run actual Hex1b applications
2. Each example in `src/Hex1b.Website/Examples/` implements `IGalleryExample`
3. The VitePress documentation uses the `<TerminalDemo>` component to connect to these endpoints
4. Users can interact with the live terminal directly in their browser
###### Code Duplication
Example code in the documentation may be **duplicated** from the main code samples with minor modifications:
- **Why**: The WebSocket terminal environment has slightly different requirements than running locally (e.g., terminal size handling, connection lifecycle)
- **What changes**: Usually minor adjustments to initialization, cleanup, or terminal configuration
- **Goal**: Give developers an accurate preview of runtime behavior, even if the hosted code differs slightly from the documented snippet
**Example structure**:src/Hex1b.Website/Examples/ ├── CounterExample.cs # Live demo version ├── TodoExample.cs # Live demo version └── ...
The documentation code block shows the "clean" version a developer would write locally, while the `Examples/` folder contains the WebSocket-compatible version.
###### When to Create Live Demos
✅ **Good candidates for live demos**:
- Interactive widgets (buttons, text boxes, lists)
- Layout examples showing responsive behavior
- Input handling demonstrations
- Theming examples
❌ **Not suitable for live demos**:
- Examples using `Hex1bTerminal` for testing (headless/mock terminals)
- Examples that require local file system access
- Performance benchmarks or stress tests
- Examples with external dependencies
###### Registering Examples in Program.cs
**IMPORTANT**: After creating WebSocket example files, you must register them in `src/Hex1b.Website/Program.cs`. Examples will not be available in the live demos until registered.
Add a line for each example in the appropriate section:
```csharp
// Register [Widget name] widget documentation examples
builder.Services.AddSingleton<IGalleryExample, YourNewExample>();Look for existing example registrations grouped by feature area and add your new examples in the corresponding section. If documenting a new widget, create a new comment section for clarity.
When updating documentation examples that have live demos:
Examples/ implementationExamples/ fileDon't just describe what methods exist—explain:
Example from widgets-and-nodes.md:
## Why This Matters
1. **State Preservation**: Focus doesn't jump around when the UI re-renders
2. **Performance**: Only changed parts of the tree get updated
3. **Simplicity**: You describe the UI declaratively; Hex1b figures out the transitionsInclude:
Example:
| Layer | Type | Mutability | Purpose |
|-------|------|------------|---------|
| **Widget** | `record` | Immutable | Describes the desired UI |
| **Node** | `class` | Mutable | Manages state, renders to terminal |Create a documentation graph:
Example from getting-started.md:
## Next Steps
- [Widgets & Nodes](/guide/widgets-and-nodes) - Understand the core architecture
- [Layout System](/guide/layout) - Master the constraint-based layout
- [Input Handling](/guide/input) - Learn about keyboard shortcuts and focus
- [Theming](/guide/theming) - Customize the appearance of your appEach example should demonstrate one concept:
samples/Documentation changes should accompany code changes:
guide/widgets/*.md fileBefore finalizing documentation:
When documenting widgets in guide/widgets/, follow this consistent structure to ensure users can quickly find what they need.
📖 Canonical Example: See guide/widgets/text.md for a fully-realized example demonstrating all the patterns described below, including:
.cs snippet files with ?raw imports<CodeBlock> for full examples<StaticTerminalPreview> for visual variationsHex1bApp setupIMPORTANT: After creating a new widget documentation file, you MUST add it to the navigation sidebar in src/content/.vitepress/config.ts.
src/content/.vitepress/config.ts'Widgets' section under sidebar: { '/guide/': [...] }{ text: 'WidgetName', link: '/guide/widgets/widget-name' }text propertyFailure to update the navigation means users cannot discover the new documentation through the sidebar!
Include these when they add clear value:
Widget documentation benefits from live terminal demos using the <CodeBlock> component. However, choose the appropriate demo type based on the widget's nature.
Use Live Demo (<CodeBlock>) | Use Static Preview (<StaticTerminalPreview>) |
|---|---|
| Interactive widgets (buttons, text boxes) | Display-only widgets (text, layout) |
| User input demonstration needed | Showing specific visual states |
| Responsive behavior on resize | Code snippet with visual result |
| Focus/navigation demonstrations | Documenting multiple variations |
Live demos are best when:
Static previews are best when:
Hex1bApp setup)Every widget documentation page with interactive elements MUST include:
<CodeBlock example="..."> componentsrc/Hex1b.Website/Examples/src/Hex1b.Website/Program.csThis is NOT optional. Documentation without working interactive demos is incomplete. When writing widget docs:
.cs file in src/Hex1b.Website/Examples/Program.cs with builder.Services.AddSingleton<IGalleryExample, YourExample>()example="example-id" attribute to <CodeBlock> in the markdownVerification: After writing documentation, navigate to the page in a browser and click "Run in browser" to confirm the demo works.
src/Hex1b.Website/Examples/ for each demo<CodeBlock> component with the example attribute linking to the example Id<script setup> at the top of the markdown fileExample structure for widget docs:
<script setup>
const basicCode = \`using Hex1b;
using Hex1b.Widgets;
var app = new Hex1bApp(ctx => Task.FromResult<Hex1bWidget>(
ctx.VStack(v => [
v.WidgetMethod("example")
])
));
await app.RunAsync();\`
</script>
# WidgetName
Brief description.
## Basic Usage
<CodeBlock lang="csharp" :code="basicCode" command="dotnet run" example="widget-basic" exampleTitle="Widget - Basic Usage" />Creating the WebSocket example file (src/Hex1b.Website/Examples/WidgetBasicExample.cs):
using Hex1b;
using Hex1b.Widgets;
using Microsoft.Extensions.Logging;
namespace Hex1b.Website.Examples;
public class WidgetBasicExample(ILogger<WidgetBasicExample> logger) : Hex1bExample
{
private readonly ILogger<WidgetBasicExample> _logger = logger;
public override string Id => "widget-basic"; // Must match example attribute in CodeBlock
public override string Title => "Widget - Basic Usage";
public override string Description => "Demonstrates basic widget usage";
public override Func<Hex1bWidget> CreateWidgetBuilder()
{
_logger.LogInformation("Creating widget basic example");
return () =>
{
var ctx = new RootContext();
return ctx.VStack(v => [
v.WidgetMethod("example")
]);
};
}
}Always use the fluent API:
ctx.Text("Hello") or v.Text("Hello")new TextBlockWidget("Hello") - Do not show direct widget constructionBasic Usage must include Hex1bApp:
using Hex1b;
using Hex1b.Widgets;
var app = new Hex1bApp(ctx => Task.FromResult<Hex1bWidget>(
ctx.Text("Hello, World!")
));
await app.RunAsync();Show widgets in context - Demonstrate usage within layout containers:
var app = new Hex1bApp(ctx => Task.FromResult<Hex1bWidget>(
ctx.VStack(v => [
v.Text("Title"),
v.Text("Description")
])
));The following template shows the recommended structure. Adapt it based on the widget's complexity:
<script setup>
const basicCode = \`using Hex1b;
using Hex1b.Widgets;
var app = new Hex1bApp(ctx => Task.FromResult<Hex1bWidget>(
ctx.WidgetMethod("example")
));
await app.RunAsync();\`
</script>
# WidgetName
Brief description of what the widget does.
## Basic Usage
<CodeBlock lang="csharp" :code="basicCode" command="dotnet run" example="widget-basic" exampleTitle="Widget - Basic Usage" />
## [Feature Section(s)]
Document widget-specific features with focused examples.
Store code snippets as external `.cs` files and import them with `?raw`:
```markdown
<script setup>
import featureSnippet from './snippets/widget-feature.cs?raw'
</script>
<StaticTerminalPreview svgPath="/svg/widget-feature.svg" :code="featureSnippet" />
##### Mirror Warning for Code Samples
When a documentation code sample mirrors a WebSocket example, add a warning comment to remind maintainers to keep them in sync:
```markdown
<!--
⚠️ MIRROR WARNING: This code sample mirrors the WebSocket example in:
src/Hex1b.Website/Examples/WidgetBasicExample.cs
Keep both files in sync when making changes.
-->Place this comment directly before the code block or <script setup> section.
For static previews with interactive cell inspection, use the Static Generator to create SVG and HTML files. These offer:
A template console application is provided at:
.github/skills/doc-writer/static-generator/
├── StaticGenerator.csproj # Project file (references Hex1b)
├── Program.cs # Template with GenerateSnapshot helper
└── README.md # Detailed usage instructionsIMPORTANT: Do NOT modify the template files directly. Always copy to a temporary location first.
Step 1: Create working directory inside workspace
mkdir -p .tmp-static-gen
cp .github/skills/doc-writer/static-generator/* .tmp-static-gen/Step 2: Fix the project reference path
The template uses a relative path for the original location. Update the project reference in .tmp-static-gen/StaticGenerator.csproj:
# Change the ProjectReference Include path from:
# Include="../../../../src/Hex1b/Hex1b.csproj"
# To:
# Include="../src/Hex1b/Hex1b.csproj"Step 3: Modify Program.cs in the working copy
Edit .tmp-static-gen/Program.cs and replace the contents of GenerateSnapshots() with your specific widget:
static async Task GenerateSnapshots(string outputDir)
{
// Example: Generate a text widget with wrapping
await GenerateSnapshot(outputDir, "text-wrap-demo", "Text Wrapping Demo", 50, 5,
ctx => ctx.VStack(v => [
v.Text(
"This long paragraph demonstrates how text wrapping works in Hex1b. " +
"When content exceeds the available width, it automatically breaks " +
"at word boundaries."
).Wrap()
]));
}Step 4: Run the generator
cd .tmp-static-gen
dotnet run -- outputStep 5: Verify the output
Check that the files were created:
ls -la output/
# Should contain: text-wrap-demo.svgStep 6: Copy to public assets
cp output/*.svg ../src/content/public/svg/Step 7: Clean up
cd ..
rm -rf .tmp-static-genStep 8: Use in documentation
Create a snippets folder alongside your markdown and add the code as a .cs file:
guide/widgets/
├── your-widget.md
└── snippets/
└── text-wrap-demo.csThen import and use it in your markdown:
<script setup>
import wrapSnippet from './snippets/text-wrap-demo.cs?raw'
</script>
<StaticTerminalPreview svgPath="/svg/text-wrap-demo.svg" :code="wrapSnippet" />await GenerateSnapshot(
outputDir, // Always use "output"
"filename", // Name without extension (creates .svg)
"Description", // For console output only
width, // Terminal columns
height, // Terminal rows
ctx => widget // Widget builder using RootContext
);The <StaticTerminalPreview> component displays code with an expandable "View output" panel. Clicking the chevron icon slides open a panel showing the rendered terminal output.
This component uses Shiki for syntax highlighting with line numbers, matching the styling of the main <CodeBlock> component.
Usage (recommended - external .cs files with ?raw import):
Store code snippets as external .cs files in a snippets/ folder alongside your markdown, then import them using Vite's ?raw suffix:
guide/widgets/
├── text.md
└── snippets/
├── text-truncate.cs
├── text-wrap.cs
└── text-ellipsis.cs<script setup>
import truncateSnippet from './snippets/text-truncate.cs?raw'
import wrapSnippet from './snippets/text-wrap.cs?raw'
import ellipsisSnippet from './snippets/text-ellipsis.cs?raw'
</script>
<StaticTerminalPreview svgPath="/svg/text-truncate.svg" :code="truncateSnippet" />Benefits of external files:
.cs files with proper syntax highlighting in your editorProps:
| Prop | Type | Default | Description |
|---|---|---|---|
svgPath | string | required | Path to .svg file relative to public folder |
code | string | (from slot) | Code to display (use with ?raw imports) |
language | string | "csharp" | Language for syntax highlighting |
Features:
Note: The component parses cell data directly from the SVG's DOM structure (using data-x, data-y attributes and element properties). No separate HTML file is needed.
| Option | Default | Description |
|---|---|---|
ShowCellGrid | false | Show grid lines between cells |
ShowPixelGrid | false | Show pixel-level grid |
DefaultBackground | #0f0f1a | Background color |
DefaultForeground | #e0e0e0 | Text color |
FontFamily | Cascadia Code stack | Monospace font |
FontSize | 14 | Font size in pixels |
CellWidth | 9 | Cell width in pixels |
CellHeight | 18 | Cell height in pixels |
IMPORTANT: Unless your code sample specifically demonstrates cursor/mouse behavior, disable the cursor in generated SVGs. A random cursor block appearing in documentation screenshots confuses readers.
The Hex1bTerminalSnapshot.ToSvg() method includes cursor position by default. To hide the cursor, cast to IHex1bTerminalRegion:
// Cast to IHex1bTerminalRegion to use the overload without cursor
var svg = ((IHex1bTerminalRegion)snapshot).ToSvg(svgOptions);The template's GenerateSnapshot function already uses this approach by default.
Only include the cursor when documenting cursor-related features (e.g., TextBox focus states, cursor shapes).
// Simple text
await GenerateSnapshot(outputDir, "text-simple", "Simple", 40, 3,
ctx => ctx.Text("Hello, World!"));
// Text with overflow
await GenerateSnapshot(outputDir, "text-ellipsis", "Ellipsis", 50, 3,
ctx => ctx.Text("Very long text here...").Ellipsis().FixedWidth(30));
// VStack layout
await GenerateSnapshot(outputDir, "layout-vstack", "VStack", 60, 10,
ctx => ctx.VStack(v => [
v.Text("Header"),
v.Text(""),
v.Text("Body content")
]));
// Border with content
await GenerateSnapshot(outputDir, "border-demo", "Border", 40, 6,
ctx => ctx.Border(b => [
b.Text("Content inside border")
], title: "Title"));Write XML docs as you write the code
<summary>, <param>, <returns>, <remarks><example> for non-obvious usageCreate or update end-user guides
guide/widgets/getting-started.md if appropriateCheck if documentation needs updates
Update affected documentation
Before considering documentation complete:
<summary> tags<see> and <seealso> tagsCRITICAL: Before completing documentation work, verify that the VitePress content build succeeds. This catches issues like dead links, missing files, or syntax errors before deployment.
Run the Aspire content build pipeline:
cd /path/to/hex1b
aspire do build-contentThis executes the deployment pipeline step that builds the static resources from the VitePress site. The build must succeed before documentation changes are complete.
Expected output on success:
✓ PIPELINE SUCCEEDEDIf the build fails, proceed to the diagnostic step below.
If aspire do build-content fails, run the underlying npm build command directly to see the detailed error message:
cd src/content
npm install # Ensure dependencies are installed
npm run buildThis is the step most likely to fail inside aspire do build-content. The npm build output provides detailed error messages explaining:
Common issues to fix:
snippets/ folders<script setup> sectionsIf you see an error like:
Found dead link /guide/widgets/nonexistent in file guide/widgets/mywidget.mdEither:
After fixing issues, re-run both verification commands to ensure the build succeeds.
❌ Don't repeat the member name in the summary
/// <summary>
/// ButtonWidget is a widget for buttons.
/// </summary>✅ Do describe what it does
/// <summary>
/// An interactive button that responds to Enter, Space, or mouse clicks.
/// </summary>❌ Don't use implementation details in public API docs
/// <summary>
/// Sets the internal _label field to the specified value.
/// </summary>✅ Do describe the effect
/// <summary>
/// Sets the text displayed on the button.
/// </summary>❌ Don't assume prior knowledge
Use reconciliation to update nodes efficiently.✅ Do explain concepts
When you call `SetState()`, Hex1b diffs the new widget tree against existing nodes
and updates only what changed. This reconciliation process preserves focus and scroll
state while keeping your UI responsive.❌ Don't use code snippets without context
.OnClick(_ => count++)✅ Do provide complete, runnable examples
var state = new CounterState();
var app = new Hex1bApp(ctx =>
ctx.Button("Increment").OnClick(_ => state.Count++)
);dotnet tool install -g xmldocmd)src/content/.vitepress/)Good documentation:
When in doubt, look at existing documentation in the repository and match its style, tone, and level of detail.
© mitchdenny, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 6 other files in .github/skills/doc-writer of mitchdenny/hex1b.
Open the folder on GitHubat commit e2335bd
Doc Writer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Doc Writer this skillmitchdenny/hex1b | 178 | — | ~8.7k | Automated safety check: Pass | MIT | |
| Technical Writerfinos/morphir | 213 | — | ~4.4k | Automated safety check: Pass | Apache-2.0 | |
| Diataxis Docs Writercalf-ai/calfkit-sdk | 149 | 1 repos | ~3k | Automated safety check: Pass | Apache-2.0 | |
| Create Skill Samplepnp/copilot-prompts | 892 | — | ~3.1k | Automated safety check: Pass | MIT | |
| Docsbrickbots/PiFinder | 250 | — | ~6.2k | Automated safety check: Pass | GPL-3.0 | |
| ScottPlot Cookbook RecipeScottPlot/ScottPlot | 6.8k | — | ~384 | Automated safety check: Pass | MIT |
finos/morphir
Assists with writing and maintaining Morphir technical documentation.
calf-ai/calfkit-sdk
Write or improve software documentation using the Diátaxis framework — four documentation types (tutorials, how-to guides, reference, explanation), each serving a different user need.
pnp/copilot-prompts
This skill should be used when the user asks to "create a new skill sample", "add a skill", "scaffold a new skill", "contribute a skill", "create a GitHub Copilot skill", "build a custom skill", or…
brickbots/PiFinder
Author and edit PiFinder's user-facing documentation in the project's house style.
ScottPlot/ScottPlot
Adds or extends a ScottPlot Cookbook recipe for a given plottable, in the right PlotTypes category and in the style of neighboring recipes.
streamlit/docs
Update the streamlit/docs repo for a new Streamlit release. An agent skill from streamlit/docs.
mitchdenny/hex1b
Guidelines for reviewing API design in the Hex1b codebase. An agent skill from mitchdenny/hex1b.
mitchdenny/hex1b
Guidelines for running and interpreting Surface API performance benchmarks.
mitchdenny/hex1b
Agent for validating Hex1b documentation against actual library behavior.
mitchdenny/hex1b
Agent for diagnosing and fixing flaky terminal UI tests in the Hex1b test suite.
mitchdenny/hex1b
Step-by-step guide for creating new widgets in the Hex1b TUI library.
mitchdenny/hex1b
Guidelines for writing unit tests in the Hex1b TUI library. An agent skill from mitchdenny/hex1b.
Works with
Categories
Guidelines for producing accurate and maintainable documentation for the Hex1b TUI library. Doc Writer is an agent skill from mitchdenny/hex1b. Guidelines for producing accurate and maintainable documentation for the Hex1b TUI library.
Doc Writer fits situations like: writing XML API documentation comments; creating end-user guides; updating existing documentation.
Run `npx skills add mitchdenny/hex1b --skill doc-writer -a claude-code`. Or copy the skill folder (.github/skills/doc-writer in mitchdenny/hex1b) into .claude/skills/doc-writer in your project. Claude Code loads it when a task matches its description.
Run `npx skills add mitchdenny/hex1b --skill doc-writer -a codex`. Or copy the skill folder (.github/skills/doc-writer in mitchdenny/hex1b) into .agents/skills/doc-writer in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add mitchdenny/hex1b --skill doc-writer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/doc-writer, .gemini/skills/doc-writer, .github/skills/doc-writer and .opencode/skills/doc-writer in your project.
Going by SKILL.md and its folder, Doc Writer needs C# for the scripts in its folder and the command-line tools its instructions call (dotnet and npm).
SKILL.md names 2 domains. As links in the text: learn.microsoft.com and vitepress.dev. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Doc Writer is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.7k tokens (SKILL.md is roughly 35k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Doc Writer: Technical Writer (finos/morphir, 213 stars), Diataxis Docs Writer (calf-ai/calfkit-sdk, 149 stars), Create Skill Sample (pnp/copilot-prompts, 892 stars) and Docs (brickbots/PiFinder, 250 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
mitchdenny (a GitHub user) maintains it in mitchdenny/hex1b, which has 178 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on October 9, 2026.
Source: mitchdenny/hex1b on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.