sep
Sep is a high-performance .NET library for parsing and writing delimited-value files with minimal memory allocation and explicit control over separator inference, escaping, and header behavior. Use it when processing large datasets in ML, ETL, or analytics pipelines where startup time and garbage collection pressure are critical concerns, or when you need fine-grained control over CSV/TSV parsing options and AOT compatibility.
git clone --depth 1 https://github.com/managedcode/dotnet-skills /tmp/sep && cp -r /tmp/sep/catalog/Libraries/Sep/skills/sep ~/.claude/skills/sepSKILL.md
# Sep for .NET separated values
## Trigger On
- delimited data needs are performance-sensitive and allocation-aware
- project needs explicit control over separator inference, escaping, trimming, and header behavior
- reading/writing large or long-lived file pipelines in ML, ETL, or analytics workloads
- startup/perf tests require AOT/trimming-friendly CSV/TSV processing
## Install
- NuGet:
- `dotnet add package Sep`
- `dotnet add package Sep --version <version>`
- XML package reference:
- `<PackageReference Include="Sep" Version="x.y.z" />`
- Verify baseline support by checking the package page:
- [NuGet: Sep](https://www.nuget.org/packages/Sep/)
- Source:
- [GitHub: nietras/Sep](https://github.com/nietras/Sep)
## Workflow
```mermaid
flowchart LR
A[Input source: file/text/stream] --> B[Sep.Reader or Sep.New(...).Reader]
B --> C[SepReaderOptions]
C --> D[Rows -> Cols -> Span/Parse]
D --> E[Transform and validate]
E --> F[SepWriter via SepWriterOptions]
F --> G[To file/text output]
```
1. Decide schema shape
- header present or no header
- separator known (`;`, `,`, tab, custom) or infer from first row
- row/column quoting rules
2. Build reader with `Sep.Reader(...)` and explicit options only where needed:
- `Sep.Reader()` for inferred separator from header-like first row
- `Sep.New(',').Reader(...)` for explicit separator mode
- `Sep.Reader(o => o with { HasHeader = false })` if header is absent
3. Read rows and map columns as `ReadOnlySpan<char>` first, convert only when needed.
4. For output, use `reader.Spec.Writer()` when you need the same separator/culture as input.
5. Control writer behavior with `Sep.Writer(...)` and `SepWriterOptions` (`WriteHeader`, `Escape`, `DisableColCountCheck`).
6. Add async only where it brings value and your runtime is C# 13 / .NET 9+ for `await foreach` over async reader rows.
7. Use `ParallelEnumerate` for CPU-heavy transformations only after benchmarking single-threaded baseline.
### Install and read patterns
```csharp
using var reader = Sep.Reader(o => o with
{
HasHeader = true,
Unescape = true,
Trim = SepTrim.Both
}).FromText(data);
foreach (var row in reader)
{
var id = row["Id"].Parse<int>();
var name = row[1].ToString();
// process row
}
```
### Write patterns
```csharp
using var reader = Sep.Reader().FromFile("input.csv");
using var writer = reader.Spec.Writer().ToFile("output.csv");
foreach (var row in reader)
{
using var writeRow = writer.NewRow(row);
writeRow["Amount"].Format(row["Amount"].Parse<double>() * 1.2);
}
```
### Async reading and writing
```csharp
var text = "A;B\n1;hello\n";
using var reader = await Sep.Reader().FromTextAsync(text);
await using var writer = reader.Spec.Writer().ToText();
await foreach (var row in reader)
{
await using var writeRow = writer.NewRow(row);
var normalized = row["B"].ToString().ToUpperInvariant();
writeRow["B"].Set(normalized);
}
```
### Common configuration patterns
- Header-driven read
- default `HasHeader = true`
- query by name: `row["ColName"]`
- Headerless pipelines
- `HasHeader = false`
- use index-based access: `row[0]`, `row[1]`
- Round-trip output
- start writer with `reader.Spec.Writer()` to preserve inference and formatting contract
- Speed-first processing
- keep default buffer + culture unless profiling proves a need to tune
## Best practices
- Parse to primitive types with `Parse<T>` in hot paths to avoid extra allocations.
- Keep `ToString`/format conversions at the edge (presentational layers), not in inner loops.
- Prefer `Unescape`, `Trim`, and `DisableQuotesParsing` settings deliberately and test with realistic samples.
- For large transforms, isolate heavy CPU work after enumeration and then apply `ParallelEnumerate` where appropriate.
## Limitations to check before production
- `SepReader.Row` and `SepWriter.Row` are `ref struct`s:
- avoid patterns that store rows beyond immediate scope
- materialize if you truly need random async/LINQ-style buffering
- `SepReader` row iteration is row-by-row by design; it is intentionally not the same as a classic collection model.
## Deliver
- installation and usage guide that is ready to copy into a .NET repo
- practical reader/writer configuration patterns
- clear notes on defaults, tradeoffs, and constraints
## Validate
- `dotnet add package Sep` installs correctly and project compiles
- one file-read sample and one file-write sample execute successfully
- header/no-header and explicit-separator cases are covered
- at least one validation sample for quoting/unescaping or async path exists if required by task
## Load References
- [references/overview.md](references/overview.md) - official links and practical decision notes.Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration, hosting, or deployment behavior; deciding between ASP.NET Core sub-stacks. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Build, upgrade, and operate .NET Aspire 13.3.x application hosts with current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, and Azure deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*, DistributedApplication.CreateBuilder, WithReference, WaitFor, AddProject, AddRedis, AddPostgres, aspire run, aspire init, aspire. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable Functions, bindings, or host configuration. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or Auto render modes; designing component hierarchies and state. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is not the right next step. USE FOR: EF6 codebases; runtime versus ORM migration decisions; EDMX, code-first, ObjectContext, and legacy data-access review. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and EF6 migration decisions. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Build, review, or migrate .NET MAUI applications across Android, iOS, macOS, and Windows with correct cross-platform UI, platform integration, and native packaging assumptions. USE FOR: working on cross-platform mobile or desktop UI in .NET MAUI; integrating device capabilities, navigation, or platform-specific code; migrating Xamarin.Forms or aligning. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.
Use ML.NET to train, evaluate, or integrate machine-learning models into .NET applications with realistic data preparation, inference, and deployment expectations. USE FOR: ML.NET integration; local model training or retraining; inference pipelines, model loading, evaluation, and deployment review. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.