Iii iii-state-reactions
install
source · Clone the upstream repo
git clone https://github.com/iii-hq/iii
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/iii-hq/iii "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/iii-state-reactions" ~/.claude/skills/iii-hq-iii-iii-state-reactions && rm -rf "$T"
manifest:
skills/iii-state-reactions/SKILL.mdsource content
State Reactions
Comparable to: Firebase onSnapshot, Convex mutations
Key Concepts
Use the concepts below when they fit the task. Not every state reaction needs all of them.
- A state trigger fires whenever a value changes within a watched scope
- The handler receives
describing the change{ new_value, old_value, key, event_type } - condition_function_id gates execution — the reaction only fires if the condition returns truthy
- Multiple reactions can independently watch the same scope
- Reactions fire on
,state::set
, andstate::update
operationsstate::delete
Architecture
state::set, state::update, or state::delete → iii-state emits change event → registerTrigger type:'state' (scope match) → condition_function_id check (if configured) → registerFunction handler ({ new_value, old_value, key, event_type })
iii Primitives Used
| Primitive | Purpose |
|---|---|
| Define the reaction handler |
| Watch a scope for changes |
| Scope filter and optional condition gate |
Event payload: | Change details passed to the handler |
Reference Implementation
See ../references/state-reactions.js for the full working example — a reaction that watches a state scope and fires side effects when values change, with an optional condition gate.
Also available in Python: ../references/state-reactions.py
Also available in Rust: ../references/state-reactions.rs
Common Patterns
Code using this pattern commonly includes, when relevant:
— worker initializationregisterWorker(url, { workerName })
— define the reaction handlerregisterFunction(id, handler)
— watch for changesregisterTrigger({ type: 'state', function_id, config: { scope, key, condition_function_id } })
/payload.new_value
— compare before and afterpayload.old_value
— distinguish between set, update, and delete eventspayload.event_type
— write derived state from the reactiontrigger({ function_id: 'state::set', payload })
— structured logging per reactionconst logger = new Logger()
Adapting This Pattern
Use the adaptations below when they apply to the task.
- Set
to watch a specific domain (e.g.scope
,orders
)user-profiles - Use
to narrow reactions to a single key within a scopekey - Add a
to filter — only react when the condition function returns truthycondition_function_id - Chain reactions by writing state in one handler that triggers another reaction on a different scope
Engine Configuration
iii-state must be enabled in iii-config.yaml for state triggers to fire. See ../references/iii-config.yaml for the full annotated config reference.
Pattern Boundaries
- If the task is about directly reading or writing state without reactions, prefer
.iii-state-management - If the task needs conditional trigger logic shared across trigger types, prefer
.iii-trigger-conditions - Stay with
when the primary need is automatic side effects on state changes.iii-state-reactions
When to Use
- Use this skill when the task is primarily about
in the iii engine.iii-state-reactions - Use this skill when the request directly asks for this pattern or an equivalent implementation.
Boundaries
- Never use this skill as a generic fallback for unrelated tasks.
- You must not apply this skill when a more specific iii skill is a better fit.
- Always verify environment and safety constraints before applying examples from this skill.