Skip to main content

Getting Started

5 min read

Installation

Get Directive set up in your project in under a minute.


Requirements

  • Node.js 18.0 or higher
  • TypeScript 5.0 or higher (recommended but optional)

Install the Package

Using npm:

npm install @directive-run/core

Using pnpm:

pnpm add @directive-run/core

Using yarn:

yarn add @directive-run/core

Package Exports

Directive uses subpath exports for tree-shaking and smaller bundles:

// Core API – modules, systems, and type builders
import { createModule, createSystem, t } from '@directive-run/core';

// React adapter – reactive hooks for facts and derivations
import { useFact, useDerived, useDispatch } from '@directive-run/react';

// Plugins – extend the system with logging, devtools, or persistence
import { loggingPlugin, devtoolsPlugin, persistencePlugin } from '@directive-run/core/plugins';

// Testing utilities – mock resolvers and control async timing
import { createTestSystem, createMockResolver, flushMicrotasks } from '@directive-run/core/testing';

TypeScript Configuration

Directive is written in TypeScript and provides full type inference. For the best experience, ensure your tsconfig.json includes:

{
  "compilerOptions": {
    "strict": true,                  // Required for full type inference
    "moduleResolution": "bundler",   // Enables scoped package resolution
    "target": "ES2022"               // Proxy and WeakRef support
  }
}

Module Resolution

If you're using Node.js module resolution, you may need to set "moduleResolution": "node16" or "nodenext" instead of "bundler".


Bundle Size

Directive is designed to be lightweight:

ExportMinifiedGzipped
@directive-run/core~8 KB~3 KB
@directive-run/react~2 KB~1 KB
@directive-run/vue~2 KB~1 KB
@directive-run/svelte~2 KB~1 KB
@directive-run/solid~2 KB~1 KB
@directive-run/lit~2 KB~1 KB
@directive-run/core/plugins~4 KB~1.5 KB

All exports are tree-shakeable. Import only what you use.


Framework Setup

React

import { createSystem } from '@directive-run/core';
import { useFact, useDerived } from '@directive-run/react';
import { userModule } from './modules/user';

// Create and start the system at module scope
const system = createSystem({ module: userModule });
system.start();

// No provider needed – pass the system directly to hooks
function App() {
  const displayName = useDerived(system, "displayName");

  return <div>Hello, {displayName}</div>;
}

Vue

<script setup>
import { createSystem } from '@directive-run/core';
import { useFact } from '@directive-run/vue';
import { userModule } from './modules/user';

// Create the system
const system = createSystem({ module: userModule });
system.start();

// Pass system explicitly to hooks
const name = useFact(system, 'name');
</script>

Svelte

<script>
  import { createSystem } from '@directive-run/core';
  import { useFact } from '@directive-run/svelte';
  import { userModule } from './modules/user';

  // Create the system
  const system = createSystem({ module: userModule });
  system.start();

  // Pass system explicitly to hooks
  const name = useFact(system, 'name');
</script>

Vanilla TypeScript

import { createSystem } from '@directive-run/core';
import { userModule } from './modules/user';

const system = createSystem({ module: userModule });
system.start();

// Subscribe to derivation changes with a callback
system.watch("displayName", (newValue, prevValue) => {
  console.log('Display name changed:', newValue);
});

// Setting a fact triggers constraints and resolvers automatically
system.facts.userId = 123;

// Wait for all async resolvers to finish before reading results
await system.settle();

AI Setup

To use Directive's AI agent orchestration, install the AI package:

pnpm add @directive-run/core @directive-run/ai

Then import a provider adapter via subpath exports:

OpenAI

import { createAgentStack } from '@directive-run/ai';
import { createOpenAIRunner } from '@directive-run/ai/openai';

const runner = createOpenAIRunner({ apiKey: process.env.OPENAI_API_KEY! });
const stack = createAgentStack({ runner, agents: { assistant: { instructions: "You are helpful." } } });

Anthropic

import { createAgentStack } from '@directive-run/ai';
import { createAnthropicRunner } from '@directive-run/ai/anthropic';

const runner = createAnthropicRunner({ apiKey: process.env.ANTHROPIC_API_KEY! });

Ollama (local)

import { createAgentStack } from '@directive-run/ai';
import { createOllamaRunner } from '@directive-run/ai/ollama';

const runner = createOllamaRunner(); // defaults to localhost:11434
SubpathDescription
@directive-run/aiAgent orchestration, streaming, guardrails
@directive-run/ai/openaiOpenAI, Azure, Together, any OpenAI-compatible API
@directive-run/ai/anthropicAnthropic Claude models
@directive-run/ai/ollamaLocal Ollama inference

Development Setup

For the best development experience, add the devtools plugin:

import { createSystem } from '@directive-run/core';
import { devtoolsPlugin, loggingPlugin } from '@directive-run/core/plugins';
import { userModule } from './modules/user';

const system = createSystem({
  module: userModule,

  // Stack plugins for visibility into every state change
  plugins: [
    loggingPlugin({ level: 'debug' }),
    devtoolsPlugin(),
  ],

  // Enable time-travel to step through state history
  debug: {
    timeTravel: true,
    maxSnapshots: 100,
  },
});

system.start();

CDN Usage

For quick prototyping, you can use Directive from a CDN:

<script type="module">
  // Import directly from a CDN – no build step needed
  import { createModule, createSystem, t } from 'https://esm.sh/@directive-run/core';

  // Define a minimal counter module
  const counterModule = createModule("counter", {
    schema: {
      facts: { count: t.number() },
      derivations: {},
      events: {},
      requirements: {},
    },
    init: (facts) => { facts.count = 0; },
  });

  // Wire it up and start
  const system = createSystem({ module: counterModule });
  system.start();

  // Mutate facts directly – the proxy tracks the change
  system.facts.count++;
  console.log(system.facts.count); // 1
</script>

Troubleshooting

Cannot find module @directive-run/react

Ensure your TypeScript config uses a compatible module resolution:

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}

Type errors with facts

Make sure you've initialized all facts in the init function. Uninitialized facts will have undefined type.

Bundle too large

Check that you're only importing what you need. Avoid:

// Pulls in everything, defeating tree-shaking
import * as Directive from '@directive-run/core'; // Don't do this

Instead:

// Import only what you need – unused exports are removed at build time
import { createModule, createSystem } from '@directive-run/core';

Next Steps

Previous
Quick Start

We care about your data. We'll never share your email.

Powered by Directive. This signup uses a Directive module with facts, derivations, constraints, and resolvers – zero useState, zero useEffect. Read how it works

Directive - Constraint-Driven State Management for TypeScript