/fsharp
Write, review, or modernize F# code in .NET repositories with functional-first design, algebraic data types, pattern matching, pipelines, async workflows, project ordering, and C# interop. USE FOR: F# .fs/.fsproj code; discriminated unions, records, options, results, pattern
$ npx -y skills add managedcode/dotnet-skills --skill fsharp --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/fsharp
Context preview
The summary Claude sees to decide when to auto-load this skill.
Write, review, or modernize F# code in .NET repositories with functional-first design, algebraic data types, pattern matching, pipelines, async workflows, project ordering, and C# interop. USE FOR: F# .fs/.fsproj code; discriminated unions, records, options, results, pattern
SKILL.md
fsharp.SKILL.mdname: fsharp
description: "Write, review, or modernize F# code in .NET repositories with functional-first design, algebraic data types, pattern matching, pipelines, async workflows, project ordering, and C# interop. USE FOR: F# .fs/.fsproj code; discriminated unions, records, options, results, pattern matching, computation expressions, or functional domain modeling; strongly typed AI-generated .NET code. DO NOT USE FOR: C# language modernization; FSI-only exploratory scripts with no project changes. INVOKES: inspect .fsproj file order and SDK settings, edit F# source and project files, and run dotnet build/test or dotnet fsi validation commands when changes are made."
compatibility: "Requires a .NET SDK with F# support and an F# project, script, or interop boundary."
F# for .NET
Trigger On
- the task touches `.fs`, `.fsx`, `.fsi`, or `.fsproj` files
- domain logic benefits from records, discriminated unions, options, results, or exhaustive pattern matching
- generated code needs a strongly typed functional model instead of nullable primitive state
- F# code must interoperate with C# or other .NET libraries
- the repository needs project setup, source ordering, or validation for F# code
Do Not Use For
- C# language feature selection; use `modern-csharp`
- analyzer-only, formatter-only, or CI-only work with no F# language decisions
- one-off REPL or scripting exploration that does not affect project code; use `fsi`
- non-.NET functional languages
Project Setup
Use the .NET SDK templates when adding F# projects.
dotnet new classlib -lang "F#" -o src/Domain
dotnet new console -lang "F#" -o src/App
dotnet new xunit -lang "F#" -o tests/Domain.Tests
dotnet sln add src/Domain/Domain.fsproj tests/Domain.Tests/Domain.Tests.fsproj
dotnet add tests/Domain.Tests/Domain.Tests.fsproj reference src/Domain/Domain.fsproj
dotnet build
`FSharp.Core` is normally supplied by the F# SDK project. Add or pin it explicitly only when the repo has a package policy that requires deterministic package versions.
dotnet add src/Domain/Domain.fsproj package FSharp.Core
Source Ordering
F# compiles files in the order listed in the project file. Define types and modules before files that consume them.
<ItemGroup>
<Compile Include="Domain.fs" />
<Compile Include="Validation.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
When adding a file, update the `.fsproj` intentionally. Do not assume wildcard ordering.
Workflow
1. Inspect the existing `.fsproj`, `.fs`, `.fsi`, and `.fsx` files to determine compile order, public boundaries, and whether the code is F#-first or C#-facing. 2. Choose the smallest F# model that represents the invariant: records for named product data, discriminated unions for closed state, `option` for absence, and `Result` for expected failures. 3. Add or edit source files in dependency order, then update the `.fsproj` compile list before consumers reference the new code. 4. Review public API shape for .NET interop. Translate F#-specific internal models to DTOs, methods, or `Try*` patterns when C# callers need a stable surface. 5. Run `dotnet build`, targeted tests, and any relevant `dotnet fsi` probes before returning the final result.
Current Upstream Notes
- The July 2026 F# overview refresh continues to emphasize functional-first programming on .NET with records, discriminated unions, pattern matching, units of measure, type providers, and interop. Keep F# guidance domain-model oriented rather than translating C# object patterns mechanically.
- Use `fsi` for exploratory scripts, but move durable code into ordered `.fsproj` files before it becomes production behavior.
Practical Patterns
Model State With Records And Unions
Prefer a type that names every valid state over loose strings, nullable values, or parallel booleans.
module Orders
type OrderId = private OrderId of string
module OrderId =
let tryCreate value =
if System.String.IsNullOrWhiteSpace value then
Error "Order id is required."
else
Ok (OrderId value)
type Payment =
| Card of last4: string
| Wire of iban: string
| PurchaseOrder of number: string
type Order =
{ Id: OrderId
Customer: string
Payment: Payment }
let describePayment payment =
match payment with
| Card last4 -> $"card ending {last4}"
| Wire iban -> $"wire transfer {iban}"
| PurchaseOrder number -> $"purchase order {number}"Compose Validation With Result
Return `Result<'T,'Error>` when callers must handle failure and when failures are part of the domain.
module Pricing
type Price =
private
| Price of decimal
module Price =
let tryCreate amount =
if amount < 0m then
Error "Price cannot be negative."
else
Ok (Price amount)
let value (Price amount) = amount
type Line =
{ Sku: string
Quantity: int
UnitPrice: Price }
let tryCreateLine sku quantity amount =
match Price.tryCreate amount with
| Ok price when quantity > 0 ->
Ok { Sku = sku; Quantity = quantity; UnitPrice = price }
| Ok _ ->
Error "Quantity must be positive."
| Error message ->
Error messageRead And Transform Data
Use pipelines for readable transformations, but stop before the pipeline hides error handling or allocation cost.
open System.IO
let readActiveUsers path =
File.ReadLines path
|> Seq.skip 1
|> Seq.choose (fun line ->
match line.Split(',') with
| [| id; name; "active" |] -> Some {| Id = id; Name = name |}
| _ -> None)
|> Seq.toListWrite A Small .NET Boundary
Make public interop APIs easy for C# callers. Hide F#-specific details behind functions, methods, or DTO records when needed.
namespace Company.Domain
type InvoiceDto =
{ Id: string
Total: decimal
IsPaid: bool }
module InvoRead more
name: fsharp description: "Write, review, or modernize F# code in .NET repositories with functional-first design, algebraic data types, pattern matching, pipelines, async workflows, project ordering, and C# interop. USE FOR: F# .fs/.fsproj code; discriminated unions, records, options, results, pattern matching, computation expressions, or functional domain modeling; strongly typed AI-generated .NET code. DO NOT USE FOR: C# language modernization; FSI-only exploratory scripts with no project changes. INVOKES: inspect .fsproj file order and SDK settings, edit F# source and project files, and run dotnet build/test or dotnet fsi validation commands when changes are made." compatibility: "Requires a .NET SDK with F# support and an F# project, script, or interop boundary."
F# for .NET
Trigger On
- the task touches `.fs`, `.fsx`, `.fsi`, or `.fsproj` files
- domain logic benefits from records, discriminated unions, options, results, or exhaustive pattern matching
- generated code needs a strongly typed functional model instead of nullable primitive state
- F# code must interoperate with C# or other .NET libraries
- the repository needs project setup, source ordering, or validation for F# code
Do Not Use For
- C# language feature selection; use `modern-csharp`
- analyzer-only, formatter-only, or CI-only work with no F# language decisions
- one-off REPL or scripting exploration that does not affect project code; use `fsi`
- non-.NET functional languages
Project Setup
Use the .NET SDK templates when adding F# projects.
dotnet new classlib -lang "F#" -o src/Domain dotnet new console -lang "F#" -o src/App dotnet new xunit -lang "F#" -o tests/Domain.Tests dotnet sln add src/Domain/Domain.fsproj tests/Domain.Tests/Domain.Tests.fsproj dotnet add tests/Domain.Tests/Domain.Tests.fsproj reference src/Domain/Domain.fsproj dotnet build
`FSharp.Core` is normally supplied by the F# SDK project. Add or pin it explicitly only when the repo has a package policy that requires deterministic package versions.
dotnet add src/Domain/Domain.fsproj package FSharp.Core
Source Ordering
F# compiles files in the order listed in the project file. Define types and modules before files that consume them.
<ItemGroup> <Compile Include="Domain.fs" /> <Compile Include="Validation.fs" /> <Compile Include="Program.fs" /> </ItemGroup>
When adding a file, update the `.fsproj` intentionally. Do not assume wildcard ordering.
Workflow
1. Inspect the existing `.fsproj`, `.fs`, `.fsi`, and `.fsx` files to determine compile order, public boundaries, and whether the code is F#-first or C#-facing. 2. Choose the smallest F# model that represents the invariant: records for named product data, discriminated unions for closed state, `option` for absence, and `Result` for expected failures. 3. Add or edit source files in dependency order, then update the `.fsproj` compile list before consumers reference the new code. 4. Review public API shape for .NET interop. Translate F#-specific internal models to DTOs, methods, or `Try*` patterns when C# callers need a stable surface. 5. Run `dotnet build`, targeted tests, and any relevant `dotnet fsi` probes before returning the final result.
Current Upstream Notes
- The July 2026 F# overview refresh continues to emphasize functional-first programming on .NET with records, discriminated unions, pattern matching, units of measure, type providers, and interop. Keep F# guidance domain-model oriented rather than translating C# object patterns mechanically.
- Use `fsi` for exploratory scripts, but move durable code into ordered `.fsproj` files before it becomes production behavior.
Practical Patterns
Model State With Records And Unions
Prefer a type that names every valid state over loose strings, nullable values, or parallel booleans.
module Orders
type OrderId = private OrderId of string
module OrderId =
let tryCreate value =
if System.String.IsNullOrWhiteSpace value then
Error "Order id is required."
else
Ok (OrderId value)
type Payment =
| Card of last4: string
| Wire of iban: string
| PurchaseOrder of number: string
type Order =
{ Id: OrderId
Customer: string
Payment: Payment }
let describePayment payment =
match payment with
| Card last4 -> $"card ending {last4}"
| Wire iban -> $"wire transfer {iban}"
| PurchaseOrder number -> $"purchase order {number}"Compose Validation With Result
Return `Result<'T,'Error>` when callers must handle failure and when failures are part of the domain.
module Pricing
type Price =
private
| Price of decimal
module Price =
let tryCreate amount =
if amount < 0m then
Error "Price cannot be negative."
else
Ok (Price amount)
let value (Price amount) = amount
type Line =
{ Sku: string
Quantity: int
UnitPrice: Price }
let tryCreateLine sku quantity amount =
match Price.tryCreate amount with
| Ok price when quantity > 0 ->
Ok { Sku = sku; Quantity = quantity; UnitPrice = price }
| Ok _ ->
Error "Quantity must be positive."
| Error message ->
Error messageRead And Transform Data
Use pipelines for readable transformations, but stop before the pipeline hides error handling or allocation cost.
open System.IO
let readActiveUsers path =
File.ReadLines path
|> Seq.skip 1
|> Seq.choose (fun line ->
match line.Split(',') with
| [| id; name; "active" |] -> Some {| Id = id; Name = name |}
| _ -> None)
|> Seq.toListWrite A Small .NET Boundary
Make public interop APIs easy for C# callers. Hide F#-specific details behind functions, methods, or DTO records when needed.
namespace Company.Domain
type InvoiceDto =
{ Id: string
Total: decimal
IsPaid: bool }
module InvoStop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other skills on dotnet-skills.
- /aspnet-core
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,
Open skill - /aspire
Build, upgrade, and operate Aspire 13.4.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, MCP, and deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*,
Open skill - /azure-functions
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
Open skill - /blazor
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
Open skill - /entity-framework6
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
Open skill - /entity-framework-core
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
Open skill

