@directive-run/scaffold
v0.2.1
Published
Pure source-string generators for Directive modules and orchestrators. Shared substrate consumed by @directive-run/cli (its `directive new` command) and @directive-run/mcp (its `generate_module` tool). Zero runtime dependencies.
Maintainers
Readme
@directive-run/scaffold
Pure source-string generators for Directive modules and orchestrators. Zero runtime dependencies. Shared substrate consumed by @directive-run/cli (its directive new <name> command writes the result to disk) and @directive-run/mcp (its generate_module MCP tool returns the result to the calling AI client without ever touching disk).
You probably don't depend on this package directly — it's the engine behind the user-facing scaffolding flows. Install it explicitly if you're building tooling that needs to programmatically generate Directive module skeletons.
API
import {
generateModule,
generateOrchestrator,
generateRunner,
validateModuleName,
suggestFileNames,
requiredPackages,
toCamelCase,
MODULE_SECTIONS,
SCAFFOLD_KINDS,
type GeneratedScaffold,
type ModuleSection,
type ScaffoldKind,
} from "@directive-run/scaffold";
// Generate a full Directive module with every section. Returns a
// `GeneratedScaffold` object — a paired (moduleSource, runnerSource)
// bundle so the consumer can drop the library AND a driver that
// boots it in one go.
const result = generateModule("traffic-light");
// result.moduleSource — the `createModule(...)` library text
// result.runnerSource — the `createSystem` + `start` + log driver
// result.suggestedFilenames — { module: "traffic-light.ts", runner: "main.ts" }
// result.runnable — true when moduleSource already calls .start()
// Generate a minimal module (schema + init only)
const minimal = generateModule("traffic-light", []);
// Pick which sections to include
const customized = generateModule("traffic-light", [
"derive",
"constraints",
"resolvers",
]);
// Generate an AI orchestrator module (also returns GeneratedScaffold)
const orch = generateOrchestrator("chat-agent");
// Build a runner for an existing module source (useful when the
// consumer already has a module and just wants the driver scaffolded).
const runner = generateRunner({
moduleSource: result.moduleSource,
kebabName: "traffic-light",
});
// Validate a name before generating
const ok = validateModuleName("traffic-light"); // true | string
// Suggested file names
suggestFileNames("traffic-light", "module");
// → { sourceFileName: "traffic-light.ts", testFileName: "traffic-light.test.ts" }
// What the consumer needs to install
requiredPackages("orchestrator");
// → ["@directive-run/core", "@directive-run/ai"]Writing to disk
generateModule returns paired sources, not a single string. Drop both
files onto the consumer's filesystem so the runner can import from the
module:
import { writeFileSync } from "node:fs";
const { moduleSource, runnerSource, suggestedFilenames } =
generateModule("traffic-light");
writeFileSync(suggestedFilenames.module, moduleSource);
if (runnerSource) writeFileSync(suggestedFilenames.runner, runnerSource);Naming rule
Module names must match /^[a-z][a-z0-9-]{0,63}$/ — start with a lowercase letter, contain only lowercase letters, digits, and hyphens, and be 64 characters or fewer. validateModuleName(name) returns true on success or a human-readable error string. All generator functions assert the same rule and throw Error on invalid input — important because the generated source embeds the name as a JavaScript identifier and a string literal.
See also
@directive-run/cli—directive new <name>writes the generated source to disk.@directive-run/mcp—generate_moduleMCP tool returns the generated source to AI clients.@directive-run/core— the runtime the generated modules import from.
