The constraint-driven runtime for TypeScript. Declare what must be true. The runtime makes it happen.
Other state libraries react to what happened. Directive enforces what must be true.
// Traditional: describe HOW to change state
dispatch({ type: 'FETCH_USER', id: 123 });
// then write a thunk, saga, or effect to handle it...
// Directive: declare WHAT must be true
constraints: {
needsUser: {
when: (facts) => facts.userId > 0 && !facts.user,
require: { type: "FETCH_USER" },
},
}
// The runtime handles when, how, retry, and error recovery.
Set userId = 123 and the constraint fires, the resolver fetches the user, and the system settles — automatically.
npm install @directive-run/core
import { createModule, createSystem, t, type ModuleSchema } from '@directive-run/core';
const userModule = createModule("user", {
schema: {
facts: {
userId: t.number(),
user: t.object<{ id: number; name: string } | null>(),
},
derivations: { isLoggedIn: t.boolean() },
events: {},
requirements: { FETCH_USER: {} },
} satisfies ModuleSchema,
init: (facts) => {
facts.userId = 0;
facts.user = null;
},
constraints: {
needsUser: {
when: (facts) => facts.userId > 0 && facts.user === null,
require: { type: "FETCH_USER" },
},
},
resolvers: {
fetchUser: {
requirement: "FETCH_USER",
resolve: async (req, context) => {
const res = await fetch(`/api/users/${context.facts.userId}`);
context.facts.user = await res.json();
},
},
},
derive: {
isLoggedIn: (facts) => facts.user !== null,
},
});
const system = createSystem({ module: userModule });
system.start();
system.facts.userId = 123; // Constraint fires automatically
await system.settle(); // Wait for resolution
console.log(system.facts.user); // { id: 123, name: "John" }
The same constraint-driven model powers AI agent safety. Guardrails are constraints. Agent runs are resolvers. The runtime enforces them automatically.
npm install @directive-run/ai
import { createAgentOrchestrator } from '@directive-run/ai';
import { createAnthropicAdapter } from '@directive-run/ai/anthropic';
const orchestrator = createAgentOrchestrator({
agent: {
name: "assistant",
model: createAnthropicAdapter({ model: "claude-sonnet-4-5-20250514" }),
systemPrompt: "You are a helpful assistant.",
},
guardrails: {
input: [promptInjectionGuardrail(), piiGuardrail()],
output: [contentModerationGuardrail()],
},
budget: { maxTotalCost: 1.00 },
});
fetch, zero SDK deps)npm install @directive-run/react
import { useFact, useDerived } from '@directive-run/react';
function UserProfile({ system }) {
const user = useFact(system, "user");
const isLoggedIn = useDerived(system, "isLoggedIn");
if (!isLoggedIn) return <p>Please log in</p>;
return <p>Hello, {user?.name}!</p>;
}
| Framework | Package | Style |
|---|---|---|
| React | @directive-run/react |
Hooks with useSyncExternalStore |
| Vue | @directive-run/vue |
Composables with reactive refs |
| Svelte | @directive-run/svelte |
Stores with $ syntax |
| Solid | @directive-run/solid |
Signals with fine-grained reactivity |
| Lit | @directive-run/lit |
Reactive Controllers for Web Components |
| Redux | Zustand | XState | Directive | |
|---|---|---|---|---|
| Constraint-driven resolution | Yes | |||
| Auto-tracking derivations | Yes | |||
| AI guardrails + orchestration | Yes | |||
| Retry, batching, error boundaries | Manual | Manual | Manual | Built-in |
| Time-travel debugging | Extension | Partial | Built-in | |
| Framework-agnostic (6 adapters) | React only | React only | Any | Any |
| Zero runtime dependencies | Yes | Yes | ||
explain() – why does this state exist? |
Yes |
| Package | Description |
|---|---|
@directive-run/core |
Core runtime – modules, systems, plugins, testing |
@directive-run/react |
React hooks (useFact, useDerived, useSelector, etc.) |
@directive-run/vue |
Vue composables with reactive refs |
@directive-run/svelte |
Svelte stores with $ syntax |
@directive-run/solid |
Solid signals with fine-grained reactivity |
@directive-run/lit |
Lit reactive controllers |
@directive-run/ai |
AI orchestration, guardrails, multi-agent |
@directive-run/cli |
CLI – scaffolding, inspection, AI coding rules |
See CONTRIBUTING.md for development setup and architecture overview. A CLA signature is required for all contributions.
MIT OR Apache-2.0 — your choice.