Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .claude/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .agents/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .cursor/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .gemini/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .github/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "r3-reactive-extensions" agent skill from https://github.com/Aaronontheweb/dotnet-skills/tree/master/skills/r3-reactive-extensions into .opencode/skills/r3-reactive-extensions/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "r3-reactive-extensions", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
r3-reactive-extensions
GitHub stars
1.2k
Used in
1 other repo
Token cost
~3.4k tokens
SKILL.md length
1,149 words
Files
4
Skills in repo
35
Repo updated
First seen
Licence
MIT
At a glance
Build reactive/event-driven C with R3 (Cysharp's modern reimplementation of Reactive Extensions).
Works in 5 steps: Exceptions silently kill subscriptions.… → IScheduler is heavy and confusing.… → Subscription leaks are hard to find. R3… → …
Tasks that involve Event-driven systems
SKILL.md covers When to Use This Skill, Reference Files, Why R3 Exists (the "why use it") and Install, plus 6 more sections
Calls dotnet
What it does
R3 Reactive Extensions is an agent skill from Aaronontheweb/dotnet-skills. 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).
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files (for example `async-and-integration-patterns.md`, `rx-net-differences.md` and `scheduling-and-concurrency.md`).
It sits in Backend & APIs, covering Event-driven systems. It works with C#. The repository describes itself as: Claude Code skills and sub-agents for .NET Developers. The licence is MIT.
When your agent uses it
Tasks that involve Event-driven systems
Example prompts
“/r3-reactive-extensions”
Workflow steps
5 steps, taken from the first numbered list in SKILL.md.
1Exceptions silently kill subscriptions. In Rx, one exception in the pipeline calls
2IScheduler is heavy and confusing. ImmediateScheduler/Merge were measured causing
3Subscription leaks are hard to find. R3 makes every Observable an abstract class so
4Rx and async were awkwardly fused. R3 treats Rx as event-first and adds explicit
5One library, every UI. A platform-neutral core plus thin provider packages for Unity,
What it can do on your machine
Read from SKILL.md and the folder at commit 46003af. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
Shell commands in SKILL.md call:
dotnet
From the folder's file list and the shell code blocks in SKILL.md.
Network
Links to these hosts (documentation or services it may open):
github.com
neuecc.medium.com
nuget.org
learn.microsoft.com
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
R3 Reactive Extensions loads about 3.4k tokens when it runs. Until then it costs about 96 tokens; SKILL.md has 1,149 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~96
When it runs· the whole SKILL.md, loaded when a task matches
~3.4k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/r3-reactive-extensions/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.
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).
user-invocable
false
R3: Modern Reactive Extensions for .NET
R3 is Cysharp's 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):
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: 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: Common patterns — async dispatch with AwaitOperation, Task integration, IAsyncEnumerable round-tripping, ReactiveProperty/MVVM, subjects, and subscription lifecycle.
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)
built R3 to fix concrete defects in System.Reactive:
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.
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).
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.
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.
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
bash
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.
csharp
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.
csharp
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
csharp
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)
.DistinctUntilChanged()
.SubscribeAwait(async (text, ct) =>
{
var results = await _api.SearchAsync(text, ct);
Render(results);
}, AwaitOperation.Switch); // cancel the in-flight search on a new keystroke
// Dispose to unsubscribe; or route into a DisposableBag / AddTo(token).
subscription.Dispose();
Core Behavior, Verified
Errors do not terminate by default
csharp
var subject = new Subject<int>();
subject.Select(x => 100 / x).Subscribe(
onNext: x => Console.WriteLine($"next {x}"),
onErrorResume: e => Console.WriteLine($"errorResume {e.GetType().Name}"),
onCompleted: (Result r) => Console.WriteLine($"completed IsSuccess={r.IsSuccess}"));
subject.OnNext(2); // next 50
subject.OnNext(0); // errorResume DivideByZeroException <-- NOT terminated
subject.OnNext(5); // next 20 <-- subscription is still alive!
subject.OnCompleted(); // completed IsSuccess=True
This is the single biggest behavioral change from Rx. To opt back into classic "an error
terminates the sequence" behavior, insert .OnErrorResumeAsFailure() — the error then flows to
OnCompleted(Result.Failure(e)) and downstream OnNexts stop. Recover with Catch. Full
captured runs and the (deliberately absent) Retry story are in
rx-net-differences.md.
Async dispatch is explicit
R3's async operators (SubscribeAwait, SelectAwait, WhereAwait, …) take an AwaitOperation
that decides what happens when values arrive faster than the async work completes:
AwaitOperation
Overlap behavior
Typical use
Sequential (default)
Queue values, run one at a time
Ordered processing
Drop
Ignore new values while one is running
Debounced submit / cooldown
Switch
Cancel the running one, start the new
Search-as-you-type, latest-wins
Parallel
Run all concurrently
Independent fan-out
SequentialParallel
Run concurrently, emit results in order
Parallel map, ordered output
ThrottleFirstLast
Run first + last of a burst
Leading/trailing sampling
These were verified to behave exactly as described (including Switch cancelling the superseded
operation's CancellationToken). See async-and-integration-patterns.md.
Task and IAsyncEnumerable bridges
csharp
// Task -> Observable
await Observable.FromAsync(async ct => await LoadAsync(ct)).FirstAsync();
// Observable -> Task (terminal operators return Task<T>)
List<int> all = await source.ToListAsync();
int last = await source.LastAsync();
// IAsyncEnumerable -> Observable, and back
await asyncEnumerable.ToObservable().ForEachAsync(Handle);
await foreach (var x in source.ToAsyncEnumerable()) { /* ... */ }
R3 does not serialize concurrent producers. Like Rx, it assumes the Rx grammar: OnNext
must not be called concurrently or re-entrantly from multiple threads. Operators (Where,
Select, Subject, …) are not internally locked. Pushing OnNext from many threads at once
into a stateful downstream corrupts state — in testing, 20,000 concurrent OnNext calls into
a List<T> subscriber lost ~half the items and threw inside the operator chain.
The fix is to make the boundary explicit:
csharp
// Multiple producer threads -> one serialized consumer
subject.Synchronize() // lock-based gate; delivery becomes single-threaded
.Where(x => x.IsValid)
.Subscribe(Handle); // verified: 10000/10000 items, no corruption
// Or marshal onto a context/threadpool, which also serializes delivery:
source.ObserveOnThreadPool().Subscribe(Handle);
// For shared MVVM state written from many threads:
var counter = new SynchronizedReactiveProperty<int>(0); // thread-safe writes
Practical rule: if more than one thread can publish into a stream, put Synchronize() (or an
ObserveOn*) immediately after the source, or use SynchronizedReactiveProperty. Full race
reproductions and outputs are in scheduling-and-concurrency.md.
Time vs Frames: TimeProvider and FrameProvider
R3 has two notions of "when," and both are abstractions you can fake in tests:
TimeProvider (the .NET 8 BCL type) = wall-clock time. Used by Delay, Debounce,
Interval, Timer, Timeout. This is what server/business code uses.
FrameProvider (R3-specific) = a frame clock. Used by EveryUpdate, DelayFrame(n),
IntervalFrame(n), etc.
When is a FrameProvider necessary? Whenever "progress" is measured in render/update ticks
instead of elapsed time:
Game engines (Unity, Godot, Stride, MonoGame) — logic ticks with the engine's update loop,
so it respects pause and time-scale and stays in lockstep with rendering.
UI render loops (WPF/Avalonia/WinUI composition frames) — react per frame.
Deterministic tests — FakeFrameProvider.Advance(n) drives frames with zero real time,
exactly as FakeTimeProvider.Advance(timeSpan) drives the clock.
Plain server/business code virtually never needs FrameProvider — that's TimeProvider
territory. Both fakes make time-dependent pipelines fully deterministic; examples in
scheduling-and-concurrency.md.
Best Practices Summary
DO
Treat OnErrorResume as the default: design streams that survive individual bad events.
Add .OnErrorResumeAsFailure() when you genuinely want an error to terminate the stream.
Choose an AwaitOperation deliberately for every async operator (Switch for latest-wins,
Sequential for ordering, Drop for cooldowns).
Put Synchronize() / ObserveOn* after any source that multiple threads publish into.
Pass a TimeProvider to time operators and a FrameProvider to frame operators so tests can
use FakeTimeProvider / FakeFrameProvider.
Manage lifetime: route subscriptions into a DisposableBag, CompositeDisposable, or
.AddTo(cancellationToken); turn on ObservableTracker in dev to catch leaks.
Use ReactiveProperty for de-duplicated observable state; BindableReactiveProperty for
XAML-bound state.
DON'T
Don't assume an exception ends the stream (that's Rx, not R3).
Don't reach for Rx names that R3 renamed: it's Debounce (not Throttle), ThrottleLast
(not Sample), Chunk (not Buffer). Retry, GroupBy, Finally, and plain Buffer are
absent in 1.3.1 — see the differences file for replacements.
Don't call OnNext concurrently/re-entrantly from multiple threads without Synchronize().
Don't use R3 for backpressured throughput pipelines — use Channels or Akka.NET Streams.
Don't block on terminal operators (.Result/.Wait()); they return Task<T> — await them.
We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in Aaronontheweb/dotnet-skills, which our catalogue first saw on October 7, 2026.
R3 Reactive Extensions next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
R3 Reactive Extensions compared with similar skills
Skill
Stars
Used in
Tokens
Auto-check
Licence
Repo updated
R3 Reactive Extensions this skillAaronontheweb/dotnet-skills
Advanced engineering for sophisticated FoundationDB layers with the .NET client (FoundationDB.Client / SnowBank) — the cluster model and transaction lifecycle (proxies, resolvers, tlogs, storage…
A skill your agent uses when building .NET 8/9 applications, ASP.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT…
Guides making .NET libraries trimming-safe and Native-AOT compatible: the MSBuild properties, trimming attributes, warning codes and a playbook of safe patterns.
Publish .NET services as container images with the built-in SDK tooling (dotnet publish /t:PublishContainer, Microsoft.NET.Build.Containers) - no Dockerfile required.
Guidance for Akka.NET actor systems covering EventStream versus DistributedPubSub, supervision, Props versus DependencyResolver, work distribution and testable cluster code.
Sets up Akka.Management and Cluster.Bootstrap so Akka.NET clusters form through service discovery on Kubernetes, Azure or config instead of static seed nodes.
Build reactive/event-driven C with R3 (Cysharp's modern reimplementation of Reactive Extensions). R3 Reactive Extensions is an agent skill from Aaronontheweb/dotnet-skills. Build reactive/event-driven C with R3 (Cysharp's modern reimplementation of Reactive Extensions).
How do I install R3 Reactive Extensions in Claude Code?
Run `npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a claude-code`. Or copy the skill folder (skills/r3-reactive-extensions in Aaronontheweb/dotnet-skills) into .claude/skills/r3-reactive-extensions in your project. Claude Code loads it when a task matches its description.
How do I install R3 Reactive Extensions in Codex?
Run `npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a codex`. Or copy the skill folder (skills/r3-reactive-extensions in Aaronontheweb/dotnet-skills) into .agents/skills/r3-reactive-extensions in your project. Codex loads it when a task matches its description.
Can I use R3 Reactive Extensions in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Aaronontheweb/dotnet-skills --skill r3-reactive-extensions -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/r3-reactive-extensions, .gemini/skills/r3-reactive-extensions, .github/skills/r3-reactive-extensions and .opencode/skills/r3-reactive-extensions in your project.
What does R3 Reactive Extensions need to run?
Going by SKILL.md and its folder, R3 Reactive Extensions needs the command-line tools its instructions call (dotnet).
Does R3 Reactive Extensions access the network?
SKILL.md names 4 domains. As links in the text: github.com, neuecc.medium.com, nuget.org and learn.microsoft.com. This is read from the text; nothing was executed.
Is R3 Reactive Extensions safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does R3 Reactive Extensions use?
R3 Reactive Extensions is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does R3 Reactive Extensions use?
About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to R3 Reactive Extensions?
Skills that share tags, products or a category with R3 Reactive Extensions: Foundationdb Advanced Layers (SnowBankSDK/foundationdb-dotnet-client, 158 stars), Dotnet Expert (LeoYeAI/openclaw-master-skills, 2.2k stars), Event Bus (jame581/GodotPrompter, 805 stars) and Csharp Signals (jame581/GodotPrompter, 805 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains R3 Reactive Extensions?
Aaronontheweb (a GitHub user) maintains it in Aaronontheweb/dotnet-skills, which has 1,206 GitHub stars. The repository holds 35 skills in this directory. The repository was last updated on October 10, 2026.
Source: Aaronontheweb/dotnet-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.