diff --git a/plugins/dotnet11/README.md b/plugins/dotnet11/README.md
index 7a85a71559..b706f171e1 100644
--- a/plugins/dotnet11/README.md
+++ b/plugins/dotnet11/README.md
@@ -4,4 +4,5 @@ Skills focused on new APIs and language features introduced in .NET 11.
## Skills
+- process-api-net11
- system-text-json-net11
diff --git a/plugins/dotnet11/skills/process-api-net11/SKILL.md b/plugins/dotnet11/skills/process-api-net11/SKILL.md
new file mode 100644
index 0000000000..891285a6ec
--- /dev/null
+++ b/plugins/dotnet11/skills/process-api-net11/SKILL.md
@@ -0,0 +1,179 @@
+---
+name: process-api-net11
+description: >
+ Provides guidance on the new System.Diagnostics.Process APIs introduced in .NET 11.
+ It covers high-level convenience methods (Process.Run, Process.RunAndCaptureText, Process.StartAndForget),
+ reliable deadlock-free output reading (Process.ReadAllText/Bytes/Lines), and lifecycle/handle management
+ (KillOnParentExit, InheritedHandles, StartDetached).
+ Use when starting, orchestrating, or capturing output from external processes in .NET 11 applications.
+license: MIT
+---
+
+# Process API Improvements — .NET 11
+
+New APIs added to `System.Diagnostics.Process` in .NET 11 simplify process management, eliminate boilerplate, and prevent common deadlock patterns when capturing output.
+
+## When to Use
+
+- Running or orchestrating external processes in a .NET 11 (or later) project.
+- Needing to start a process, wait for it to exit, and capture its output/error streams without risking deadlocks (`Process.RunAndCaptureTextAsync`).
+- Wanting to ensure child processes are automatically terminated when the parent process exits (`KillOnParentExit`).
+- Requiring trimmer-friendly and NativeAOT-compatible process creation via `SafeProcessHandle`.
+- Requiring fine-grained control over handle inheritance (`InheritedHandles`) or starting detached processes (`StartDetached`).
+
+## When Not to Use
+
+- The project targets .NET 10 or earlier — these APIs are not available before .NET 11.
+- Running simple shells where custom execution code is unnecessary.
+- The default `Process.Start()` is sufficient and does not require output capturing or advanced lifecycle rules.
+
+## Target Framework
+
+```xml
+net11.0
+```
+
+## New APIs & Convenience Methods
+
+### High-Level Convenience APIs (Static Methods)
+
+#### `Process.Run` / `Process.RunAsync`
+Starts a process and waits for it to exit, returning the exit status. Does not capture standard output or error.
+```csharp
+public static ProcessExitStatus Run(string fileName, IList? arguments = null, bool silent = false, TimeSpan? timeout = null)
+public static Task RunAsync(string fileName, IList? arguments = null, bool silent = false, CancellationToken cancellationToken = default)
+public static ProcessExitStatus Run(ProcessStartInfo startInfo, TimeSpan? timeout = null)
+public static Task RunAsync(ProcessStartInfo startInfo, CancellationToken cancellationToken = default)
+```
+
+#### `Process.RunAndCaptureText` / `Process.RunAndCaptureTextAsync`
+Starts a process, captures both standard output and error, and waits for it to exit. Extremely useful for avoiding deadlocks on stream redirection.
+```csharp
+public static ProcessTextOutput RunAndCaptureText(string fileName, IList? arguments = null, TimeSpan? timeout = null)
+public static Task RunAndCaptureTextAsync(string fileName, IList? arguments = null, CancellationToken cancellationToken = default)
+public static ProcessTextOutput RunAndCaptureText(ProcessStartInfo startInfo, TimeSpan? timeout = null)
+public static Task RunAndCaptureTextAsync(ProcessStartInfo startInfo, CancellationToken cancellationToken = default)
+```
+
+#### `Process.StartAndForget`
+Launches a process and immediately releases the system handle resources, returning only the process ID (PID).
+```csharp
+public static int StartAndForget(string fileName, IList? arguments = null)
+public static int StartAndForget(ProcessStartInfo startInfo)
+```
+
+### Reliable Output Reading APIs (Instance Methods)
+These methods are called on a `Process` instance to directly read stdout and stderr, guaranteeing no OS pipe buffer overflow deadlocks.
+
+```csharp
+public (string StandardOutput, string StandardError) ReadAllText(TimeSpan? timeout = null)
+public Task<(string StandardOutput, string StandardError)> ReadAllTextAsync(CancellationToken cancellationToken = default)
+public (byte[] StandardOutput, byte[] StandardError) ReadAllBytes(TimeSpan? timeout = null)
+public Task<(byte[] StandardOutput, byte[] StandardError)> ReadAllBytesAsync(CancellationToken cancellationToken = default)
+public IEnumerable ReadAllLines(TimeSpan? timeout = null)
+public IAsyncEnumerable ReadAllLinesAsync(CancellationToken cancellationToken = default)
+```
+*Note: `ProcessOutputLine` is a readonly struct containing `string Content` and `bool StandardError` properties.*
+
+### ProcessStartInfo Properties
+
+#### `KillOnParentExit`
+Ensures that the spawned child process is terminated when the current (parent) process exits. Works across both Windows and Unix platforms.
+```csharp
+public bool KillOnParentExit { get; set; }
+```
+
+#### `InheritedHandles`
+Provides precise control over which file/kernel handles are inherited by the child process, preventing accidental resource leaks.
+```csharp
+public IList? InheritedHandles { get; set; }
+```
+
+#### `StartDetached`
+Starts the process detached from the parent's terminal or job session, ensuring it survives the parent's exit.
+```csharp
+public bool StartDetached { get; set; }
+```
+
+---
+
+## Examples
+
+### 1. One-Line Run and Capture Output
+
+Run a process and safely read all output text without stream deadlock risks:
+
+```csharp
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+// Run 'git status' and capture output (arguments passed as list)
+ProcessTextOutput result = await Process.RunAndCaptureTextAsync("git", ["status"]);
+
+if (result.ExitStatus.ExitCode == 0)
+{
+ Console.WriteLine($"Git Output: {result.StandardOutput.Trim()}");
+}
+else
+{
+ Console.WriteLine($"Failed with exit code: {result.ExitStatus.ExitCode}");
+ Console.WriteLine($"Error: {result.StandardError}");
+}
+```
+
+### 2. Auto-Killing Child Processes on Parent Exit
+
+Ensure a long-running background worker process is killed when the main application terminates:
+
+```csharp
+using System.Diagnostics;
+
+var startInfo = new ProcessStartInfo("dotnet", ["run", "--project", "BackgroundWorker.csproj"])
+{
+ KillOnParentExit = true // Auto-teardown when this parent process exits
+};
+
+using var process = Process.Start(startInfo);
+// The background worker is now tied to this process's lifecycle
+```
+
+### 3. Read All Lines From Output
+
+Start a process and read its output lines safely:
+
+```csharp
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+var startInfo = new ProcessStartInfo("ping", ["127.0.0.1"])
+{
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+};
+
+using var process = Process.Start(startInfo);
+if (process != null)
+{
+ // Read all output lines safely and asynchronously
+ await foreach (ProcessOutputLine line in process.ReadAllLinesAsync())
+ {
+ string prefix = line.StandardError ? "[Err]" : "[Out]";
+ Console.WriteLine($"{prefix} > {line.Content}");
+ }
+}
+```
+
+### 4. Start and Forget (Fire & Forget)
+
+Launch a helper tool or browser without holding onto system handle structures:
+
+```csharp
+using System;
+using System.Diagnostics;
+
+// Fire and forget, getting back only the process ID
+int pid = Process.StartAndForget("notepad.exe");
+Console.WriteLine($"Notepad started with PID: {pid}");
+```
diff --git a/tests/dotnet11/process-api-net11/eval.yaml b/tests/dotnet11/process-api-net11/eval.yaml
new file mode 100644
index 0000000000..1791924c10
--- /dev/null
+++ b/tests/dotnet11/process-api-net11/eval.yaml
@@ -0,0 +1,140 @@
+scenarios:
+ # --- Scenario 1: Run and capture output in .NET 11 ---
+ - name: "Run and capture process output in .NET 11"
+ prompt: |
+ I'm writing a .NET 11 command-line tool that needs to run an external CLI (e.g. 'git status') and capture both stdout and stderr.
+ I want to make sure I don't run into any OS pipe deadlock issues, and I want to write it in the cleanest way possible using new .NET 11 features.
+ Show me the C# program and the `.csproj` XML targeting `net11.0` for this tool. Print both in your response.
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "Process\\.RunAndCaptureText(Async)?"
+ - type: "output_matches"
+ pattern: "net11\\.0"
+ # The prompt asks for BOTH stdout AND stderr — require both members.
+ - type: "output_matches"
+ pattern: "\\.StandardOutput\\b"
+ - type: "output_matches"
+ pattern: "\\.StandardError\\b"
+ - type: "output_not_matches"
+ pattern: "RedirectStandardOutput\\s*=\\s*true"
+ - type: "output_not_matches"
+ pattern: "BeginOutputReadLine|OutputDataReceived"
+ rubric:
+ - "Uses the new built-in Process.RunAndCaptureText or Process.RunAndCaptureTextAsync static method"
+ - "Targets net11.0 in the project file"
+ - "Avoids manual redirection setup boilerplate (like RedirectStandardOutput = true, BeginOutputReadLine, etc.)"
+ timeout: 180
+
+ # --- Scenario 2: Auto-teardown child processes on parent exit ---
+ - name: "Auto-teardown child processes on parent exit in .NET 11"
+ prompt: |
+ In a .NET 11 application, I need to spawn a background daemon process.
+ To prevent orphan processes, I want to ensure that this daemon process is automatically killed by the operating system if my main parent process crashes or exits.
+ How do I configure this in .NET 11 using ProcessStartInfo? Show me a minimal example, and show the `.csproj` XML targeting `net11.0` in your response.
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "KillOnParentExit\\s*=\\s*true"
+ - type: "output_matches"
+ pattern: "net11\\.0"
+ rubric:
+ - "Uses the new KillOnParentExit property on ProcessStartInfo set to true"
+ - "Targets net11.0"
+ timeout: 180
+
+ # --- Scenario 3: deadlock-free full read via instance ReadAllText (tuple return) ---
+ - name: "Deadlock-free full-output read via instance ReadAllText in .NET 11"
+ prompt: |
+ In a .NET 11 app I start a child process myself with `Process.Start(...)` because I
+ need to configure `ProcessStartInfo` first. After it starts I want to read its ENTIRE
+ standard output AND standard error to completion, without the classic deadlock where
+ one buffer fills while I'm draining the other. Give me the simplest first-party .NET 11
+ way to get both back at once. Show a minimal program and the `net11.0` `.csproj`.
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "net11\\.0"
+ - type: "output_matches"
+ pattern: "ReadAllText(Async)?\\s*\\("
+ # Correct: destructure the (StandardOutput, StandardError) tuple (sync or async form).
+ - type: "output_matches"
+ pattern: "\\)\\s*=\\s*(await\\s+)?\\w+\\.ReadAllText(Async)?\\s*\\("
+ # Wrong: assigning the tuple-returning call to a single string.
+ - type: "output_not_matches"
+ pattern: "string\\s+\\w+\\s*=\\s*(await\\s+)?\\w+\\.ReadAllText(Async)?\\s*\\("
+ rubric:
+ - "Uses the new instance method Process.ReadAllText/ReadAllTextAsync"
+ - "Destructures the (string StandardOutput, string StandardError) tuple — not a single string"
+ - "Does not fall back to manual StandardOutput.ReadToEndAsync() as the primary mechanism"
+ - "Targets net11.0"
+ timeout: 180
+
+ # --- Scenario 4: stream tagged output lines via ReadAllLinesAsync ---
+ - name: "Stream tagged process output lines in .NET 11"
+ prompt: |
+ I have a long-running child process in a .NET 11 app. As it runs I want to handle each
+ output line the moment it is produced — not buffer everything to the end — and for each
+ line I need to know whether it came from stdout or stderr. I want the cleanest first-party
+ .NET 11 approach, with no event-callback plumbing and no deadlock risk. Show a minimal
+ program and the `net11.0` `.csproj`.
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "net11\\.0"
+ - type: "output_matches"
+ pattern: "ReadAllLines(Async)?\\s*\\("
+ - type: "output_matches"
+ pattern: "await\\s+foreach"
+ - type: "output_matches"
+ pattern: "\\.Content\\b|ProcessOutputLine"
+ - type: "output_matches"
+ pattern: "\\.StandardError\\b"
+ - type: "output_not_matches"
+ pattern: "OutputDataReceived|BeginOutputReadLine"
+ rubric:
+ - "Uses Process.ReadAllLinesAsync consumed with `await foreach` over IAsyncEnumerable"
+ - "Reads ProcessOutputLine.Content and distinguishes stdout vs stderr via .StandardError"
+ - "Does NOT use the old OutputDataReceived/BeginOutputReadLine event model; targets net11.0"
+ timeout: 180
+
+ # --- Scenario 5: Negative — skill should NOT activate on .NET 8 ---
+ - name: "Non-activation: Running a process on .NET 8"
+ prompt: |
+ I have a .NET 8 console app and I need to start a process 'notepad.exe'.
+ Show me a minimal C# program and the `.csproj` XML targeting `net8.0` that starts this process using the traditional Process.Start. Print both in your response.
+ expect_activation: false
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "net8\\.0"
+ - type: "output_matches"
+ pattern: "Process\\.Start\\("
+ - type: "output_not_matches"
+ pattern: "RunAndCaptureText|ReadAllTextAsync|ReadAllLinesAsync|KillOnParentExit"
+ rubric:
+ - "Solves the task using standard pre-.NET 11 APIs (Process.Start)"
+ - "Does NOT load or reference the process-api-net11 skill"
+ - "Targets net8.0"
+ timeout: 180
+
+ # --- Scenario 6: subtle non-activation — capture output on .NET 10 (APIs are net11-only) ---
+ - name: "Non-activation: capture process output on .NET 10"
+ prompt: |
+ I'm on a `.NET 10` project (`net10.0`). I need to run `git` with the argument `status`
+ and capture its standard output into a string. Show a minimal C# program and the
+ `.csproj` XML targeting `net10.0`, and print both.
+ expect_activation: false
+ assertions:
+ - type: "exit_success"
+ - type: "output_matches"
+ pattern: "net10\\.0"
+ - type: "output_not_matches"
+ pattern: "RunAndCaptureText|ReadAllTextAsync|ReadAllLinesAsync"
+ - type: "output_matches"
+ pattern: "RedirectStandardOutput|ReadToEnd"
+ rubric:
+ - "Solves the task with pre-.NET 11 APIs (RedirectStandardOutput + ReadToEnd/ReadToEndAsync)"
+ - "Recognizes the new .NET 11 Process convenience APIs are unavailable on net10.0 and does not use them"
+ - "Does NOT load the process-api-net11 skill; targets net10.0"
+ timeout: 180