Skip to content

Commit e983eec

Browse files
Plugin format for skills + local NuGet flow + agent kit
Restructures the agent-facing skills around the Copilot CLI / Claude plugin layout (plugins/reactor/{plugin.json, agents/, skills/<name>/SKILL.md}) so the SDK's native skill-loading subsystem fires `skill.invoked` instead of the agent treating SKILL.md as an ordinary file. Each topical skill gets a focused SKILL.md with keyword-rich frontmatter; deeper content lives under references/. New skills (under plugins/reactor/skills/): - reactor-getting-started — minimal single-file `#:package` starter, .csproj template, mode detection, package consumption, cache map fallback - reactor-dsl — DSL essentials, hooks, components, theme tokens, gotchas; references/reactor.api.txt is the full alphabetized signatures index - reactor-build-and-check — `mur check` usage, common-build-errors cheat table mapping REACTOR_* / CS* IDs to one-line fixes - reactor-{async,design,forms,navigation,input,charts,commanding,devtools} — migrated from skills/<name>.md with plugin-format frontmatter - reactor-recipes — paste-ready single-file recipes in references/ Local NuGet flow + agent kit: - tools/Reactor.SignaturesGen — reflection-based generator emitting skills/reactor.api.txt from the built Reactor.dll. AfterBuild target skips when RuntimeIdentifier is set so cross-arch publishes don't fail. - nuget.config + local-nupkgs/ — repo-level local feed - mur pack-local — packs Microsoft.UI.Reactor.0.0.0-local.nupkg into the feed and clears NuGet's HTTP cache - mur api / --regen-api — print / regenerate the signatures index - mur check — runs `dotnet build` and emits one-line diagnostics with skill-file pointers for known REACTOR_* analyzer IDs - Reactor.csproj packs the full plugin tree into agentkit/plugins/reactor/ alongside the legacy SKILL.md + skills/ + reactor.api.txt New analyzer: - REACTOR_DSL_001 (MissingWithKeyAnalyzer) — flags Select(...) into a layout container without .WithKey on items Recipes (skills/recipes/): - async-fetch-list, form-with-validation, list-add-delete, sidebar-nav, themed-card — all compile against the local feed; verified end-to-end via c:\temp\nuget-test*. Root SKILL.md is preserved as a fallback for environments without plugin loading and now leads with a pointer to the plugin path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3f412fe commit e983eec

42 files changed

Lines changed: 6679 additions & 9 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Reactor.slnx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@
304304
<Project Path="tests/stress_perf/StressPerf.Wpf/StressPerf.Wpf.csproj" />
305305
</Folder>
306306
<Folder Name="/tools/" />
307+
<Folder Name="/tools/Reactor.SignaturesGen/">
308+
<Project Path="tools/Reactor.SignaturesGen/Reactor.SignaturesGen.csproj">
309+
<Platform Solution="*|ARM64" Project="ARM64" />
310+
<Platform Solution="*|x64" Project="x64" />
311+
</Project>
312+
</Folder>
307313
<Folder Name="/tools/Templates/">
308314
<Project Path="tools/Templates/Microsoft.UI.Reactor.Templates.csproj" />
309315
</Folder>

SKILL.md

Lines changed: 142 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,127 @@ name: reactor-app
33
description: >
44
Create WinUI 3 desktop applications using the Reactor framework — a React-inspired
55
declarative C# projection over WinUI 3. No XAML, no data binding, no templates.
6-
This root skill teaches the core mental model and common patterns; load a
7-
sub-skill from /skills when the task calls for it.
6+
This file is the legacy single-file skill — prefer the `reactor` plugin under
7+
`plugins/reactor/` (or `agentkit/plugins/reactor/` in the NuGet) for a more
8+
efficient skill-loading experience.
89
---
910

1011
# Reactor — Getting Started
1112

13+
> **Prefer the plugin.** This file is preserved for environments that don't
14+
> support the Copilot CLI / Claude plugin loading model. If you have a plugin
15+
> SDK available, install / load the `reactor` plugin (under
16+
> `plugins/reactor/` in source, or `agentkit/plugins/reactor/` in the NuGet).
17+
> The plugin splits this content into focused per-skill files and is materially
18+
> cheaper to load than this monolith.
19+
20+
21+
1222
Reactor is a **React-inspired functional projection for WinUI 3**. You write
1323
functions that return lightweight element descriptions; a reconciler diffs
1424
old vs new trees and patches real WinUI controls. State changes trigger
1525
re-renders automatically. No XAML. No data binding. No ViewModels.
1626

27+
## Which mode are you in? (read this first)
28+
29+
Reactor ships as a NuGet package — apps reference it as
30+
`<PackageReference Include="Microsoft.UI.Reactor" Version="…" />` (or
31+
`#:package Microsoft.UI.Reactor@…` for single-file). The package carries
32+
the framework, the analyzers, and an **agent kit** (signatures index +
33+
this SKILL.md). Two paths:
34+
35+
| Mode | How to detect | Bootstrap |
36+
|---|---|---|
37+
| **Selfhost** — you're in a Reactor source clone (`src/Reactor/Reactor.csproj` exists) | The repo's `local-nupkgs/` folder is the package source — see `nuget.config` at repo root. | Build `mur` once, then **`mur pack-local`** to populate `local-nupkgs/Microsoft.UI.Reactor.0.0.0-local.nupkg`. Re-run after framework changes. |
38+
| **Consumer** — you're in an app that depends on Microsoft.UI.Reactor | No `src/Reactor/` next to your project. | Nothing extra — the package already carries the analyzers and agent kit. If `mur` is on PATH, `mur --skill` and `mur --api` print the embedded docs. Otherwise read `<package-cache>/microsoft.ui.reactor/<version>/agentkit/`. |
39+
40+
If you're in selfhost and `local-nupkgs/` is empty, restore will fail with
41+
"package Microsoft.UI.Reactor 0.0.0-local was not found." Run `mur pack-local`
42+
to fix it.
43+
44+
### Bootstrap (selfhost, fresh clone)
45+
46+
```powershell
47+
# Build the CLI; on first build the SignaturesGen project also writes
48+
# skills/reactor.api.txt as part of its AfterBuild target.
49+
dotnet build src/Reactor.Cli -p:Platform=ARM64
50+
51+
# `mur` mirrors itself to <repo>/bin/<arch>/. Add that to PATH or invoke directly.
52+
.\bin\arm64\mur.exe pack-local
53+
```
54+
55+
After this, any project under the clone resolves
56+
`Microsoft.UI.Reactor 0.0.0-local` from `local-nupkgs/` automatically (the
57+
repo-level `nuget.config` configures it). A consumer **outside** the clone
58+
needs a project-local `nuget.config` pointing at the absolute path of
59+
`<repo>/local-nupkgs/`.
60+
61+
## Where to find docs (`mur --skill`, `mur --api`)
62+
63+
The `mur` CLI ships these embedded — works from any directory:
64+
65+
| Command | What it prints | Source |
66+
|---|---|---|
67+
| `mur --skill` | This SKILL.md | embedded in `mur` |
68+
| `mur --api` | The signatures index (≈12K tokens, every factory/modifier/hook/Theme token/enum) | embedded in `mur` |
69+
| `mur --regen-api` | Rebuilds `skills/reactor.api.txt` from a freshly-built `Reactor.dll` (selfhost only) | rebuilds `tools/Reactor.SignaturesGen` |
70+
| `mur check <path>` | Runs `dotnet build` and emits one-line diagnostics with skill-file pointers for known REACTOR_* IDs | wraps MSBuild |
71+
72+
A consumer who doesn't have `mur` can read the same files directly from the
73+
NuGet cache:
74+
75+
```
76+
%USERPROFILE%\.nuget\packages\microsoft.ui.reactor\<version>\agentkit\
77+
├─ SKILL.md ← this file
78+
├─ reactor.api.txt ← signatures index
79+
└─ skills\
80+
├─ async.md, design.md, commanding.md, navigation.md, forms.md,
81+
│ input.md, charts.md, dsl-reference.md, devtools.md, perf-tips.md
82+
└─ recipes\
83+
├─ index.md ← intent → recipe map
84+
└─ <name>.cs ← paste-ready single-file programs
85+
```
86+
87+
When SKILL.md or a recipe references `skills/foo.md`, a consumer agent
88+
reads it from `agentkit/skills/foo.md` in the package cache. Selfhost
89+
agents read it from `<repo>/skills/foo.md`.
90+
91+
## API signatures index — load this before grepping source
92+
93+
[`skills/reactor.api.txt`](skills/reactor.api.txt) is a generated, alphabetized
94+
flat list of every public Factory, Modifier, Hook, Theme token (with WinUI
95+
resource key), and enum in Reactor. **Load this when you need to confirm a
96+
signature.** It replaces grepping `src/Reactor/Elements/*.cs` and walking the
97+
sub-skills' tables.
98+
99+
- **Local / selfhost:** the file is committed at `skills/reactor.api.txt`.
100+
Run `mur --api` to print it. Run `mur --regen-api` after framework changes.
101+
- **NuGet consumer:** the same file ships in the package at
102+
`<package-cache>/microsoft.ui.reactor/<version>/agentkit/reactor.api.txt`
103+
(typically `%USERPROFILE%\.nuget\packages\microsoft.ui.reactor\<version>\agentkit\reactor.api.txt`).
104+
If `mur` is on PATH, `mur --api` prints the embedded copy.
105+
106+
## Recipes — paste-ready snippets indexed by intent
107+
108+
[`skills/recipes/`](skills/recipes/) holds compilable single-file recipes for
109+
the most common Reactor patterns. **Load a recipe instead of synthesizing
110+
from skill prose.** See [`skills/recipes/index.md`](skills/recipes/index.md)
111+
for the intent → recipe map. Available today: list-add-delete, sidebar-nav,
112+
form-with-validation, async-fetch-list, themed-card.
113+
114+
## `mur check` — fast feedback with skill pointers
115+
116+
`mur check <path>` builds the target and emits one-line diagnostics with
117+
pointers into the skill files for known Reactor analyzer IDs:
118+
119+
```
120+
C:\path\Program.cs:15:23 W REACTOR_DSL_001 Element produced by Select(...)… → SKILL.md gotcha #6 (.WithKey on dynamic list items)
121+
```
122+
123+
`<path>` defaults to `.` and accepts a `.csproj` or directory. Single-file
124+
`.cs` builds work but **don't load analyzers** — for analyzer coverage,
125+
use a `.csproj`.
126+
17127
## Sub-skills — load when the task calls for them
18128

19129
| Skill | When to load |
@@ -44,12 +154,34 @@ re-renders automatically. No XAML. No data binding. No ViewModels.
44154
<WindowsPackageType>None</WindowsPackageType>
45155
</PropertyGroup>
46156
<ItemGroup>
157+
<PackageReference Include="Microsoft.UI.Reactor" Version="0.0.0-local" />
47158
<PackageReference Include="Microsoft.WindowsAppSDK" Version="2.0.1" />
48-
<ProjectReference Include="..\src\Reactor\Reactor.csproj" />
49159
</ItemGroup>
50160
</Project>
51161
```
52162

163+
In selfhost the version is `0.0.0-local` (produced by `mur pack-local`
164+
see "Which mode are you in?" above). Outside the source clone, replace it
165+
with whatever Microsoft.UI.Reactor version you depend on.
166+
167+
### nuget.config (selfhost only — sibling of the .csproj)
168+
169+
If your .csproj lives **outside** the Reactor clone, add a `nuget.config`
170+
next to it pointing at the clone's `local-nupkgs/` (absolute path):
171+
172+
```xml
173+
<?xml version="1.0" encoding="utf-8"?>
174+
<configuration>
175+
<packageSources>
176+
<add key="reactor-local" value="C:\path\to\reactor2\local-nupkgs" />
177+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
178+
</packageSources>
179+
</configuration>
180+
```
181+
182+
Inside the clone you don't need this — the repo-level `nuget.config`
183+
already configures the feed.
184+
53185
`WindowsPackageType` MUST be `None` (unpackaged, no App.xaml). `UseWinUI`
54186
MUST be `true`. No XAML files of any kind.
55187

@@ -309,14 +441,12 @@ dotnet test Reactor.slnx
309441
For lightweight demos, skip the `.csproj` entirely. Add a file-level header:
310442

311443
```csharp
312-
#:project ./src/Reactor
444+
#:package Microsoft.UI.Reactor@0.0.0-local
313445
#:package Microsoft.WindowsAppSDK@2.0.1
314446
#:property OutputType=WinExe
315447
#:property TargetFramework=net10.0-windows10.0.22621.0
316448
#:property UseWinUI=true
317449
#:property WindowsPackageType=None
318-
#:property WindowsAppSDKSelfContained=true
319-
#:property RuntimeIdentifier=win-arm64
320450

321451
using Microsoft.UI.Reactor;
322452
using static Microsoft.UI.Reactor.Factories;
@@ -328,12 +458,15 @@ ReactorApp.Run("Hello", ctx =>
328458
});
329459
```
330460

331-
Run with `dotnet run MyApp.cs`. Adjust `#:project` to your clone's
332-
`src/Reactor` directory. Use `win-arm64` on ARM, `win-x64` on x64 — check
333-
with `dotnet --info`.
461+
Run with `dotnet run MyApp.cs -p:Platform=ARM64` (or `x64`). In selfhost
462+
the version is `0.0.0-local` — run `mur pack-local` first if the package
463+
isn't found. Outside the clone, replace the version with the published
464+
release you depend on.
334465

335466
> **Always capture `dotnet run` output.** Build errors exit with code 1.
336467
> Read compiler output, fix, retry. Don't assume success without checking.
468+
> Note: single-file builds **do not load analyzers** — for analyzer
469+
> coverage (`REACTOR_DSL_001`, `REACTOR_HOOKS_*`, etc.), use a `.csproj`.
337470
338471
## Comparison to React
339472

local-nupkgs/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Local NuGet feed — generated by `mur pack-local`. Don't commit packages.
2+
*.nupkg
3+
*.snupkg

nuget.config

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<!-- Repo-level NuGet sources. The `local-nupkgs/` folder is the feed that
4+
`mur pack-local` writes to. It carries the Microsoft.UI.Reactor package
5+
built from this clone (version 0.0.0-local by default). Recipes and
6+
scaffolded apps under this repo use #:package Microsoft.UI.Reactor and
7+
resolve through this feed.
8+
9+
nuget.org remains the source for everything else (Microsoft.WindowsAppSDK
10+
and friends). It's added explicitly here so this file is self-contained
11+
— global sources still apply additively. -->
12+
<packageSources>
13+
<add key="reactor-local" value="local-nupkgs" />
14+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
15+
</packageSources>
16+
</configuration>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "reactor",
3+
"description": "Agents and skills for building WinUI 3 desktop apps with Microsoft.UI.Reactor — a React-inspired declarative C# projection (no XAML, no data binding, no ViewModels). Use for creating new apps, adding features, fixing bugs, or any Reactor / Microsoft.UI.Reactor / functional WinUI task.",
4+
"version": "0.1.0",
5+
"author": {
6+
"name": "Microsoft",
7+
"url": "https://github.com/microsoft/microsoft-ui-reactor"
8+
},
9+
"homepage": "https://github.com/microsoft/microsoft-ui-reactor",
10+
"repository": "https://github.com/microsoft/microsoft-ui-reactor",
11+
"license": "MIT",
12+
"keywords": [
13+
"reactor",
14+
"microsoft.ui.reactor",
15+
"winui",
16+
"winui3",
17+
"windows app sdk",
18+
"desktop app",
19+
"react",
20+
"declarative ui",
21+
"functional ui",
22+
"csharp",
23+
"dotnet",
24+
"winrt",
25+
"hooks",
26+
"components",
27+
"no xaml"
28+
]
29+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: reactor-dev
3+
description: "Builds WinUI 3 desktop apps with Microsoft.UI.Reactor — a React-inspired declarative C# projection (no XAML, no data binding, no ViewModels). Use for creating new Reactor apps, adding features, converting from XAML/MVVM to Reactor, fixing bugs, or any Microsoft.UI.Reactor / functional WinUI task."
4+
user-invocable: true
5+
---
6+
7+
## Process
8+
9+
You build Reactor apps following this process: understand requirements → write a minimal app → expand → build & verify. Reactor is novel (post-training), so **you must ground every API call in real signatures** from the bundled reference — not from memory.
10+
11+
Before writing any Reactor code, load these two skills (the plugin SDK does this efficiently — far cheaper than reading files via tool calls):
12+
13+
1. **`reactor-getting-started`** — minimal app shape, project setup, package consumption (selfhost vs. NuGet).
14+
2. **`reactor-dsl`** — DSL essentials, hooks, components, theme tokens, critical gotchas, full signatures index in `references/`.
15+
16+
Load other skills only when the task explicitly calls for them — see the table below. Loading every skill up front is the failure mode that bloats context.
17+
18+
**Always prefer the loaded skill over invoking `mur --skill` / `mur --api` / cache-map file reads.** The plugin SDK ships these contents to you directly; falling back to tool calls (PowerShell, Read, Bash) wastes turns and tokens. Use those fallbacks only when the plugin isn't installed.
19+
20+
## When to load each skill
21+
22+
| Skill | Trigger |
23+
|---|---|
24+
| `reactor-getting-started` | Any new Reactor work. Always first. |
25+
| `reactor-dsl` | Any Reactor work. Always second. Has the api index pointer. |
26+
| `reactor-build-and-check` | Build fails, you see a `REACTOR_*` analyzer warning, or you want one-line diagnostic output. |
27+
| `reactor-async` | Fetching data, caching, pagination, optimistic writes. `UseResource`, `UseMutation`, `UseInfiniteResource`. |
28+
| `reactor-design` | Visual styling — theme tokens, High Contrast, typography, 4px grid, accessibility. |
29+
| `reactor-forms` | Data-entry screens, validation, masked input. `UseValidationContext`, `FormField`. |
30+
| `reactor-navigation` | Multi-page apps, sidebar/tab navigation, routes, deep linking. |
31+
| `reactor-input` | Gestures, drag-drop, focus management. |
32+
| `reactor-charts` | Data visualization. |
33+
| `reactor-commanding` | Actions in multiple surfaces, keyboard shortcuts, `CanExecute`. |
34+
| `reactor-devtools` | Driving a running app via `mur devtools` for screenshots / inspection. |
35+
| `reactor-recipes` | You need a paste-ready snippet for a common pattern (list with add/delete, themed card, sidebar nav, etc.). |
36+
37+
## Best Practices
38+
39+
- **Ground every API call.** Reactor is novel. If you're not 100% sure a method exists with the signature you remember, consult the api index from `reactor-dsl` references — never guess.
40+
- **Single-file `#:package` is the default for new apps.** Use a `.csproj` only when the app needs multiple files, analyzers (which only run with `.csproj`), or shared project references.
41+
- **Don't grep `src/Reactor/`.** The bundled api index is the source of truth for public API. Source-code grep is slower and includes private/internal noise.
42+
- **Don't add features beyond what's asked.** Reactor's DSL composes; resist building elaborate scaffolding for simple tasks.
43+
- **Hooks must be called unconditionally.** Same order every render. Conditionally use the *result*, not the call.
44+
- **Run `mur check <path>` after non-trivial edits.** It emits one-line diagnostics with skill pointers for known `REACTOR_*` IDs.

plugins/reactor/plugin.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "reactor",
3+
"description": "Agents and skills for building WinUI 3 desktop apps with Microsoft.UI.Reactor — a React-inspired declarative C# projection (no XAML, no data binding, no ViewModels). Use for creating new apps, adding features, fixing bugs, or any Reactor / Microsoft.UI.Reactor / functional WinUI task.",
4+
"version": "0.1.0",
5+
"author": {
6+
"name": "Microsoft",
7+
"url": "https://github.com/microsoft/microsoft-ui-reactor"
8+
},
9+
"license": "MIT",
10+
"keywords": [
11+
"reactor",
12+
"microsoft.ui.reactor",
13+
"winui",
14+
"winui3",
15+
"windows app sdk",
16+
"desktop app",
17+
"react",
18+
"declarative ui",
19+
"functional ui",
20+
"csharp",
21+
"dotnet",
22+
"winrt",
23+
"hooks",
24+
"components",
25+
"no xaml"
26+
],
27+
"category": "windows-development",
28+
"tags": [
29+
"windows",
30+
"winui",
31+
"winui3",
32+
"desktop",
33+
"reactor",
34+
"react",
35+
"declarative",
36+
"functional",
37+
"csharp"
38+
],
39+
"agents": "agents/",
40+
"skills": [
41+
"skills/"
42+
]
43+
}

0 commit comments

Comments
 (0)