Epsitec.Tool.Format
0.9.3.2624
Prefix Reserved
dotnet tool install --global Epsitec.Tool.Format --version 0.9.3.2624
dotnet new tool-manifest
dotnet tool install --local Epsitec.Tool.Format --version 0.9.3.2624
#tool dotnet:?package=Epsitec.Tool.Format&version=0.9.3.2624
nuke :add-package Epsitec.Tool.Format --version 0.9.3.2624
author: Pierre Arnaud maintainer: Pierre Arnaud tags:
- technical
Epsitec Source Format Tool
epsitec-format is a dotnet tool that reformats C# source text according to
advanced, line-based rules. It is a faithful port of the Python scripts in
briefcases/_tools (check_comment_truncation.py, fix_cs_indentation.py,
check_initializer_indent.py), validated against a checked-in golden oracle.
The tool is purely line/text based (regex plus greedy word wrapping). It does not
use Roslyn syntax trees, semantic analysis, or MSBuild, so it starts fast and has
a minimal dependency surface. It is intentionally not part of the
Symbolic.* family.
Installation
dotnet pack build-tools/Tool.Format/Tool.Format.csproj
dotnet tool install --global --add-source build-tools/Tool.Format/.nupkg epsitec-format
To uninstall:
dotnet tool uninstall --global epsitec-format
Publishing
Run zou-nuget.ps1 (beside this README) to pack the tool in Release and
optionally publish it to nuget.org:
build-tools/Tool.Format/zou-nuget.ps1
It packs Tool.Format.csproj (a PackAsTool project) to
build-tools/Tool.Format/.nupkg/, prints the resulting Epsitec.Tool.Format
package (the dotnet tool exposing the epsitec-format command), and prompts
before pushing with dotnet nuget push (API key from $env:NUGET_API_KEY). It
mirrors the zou-nuget.ps1 scripts used by the other Epsitec NuGet packages.
Usage
epsitec-format [<targets>...]
[--fix]
[--rules comments,indent,initializers]
[--max-columns <N>]
[--json]
Options
<targets>— zero or more files, directories, or glob patterns (*,**). Defaults to the current directory (.). Directories are scanned recursively for*.cs; thebin,obj, and.gitdirectories are skipped. Glob expansion usesMicrosoft.Extensions.FileSystemGlobbing.--fix— apply fixable rules in place. Absent means check mode (no writes).--rules— comma-separated subset ofcomments,indent,initializers. Matching is case-insensitive; duplicates are collapsed preserving first-seen order. Absent means all three in canonical order. An unknown token, or an empty value, is an input error.--max-columns— positive integer wrap width. Defaults to79. Affects comment prose reflow only; separator normalization always targets 79 columns.--json— emit the structured JSON report on stdout. Absent means a human-readable summary.
Examples
Check the current directory and print a human summary:
epsitec-format .
Emit the JSON report for one project:
epsitec-format MyProject --json
Apply fixes in place across a glob, then re-check (idempotent):
epsitec-format "MyProject/**/*.cs" --fix
epsitec-format "MyProject/**/*.cs"
Rule catalog
comments
Reflows contiguous // and /// comment prose runs so each line is as full as
possible without exceeding the configured width, and normalizes
/*****…*****/ separator lines to exactly 79 visual columns. Produces two issue
kinds: comment_prose_reflow and separator_reflow.
The following comment shapes are deliberately preserved (never reflowed):
- the file's first-line copyright block (the topmost block starting at line 1);
- any block containing an XML
<code> … </code>snippet; - ASCII-table and drawing blocks (aligned columns, rulers, spacious layouts);
- JSON-style comment snippets delimited by
{ … }; - standalone and inline XML-doc element lines (
/// <summary>,/// <param …>…</param>); // var …code-like comment lines;- decorative separators, bare labels, list markers, AAA markers (
// Arrange), headers (Copyright,Author:), and lines containing a URL; - oversized lines whose final token is an XML element (optionally followed by
.or,) or that end with;.
In addition, reflows are suppressed when they are negligible (every break column
moves by 4 columns or less) or when every existing line already fits within the
configured width plus a 10-column relaxed margin. Files whose first line contains
<auto-generated are skipped entirely.
indent
Replaces tab-based leading indentation with spaces, using a tab width of 4
(next-multiple-of-4 tab stops). Only the leading whitespace run is expanded; tabs
elsewhere on the line are left untouched. Each changed line is one
tab_indentation issue.
initializers
Reports object-initializer braces indented deeper than their owning
var … = new … line. Report-only: these issues are never auto-fixed, even
with --fix. Each issue is one initializer_indent finding carrying a
brace indent N, expected M detail. Gate CI on these with check mode.
Exit codes
| Exit code | Meaning |
|---|---|
0 |
Check mode with zero issues, or a fix run that completed (including the no-change case). |
1 |
Check mode only: at least one issue was found (nothing was written). The CI lint-gate signal. |
2 |
Bad usage, unknown or empty --rules, non-positive --max-columns, or a literal target path that does not exist. A glob or directory matching zero .cs files is not an error (exits 0). |
3 |
A fix-time safety check failed (file changed under the tool) or a read/write error occurred. |
In fix mode, report-only initializers issues do not affect the exit code: a fix
run that surfaces unfixable initializer issues still exits 0. Gate CI on those
with check mode, which returns 1.
JSON report schema
--json emits a single UTF-8 JSON object on stdout with stable camelCase fields:
{
"root": "<absolute run root>",
"targets": ["..."],
"maxColumns": 79,
"fixMode": false,
"rules": ["comments", "indent", "initializers"],
"matchedFileCount": 0,
"matchedFiles": ["..."],
"issueCount": 0,
"fixedIssueCount": 0,
"modifiedFiles": ["..."],
"issues": [
{
"rule": "comments",
"kind": "comment_prose_reflow",
"file": "Path/To/File.cs",
"startLine": 12,
"endLine": 14,
"originalLines": ["..."],
"proposedLines": ["..."],
"fixable": true,
"fixed": false,
"detail": null
}
]
}
detail is always present (serialized as JSON null when there is no note).
originalLines and proposedLines are always arrays (single-element for
separator_reflow). Integer fields are culture-invariant.
I/O contract
- Read: files are decoded as UTF-8 (a leading BOM is tolerated and
remembered). Lines are split on
\n, with a trailing\rtreated as part of the terminator, so both CRLF and LF split cleanly. - Write (only files the tool rewrites): UTF-8 without BOM, lines joined
with
\n(LF), and exactly one trailing\n. This matches.editorconfig(end_of_line = lf,charset = utf-8,insert_final_newline = true) and the Python reference. - Replacement lines never carry trailing whitespace. The tool does not trim trailing whitespace on lines it does not otherwise rewrite, and files with no applied fix are left byte-identical.
Relationship to the Python reference
The three rules are a faithful, line-based port of the briefcases/_tools Python
scripts. The comments rule is validated by a golden-oracle parity test that
compares the C# output against reference output captured from
check_comment_truncation.py over a checked-in corpus. Where this document and
the scripts disagree on a fine-grained detail, the scripts (and the golden
oracle) are authoritative.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.9.3.2624 | 112 | 6/21/2026 |