/r3-reactive-extensions
Build reactive/event-driven C# with R3 (Cysharp's modern reimplementation of Reactive Extensions). Covers the Observable<T>/Observer<T> model, the OnErrorResume error contract, async dispatch with AwaitOperation, Task/IAsyncEnumerable integration, TimeProvider/FrameProvider
$ npx -y skills add aaronontheweb/dotnet-skills --skill r3-reactive-extensions --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
/r3-reactive-extensions
Context preview
The summary Claude sees to decide when to auto-load this skill.
Build reactive/event-driven C# with R3 (Cysharp's modern reimplementation of Reactive Extensions). Covers the Observable<T>/Observer<T> model, the OnErrorResume error contract, async dispatch with AwaitOperation, Task/IAsyncEnumerable integration, TimeProvider/FrameProvider
SKILL.md
r3-reactive-extensions.SKILL.mdname: r3-reactive-extensions
description: Build reactive/event-driven C# with R3 (Cysharp's modern reimplementation of Reactive Extensions). Covers the Observable<T>/Observer<T> model, the OnErrorResume error contract, async dispatch with AwaitOperation, Task/IAsyncEnumerable integration, TimeProvider/FrameProvider scheduling, the concurrency contract, and how R3 differs from System.Reactive (Rx.NET).
invocable: false
R3: Modern Reactive Extensions for .NET
R3 is [Cysharp's](https://github.com/Cysharp/R3) ground-up reimplementation of Reactive Extensions — "the new future of dotnet/reactive and UniRx." It keeps the LINQ-over-events programming model but rebuilds the core types, error contract, and scheduler to fix long-standing problems in `System.Reactive` (Rx.NET). Use this skill when composing event streams, UI input, timers, or push-based pipelines in C#.
**Canonical sources** (link to these from code and docs):
- Repository: https://github.com/Cysharp/R3
- README (full operator reference): https://github.com/Cysharp/R3/blob/main/README.md
- Author's design rationale: https://neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826
When to Use This Skill
Use this skill when:
- Composing **events** over time — UI input, sensor/feed updates, websocket messages, domain events
- You need operators like debounce, throttle, merge, combine-latest, distinct-until-changed
- Building **MVVM** state with `ReactiveProperty` / `BindableReactiveProperty`
- Bridging push-based streams with `Task` / `async` and `IAsyncEnumerable`
- Migrating from `System.Reactive`, UniRx, or `IObservable<T>` code
- You hit Rx pain points: subscriptions dying on exceptions, scheduler overhead, or leak hunting
**Not the right tool for:** request/response I/O (use `async/await`), bounded producer/consumer with **backpressure** (use `System.Threading.Channels`), or server-side stream processing with batching/backpressure (use Akka.NET Streams). R3, like all Rx, is **push-based with no backpressure**. See the `csharp-concurrency-patterns` skill for choosing between these.
Reference Files
- [rx-net-differences.md](rx-net-differences.md): Every meaningful difference vs System.Reactive (Rx.NET) — the new core types, the error model, operator renames, dropped APIs, the scheduler swap, and a migration checklist.
- [async-and-integration-patterns.md](async-and-integration-patterns.md): Common patterns — async dispatch with `AwaitOperation`, `Task` integration, `IAsyncEnumerable` round-tripping, `ReactiveProperty`/MVVM, subjects, and subscription lifecycle.
- [scheduling-and-concurrency.md](scheduling-and-concurrency.md): How R3 handles **concurrent updates** (the threading contract, `Synchronize`, `ObserveOn`), `TimeProvider` vs `FrameProvider`, when each is necessary, and deterministic testing with fake providers.
> Everything in this skill was validated empirically against **R3 1.3.1**. Captured output > appears in the reference files as evidence.
---
Why R3 Exists (the "why use it")
The author ([neuecc](https://neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826)) built R3 to fix concrete defects in `System.Reactive`:
1. **Exceptions silently kill subscriptions.** In Rx, one exception in the pipeline calls `OnError` and *unsubscribes forever* — "a billion-dollar mistake" for long-lived event streams (a single bad UI event tears down the whole subscription). R3 routes errors to `OnErrorResume` and **keeps the subscription alive by default**. 2. **`IScheduler` is heavy and confusing.** `ImmediateScheduler`/`Merge` were measured causing real server memory/CPU bloat. R3 deletes `IScheduler` and uses .NET 8's `TimeProvider` (wall-clock) plus a new `FrameProvider` (frame-clock). 3. **Subscription leaks are hard to find.** R3 makes every `Observable<T>` an abstract class so all subscriptions funnel through one place, enabling `ObservableTracker` to list every live subscription with stack traces. 4. **Rx and async were awkwardly fused.** R3 treats Rx as **event-first** and adds explicit bridges (`AwaitOperation`, `FromAsync`, `ToAsyncEnumerable`) instead of pretending events are pull-based sequences. 5. **One library, every UI.** A platform-neutral core plus thin provider packages for Unity, Godot, WPF, WinForms, Avalonia, WinUI3, MAUI, Stride, MonoGame, and Blazor.
---
Install
dotnet add package R3
# Platform glue (pick what applies): R3.WPF, R3.Avalonia, R3.WinForms, R3.Unity (UPM),
# R3.Godot, ObservableCollections.R3, etc. See the repo README for the full list.
using R3;
---
The Mental Model
R3 replaces Rx's **interfaces** with **abstract classes**, and replaces Rx's two-method error contract with a single completion that carries a result.
public abstract class Observable<T>
{
public IDisposable Subscribe(Observer<T> observer); // tracked centrally
protected abstract IDisposable SubscribeCore(Observer<T> observer);
}
public abstract class Observer<T> : IDisposable // the observer IS the subscription
{
public void OnNext(T value);
public void OnErrorResume(Exception error); // error WITHOUT unsubscribing
public void OnCompleted(Result result); // success OR failure terminates
}The grammar is `(OnNext | OnErrorResume)* OnCompleted(Result)?`. Note the difference from Rx's `OnNext* (OnError | OnCompleted)?`: **errors and termination are decoupled**. An error is just a notification; only `OnCompleted` ends the stream, and it carries a `Result` that is either `Result.Success` or `Result.Failure(exception)`.
Quick start
using R3;
var subscription = Observable
.EveryValueChanged(model, m => m.SearchText) // emits when the property changes
.Debounce(TimeSpan.FromMilliseconds(300)) // Rx called this "Throttle" (see differences)
.DistinctUntiRead more
name: r3-reactive-extensions description: Build reactive/event-driven C# with R3 (Cysharp's modern reimplementation of Reactive Extensions). Covers the Observable<T>/Observer<T> model, the OnErrorResume error contract, async dispatch with AwaitOperation, Task/IAsyncEnumerable integration, TimeProvider/FrameProvider scheduling, the concurrency contract, and how R3 differs from System.Reactive (Rx.NET). invocable: false
R3: Modern Reactive Extensions for .NET
R3 is [Cysharp's](https://github.com/Cysharp/R3) ground-up reimplementation of Reactive Extensions — "the new future of dotnet/reactive and UniRx." It keeps the LINQ-over-events programming model but rebuilds the core types, error contract, and scheduler to fix long-standing problems in `System.Reactive` (Rx.NET). Use this skill when composing event streams, UI input, timers, or push-based pipelines in C#.
**Canonical sources** (link to these from code and docs):
- Repository: https://github.com/Cysharp/R3
- README (full operator reference): https://github.com/Cysharp/R3/blob/main/README.md
- Author's design rationale: https://neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826
When to Use This Skill
Use this skill when:
- Composing **events** over time — UI input, sensor/feed updates, websocket messages, domain events
- You need operators like debounce, throttle, merge, combine-latest, distinct-until-changed
- Building **MVVM** state with `ReactiveProperty` / `BindableReactiveProperty`
- Bridging push-based streams with `Task` / `async` and `IAsyncEnumerable`
- Migrating from `System.Reactive`, UniRx, or `IObservable<T>` code
- You hit Rx pain points: subscriptions dying on exceptions, scheduler overhead, or leak hunting
**Not the right tool for:** request/response I/O (use `async/await`), bounded producer/consumer with **backpressure** (use `System.Threading.Channels`), or server-side stream processing with batching/backpressure (use Akka.NET Streams). R3, like all Rx, is **push-based with no backpressure**. See the `csharp-concurrency-patterns` skill for choosing between these.
Reference Files
- [rx-net-differences.md](rx-net-differences.md): Every meaningful difference vs System.Reactive (Rx.NET) — the new core types, the error model, operator renames, dropped APIs, the scheduler swap, and a migration checklist.
- [async-and-integration-patterns.md](async-and-integration-patterns.md): Common patterns — async dispatch with `AwaitOperation`, `Task` integration, `IAsyncEnumerable` round-tripping, `ReactiveProperty`/MVVM, subjects, and subscription lifecycle.
- [scheduling-and-concurrency.md](scheduling-and-concurrency.md): How R3 handles **concurrent updates** (the threading contract, `Synchronize`, `ObserveOn`), `TimeProvider` vs `FrameProvider`, when each is necessary, and deterministic testing with fake providers.
> Everything in this skill was validated empirically against **R3 1.3.1**. Captured output > appears in the reference files as evidence.
---
Why R3 Exists (the "why use it")
The author ([neuecc](https://neuecc.medium.com/r3-a-new-modern-reimplementation-of-reactive-extensions-for-c-cf29abcc5826)) built R3 to fix concrete defects in `System.Reactive`:
1. **Exceptions silently kill subscriptions.** In Rx, one exception in the pipeline calls `OnError` and *unsubscribes forever* — "a billion-dollar mistake" for long-lived event streams (a single bad UI event tears down the whole subscription). R3 routes errors to `OnErrorResume` and **keeps the subscription alive by default**. 2. **`IScheduler` is heavy and confusing.** `ImmediateScheduler`/`Merge` were measured causing real server memory/CPU bloat. R3 deletes `IScheduler` and uses .NET 8's `TimeProvider` (wall-clock) plus a new `FrameProvider` (frame-clock). 3. **Subscription leaks are hard to find.** R3 makes every `Observable<T>` an abstract class so all subscriptions funnel through one place, enabling `ObservableTracker` to list every live subscription with stack traces. 4. **Rx and async were awkwardly fused.** R3 treats Rx as **event-first** and adds explicit bridges (`AwaitOperation`, `FromAsync`, `ToAsyncEnumerable`) instead of pretending events are pull-based sequences. 5. **One library, every UI.** A platform-neutral core plus thin provider packages for Unity, Godot, WPF, WinForms, Avalonia, WinUI3, MAUI, Stride, MonoGame, and Blazor.
---
Install
dotnet add package R3 # Platform glue (pick what applies): R3.WPF, R3.Avalonia, R3.WinForms, R3.Unity (UPM), # R3.Godot, ObservableCollections.R3, etc. See the repo README for the full list.
using R3;
---
The Mental Model
R3 replaces Rx's **interfaces** with **abstract classes**, and replaces Rx's two-method error contract with a single completion that carries a result.
public abstract class Observable<T>
{
public IDisposable Subscribe(Observer<T> observer); // tracked centrally
protected abstract IDisposable SubscribeCore(Observer<T> observer);
}
public abstract class Observer<T> : IDisposable // the observer IS the subscription
{
public void OnNext(T value);
public void OnErrorResume(Exception error); // error WITHOUT unsubscribing
public void OnCompleted(Result result); // success OR failure terminates
}The grammar is `(OnNext | OnErrorResume)* OnCompleted(Result)?`. Note the difference from Rx's `OnNext* (OnError | OnCompleted)?`: **errors and termination are decoupled**. An error is just a notification; only `OnCompleted` ends the stream, and it carries a `Result` that is either `Result.Success` or `Result.Failure(exception)`.
Quick start
using R3;
var subscription = Observable
.EveryValueChanged(model, m => m.SearchText) // emits when the property changes
.Debounce(TimeSpan.FromMilliseconds(300)) // Rx called this "Throttle" (see differences)
.DistinctUntiA comprehensive AI coding plugin with 30 skills and 5 specialized agents for professional .NET development. Battle-tested patterns from production systems covering C#, Akka.NET, Aspire, EF Core, testing, and performance optimization.
Other skills on dotnet-skills.
- /akka-aspire-configuration
Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.
Open skill - /akka-best-practices
Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.
Open skill - /akka-hosting-actor-patterns
Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.
Open skill - /akka-management
Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.
Open skill - /akka-testing-patterns
Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.
Open skill - /aspire-configuration
Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.
Open skill

