Getting Started

Changelog

All notable changes to Routecraft.

Routecraft is in active development -- APIs may change between minor versions.



v0.6.0 Pre-release

August 2026

This section covers every change since the v0.5.0 release. 0.6.0 is the architecture release before v1: the contracts that freeze at v1 changed shape once, now, so they do not have to change after, and the engine rework brings a significant performance improvement to route and event processing. See the 0.5.x to 0.6.0 migration guide for all upgrade steps.

Core Breaking

  • Fixed event names; identity in the payload -- hierarchical names like route:<id>:exchange:failed become a fixed set (route:exchange:failed) with routeId in details. Wildcard patterns on ctx.on() / ctx.once() are replaced by exact names, the "*" catch-all, and the forRoute() filter helper (the event() source adapter keeps its pattern support); ecosystem packages declare events by merging into EventDetailsMap. plugin:registered is removed (it duplicated plugin:starting).
  • Subscription source contract -- source adapters receive a single Subscription object ({ context, signal, meta, ready(), complete(), emit() }) instead of five positional parameters. .from() additionally accepts async generator functions and (async) iterables, and @routecraft/testing adds a testSubscription() helper.
  • StepOutcome step contract -- custom Step implementations return what happened (continue / complete / drop / branch / fanOut) and the executor owns all scheduling; the wrapper buffer/relay protocol is gone. Per-execution metadata rides the outcome instead of mutating the shared Step instance. Custom aggregators return { body, headers? } instead of a fabricated Exchange.
  • Namespaced error-code registry -- ecosystem packages own codes under a claimed namespace via registerErrorCodes() plus ErrorCodeRegistry declaration merging; RC is reserved for core. Adds RC1003 (error-code registration failed).
  • Type-enforced builder positioning -- craft() returns a pre-from builder, so pipeline operations before .from() are compile errors; builder generics move to a state bag (RouteBuilder<{ body: T }>, AnyRouteBuilder for lists).
  • Splitters return child bodies -- .split() callbacks return values (or splitChild(body, headers) for per-child header overrides) instead of hand-built Exchange instances; the framework owns child construction.
  • Consumer SPI -- Consumer.register receives the Message envelope and consumer classes construct from one ConsumerDeps bag; Message, ProcessingQueue, ConsumerType, and ConsumerDeps are exported.
  • Per-adapter header key objects -- HeadersKeys keeps framework keys only; adapter keys move to TimerHeaders / CronHeaders / FileHeaders / CsvHeaders / JsonlHeaders / MailHeaders / CarddavHeaders; HEADER_MAIL_* / HEADER_CARDDAV_* and HeaderKeysRegistry are removed (wire keys unchanged). .header() rejects every engine-owned routecraft.* key up front.
  • client.sendDirect and public capability discovery -- CraftClient.send is renamed sendDirect (response generic defaults to unknown); context.capabilities() replaces reads of the internal direct registry, and ADAPTER_DIRECT_REGISTRY / getDirectChannel / sanitizeEndpoint are no longer exported.
  • Naming sweeps -- CardDAV* exports become Carddav* (acronym casing per the Http precedent), the carddav option types adopt the two-sided Server/Client naming (CarddavServerOptions for the read role, CarddavClientOptions for writes and deletes), and jsonl's three file option types fold into one JsonlFileOptions.
  • choice() variadic surface; BranchBuilder renamed, ChoiceSubBuilder removed -- the fluent callback .choice(c => c.when(p, fn).otherwise(fn)) becomes variadic .choice(when(p, fn), ..., otherwise(fn)) with standalone when / otherwise helpers imported from @routecraft/routecraft, the path surface now shared with the new multicast. BranchBuilder is renamed PathBuilder; ChoiceSubBuilder is gone.
  • Adapter role model: Source / Destination / Enricher -- Destination.send is now strictly void and the new Enricher.fetch pulls a value in, so the operation keyword selects the role instead of an option value. Pull-in adapters are renamed to *EnricherAdapter, and @routecraft/ai, @routecraft/os and @routecraft/testing raise their core peer range to >=0.6.0. See the migration guide.
  • .enrich() replaces the body by default -- with the aggregator omitted it now replaces rather than spread-merges, so audit every bare .enrich(). only() and none() still merge, and replace() is deleted. See the migration guide.
  • File-family adapters drop mode -- file, csv, json, jsonl, xml and html take their role from the operation keyword, with append: true / delete: true selecting send behaviour. Two silent flips to audit: jsonl sends now overwrite by default, and a migrated .tap(json({ path })) writes where mode: 'read' used to read and discard. See the migration guide.
  • MailSendResult, CarddavWriteResult and CarddavDeleteResult deleted -- sends that produce a receipt now surface it on routecraft.mail.* and routecraft.carddav.* headers instead of replacing the body. See the migration guide.
  • Option laws: arity is not a discriminant, key presence means supplied -- mail() returns one read adapter for both call shapes rather than changing role with a second argument, and a supplied-but-undefined path on the codec adapters now throws RC5003 instead of silently selecting the transformer role. Both changes are additive for code that already compiled. See the migration guide.
  • .input() validation folds into the pre-from filter chain -- .error() can now observe and recover an input failure, which previously bypassed it. Migrate observers: validation failures no longer emit route:exchange:dropped, they take the normal error path.
  • .retry({ exponential }) removed in favour of factor -- migrate exponential: true to factor: 2 and exponential: false to factor: 1, the new default; the old option throws RC5003 at build with a hint. See the retry reference for the backoff, cap and jitter options.
  • authorize() defaults to actor: 'none' -- Principal becomes delegation-aware (RFC 8693 act / may_act) and the new delegate() helper mints delegated principals, so a principal carrying an actor, including a Clerk impersonation session, is rejected until the route declares its permitted actors. Adds RC5034 to RC5038. See the migration guide and securing capabilities.

Core

  • Recovery directives -- .error() handlers may return recovery.drop(reason?) (discard the failing exchange) or recovery.rethrow() (decline recovery) instead of a recovery body or a manual throw.
  • Open error and principal models -- rcError accepts a per-occurrence retryable override; RCMeta.category and Principal.kind accept ecosystem-defined strings alongside the known values.
  • Plugin identity and lifecycle -- plugins may declare name (used as pluginId on events and logs) and reserve dependsOn; registerTeardown callbacks unwind LIFO; getRoutes() returns a copy.
  • route:source:failed lifecycle event -- fires when a source subscription rejects (the source gave up producing), with { routeId, route, adapter?, error }. Unlike route:stopping it never fires for an orderly shutdown, so it is the signal to alarm on for a dead channel.
  • concurrency (bulkhead) wrapper operation -- .concurrency({ max }) bounds how many exchanges run an operation at once, the sibling of .throttle(), which bounds a rate. See the concurrency reference.
  • dispatch load-balancing operation -- .dispatch(strategy, ...targets) runs exactly one of several targets by failover, round-robin, weighted or sticky strategy, the sibling of multicast and choice. See the dispatch reference.
  • debounce flow-control operation -- .debounce({ waitMs }) releases only the last exchange in a burst after a quiet period, for file-change batching and search-as-you-type. Route scope only, and a pending exchange is flushed on drain rather than lost. See the debounce reference.
  • sample and dedupe flow-control operations -- sample() passes every Nth exchange or the first in each time window, and dedupe() suppresses duplicates by a derived key. Both drop silently, like a filter returning false. See the sample and dedupe references.
  • .timeout() propagates an AbortSignal -- an expired deadline now cancels the wrapped step instead of leaving abandoned work running in the background, and http() forwards the signal into its fetch automatically. The .timeout(ms) surface is unchanged. See the timeout reference.
  • .input({ body }) retypes the builder -- the following .from(source) opens the pipeline with the schema's inferred output type, so the duplicated .from<T>() generic is no longer needed.
  • jwt() and jwks() surface clockToleranceSec -- a consumer re-checking a verified principal's expiresAt can now see the skew the verifier allowed. The expiry boundary is also inclusive everywhere, matching jose and RFC 7519, where jwt() previously honoured an expired token for one further second. See the migration guide.

AI & MCP Breaking

  • AI error codes renamed -- RC5025 / RC5026 / RC5027 become AI1001 / AI1002 / AI1003 under the new AI namespace; update any code or alerting that matches on error.rc.

  • Agent blocks replace skills -- AgentOptions.skills and agentPlugin({ skills }) are removed in favour of a blocks record that unifies skills, memory, identity, and instructions, with progressive disclosure now the default.

  • skills({ source }) and fromFile(path) builders -- skills now returns a blocks record to spread into blocks: { ... }; fromFile reads a UTF-8 file at resolution time.

  • Nested block groups -- a blocks value can be a single block or a nested blocks group, so skills({ source }) can stay grouped under one key (blocks: { skills: await skills(...) }) instead of being spread flat. Groups flatten to group__leaf names.

  • Tag selectors on tools() removed -- the { tagged } / { tagged, from } variants and the tags override on directTool are gone. Use the new tools((catalog) => [...]) builder form for dynamic selection.

  • Block-loader calls partitioned out of toolCalls -- progressive loads surface on AgentResult.blocksLoaded and emit agent:block:* events instead of agent:tool:*.

  • skills: frontmatter on agents() rejected -- supply blocks through the per-agent overrides map instead.

  • New error codes AI1001-AI1003 -- block resolution failure, name collision / reserved _block_ prefix, and block misconfiguration.

  • direct_<routeId> and _block_load_<name> tool names renamed -- synthetic tool names now use __ as their sole structural separator, so they become direct__<routeId> and _block__load__<name>. Fn ids and mcp__<server>__<tool> are unchanged, and the Direct(...) / MCP(...) authoring grammar does not change. Update anything pinning a generated name: tool-name guards, assertions on toolCalls[].toolName or blocksLoaded[].toolName, recorded transcripts, evals. See the migration guide.

  • ResolvedTool.source is a new required field -- a resolver-set fn / direct / mcp / block discriminant. Affects only code that hand-constructs a ResolvedTool.

  • Direct(<routeId>) and fn ids validated against the provider charset -- a name that cannot survive as a provider tool name (/^[A-Za-z0-9_-]{1,64}$/) now raises RC5003 naming the offending character or length, rather than being rejected by the provider later. Expose an unsafe route id under a tool-safe alias with directTool(routeId). An MCP client tool whose remote name cannot form a valid wire name is dropped with a warning instead of failing the dispatch.

  • MCP protocol revision 2026-07-28: the server is stateless -- mcpPlugin builds a fresh server per request, so any replica can answer any request behind a plain load balancer. Sessions, their events and McpHeadersKeys.SESSION are gone, and the @modelcontextprotocol/sdk v1 peer is replaced by the v2 package split. 2025-era clients keep working. See the migration guide.

  • oauth({ endpoints, client }) removed; oauth() becomes a resource-server helper -- it no longer proxies your Authorization Server, so point clients at your IdP's own endpoints, which they discover from the RFC 9728 metadata Routecraft serves. Pass issuer instead. See the migration guide.

  • MCP client names reject __ and a trailing _ -- such a name composed an ambiguous mcp__<server>__<tool> that resolved to the wrong tool, silently, so mcpPlugin() now throws RC5003 at startup with a suggested replacement. A single underscore inside the name is unaffected. See the migration guide.

AI & MCP

  • agentPlugin({ toolPolicy }) -- repository-wide admission control for the agent tool surface, keyed by tool kind (fn / direct / mcp), each true, false, or a predicate over a read-only tool descriptor. Omit it and nothing changes; supply it and the surface becomes an allowlist where every kind must be decided. Enforced at the single point every agent form converges on, so inline, registered, markdown, and nested agents are all covered, and multiple installs compose with AND. See the tool policy reference.
  • route:agent:tool:denied event -- emitted once per tool refused admission by a policy, carrying agentName, toolName, toolKind, and a reason of rule, rule-error, or unknown-provenance, so denials are alertable and auditable rather than only logged.
  • mcpPlugin({ proxy }) re-exposes client tools -- proxy tools from registered clients through the Routecraft MCP server without a route per tool, with an optional per-tool guard. Proxied calls run no route pipeline and do not forward the caller's principal, so reserve them for simple read-only tools. See the expose as MCP guide.
  • baseURL honoured by the Anthropic and Gemini providers -- previously only OpenAI honoured it, so explicit config lost to the ambient ANTHROPIC_BASE_URL environment variable.

Internals

  • Engine restructuring -- CraftContext delegates events to an internal EventBus; adapter config keys (cron, direct, mail, telemetry, http) move to per-module config appliers; the route engine splits into pipeline/ modules (executor, validation, synthetic steps). Two behavioural notes: context store seeding for adapter config now happens in initPlugins() (called automatically by start()), and plugin teardown (including registerTeardown callbacks) drains in reverse order.
  • Uniform factory tagging -- every public adapter factory is tagged for mockAdapter(), enforced by a conformance test; previously direct, simple, timer, cron, log, noop, and others (plus two transformer-mode branches of html() / json()) were silently unmockable.
  • Every optional peer loads through loadOptionalPeer -- the mail drivers and agentBrowser() now surface a missing package as RC5017 with an install hint rather than a raw module-not-found, and detection no longer misses the phrasing Bun uses for a subpath import. A contract test scans all four code packages for bare external dynamic imports.
  • Config appliers restored in the published bundles -- a sideEffects allowlist let esbuild prune every core config applier out of the published bundle, so defineConfig({ mail: { accounts } }) typechecked but never applied at runtime. A post-build guard now asserts every applier is live in the registry, and an unrecognised defineConfig key warns instead of being a silent no-op.
  • @routecraft/ai, @routecraft/os and @routecraft/testing declare core as a peer -- at >=0.6.0 <1.0.0, with a workspace devDependency for development, instead of duplicating core as a regular dependency.
  • Dependency floors refreshed -- runtime ranges on @routecraft/ai, @routecraft/cli and create-routecraft move to their newest in-range minor and patch releases, and core's optional fast-xml-parser peer floor rises to ^5.10.1 to exclude a DOCTYPE entity-expansion advisory. No majors are included, and the imapflow floor is held back deliberately.

Adapters

  • HTTP source Breaking -- http() is now a two-sided adapter. http({ path, method? }) exposes a route over HTTP via defineConfig({ http: { port, host, auth } }); Bun runtimes bind through Bun.serve and Node 22+ uses a zero-dependency node:http shim. Global auth accepts jwt() / jwks() bearer or apiKey({...}); per-route constraints reuse .authorize({...}). Per-route auth handling has three modes via http({ auth: "required" | "optional" | "skip" }): secure-by-default "required", "optional" (admit anonymously, attach principal when a valid credential is present, reject invalid credentials), and "skip" (bypass the middleware entirely for truly identity-free routes like RSS or probes). Built-in /health, /ready, and /openapi.json endpoints register automatically. Each is configured via the uniform http: { builtins: { health, ready, openapi } } block with { enabled, requireAuth } per endpoint (Spring-Actuator-inspired). Defaults gate the routes count on /ready from anonymous callers (requireAuth: true) and keep /openapi.json public (requireAuth: false, matching the Stripe / GitHub / Twilio convention). Request bodies are parsed by Content-Type (JSON / text / urlencoded / multipart), capped by maxBodySize. Adds error codes RC5018 (request rejected) and RC5019 (server bind failed). Breaking: the destination option type HttpOptions<T> is renamed HttpClientOptions<T> (the source uses HttpServerOptions); a type-only change with no runtime impact.
  • CSV and JSONL decode transformers -- calling csv() or jsonl() with no path now returns a transformer that parses a CSV / JSONL string already in the body (for example an http() response), matching the existing json() and html() decode transformers. Adds CsvTransformerOptions, CsvFileOptions, and JsonlTransformerOptions; csv()'s path is now optional. A dynamic (function) path used as a destination now works for html() too, where it previously threw at construction.
  • xml adapter -- read, write and transform XML through a plain-object representation, mirroring the json and csv codec adapters. fast-xml-parser loads as an optional peer. See the xml reference.
  • directory adapter -- scan a directory and list its entries as a source, or pull a listing in mid-route with .enrich(). Emits one exchange with the full listing by default, or one per entry with chunked: true. See the directory reference.
  • CSV appends no longer splice records together -- appending a,b and then c,d through .to(csv({ append: true })) used to write a,bc,d. Appends are also serialised per path, so concurrent writes can no longer both emit the header.
  • Signed webhooks on the http() source -- http({ signature }) verifies the raw request bytes before the route runs, covering the GitHub, legacy HMAC-SHA1 and Stripe timestamped schemes, and http({ rawBody: true }) exposes those bytes for any other scheme. Adds RC5039. See securing capabilities.
  • /openapi.json never advertises a workspace container -- when the nearest package.json is a monorepo root, auto-detection serves the neutral fallbacks instead of the container's private, often stale identity. Apps run from their own directory are unaffected. See the http reference.

Mail

  • Mail source envelope moves to headers Breaking -- .from(mail(...)) now follows the payload-on-body, envelope-on-headers convention shared with the HTTP source. The exchange body is a MailBody ({ text?, html?, attachments? }) and the envelope (from, to, cc, bcc, subject, date, messageId, replyTo, flags, sender, rawHeaders) lands on routecraft.mail.* headers, declaration-merged into RoutecraftHeaders and exported on the MailHeaders key object. .input({ body }) now validates against the message content alone. The fetch destination (.enrich(mail(...))) still returns MailMessage[] unchanged. New exported type MailBody.
  • Direct mail no longer misclassified as auto-forwarded -- a single first-hop ARC seal (i=1, cv=none) added by the delivering MX is no longer read as forwarding, so DMARC-aligned direct mail stays direct / verified instead of unverified. Mailing-list and validated-forward classification are unchanged.
  • Connection recovery covers every failure path, and is configurable -- IDLE-mode fetch failures and the initial connect at route start now go through the same reconnect-with-backoff loop as IDLE drops and poll fetch failures (previously they killed the route), and the folder is drained right after a reconnect so mail that arrived during an outage is delivered immediately. New reconnect: { maxAttempts?, baseDelayMs?, maxDelayMs? } | false option on MailServerOptions (defaults match the old hardcoded 30 / 1s / 60s; maxAttempts: Infinity never gives up; false fails fast). Because the initial connect retries, the source signals readiness before the first connection succeeds, so route:started no longer guarantees the mailbox was reachable. New exported type MailReconnectOptions. When any source gives up for good, the new core route:source:failed event fires with { routeId, route, adapter?, error } so a dead channel can be alarmed on (#425).
  • Threading and custom headers on the send payload -- inReplyTo, references and headers, so agent replies stitch into the original email thread.
  • IMAP operations report their metadata again -- move, copy, delete, flag, unflag and append lost theirs when the role model split the observability hooks.

Packages Breaking

  • @routecraft/prettier-plugin-routecraft -- new package, formatting DSL chains compactly so a route reads as one shape rather than one operation per line. See formatting.
  • agentBrowser() moves to @routecraft/os -- browser automation folds into @routecraft/os and the standalone @routecraft/browser package is deprecated. Update imports; the factory, options and result shape are unchanged.

Docs site

  • Blog at /blog -- Markdoc-backed posts with a featured + latest layout.
  • Cheat sheet at /cheat-sheet -- searchable single-page DSL reference, print-to-PDF friendly.
  • 0.5.x to 0.6.0 migration guide -- step-by-step upgrade notes for every breaking change above.

v0.5.0 Pre-release

May 2026

Several breaking changes across the core, AI, mail, telemetry, logger, and CLI surfaces. See the 0.4.x to 0.5.0 migration guide for the full public-API diff and step-by-step upgrade notes.

Core

  • Dual-mode wrapper pattern -- .error() becomes a route-level wrapper rather than a top-level method, and source-level parse errors flow through the same handler.
  • Immutable Exchange -- the Exchange is frozen with explicit copy-on-write; state is unified on { body, headers }.
  • .authorize() route-entry guard -- a route-only authorization validator that replaces requirePrincipal and raises RC5020 when a credential expires mid-run.
  • Field-shaping helpers keep and mask -- two .transform() helpers: keep is grant-based, fail-closed allowlisting; mask obfuscates values regardless of caller.
  • Choice operation -- a conditional routing primitive with transform() and enrich() on branch builders.
  • Discovery metadata on the route builder -- route id, description, and validation move from source options to the builder.

AI & MCP Breaking

  • Agent runtime -- tool-calling loop, streaming via onEvent / onDelta, agent destination, and per-binding tool description overrides.
  • tools() DSL -- declarative tool registration, selection, and resolution.
  • Agent configuration overhaul -- agentPlugin.agents is a record (no defineAgent), and system / user accept a string or function. See the migration guide.
  • MCP OAuth 2.1 server -- OAuth 2.1 provider with principal hierarchy, plus a general MCP HTTP auth surface and tool annotations.
  • MCP protected-resource metadata -- resource identity moves to mcpPlugin({ title, resource }); both validator and OAuth-proxy modes auto-mount RFC 9728 metadata. Field-by-field moves are in the migration guide.
  • Plugin-level userinfo enrichment -- mcpPlugin({ userinfo }) hydrates the principal after verification, enabling the WorkOS AuthKit pattern. Lives on the plugin, orthogonal to the auth mode.
  • ClaimMappers.{email,name,roles} removed -- superseded by userinfo enrichment; the token-level mappers remain.
  • New error codes RC5020-RC5022 -- token expired during processing, principal enrichment failed, and userinfo sub invariant violated.

Adapters

  • Adapter mocking -- mockAdapter swaps any tagged adapter in tests; the file, csv, json, jsonl, and html factories are tagged out of the box.
  • direct<TIn, TOut>() distinct types -- a route can accept one body shape and emit another.
  • Mail (IMAP) reliability -- reconnect on transient fetch failures, a reshaped MailMessage body, and a verify-sender option.
  • Optional peer loader everywhere -- every optional-peer import now routes through loadOptionalPeer and emits RC5017 with an install hint.

Telemetry Breaking

  • Bun-only SQLite sink -- the built-in telemetry sink uses bun:sqlite; better-sqlite3 is removed. Node deployments that relied on it must bring their own sink.

Logger

  • stdout default -- the logger writes to stdout instead of stderr.

CLI & Tooling

  • Bun-only craft CLI -- the published binary now requires Bun >= 1.1.0.
  • Bun monorepo -- installs, scripts, and lockfile migrate from pnpm to Bun.
  • create-routecraft refactor -- scaffolder extracted into a library with expanded test coverage.
  • bun:test everywhere -- the internal suite migrates off vitest, retained only for the cross-runtime tests.

Docs

  • Migration guide -- new 0.4.x to 0.5.0 migration guide.
  • Canary docs at /next/ -- canary builds deploy alongside the stable build at the root.
  • Operator reference -- log and debug documented; map and schema clarified.
  • Claude Code skills -- Agent Skills for authoring adapters and capabilities bundled at the repo root.

v0.4.0 Pre-release

March 2026

Adapters

  • Cron source -- new adapter for scheduling capabilities with cron expressions.
  • JSONL adapter and chunked mode -- read and write line-delimited JSON with chunked streaming for large files.
  • Modular adapter structure -- adapters refactored into a consistent file layout with a unified DSL registration system.
  • Merged options -- cron and direct adapters now support merged options across config and route.

AI & MCP

  • stdio MCP client -- spawn and manage stdio-based MCP servers with a unified tool registry.
  • Bearer token authentication -- secure MCP HTTP transport with bearer tokens.

Framework

  • Terminal UI -- new TUI for inspecting running contexts and routes.
  • Reduced public API surface -- internal-only exports are no longer published, tightening the long-term API contract.

TypeScript

  • Declaration-merging registries -- compile-time adapter safety via type registries that adapter packages can extend.

Testing

  • Spy adapter assertions -- richer assertion helpers in @routecraft/testing for spying on capability output.

Docs

  • Light mode -- hero section and syntax highlighting now respect light mode.
  • Copy-to-clipboard -- code blocks gain a copy button.
  • Community resources -- new section linking external content and contributors.
  • Dark-mode contrast -- prose strong text is more readable on dark backgrounds.

v0.3.0 Pre-release

March 2026

Adapters

  • Agent, embedding, and LLM adapters -- new adapters for integrating AI agent workflows, embedding models, and large language models directly into capabilities.
  • HTTP adapter -- first-class HTTP source and destination support.
  • Browser and HTML adapters -- interact with web pages and parse HTML content.
  • JSON adapter -- dedicated adapter for JSON data sources.
  • Grouping adapter -- group messages by key before forwarding.
  • File adapter -- read and write text, JSON, and CSV files with a unified adapter.

AI & MCP

  • @routecraft/testing package -- expanded testing utilities with MCP integration support.
  • Consistent adapter pattern -- all adapters now follow a unified pattern for configuration, lifecycle, and error handling.

Events

  • Hierarchical event model -- new operation-level events with parent-child relationships, enabling fine-grained observability across capability execution.

TypeScript

  • TypeScript support -- author capabilities in TypeScript with full type inference and compile-time validation.

Docs

  • Capability-centric terminology -- all documentation renamed from "routes" to "capabilities" for consistency.
  • Advanced guides -- new documentation covering advanced patterns, capability composition, and adapter authoring.

v0.2.0 Pre-release

February 2026

AI & MCP

  • New @routecraft/ai package -- MCP integration with full schema validation via Zod. Expose any capability as an MCP tool for Claude Desktop, Cursor, and other MCP clients.
  • MCP server support -- run your capabilities as an MCP server with a single CLI command.
  • MCP client support -- call external MCP servers from within a capability using the mcpPlugin.

Adapters & Operations

  • direct adapter validation -- improved validation and error messages for inter-capability communication.
  • aggregate operation -- default aggregator now flattens arrays and combines scalars automatically.
  • batch operation -- new ESLint rule (batch-before-from) enforces correct batch positioning at the route level.
  • pseudo adapter -- new adapter for stubbing sources and destinations in tests and local development.

Framework

  • Cross-instance identity -- supports multiple package copies and npx-based installs resolving to the same context identity.
  • Logging configuration -- enhanced logging setup with more control over levels and output format.

v0.1.1 Pre-release

November 2025

Quality-of-life improvements.

Adapters

  • Custom log messages -- adapters and operations now support custom log message overrides.
  • Fetch adapter -- automatically parses JSON responses, no manual parsing needed.

Framework

  • .env.local support -- environment variables in .env.local are loaded automatically alongside .env.

Tooling

  • create-routecraft -- project scaffolding now supports example selection and template file configuration.
  • CodeSandbox -- added online playground link in the installation docs for zero-install experimentation.

v0.1.0 Pre-release

October 2025

Initial release.

Framework

  • Fluent DSL -- craft().from().to() builder syntax for authoring capabilities.
  • Core operations -- transform, filter, enrich, aggregate, split, validate, tap, process, header, and more.
  • Backpressure -- simple and batch consumers with built-in backpressure support.
  • CraftContext -- route lifecycle management with hot reload in development.
  • Error handling -- structured RC error codes with Pino logging.

Adapters

  • Built-in adapters -- simple, timer, direct, log, noop, fetch.

Tooling

  • CLI -- craft run and craft watch commands.
  • create-routecraft -- project scaffolding tool.
  • ESLint plugin -- require-named-route rule out of the box.
  • Test utilities -- @routecraft/testing package with testContext and spy adapter.
Previous
Installation