From routecraft-skills
Authors new Routecraft adapters for sources, destinations, transformers, or multi-role. Use when adding integrations, connectors, endpoint types, or exchange producers/consumers.
npx claudepluginhub routecraftjs/routecraft --plugin routecraft-skillsThis skill is limited to using the following tools:
Adapters are how Routecraft talks to the outside world. A source produces exchanges, a destination consumes them, and a transformer changes the body in flight. Many adapters fill more than one role.
Monitors deployed URLs for regressions after deploys, merges, or upgrades by checking HTTP status, console errors, network failures, performance (LCP/CLS/INP), content, and API health.
Share bugs, ideas, or general feedback.
Adapters are how Routecraft talks to the outside world. A source produces exchanges, a destination consumes them, and a transformer changes the body in flight. Many adapters fill more than one role.
You are writing this adapter for the user. Treat the linter (bun run lint) as authoritative once you have written the code: if it disagrees, the linter wins.
Use this skill when the user asks to:
process() calls with a reusable adapterIf the user only needs a one-shot data transformation inside a single capability, use .transform() or .process() directly instead. If the work is reusable across capabilities, it belongs in an adapter.
Before writing, confirm answers to these questions. Ask the user only the ones that are not already obvious from context.
.from(...)), Destination (.to(...), .enrich(...), .tap(...)), Transformer (.transform(...)), or several of these?body look like for sources you produce, and what does body need to look like for destinations you consume?Read reference/examples-index.md and pick the row that best matches the answers above. The index maps intent to the relevant public doc page and the closest existing adapter on GitHub.
Then, in this order:
WebFetch the linked doc page (raw markdown variant on routecraft.dev/raw/docs/...)WebFetch the linked example adapter source on GitHub (use the raw.githubusercontent.com URL)Read packages/routecraft/src/adapters/<closest>/ end to end. Pay attention to file layout, the factory, the tagAdapter call, and the types moduleDo not write the adapter from memory. The patterns are precise and the examples are short. Read first.
Create the adapter under packages/routecraft/src/adapters/<concept>/ if you are inside this monorepo, or under your project's adapters folder otherwise. Mirror the file layout of the example you read. Typical files:
index.ts -- the public factory function. Calls tagAdapter(instance, factory, factoryArgs(...)). This is what users importsource.ts -- the source class (if applicable)destination.ts -- the destination class (if applicable)transformer.ts -- the transformer class (if applicable)shared.ts -- option parsing or helpers shared between the role filestypes.ts -- exported option and result typesAuthoring rules to keep in mind while writing:
{Concept}{Role}Adapter (e.g. HttpDestinationAdapter, CronSourceAdapter). The factory function is the lowercase concept (http, cron)arguments.length and typeof, never by inspecting option valuestagAdapter(instance, factory, factoryArgs(...)). The eslint plugin and tests rely on this{Concept}ServerOptions and {Concept}ClientOptions, and export the union as {Concept}Options. If the two roles share fields, factor them into {Concept}BaseOptions and have both Server and Client extend it; if they do not, declare each independently. Source/Destination is for interface names; Server/Client is for option type namesSymbol.for("routecraft.adapter.<concept>.<key>") so keys survive duplicate package copies in the same process{ ...exchange, body: newBody }). Do not mutate the incoming exchangerc error code from @routecraft/routecraft. Capabilities catch and surface these via the capability-level error handlerTests live in the package's test/ directory: packages/<pkg>/test/<name>.test.ts. Do not colocate tests next to source. Every test must have a JSDoc with @case, @preconditions, @expectedResult. Prefer the helpers from @routecraft/testing:
testContext() to build an isolated contextspy() for destinations whose payload you want to assert onpseudo("name", options) for a stand-in source or destinationmockAdapter(factory, {...}) to assert how a factory was calledFor the full pattern, fetch:
https://routecraft.dev/raw/docs/introduction/testing.md
Run, in this order, until each is clean:
bun run typecheck
bun run lint
bun run test
Use bun run <script> (not bun <script>) so Bun invokes the package.json script rather than its built-in test runner. If bun run lint complains, fix the code rather than silencing the rule. The linter encodes Routecraft's authoring rules; it is allowed to be stricter than this skill. If the linter does not catch something the user expected it to catch, that is a follow-up for the lint package, not a workaround here.