# @x12i/runx

> Runx — Composer, Auditor, governed capability runtime (Catalox catalog, Runner scripts, folder LLM functions).

Latest version **3.0.0** (published 2026-07-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install @x12i/runx
pnpm add @x12i/runx
yarn add @x12i/runx
bun add @x12i/runx
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 3.0.0 |
| Published | 2026-07-23 |
| First published | 2026-05-17 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20 |
| Dependencies | 6 |
| Unpacked size | 790.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | x12i |
| Keywords | runx, catalox, capabilities, condition, jsonlogic, x12i |

## Links

- npm: https://www.npmjs.com/package/@x12i/runx
- Repository: https://github.com/x12i/funcx
- Homepage: https://github.com/x12i/funcx/tree/main/runx/packages/runx#readme
- Issues: https://github.com/x12i/funcx/issues
- npm.io page: https://npm.io/package/@x12i/runx

## Dependencies (6)

- [zod](https://npm.io/package/zod.md) ^3.25.76
- [jsonata](https://npm.io/package/jsonata.md) ^2.2.0
- [@x12i/catalox](https://npm.io/package/@x12i/catalox.md) ^6.0.0
- [@x12i/rendrix](https://npm.io/package/@x12i/rendrix.md) ^4.3.0
- [json-logic-js](https://npm.io/package/json-logic-js.md) ^2.0.5
- [@x12i/runx-mcp](https://npm.io/package/@x12i/runx-mcp.md) 3.0.0

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 3.0.0 (latest) — 2026-07-23
- 2.0.0 — 2026-06-26
- 1.3.2 — 2026-06-04
- 1.3.0 — 2026-05-17

## README

# @x12i/runx

**Runx** is a Catalox-backed capability platform with:

- **Composer** — `@x12i/runx/composer` (folder LLM functions → drafts)
- **Auditor / governance** — `@x12i/runx/auditor` (static → audit → shadow → contract → lock)
- **Run** — JS via `createRunx().run`; scripts via locked `scriptId` + production Runner (`@x12i/runx/run`)

Contracts: `@x12i/runx/contracts`. LLM folders: `llm-functions/` in this package. Redesign docs: [`docs/redesign/`](../../docs/redesign/).

**Runx** stores capability records in [Catalox](https://www.npmjs.com/package/@x12i/catalox), loads them into an in-memory cache, **executes** active JavaScript capabilities, and governs script publication. Function / API / script / mapping **authoring** is owned by Runx Composer (not FuncX). `@x12i/funcx` is an optional peer for legacy helpers / `createClient` re-export.

---

## What Runx is good for

| Goal | How Runx helps |
|------|----------------|
| **Shared capability catalog** | One source of truth in Catalox; reload into cache when the catalog changes. |
| **Runtime execution** | Call `runx.run(capabilityId, input, params)` for active JavaScript capabilities (v1). |
| **Transparent artifacts** | Fetch source, tests, docs, and dependency manifests via `getCapabilityArtifact` / `getCapabilityBundle`—Runx does not hide generated code. |
| **AI / agent integration** | Expose the **stored capability catalog** over [MCP](https://modelcontextprotocol.io) (`@x12i/runx-mcp`, CLI `runx-mcp`) so clients discover and call tools dynamically. |
| **Reuse before regeneration** | Capabilities can compose, wrap, or parameterize others; metadata tracks reuse and dependencies. |
| **Runtime condition checks** | Evaluate whether content meets a JavaScript or JSON rule via `checkContentCondition` / `runx.condition.checkContentCondition` (Rendrix templates, filter predicates, JSONLogic, JSONata, optional model). |
| **Ops / UI deliverables** | Script and UI capabilities are **artifact-first** (runbooks, React/HTML panels)—export and run outside Runx when needed. |

---

## How the pieces fit together

```text
Composer (folder LLM + AI router)  →  candidate draft (no scriptId)
Governance (static/audit/shadow/contract) → lock → scriptId
Catalox catalogs  →  Runx SDK run / artifacts / MCP
```

- **Composer / Auditor** — `@x12i/runx/composer`, `@x12i/runx/auditor`; instructions in `llm-functions/`.
- **Catalox** — persists capabilities and locked scripts.
- **Run** — JS in-process; Python/Bash only through production Runner with locked ids.
- **FuncX** — optional peer; `runx.*` generators for the four Composer modes are deprecated (`RUNX_AUTHORING_MODE`).

**Important:** Runx MCP exposes the **Runx capability catalog** plus optional `runx.execute`. It does not mirror the full FuncX function catalog.

---

## Capability kinds

| Kind | Typical use | Runtime in v1 core |
|------|-------------|---------------------|
| `javascript` | Transforms, scoring, helpers | **Executed** via `runx.run` |
| `api-adapter` | External API connectors | Stored; execution path evolving (MCP gated) |
| `composition` / `wrapper` / `parameterized` | Reuse and specialization | Stored; JS execution for leaf nodes |
| `ui` | React / OpenUI / HTML panels | **Artifacts** (not executed in-process by default) |
| `script` | PowerShell, bash, runbooks | **Artifacts** (controlled runner not enabled by default) |

Every capability supports two consumption modes:

- **Runtime** — `await runx.run(id, input, params)`
- **Artifact** — `await runx.getCapabilityBundle(id, { includeDependencies: true, ... })`

---

## Install

```bash
npm install @x12i/runx
```

Requires **Node.js ≥ 20**.

---

## Configuration

Copy [`.env.example`](./.env.example) to `.env` for local development (do not commit secrets).

| Variable | Purpose |
|----------|---------|
| `MONGO_URI` or `CATALOX_MONGO_URI` | **Required** — Catalox 6 Mongo backend |
| `OPEN_ROUTER_KEY` | FuncX LLM backend when using `funcxCreateOptions` |
| `CATALOX_RECORD_HISTORY` | Set to `1` to enable record history (requires S3/R2 env) |
| `RUNX_CAPABILITIES_CATALOG_ID` | Override default `runx-capabilities` |
| `RUNX_RUNTIME_PACKAGES_CATALOG_ID` | Override default `runx-runtime-packages` |

You can also pass a custom `catalox` instance into `createRunx({ catalox })` for tests or alternate backends.

---

## Quick start (SDK)

```ts
import { createRunx } from "@x12i/runx";
import type { RunxCapability } from "@x12i/runx";

const runx = await createRunx({
  // Optional: FuncX for authoring
  // funcxCreateOptions: { backend: "openrouter", ... },
});

await runx.bootstrap();   // ensure Runx catalogs exist in Catalox
await runx.reload();        // load capabilities into the in-memory cache

// Persist a capability (often produced by FuncX authoring, then normalized)
const capability: RunxCapability = {
  capabilityId: "normalize-finding",
  displayName: "Normalize finding",
  description: "Maps raw finding input to a canonical shape",
  kind: "javascript",
  status: "active",
  revision: 1,
  runtime: {
    runtimeLanguage: "javascript",
    executionRuntime: "node",
    moduleFormat: "esm",
    entrypoint: "run",
    executionKind: "node-js",
  },
  contract: {
    inputSchema: { type: "object" },
    outputSchema: { type: "object" },
  },
  artifacts: {
    javascript: {
      language: "javascript",
      moduleFormat: "esm",
      source: `export async function run(input, params = {}, _context = {}) {
        return { normalized: input, params };
      }`,
      filename: "normalize-finding.mjs",
      entrypoint: "run",
      exports: ["run"],
      sourceHash: "",
      sizeBytes: 0,
    },
  },
  dependencies: { internalCapabilities: [], runtimePackages: [] },
  reuse: { searchKeys: [], reusedFrom: [] },
  exposure: { publicName: "normalize-finding", toolExposureMode: "input-only" },
  tags: ["example"],
  audit: { createdAt: new Date().toISOString(), createdBy: "app" },
};

await runx.putCapability(capability);
await runx.reloadCapability("normalize-finding");

// Run
const result = await runx.run("normalize-finding", { title: "Issue" }, {});
if (result.ok) console.log(result.output);

// Export full bundle (code + dependency manifest)
const bundle = await runx.getCapabilityBundle("normalize-finding", {
  includeDependencies: true,
  includeTests: true,
});
```

### Condition evaluation (`checkContentCondition`)

Use the built-in runtime evaluator to answer: **does this content meet this condition?**

```ts
import {
  checkContentCondition,
  seedCheckContentConditionCapability,
} from "@x12i/runx";
// Or import only the library: import { checkContentCondition } from "@x12i/runx/condition";

// Direct (no Catalox)
const result = await checkContentCondition({
  content: { status: "active", score: 91 },
  condition: "content.status === 'active' && content.score >= parameters.minScore",
  parameters: { minScore: 80 },
  conditionType: "javascript",
});
// { ok: true, meetsCondition: true, reasoning: "..." }

// Via stored capability (after seeding once per catalog)
await seedCheckContentConditionCapability(runx);
await runx.reloadCapability("runx.condition.checkContentCondition");
const runResult = await runx.run("runx.condition.checkContentCondition", {
  content: { department: "Finance" },
  conditionType: "json",
  condition: {
    all: [{ path: "content.department", op: "eq", value: "Finance" }],
  },
}, {});
```

Supported condition types:

| `conditionType` | Formats | Notes |
|-----------------|---------|--------|
| `javascript` | expression, `return` body, function | Sandboxed `node:vm`; Rendrix `{{tokens}}` from `parameters` |
| `json` | native filter predicate (`all` / `any` / `not`), JSONLogic, JSONata wrapper | `options.jsonConditionFormat`: `auto` (default) or explicit |
| either | custom semantic rules | `mode: "hybrid"` or `mode: "model"` + `client` / `funcx` on `createRunx` |

Authoring flows (FuncX `runx.condition.create*`) can smoke-test generated rules with `verifyConditionWithRunx(runx, input)`.

### Typical application flow

1. **`createRunx()`** — connect to Catalox (from env or injected client).
2. **`bootstrap()`** — create Runx catalog entries if missing.
3. **`reload()`** — refresh the in-memory cache from Catalox.
4. **Author** — use FuncX `runx.*` skills, then **`putCapability`** (or upsert via your pipeline).
5. **`run` / `getCapabilityBundle` / `getCapabilityArtifact`** — execute or export.
6. **`reloadCapability(id)`** after external catalog edits.

`createCapability()` on the client is reserved for a future end-to-end path; today, persist with **`putCapability`** after FuncX authoring (see error message in `createRunx.ts`).

---

## MCP: expose capabilities to AI clients

Install globally or use `npx`:

```bash
npx @x12i/runx-mcp runx-mcp --transport stdio
```

Each **active executable** capability becomes a tool named `runx.<capabilityId>`. UI/script capabilities can expose artifact/bundle tools when configured (`--expose-artifacts`, `--expose-bundles`).

### Cursor / Claude Desktop (stdio)

```json
{
  "mcpServers": {
    "runx": {
      "command": "npx",
      "args": ["-y", "@x12i/runx-mcp", "runx-mcp", "--transport", "stdio", "--active-only"],
      "env": {
        "MONGO_URI": "mongodb://..."
      }
    }
  }
}
```

### Programmatic server

```ts
import { createRunx } from "@x12i/runx";
import { createRunxMcpStdioServer } from "@x12i/runx-mcp";

const runx = await createRunx();
await runx.bootstrap();
await runx.reload();

const mcp = await createRunxMcpStdioServer({
  runx,
  exposure: { activeOnly: true, exposeArtifactTools: true },
});
await mcp.start();
```

HTTP transport: `createRunxMcpHttpServer` or `runx-mcp --transport http --port 3334`.

Read-only catalog context is available as MCP resources (e.g. `runx://catalog/capabilities`, `runx://capabilities/{id}/artifacts/javascript`). See [docs/mcp.md](./docs/mcp.md) for tool naming, security defaults, and exposure policy.

---

## Main API surface

| Method | Description |
|--------|-------------|
| `bootstrap()` | Ensure Runx Catalox catalogs exist |
| `load()` / `reload()` | Refresh in-memory cache from Catalox |
| `putCapability` / `getCapability` / `listCapabilities` | CRUD against the capability catalog |
| `run(capabilityId, input?, params?, options?)` | Execute (JavaScript in v1 core) |
| `getCapabilityArtifact` / `getCapabilityBundle` / `exportCapability` | Artifact and export paths |
| `activateCapability` / `archiveCapability` / `deleteCapability` | Lifecycle |
| `getToolSpec` / `listToolSpecs` | Tool metadata for integrators |
| `listRuntimePackages` / `putRuntimePackage` | Allowed npm packages for sandboxed runs |
| `checkContentCondition` | Evaluate content against a JS/JSON condition (also `@x12i/runx/condition`) |
| `seedCheckContentConditionCapability` | Idempotent `putCapability` for `runx.condition.checkContentCondition` |
| `verifyConditionWithRunx` | Authoring smoke-test helper wrapping `runx.run` for the condition capability |

Types are exported from `@x12i/runx`. Subpath export: `@x12i/runx/condition`. MCP: `@x12i/runx-mcp`.

---

## Development

```bash
npm install
npm run build
npm test
# Live tests (Mongo/Catalox + condition evaluator; requires .env with MONGO_URI):
RUNX_LIVE_TESTS=1 npm run test:live
```

Live suite covers catalog bootstrap, `runx.condition.checkContentCondition` seed/run/bundle, and direct `checkContentCondition` against Mongo when `RUNX_LIVE_TESTS=1` (or deprecated `FIRESTORE_LIVE_TESTS=1`).

---

## Documentation

| Doc | Contents |
|-----|----------|
| [docs/specs.md](./docs/specs.md) | Full product and package specification |
| [docs/mcp.md](./docs/mcp.md) | MCP tools, resources, prompts, security |
| [docs/appendix.md](./docs/appendix.md) | Supplementary notes |

---

## V1 scope (read before production)

- **JavaScript** capabilities are fully executed in the core library; other executable kinds are stored and exposed but may return `unsupported_kind` until implemented.
- **Condition evaluation** (`runx.condition.checkContentCondition`) sandboxes condition JavaScript in `node:vm`; the outer capability module still runs in the host Node process. Seed with `seedCheckContentConditionCapability` before calling via `runx.run`.
- **Scripts** are not executed through Runx or MCP by default—use artifacts and an external runner.
- **Authoring** goes through **FuncX**, not `runx.createCapability()`.
- MCP reflects the **Runx catalog** dynamically; tighten exposure with `--active-only`, kind/id allowlists, and auth policies for HTTP deployments.

---

## License

MIT

---
_Source: https://npm.io/package/@x12i/runx · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
