Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "mobx-dart",
"owner": {
"name": "MobX.dart Contributors"
},
"metadata": {
"description": "Claude Code plugins for MobX.dart — reactive state management for Dart and Flutter",
"version": "1.0.0",
"pluginRoot": "."
},
"plugins": [
{
"name": "mobx-dart",
"version": "2.6.0",
"description": "MobX.dart agent skills — observables, actions, reactions, Observer widget, store patterns, and code generation",
"source": "."
}
]
}
13 changes: 13 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "mobx-dart",
"version": "2.6.0",
"description": "MobX.dart agent skills for Claude Code — reactive state management with observables, actions, reactions, and Flutter integration",
"author": {
"name": "MobX.dart Contributors",
"url": "https://github.com/mobxjs/mobx.dart"
},
"homepage": "https://mobx.netlify.app",
"repository": "https://github.com/mobxjs/mobx.dart",
"license": "MIT",
"keywords": ["dart", "flutter", "mobx", "state-management", "reactive"]
}
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,47 @@ class _CounterExampleState extends State<CounterExample> {
}
```

## Working with AI

This repository includes [Agent Skills](https://agentskills.io) that give AI coding assistants deep knowledge of MobX.dart APIs, patterns, and best practices. Skills work with Claude Code, Cursor, Windsurf, and [35+ other agents](https://skills.sh).

### Installation

```bash
npx skills add mobxjs/mobx.dart
```

Target a specific agent with `--agent`:

```bash
npx skills add mobxjs/mobx.dart --agent cursor
npx skills add mobxjs/mobx.dart --agent claude-code
```

Or install globally so the skill is available across all your projects:

```bash
npx skills add mobxjs/mobx.dart --global
```

For Claude Code, you can also install via the plugin system:

```
/plugin marketplace add mobxjs/mobx.dart
/plugin install mobx-dart@mobx-dart
```

### What's Included

The `mobx-dart` skill covers:

- **Core APIs** — Store class pattern, `@observable`, `@computed`, `@action`, `@readonly` annotations, code generation with `mobx_codegen`
- **Reactions** — `autorun`, `reaction`, `when`, `asyncWhen`, custom schedulers
- **Flutter Integration** — `Observer` widget, `Observer.withBuiltChild`, `ReactionBuilder`
- **Reactive Collections** — `ObservableList`, `ObservableMap`, `ObservableSet`, `ObservableFuture`, `ObservableStream`, `Atom`
- **Best Practices** — Widget-Store-Service triad, store organization, reactivity rules, JSON serialization
- **Advanced** — `ReactiveContext`, `ReactiveConfig`, read/write policies, Spy debugging

## Contributing

If you have read up till here, then 🎉🎉🎉. There are couple of ways in which you can contribute to
Expand Down
117 changes: 117 additions & 0 deletions docs/docs/guides/working-with-ai.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
slug: /guides/working-with-ai
title: Working with AI
---

import { PubBadge } from '../../src/components/Shield';

AI coding assistants like Claude Code, GitHub Copilot, and Cursor can be powerful
allies when building MobX.dart applications. This guide covers tips for getting
the most out of AI tools with MobX.

## Tips for Prompting AI

### Be Explicit About the MobX Triad

When asking AI to create stores, mention the specific MobX concepts you want:

- **"Create a store with `@observable` fields, `@computed` getters, and `@action` methods"**
- **"Add a `reaction` that validates the email field when it changes"**
- **"Wrap the counter display in an `Observer` widget"**

AI tools work best when you use MobX-specific terminology rather than generic
descriptions.

### Remind AI About Code Generation

MobX.dart relies on `mobx_codegen`. When asking AI to create a store, remind it
about the boilerplate:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this part is not necessarily true for every project. Some projects rely purely on raw observables rather than using codegen, so we should not make it a mandate that everyone has to go through codegen.


```dart
// Include the part directive and class structure
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = _Counter with _$Counter;

abstract class _Counter with Store {
// ... store body
}
```

### Common Pitfalls to Watch For

When reviewing AI-generated MobX code, watch for these issues:

1. **Missing `part` directive** — AI may forget `part 'filename.g.dart';`
2. **Deep observability assumption** — AI may assume nested objects are automatically
tracked. Dart MobX does **not** support deep observability.
3. **Observer tracking scope** — AI may place observable reads inside nested
functions within `Observer.builder`, where they won't be tracked.
4. **Plain collections** — AI may use `List<T>` instead of `ObservableList<T>`
when item-level tracking is needed.

## Agent Skills

This repository includes [Agent Skills](https://agentskills.io) that give AI
coding assistants deep knowledge of MobX.dart APIs, patterns, and best practices.
Skills work with Claude Code, Cursor, Windsurf, and other AI tools that support them.

### Installation

```bash
npx skills add mobxjs/mobx.dart
```

Target a specific agent with `--agent`:

```bash
npx skills add mobxjs/mobx.dart --agent cursor
npx skills add mobxjs/mobx.dart --agent claude-code
```

Or install globally so the skill is available across all your projects:

```bash
npx skills add mobxjs/mobx.dart --global
```

For Claude Code, you can also install via the plugin system:

```
/plugin marketplace add mobxjs/mobx.dart
/plugin install mobx-dart@mobx-dart
```

### What's Included

The `mobx-dart` skill covers:

- **Core APIs** — Store class pattern, `@observable`, `@computed`, `@action`, `@readonly`,
code generation with <PubBadge name="mobx_codegen" />
- **Reactions** — `autorun`, `reaction`, `when`, `asyncWhen`, custom schedulers
- **Flutter Integration** — `Observer` widget, `Observer.withBuiltChild`, `ReactionBuilder`
- **Reactive Collections** — `ObservableList`, `ObservableMap`, `ObservableSet`,
`ObservableFuture`, `ObservableStream`, `Atom`
- **Best Practices** — Widget-Store-Service triad, store organization, reactivity rules,
JSON serialization
- **Advanced** — `ReactiveContext`, `ReactiveConfig`, read/write policies, Spy debugging

## Custom Instructions for AI Tools

If your AI tool supports custom instructions (e.g., `.cursorrules`, `CLAUDE.md`,
`.github/copilot-instructions.md`), consider adding MobX-specific guidance:

```markdown
## MobX.dart Conventions

- Use `mobx_codegen` annotations (`@observable`, `@computed`, `@action`)
- Always include `part 'filename.g.dart';` in store files
- Use `ObservableList`/`ObservableMap`/`ObservableSet` for reactive collections
- Wrap UI in `Observer` widget and read observables in immediate builder context
- Follow Widget-Store-Service triad for architecture
- Do not mutate observables outside of actions
```

This ensures consistent, correct MobX code regardless of which AI tool you use.
1 change: 1 addition & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module.exports = {
'guides/when-does-mobx-react',
'guides/mobx-vs-inherited-model',
'guides/mobx-utils',
'guides/working-with-ai',
],
},
'community',
Expand Down
5 changes: 5 additions & 0 deletions skills/mobx-dart/GENERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Generation Info

- **Source:** `sources/mobx.dart`
- **Git SHA:** `39a1f18c2e76a564b5e5358426d335569bc332ec`
- **Generated:** 2026-03-30
110 changes: 110 additions & 0 deletions skills/mobx-dart/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
name: mobx-dart
description: >-
This skill should be used when working with MobX.dart for Dart/Flutter state management,
when the user asks to "create a store", "add observable", "add action", "add computed",
"use Observer widget", "set up reactions", "organize stores",
or when code imports `package:mobx/mobx.dart`, `package:flutter_mobx/flutter_mobx.dart`,
or `package:mobx_codegen/mobx_codegen.dart`.
Covers observables, actions, reactions, Observer widget, store patterns,
code generation with mobx_codegen, and reactive collections.
---

# MobX.dart

MobX.dart is a reactive state management library for Dart and Flutter built around three core concepts: **Observables** (reactive state), **Actions** (state mutations), and **Reactions** (side-effects). It uses `mobx_codegen` for annotation-based code generation to minimize boilerplate.

## Packages

| Package | Purpose |
|---------|---------|
| `mobx` | Core library: Observables, Actions, Reactions |
| `flutter_mobx` | Flutter integration: Observer widget, ReactionBuilder |
| `mobx_codegen` | Code generation: `@observable`, `@computed`, `@action` annotations |

## Store Declaration Pattern

Every store follows this boilerplate:

```dart
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = _Counter with _$Counter;

abstract class _Counter with Store {
@observable
int value = 0;

@computed
bool get isPositive => value > 0;

@action
void increment() {
value++;
}
}
```

Run code generation with:
```bash
flutter pub run build_runner watch --delete-conflicting-outputs
```

## Key Annotations

| Annotation | Target | Purpose |
|---|---|---|
| `@observable` | Field | Make field reactive |
| `@readonly` | Private field | Observable with auto-generated public getter; mutations only via `@action` |
| `@computed` | Getter | Derived state that auto-updates when dependencies change |
| `@action` | Method | Wrap mutations in a transaction; supports async |
| `@MakeObservable()` | Field | Advanced config (e.g., `useDeepEquals: true`) |

## Observer Widget

Wrap reactive UI in `Observer` from `flutter_mobx`:

```dart
Observer(builder: (_) => Text('${counter.value}'))
```

**Critical**: Only observables read in the **immediate execution context** of the builder are tracked. Observables read inside nested functions or callbacks are NOT tracked.

## Reactive Collections

Use `ObservableList`, `ObservableMap`, `ObservableSet` instead of plain Dart collections for item-level tracking. Use `ObservableFuture` and `ObservableStream` for async state.

## Reference Files

For detailed API documentation, patterns, and best practices, consult:

### Core

- **[`references/core-store-and-codegen.md`](references/core-store-and-codegen.md)** — Store class pattern, annotations, build_runner, generated output
- **[`references/core-observables.md`](references/core-observables.md)** — Observable, Computed, @observable, @readonly, @computed, reactive extensions
- **[`references/core-actions.md`](references/core-actions.md)** — @action, runInAction, untracked, transaction, async actions
- **[`references/core-reactions.md`](references/core-reactions.md)** — autorun, reaction, when, asyncWhen, custom schedulers

### Flutter Integration

- **[`references/features-observer-widget.md`](references/features-observer-widget.md)** — Observer, Observer.withBuiltChild, ReactionBuilder
- **[`references/features-reactive-collections.md`](references/features-reactive-collections.md)** — ObservableList/Map/Set/Future/Stream, Atom

### Best Practices

- **[`references/best-practices-store-organization.md`](references/best-practices-store-organization.md)** — Widget-Store-Service triad, store hierarchy, Provider integration
- **[`references/best-practices-reactivity-rules.md`](references/best-practices-reactivity-rules.md)** — When MobX reacts, tracking pitfalls, form validation
- **[`references/best-practices-json-serialization.md`](references/best-practices-json-serialization.md)** — json_serializable integration, custom converters

### Advanced

- **[`references/advanced-context-and-config.md`](references/advanced-context-and-config.md)** — ReactiveContext, ReactiveConfig, read/write policies
- **[`references/advanced-spy.md`](references/advanced-spy.md)** — Spy API for tracing and debugging reactive events

## Important Notes

- **No deep observability**: Unlike JS MobX, marking a complex object as `@observable` only tracks reference reassignment, not internal field changes. Mark individual fields with `@observable`.
- **Action enforcement**: By default, mutating an observed observable outside an action throws. Single-property setters in codegen stores are auto-wrapped.
- **Computed caching**: `.value` always re-evaluates, but notifications only fire when the result differs from the previous value.
72 changes: 72 additions & 0 deletions skills/mobx-dart/references/advanced-context-and-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
name: advanced-context-and-config
description: ReactiveContext and ReactiveConfig for custom MobX contexts, read/write policies, and error boundaries
---

# ReactiveContext and Configuration

MobX operates within a `ReactiveContext` that manages observables and reactions. By default, the singleton `mainContext` is used. Custom contexts are an advanced feature for isolating reactive systems.

## ReactiveContext

Create a custom context for isolated reactivity (e.g., a library using MobX internally that shouldn't share context with the host app):

```dart
final myContext = ReactiveContext(config: ReactiveConfig(
writePolicy: ReactiveWritePolicy.always,
));

final counter = Observable(0, context: myContext);
```

## ReactiveConfig

```dart
ReactiveConfig({
bool disableErrorBoundaries = false,
ReactiveWritePolicy writePolicy = ReactiveWritePolicy.observed,
ReactiveReadPolicy readPolicy = ReactiveReadPolicy.never,
int maxIterations = 100,
})
```

### Write Policy

Controls enforcement of mutations inside actions:

| Policy | Behavior |
|---|---|
| `observed` (default) | Throws only if the mutated observable is currently being observed |
| `always` | Always requires mutations inside an action |
| `never` | No enforcement (discouraged) |

### Read Policy

Controls enforcement of reading observables inside reactive contexts:

| Policy | Behavior |
|---|---|
| `never` (default) | Reads allowed anywhere |
| `always` | Reads must happen inside an Action or Reaction |

### Error Boundaries

`disableErrorBoundaries: true` makes MobX not catch exceptions in reactions (useful for debugging). Default is `false` — MobX catches and logs unhandled exceptions.

### Max Iterations

`maxIterations` (default: 100) limits reaction cycles. If reactions keep triggering more reactions beyond this limit, MobX throws to prevent infinite loops from cyclical dependencies.

## Modifying mainContext

```dart
mainContext.config = mainContext.config.clone(
writePolicy: ReactiveWritePolicy.always,
isSpyEnabled: true,
);
```

<!--
Source references:
- https://mobx.netlify.app/api/context
-->
Loading
Loading