Provides API guidance for FlowMVI stores, decorators, and plugin pipelines. Use for architectural patterns in MVI projects.

Install

mkdir -p .claude/skills/flowmvi && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6369" && unzip -o skill.zip -d .claude/skills/flowmvi && rm skill.zip

Installs to .claude/skills/flowmvi

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

FlowMVI usage guidance. Use when working with FlowMVI stores/containers, plugin pipelines, composing stores, decorators, or authoring plugins.
142 chars✓ has a “when” trigger
Advanced

Key capabilities

  • Defines immutable MVI state models using sealed interfaces
  • Constructs plugin pipelines for MVI stores
  • Implements intent and action contracts
  • Authors store decorators for short-circuiting logic
  • Configures ordered plugin chains

How it works

It provides a set of reference templates and API signatures that structure the MVI store, enforcing a strict pipeline of intents, actions, and plugin callbacks.

Inputs & outputs

You give it
Store definition requirements
You get back
MVI-compliant store code

When to use flowmvi

  • Defining MVI contracts with State, Intent, and Action
  • Building and configuring MVI store plugin pipelines
  • Authoring decorators to wrap and modify plugin chain behavior
  • Designing immutable state models

About this skill

Overview

Use this to learn the API of FlowMVI. Prefer the bundled references for exact APIs and the live official docs for plugins/integrations/state.

Key references in this skill:

  • references/api-signatures.md for core API signatures.
  • references/plugin-signatures.md for all plugin/decorator signatures.
  • references/plugin-callbacks.md for callback behavior and decorator semantics.
  • references/docs-index.md for live docs URLs (plugins, integrations, state).

Use rg over references/*signatures*.md for discovery and open URLs from references/docs-index.md when you need full docs.

Core loop

  • Define a Contract: MVIState, MVIIntent, MVIAction.
  • Build a Store: uses a plugin pipeline, handles intents, updates state, emits actions (side effects).
  • Install Plugins: ordered chain of responsibility. Order changes behavior.
  • Install Decorators: wrap the entire plugin chain and can short-circuit it.
  • Subscribers render state and handle actions.

Contract and state design

State

  • Make state immutable and comparable. Use data class / data object.
  • Use sealed interfaces for LCE or multi-branch screens. Avoid placeholder fields.
  • Use EmptyState if no state is needed.

Example (state family):

sealed interface CounterState : MVIState {
    data object Loading : CounterState
    data class Content(val count: Int) : CounterState
    data class Error(val cause: Exception) : CounterState
}

Intent and action

  • MVIIntent: inputs/events. Use sealed interfaces for MVI style.
  • MVIAction: one-off effects, never rely on them for critical logic.
  • If no actions, use Nothing or the no-action store overload.
sealed interface CounterIntent : MVIIntent {
    data object Tap : CounterIntent
    data class Set(val value: Int) : CounterIntent
}

sealed interface CounterAction : MVIAction {
    data class ShowToast(val text: String) : CounterAction
}

Store creation patterns

Container pattern

Prefer a container per screen/feature and expose the store as a property.

class CounterContainer : Container<CounterState, CounterIntent, CounterAction> {
    override val store = store(initial = CounterState.Loading) {
        configure { debuggable = BuildFlags.debuggable; name = "CounterStore" }
        reduce { intent ->
            when (intent) {
                is CounterIntent.Set -> updateState<_, CounterState.Content> { copy(count = intent.value) }
                is CounterIntent.Tap -> action(CounterAction.ShowToast("tap"))
            }
        }
    }
}

Use lazyStore when construction is heavy or should be deferred.

MVVM+ Intents

Intents can be lambdas (Orbit MVI-style):

// contract
typealias CounterIntent = LambdaIntent<CounterState, CounterAction>

// sending
fun onTap() = store.intent { updateState<State.Content, _> { copy(count = count + 1) } }

When using LambdaIntent:

  • Mandatory: Install reduceLambdas plugin to invoke intent blocks.
  • Prefer ImmutableStore/ImmutableContainer at the edges to avoid leaking context.
  • Plugins lose observability into intent contents, prefer regular intents unless codebase already uses lambdas.

State management (SST)

FlowMVI serializes state transactions by default.

Use:

  • updateState { } for atomic updates.
  • withState { } for safe reads.
  • Typed overloads for state families: updateState<T, R> { } and withState<T, R> { } (note always two parameters, of which first is target state, and second is always underscore _). Also these need an import.
  • updateStateImmediate only for performance-critical hot paths; it bypasses plugins and safety.

PipelineContext API

You get PipelineContext receiver inside most of the store DSLs and plugin callbacks. Key operations:

  • updateState { }, withState { }, updateStateImmediate { }
  • action(action) and intent(intent)
  • config for store config and logging
  • Flow.consume(context) for safe collection in store context

Exact signatures in references/api-signatures.md.

Store configuration

Configure inside store { configure { ... } }. Defaults are defined in StoreConfigurationBuilder.

Key flags:

  • debuggable: enable validations + verbose logging.
  • name: used for logging/debugging and store identity.
  • parallelIntents: process intents concurrently (state safety becomes critical).
  • coroutineContext: merged with start scope.
  • actionShareBehavior: Distribute, Share, Restrict, Disabled.
  • intentCapacity + onOverflow: buffer sizing and backpressure.
  • stateStrategy: Atomic(reentrant = true/false) or Immediate.
  • allowIdleSubscriptions, allowTransientSubscriptions.
  • logger, verifyPlugins.

See exact defaults in references/api-signatures.md and use references/docs-index.md for the latest state docs.

Exact signatures: references/api-signatures.md.

Plugins (system)

Plugins are the core of FlowMVI. Order matters.

  • Install plugins in the order you want them to intercept events.
  • Plugins can consume, modify, or veto intents/actions/states.
  • Use reduce early if you want later plugins to observe processed intents.

All plugin signatures are in references/plugin-signatures.md. All callback signatures and behavior are in references/plugin-callbacks.md.

Prebuilt plugin catalog

Open references/docs-index.md and references/plugin-signatures.md for the full list. Core plugins include:

  • reduce, init, asyncInit, recover, whileSubscribed
  • enableLogging
  • cache / asyncCache
  • manageJobs
  • awaitSubscribers
  • undoRedo
  • disallowRestart
  • timeTravel
  • consumeIntents
  • deinit, resetStateOnStop
  • saved state plugins (savedstate module)
  • remote debugger plugins (debugger modules)

Creating custom plugins

Use the plugin DSL to intercept store events. Use lazyPlugin when you need config at creation time.

val analytics = plugin<State, Intent, Action> {
    onIntent { intent -> log { "intent = $intent" }; intent }
}

Rules:

  • Do not call updateState inside onState to avoid loops.
  • Never throw from onUndeliveredIntent/onUndeliveredAction.

Use references/plugin-callbacks.md for full behavior rules.

Decorators (plugins for plugins)

Decorators wrap plugins and can short-circuit the entire chain.

  • decorators run after plugins; they wrap all previously installed plugins.
  • If you do not invoke child.onX(...) in a decorator, the chain stops there.
  • Decorators return final values, not intermediate chain values.

Use decorators only when:

  • You need to instrument, retry, debounce, or batch the whole chain.
  • You want cross-cutting behavior that is hard to express as a plugin without chain control.

Child stores

Tie lifecycle of child stores to a parent store:

val child = store(ChildState.Loading) { /* ... */ }
val parent = store(ParentState.Loading) {
    this hasChild child
}

Delegation

Delegate state/actions from another store and project them:

val feedState by delegate(feedStore) { action -> /* handle */ }
whileSubscribed { feedState.collect { state -> /* render */ } }

Use DelegationMode.Immediate when you need always-hot projections. Default WhileSubscribed mode yields stale projections when no subscribers.

Prefer building tree-like store hierarchies using children and delegates for complex business logic.

Other

Use savedstate module for persistence, metrics module to set up metrics, and essenty for decompose integration.

More info in references/docs-index.md

When not to use it

  • When the application logic is simple enough for standard state lifting
  • When the project architecture is not MVI-compliant

Prerequisites

kotlinFlowMVI library

Limitations

  • Requires deep familiarity with Kotlin
  • Plugin order behavior is complex to debug

How it compares

It provides structured API references and patterns for MVI, whereas manual implementation often leads to inconsistent plugin ordering.

Compared to similar skills

flowmvi side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
flowmvi (this skill)16moNo flagsAdvanced
Android Dependency Injection (Hilt)05moNo flagsBeginner
kotlin-multiplatform323moReviewAdvanced
backend-microservice-development23moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

Android Dependency Injection (Hilt)

li-lance

Standards for Hilt Setup, Scoping, and Modules

00

kotlin-multiplatform

vitorpamplona

Platform abstraction decision-making for Amethyst KMP project. Guides when to abstract vs keep platform-specific, source set placement (commonMain, jvmAndroid, platform-specific), expect/actual patterns. Covers primary targets (Android, JVM/Desktop, iOS) with web/wasm future considerations. Integrates with gradle-expert for dependency issues. Triggers on: abstraction decisions ("should I share this?"), source set placement questions, expect/actual creation, build.gradle.kts work, incorrect placement detection, KMP dependency suggestions.

32156

backend-microservice-development

TencentBlueKing

后端微服务开发规范,涵盖目录结构、分层架构(API/Service/DAO)、依赖注入、配置管理、Spring Boot 最佳实践。当用户进行后端开发、创建新微服务、编写 Kotlin/Java 代码或设计服务架构时使用。

213

kotlin-coroutines

vitorpamplona

Advanced Kotlin coroutines patterns for AmethystMultiplatform. Use when working with: (1) Structured concurrency (supervisorScope, coroutineScope), (2) Advanced Flow operators (flatMapLatest, combine, merge, shareIn, stateIn), (3) Channels and callbackFlow, (4) Dispatcher management and context switching, (5) Exception handling (CoroutineExceptionHandler, SupervisorJob), (6) Testing async code (runTest, Turbine), (7) Nostr relay connection pools and subscriptions, (8) Backpressure handling in event streams. Delegates to kotlin-expert for basic StateFlow/SharedFlow patterns. Complements nostr-expert for relay communication.

311

extensions-api-migration

JetBrains

Migrates IdeaVim extensions from the old VimExtensionFacade API to the new @VimPlugin annotation-based API. Use when converting existing extensions to use the new API patterns.

13

trail-sense-database-persistence

kylecorry31

Add new Room database persistence to Trail-Sense Android app. Use when the user asks to create, add, or implement database persistence for a model, including Entity, DAO, Repository, and AppDatabase migration. Covers entity-to-model mapping, index configuration, and standard CRUD operations.

10

Search skills

Search the agent skills registry