From a9b042a2d57d0e9d8dc718e84aebb63d9c2e7b58 Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Sat, 16 May 2026 02:41:07 -0700
Subject: [PATCH 1/2] scaffold executor docs
---
bun.lock | 14 +++
docs/cloud/api-keys.mdx | 6 +
docs/cloud/hosting-model.mdx | 6 +
docs/cloud/overview.mdx | 6 +
docs/cloud/sources.mdx | 6 +
docs/cloud/workspaces.mdx | 6 +
docs/concepts/connections.mdx | 8 ++
docs/concepts/executor.mdx | 6 +
docs/concepts/policies.mdx | 6 +
docs/concepts/scopes.mdx | 6 +
docs/concepts/secrets.mdx | 6 +
docs/concepts/sources.mdx | 6 +
docs/concepts/tools.mdx | 6 +
docs/docs.json | 93 +++++++++++++++
docs/getting-started/cloud.mdx | 8 ++
docs/getting-started/local.mdx | 8 ++
docs/getting-started/overview.mdx | 10 ++
docs/getting-started/sdk.mdx | 8 ++
docs/index.mdx | 8 ++
docs/local/auth-and-secrets.mdx | 6 +
docs/local/cli.mdx | 6 +
docs/local/install.mdx | 6 +
docs/local/mcp-server.mdx | 6 +
docs/local/web-ui.mdx | 6 +
docs/sdk/approvals.mdx | 6 +
docs/sdk/create-executor.mdx | 6 +
docs/sdk/errors.mdx | 6 +
docs/sdk/quickstart.mdx | 70 ++++++++++++
docs/sdk/secrets.mdx | 6 +
docs/sdk/sources.mdx | 6 +
docs/sdk/tools.mdx | 6 +
docs/snippets/README.md | 7 ++
docs/snippets/sdk/quickstart/add-source.mdx | 12 ++
.../sdk/quickstart/close-executor.mdx | 8 ++
.../sdk/quickstart/create-executor.mdx | 12 ++
.../sdk/quickstart/inspect-schema.mdx | 10 ++
docs/snippets/sdk/quickstart/list-tools.mdx | 12 ++
examples/docs-sdk-quickstart/package.json | 19 ++++
examples/docs-sdk-quickstart/src/main.ts | 106 ++++++++++++++++++
examples/docs-sdk-quickstart/tsconfig.json | 14 +++
package.json | 2 +
packages/core/fumadb/tsup.config.ts | 1 +
scripts/generate-doc-snippets.ts | 70 ++++++++++++
scripts/smoke-docs-install.ts | 97 ++++++++++++++++
44 files changed, 729 insertions(+)
create mode 100644 docs/cloud/api-keys.mdx
create mode 100644 docs/cloud/hosting-model.mdx
create mode 100644 docs/cloud/overview.mdx
create mode 100644 docs/cloud/sources.mdx
create mode 100644 docs/cloud/workspaces.mdx
create mode 100644 docs/concepts/connections.mdx
create mode 100644 docs/concepts/executor.mdx
create mode 100644 docs/concepts/policies.mdx
create mode 100644 docs/concepts/scopes.mdx
create mode 100644 docs/concepts/secrets.mdx
create mode 100644 docs/concepts/sources.mdx
create mode 100644 docs/concepts/tools.mdx
create mode 100644 docs/docs.json
create mode 100644 docs/getting-started/cloud.mdx
create mode 100644 docs/getting-started/local.mdx
create mode 100644 docs/getting-started/overview.mdx
create mode 100644 docs/getting-started/sdk.mdx
create mode 100644 docs/index.mdx
create mode 100644 docs/local/auth-and-secrets.mdx
create mode 100644 docs/local/cli.mdx
create mode 100644 docs/local/install.mdx
create mode 100644 docs/local/mcp-server.mdx
create mode 100644 docs/local/web-ui.mdx
create mode 100644 docs/sdk/approvals.mdx
create mode 100644 docs/sdk/create-executor.mdx
create mode 100644 docs/sdk/errors.mdx
create mode 100644 docs/sdk/quickstart.mdx
create mode 100644 docs/sdk/secrets.mdx
create mode 100644 docs/sdk/sources.mdx
create mode 100644 docs/sdk/tools.mdx
create mode 100644 docs/snippets/README.md
create mode 100644 docs/snippets/sdk/quickstart/add-source.mdx
create mode 100644 docs/snippets/sdk/quickstart/close-executor.mdx
create mode 100644 docs/snippets/sdk/quickstart/create-executor.mdx
create mode 100644 docs/snippets/sdk/quickstart/inspect-schema.mdx
create mode 100644 docs/snippets/sdk/quickstart/list-tools.mdx
create mode 100644 examples/docs-sdk-quickstart/package.json
create mode 100644 examples/docs-sdk-quickstart/src/main.ts
create mode 100644 examples/docs-sdk-quickstart/tsconfig.json
create mode 100644 scripts/generate-doc-snippets.ts
create mode 100644 scripts/smoke-docs-install.ts
diff --git a/bun.lock b/bun.lock
index da3d2eae3..34821dec7 100644
--- a/bun.lock
+++ b/bun.lock
@@ -249,6 +249,18 @@
"typescript": "latest",
},
},
+ "examples/docs-sdk-quickstart": {
+ "name": "@executor-js/example-docs-sdk-quickstart",
+ "version": "0.0.0",
+ "dependencies": {
+ "@executor-js/plugin-openapi": "workspace:*",
+ "@executor-js/sdk": "workspace:*",
+ },
+ "devDependencies": {
+ "@types/node": "catalog:",
+ "typescript": "catalog:",
+ },
+ },
"examples/promise-sdk": {
"name": "@executor-js/example-promise-sdk",
"version": "0.0.2",
@@ -1319,6 +1331,8 @@
"@executor-js/example-all-plugins": ["@executor-js/example-all-plugins@workspace:examples/all-plugins"],
+ "@executor-js/example-docs-sdk-quickstart": ["@executor-js/example-docs-sdk-quickstart@workspace:examples/docs-sdk-quickstart"],
+
"@executor-js/example-promise-sdk": ["@executor-js/example-promise-sdk@workspace:examples/promise-sdk"],
"@executor-js/execution": ["@executor-js/execution@workspace:packages/core/execution"],
diff --git a/docs/cloud/api-keys.mdx b/docs/cloud/api-keys.mdx
new file mode 100644
index 000000000..f9e1cd03b
--- /dev/null
+++ b/docs/cloud/api-keys.mdx
@@ -0,0 +1,6 @@
+---
+title: API Keys
+description: Authenticate to Executor Cloud.
+---
+
+This page will document cloud API key creation, rotation, and usage once the public flow is finalized.
diff --git a/docs/cloud/hosting-model.mdx b/docs/cloud/hosting-model.mdx
new file mode 100644
index 000000000..4809fadae
--- /dev/null
+++ b/docs/cloud/hosting-model.mdx
@@ -0,0 +1,6 @@
+---
+title: Hosting Model
+description: Understand what runs in Executor Cloud.
+---
+
+This page will describe the hosted runtime boundaries for Executor Cloud.
diff --git a/docs/cloud/overview.mdx b/docs/cloud/overview.mdx
new file mode 100644
index 000000000..cb8cae5c1
--- /dev/null
+++ b/docs/cloud/overview.mdx
@@ -0,0 +1,6 @@
+---
+title: Overview
+description: Understand Executor Cloud.
+---
+
+Executor Cloud provides hosted workspaces for shared sources, credentials, policies, and agent access.
diff --git a/docs/cloud/sources.mdx b/docs/cloud/sources.mdx
new file mode 100644
index 000000000..4449efb87
--- /dev/null
+++ b/docs/cloud/sources.mdx
@@ -0,0 +1,6 @@
+---
+title: Sources
+description: Manage hosted source connections.
+---
+
+Cloud sources make shared tools available to the agents and applications connected to a workspace.
diff --git a/docs/cloud/workspaces.mdx b/docs/cloud/workspaces.mdx
new file mode 100644
index 000000000..791c55d48
--- /dev/null
+++ b/docs/cloud/workspaces.mdx
@@ -0,0 +1,6 @@
+---
+title: Workspaces
+description: Organize shared Executor resources.
+---
+
+Workspaces group sources, policies, and credentials for a team or application.
diff --git a/docs/concepts/connections.mdx b/docs/concepts/connections.mdx
new file mode 100644
index 000000000..f50ccb3f7
--- /dev/null
+++ b/docs/concepts/connections.mdx
@@ -0,0 +1,8 @@
+---
+title: Connections
+description: OAuth and provider-backed credentials connected to Executor.
+---
+
+Connections represent authenticated relationships with external providers.
+
+Use connections when a source needs provider-managed credentials, OAuth refresh behavior, or an identity label that users can recognize and manage separately from bare secrets.
diff --git a/docs/concepts/executor.mdx b/docs/concepts/executor.mdx
new file mode 100644
index 000000000..54c7904e1
--- /dev/null
+++ b/docs/concepts/executor.mdx
@@ -0,0 +1,6 @@
+---
+title: Executor
+description: The runtime that connects sources, tools, auth, and policy.
+---
+
+An Executor is the runtime surface that applications and agents use to discover tools, inspect schemas, invoke tools, and resolve credentials.
diff --git a/docs/concepts/policies.mdx b/docs/concepts/policies.mdx
new file mode 100644
index 000000000..22e2eafbc
--- /dev/null
+++ b/docs/concepts/policies.mdx
@@ -0,0 +1,6 @@
+---
+title: Policies
+description: Control which tools can run.
+---
+
+Policies decide whether tool invocations are allowed, blocked, or require approval.
diff --git a/docs/concepts/scopes.mdx b/docs/concepts/scopes.mdx
new file mode 100644
index 000000000..c6444f315
--- /dev/null
+++ b/docs/concepts/scopes.mdx
@@ -0,0 +1,6 @@
+---
+title: Scopes
+description: Resource ownership and precedence.
+---
+
+Scopes describe where resources belong and how Executor resolves resources across user, workspace, or organization boundaries.
diff --git a/docs/concepts/secrets.mdx b/docs/concepts/secrets.mdx
new file mode 100644
index 000000000..a21f5e782
--- /dev/null
+++ b/docs/concepts/secrets.mdx
@@ -0,0 +1,6 @@
+---
+title: Secrets
+description: Credential references shared by sources and tools.
+---
+
+Secrets store credentials separately from source definitions so tools can authenticate without exposing sensitive values.
diff --git a/docs/concepts/sources.mdx b/docs/concepts/sources.mdx
new file mode 100644
index 000000000..f6e3d0bd3
--- /dev/null
+++ b/docs/concepts/sources.mdx
@@ -0,0 +1,6 @@
+---
+title: Sources
+description: External systems connected to Executor.
+---
+
+A source is an external system or protocol endpoint that contributes tools to Executor.
diff --git a/docs/concepts/tools.mdx b/docs/concepts/tools.mdx
new file mode 100644
index 000000000..5b8387149
--- /dev/null
+++ b/docs/concepts/tools.mdx
@@ -0,0 +1,6 @@
+---
+title: Tools
+description: Callable actions exposed by sources.
+---
+
+A tool is a typed callable action with metadata, input schema, and invocation behavior.
diff --git a/docs/docs.json b/docs/docs.json
new file mode 100644
index 000000000..5c0c62ae9
--- /dev/null
+++ b/docs/docs.json
@@ -0,0 +1,93 @@
+{
+ "$schema": "https://mintlify.com/docs.json",
+ "theme": "aspen",
+ "name": "Executor",
+ "colors": {
+ "primary": "#009f83",
+ "light": "#009f83",
+ "dark": "#6ee7c8"
+ },
+ "navigation": {
+ "tabs": [
+ {
+ "tab": "Getting Started",
+ "groups": [
+ {
+ "group": "Start Here",
+ "pages": [
+ "index",
+ "getting-started/overview",
+ "getting-started/local",
+ "getting-started/cloud",
+ "getting-started/sdk"
+ ]
+ }
+ ]
+ },
+ {
+ "tab": "Concepts",
+ "groups": [
+ {
+ "group": "Core Concepts",
+ "pages": [
+ "concepts/executor",
+ "concepts/sources",
+ "concepts/tools",
+ "concepts/scopes",
+ "concepts/policies",
+ "concepts/secrets",
+ "concepts/connections"
+ ]
+ }
+ ]
+ },
+ {
+ "tab": "SDK",
+ "groups": [
+ {
+ "group": "SDK",
+ "pages": [
+ "sdk/quickstart",
+ "sdk/create-executor",
+ "sdk/sources",
+ "sdk/tools",
+ "sdk/secrets",
+ "sdk/approvals",
+ "sdk/errors"
+ ]
+ }
+ ]
+ },
+ {
+ "tab": "Local",
+ "groups": [
+ {
+ "group": "Local Product",
+ "pages": [
+ "local/install",
+ "local/web-ui",
+ "local/mcp-server",
+ "local/cli",
+ "local/auth-and-secrets"
+ ]
+ }
+ ]
+ },
+ {
+ "tab": "Cloud",
+ "groups": [
+ {
+ "group": "Cloud Product",
+ "pages": [
+ "cloud/overview",
+ "cloud/workspaces",
+ "cloud/sources",
+ "cloud/api-keys",
+ "cloud/hosting-model"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/docs/getting-started/cloud.mdx b/docs/getting-started/cloud.mdx
new file mode 100644
index 000000000..4b494172e
--- /dev/null
+++ b/docs/getting-started/cloud.mdx
@@ -0,0 +1,8 @@
+---
+title: Cloud Quickstart
+description: Start with Executor Cloud.
+---
+
+Use Executor Cloud when your team needs shared workspaces, hosted source management, and centralized credentials.
+
+This page will be filled in as the cloud onboarding flow stabilizes.
diff --git a/docs/getting-started/local.mdx b/docs/getting-started/local.mdx
new file mode 100644
index 000000000..c89906dd4
--- /dev/null
+++ b/docs/getting-started/local.mdx
@@ -0,0 +1,8 @@
+---
+title: Local Quickstart
+description: Start Executor locally.
+---
+
+Use the local product when you want Executor running on your machine with a web UI, CLI, and MCP server for local agents.
+
+This page will be backed by a smoke-tested local workflow.
diff --git a/docs/getting-started/overview.mdx b/docs/getting-started/overview.mdx
new file mode 100644
index 000000000..1aa856a00
--- /dev/null
+++ b/docs/getting-started/overview.mdx
@@ -0,0 +1,10 @@
+---
+title: Overview
+description: Choose the right Executor entrypoint.
+---
+
+Executor has three main entrypoints:
+
+- Local product: run Executor on your machine and connect agents through MCP or the CLI.
+- Cloud product: manage hosted workspaces, shared sources, and team-facing auth.
+- SDK: embed Executor in your own TypeScript application through `@executor-js/sdk`.
diff --git a/docs/getting-started/sdk.mdx b/docs/getting-started/sdk.mdx
new file mode 100644
index 000000000..2a275c535
--- /dev/null
+++ b/docs/getting-started/sdk.mdx
@@ -0,0 +1,8 @@
+---
+title: SDK Quickstart
+description: Embed Executor with the SDK.
+---
+
+Use the SDK when you want to create an Executor instance inside your own TypeScript application.
+
+All examples on this path should import the Executor API from `@executor-js/sdk`.
diff --git a/docs/index.mdx b/docs/index.mdx
new file mode 100644
index 000000000..b2997f71b
--- /dev/null
+++ b/docs/index.mdx
@@ -0,0 +1,8 @@
+---
+title: Executor
+description: Product and SDK documentation for Executor.
+---
+
+Executor gives AI agents one shared tool catalog, auth layer, and policy system across local, cloud, and SDK workflows.
+
+These docs are scaffolded around realistic examples. SDK examples should compile against the public SDK packages before their snippets graduate into guide content.
diff --git a/docs/local/auth-and-secrets.mdx b/docs/local/auth-and-secrets.mdx
new file mode 100644
index 000000000..26ad4fdf9
--- /dev/null
+++ b/docs/local/auth-and-secrets.mdx
@@ -0,0 +1,6 @@
+---
+title: Auth And Secrets
+description: Manage local credentials.
+---
+
+This page will explain how local credentials are stored, resolved, and used by sources.
diff --git a/docs/local/cli.mdx b/docs/local/cli.mdx
new file mode 100644
index 000000000..72ff8fd07
--- /dev/null
+++ b/docs/local/cli.mdx
@@ -0,0 +1,6 @@
+---
+title: CLI
+description: Use Executor from the command line.
+---
+
+The CLI starts local services, inspects tools, invokes tools, and manages runtime workflows.
diff --git a/docs/local/install.mdx b/docs/local/install.mdx
new file mode 100644
index 000000000..271fea9ba
--- /dev/null
+++ b/docs/local/install.mdx
@@ -0,0 +1,6 @@
+---
+title: Install
+description: Install and start Executor locally.
+---
+
+This page will cover local installation and startup commands.
diff --git a/docs/local/mcp-server.mdx b/docs/local/mcp-server.mdx
new file mode 100644
index 000000000..818c8c8d0
--- /dev/null
+++ b/docs/local/mcp-server.mdx
@@ -0,0 +1,6 @@
+---
+title: MCP Server
+description: Connect local agents to Executor through MCP.
+---
+
+Executor can run as an MCP server so compatible agents can use the same shared tool catalog.
diff --git a/docs/local/web-ui.mdx b/docs/local/web-ui.mdx
new file mode 100644
index 000000000..5a3e964ec
--- /dev/null
+++ b/docs/local/web-ui.mdx
@@ -0,0 +1,6 @@
+---
+title: Web UI
+description: Manage sources, tools, secrets, and policies locally.
+---
+
+The local web UI is the fastest way to configure Executor on your machine.
diff --git a/docs/sdk/approvals.mdx b/docs/sdk/approvals.mdx
new file mode 100644
index 000000000..ad29db2a2
--- /dev/null
+++ b/docs/sdk/approvals.mdx
@@ -0,0 +1,6 @@
+---
+title: Approvals
+description: Handle approval and elicitation requests.
+---
+
+Approvals let a tool ask for confirmation or additional input while it is being invoked.
diff --git a/docs/sdk/create-executor.mdx b/docs/sdk/create-executor.mdx
new file mode 100644
index 000000000..091a0837f
--- /dev/null
+++ b/docs/sdk/create-executor.mdx
@@ -0,0 +1,6 @@
+---
+title: Create An Executor
+description: Configure scopes, plugins, storage, and elicitation.
+---
+
+This page will explain the public `createExecutor` flow.
diff --git a/docs/sdk/errors.mdx b/docs/sdk/errors.mdx
new file mode 100644
index 000000000..40a0e2991
--- /dev/null
+++ b/docs/sdk/errors.mdx
@@ -0,0 +1,6 @@
+---
+title: Errors
+description: Handle SDK failures.
+---
+
+This page will document the public error behavior exposed by `@executor-js/sdk`.
diff --git a/docs/sdk/quickstart.mdx b/docs/sdk/quickstart.mdx
new file mode 100644
index 000000000..2305296a7
--- /dev/null
+++ b/docs/sdk/quickstart.mdx
@@ -0,0 +1,70 @@
+---
+title: Quickstart
+description: Create an Executor, add a source, and inspect its tools.
+---
+
+import CreateExecutor from "/snippets/sdk/quickstart/create-executor.mdx";
+import AddSource from "/snippets/sdk/quickstart/add-source.mdx";
+import ListTools from "/snippets/sdk/quickstart/list-tools.mdx";
+import InspectSchema from "/snippets/sdk/quickstart/inspect-schema.mdx";
+import CloseExecutor from "/snippets/sdk/quickstart/close-executor.mdx";
+
+{/* Code snippets on this page are generated from examples/docs-sdk-quickstart/src/main.ts. */}
+
+The SDK lets you embed Executor in a TypeScript application.
+
+This quickstart creates an Executor, loads an OpenAPI source from a local spec, lists the tools it contributed, and inspects one tool schema. The snippets on this page are generated from a runnable example in `examples/docs-sdk-quickstart`.
+
+## Install
+
+
+
+```bash npm
+npm install @executor-js/sdk @executor-js/plugin-openapi
+```
+
+```bash pnpm
+pnpm add @executor-js/sdk @executor-js/plugin-openapi
+```
+
+```bash yarn
+yarn add @executor-js/sdk @executor-js/plugin-openapi
+```
+
+```bash bun
+bun add @executor-js/sdk @executor-js/plugin-openapi
+```
+
+
+
+## Create An Executor
+
+Import the SDK and configure the plugins you want to expose.
+
+
+
+`onElicitation: "accept-all"` is convenient for scripts and examples. Applications with interactive approval flows should pass a handler instead.
+
+## Add A Source
+
+Sources add tools to the Executor catalog. This example registers an OpenAPI document under the `inventory` namespace.
+
+
+
+## List Tools
+
+After a source is registered, its tools appear in the unified tool catalog.
+
+
+
+## Inspect A Tool
+
+Tools expose schema metadata that agents and applications can use before invoking them.
+
+
+
+## Shut Down
+
+Close the Executor when your process is done with it.
+
+
diff --git a/docs/sdk/secrets.mdx b/docs/sdk/secrets.mdx
new file mode 100644
index 000000000..065740203
--- /dev/null
+++ b/docs/sdk/secrets.mdx
@@ -0,0 +1,6 @@
+---
+title: Secrets
+description: Store and reference credentials from SDK workflows.
+---
+
+Secrets let sources and tools use credentials without hard-coding sensitive values in source definitions.
diff --git a/docs/sdk/sources.mdx b/docs/sdk/sources.mdx
new file mode 100644
index 000000000..a2355a92e
--- /dev/null
+++ b/docs/sdk/sources.mdx
@@ -0,0 +1,6 @@
+---
+title: Sources
+description: Add MCP, OpenAPI, GraphQL, and other sources.
+---
+
+Sources turn external systems into tools that agents can discover and call.
diff --git a/docs/sdk/tools.mdx b/docs/sdk/tools.mdx
new file mode 100644
index 000000000..98a86ce37
--- /dev/null
+++ b/docs/sdk/tools.mdx
@@ -0,0 +1,6 @@
+---
+title: Tools
+description: List, inspect, and invoke tools.
+---
+
+Tools are the callable actions exposed by sources. This page will cover listing tools, reading schemas, filtering by source, and invoking tools.
diff --git a/docs/snippets/README.md b/docs/snippets/README.md
new file mode 100644
index 000000000..7a074ea82
--- /dev/null
+++ b/docs/snippets/README.md
@@ -0,0 +1,7 @@
+# Generated snippets
+
+Files in this directory are generated by `bun run docs:snippets`.
+
+Edit the source example files under `examples/` between `docs:start` and
+`docs:end` markers, then regenerate snippets. Do not edit generated `.mdx`
+snippet files directly.
diff --git a/docs/snippets/sdk/quickstart/add-source.mdx b/docs/snippets/sdk/quickstart/add-source.mdx
new file mode 100644
index 000000000..82ed0755f
--- /dev/null
+++ b/docs/snippets/sdk/quickstart/add-source.mdx
@@ -0,0 +1,12 @@
+{/*
+ This file is generated by scripts/generate-doc-snippets.ts.
+ Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+*/}
+
+```ts
+await executor.openapi.addSpec({
+ namespace: "inventory",
+ scope: "docs-workspace",
+ spec: JSON.stringify(inventoryApi),
+});
+```
diff --git a/docs/snippets/sdk/quickstart/close-executor.mdx b/docs/snippets/sdk/quickstart/close-executor.mdx
new file mode 100644
index 000000000..aa8513163
--- /dev/null
+++ b/docs/snippets/sdk/quickstart/close-executor.mdx
@@ -0,0 +1,8 @@
+{/*
+ This file is generated by scripts/generate-doc-snippets.ts.
+ Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+*/}
+
+```ts
+await executor.close();
+```
diff --git a/docs/snippets/sdk/quickstart/create-executor.mdx b/docs/snippets/sdk/quickstart/create-executor.mdx
new file mode 100644
index 000000000..9a4cab682
--- /dev/null
+++ b/docs/snippets/sdk/quickstart/create-executor.mdx
@@ -0,0 +1,12 @@
+{/*
+ This file is generated by scripts/generate-doc-snippets.ts.
+ Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+*/}
+
+```ts
+const executor = await createExecutor({
+ scopes: [{ id: "docs-workspace", name: "Docs Workspace" }],
+ plugins: [openApiPlugin()],
+ onElicitation: "accept-all",
+});
+```
diff --git a/docs/snippets/sdk/quickstart/inspect-schema.mdx b/docs/snippets/sdk/quickstart/inspect-schema.mdx
new file mode 100644
index 000000000..2674de463
--- /dev/null
+++ b/docs/snippets/sdk/quickstart/inspect-schema.mdx
@@ -0,0 +1,10 @@
+{/*
+ This file is generated by scripts/generate-doc-snippets.ts.
+ Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+*/}
+
+```ts
+const schema = await executor.tools.schema("inventory.listItems");
+
+console.log(schema?.inputTypeScript ?? "No input required");
+```
diff --git a/docs/snippets/sdk/quickstart/list-tools.mdx b/docs/snippets/sdk/quickstart/list-tools.mdx
new file mode 100644
index 000000000..15071dac2
--- /dev/null
+++ b/docs/snippets/sdk/quickstart/list-tools.mdx
@@ -0,0 +1,12 @@
+{/*
+ This file is generated by scripts/generate-doc-snippets.ts.
+ Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+*/}
+
+```ts
+const tools = await executor.tools.list({ sourceId: "inventory" });
+
+for (const tool of tools) {
+ console.log(`${tool.id}: ${tool.description}`);
+}
+```
diff --git a/examples/docs-sdk-quickstart/package.json b/examples/docs-sdk-quickstart/package.json
new file mode 100644
index 000000000..fd7cca19a
--- /dev/null
+++ b/examples/docs-sdk-quickstart/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "@executor-js/example-docs-sdk-quickstart",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "start": "bun run src/main.ts",
+ "typecheck": "tsgo --noEmit",
+ "typecheck:slow": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@executor-js/plugin-openapi": "workspace:*",
+ "@executor-js/sdk": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/node": "catalog:",
+ "typescript": "catalog:"
+ }
+}
diff --git a/examples/docs-sdk-quickstart/src/main.ts b/examples/docs-sdk-quickstart/src/main.ts
new file mode 100644
index 000000000..70960a644
--- /dev/null
+++ b/examples/docs-sdk-quickstart/src/main.ts
@@ -0,0 +1,106 @@
+// This example is the source of truth for docs snippets on /sdk/quickstart.
+// Run `bun run docs:snippets` after editing docs:start/docs:end blocks.
+import { createExecutor } from "@executor-js/sdk/promise";
+import { openApiPlugin } from "@executor-js/plugin-openapi/promise";
+
+const inventoryApi = {
+ openapi: "3.0.0",
+ info: {
+ title: "Inventory API",
+ version: "1.0.0",
+ },
+ servers: [{ url: "https://inventory.example.test" }],
+ paths: {
+ "/items": {
+ get: {
+ operationId: "listItems",
+ summary: "List inventory items",
+ responses: {
+ "200": {
+ description: "Inventory items",
+ content: {
+ "application/json": {
+ schema: {
+ type: "array",
+ items: { $ref: "#/components/schemas/Item" },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "/items/{id}": {
+ get: {
+ operationId: "getItem",
+ summary: "Get an inventory item",
+ parameters: [
+ {
+ name: "id",
+ in: "path",
+ required: true,
+ schema: { type: "string" },
+ },
+ ],
+ responses: {
+ "200": {
+ description: "Inventory item",
+ content: {
+ "application/json": {
+ schema: { $ref: "#/components/schemas/Item" },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ components: {
+ schemas: {
+ Item: {
+ type: "object",
+ required: ["id", "name"],
+ properties: {
+ id: { type: "string" },
+ name: { type: "string" },
+ },
+ },
+ },
+ },
+};
+
+// docs:start create-executor
+const executor = await createExecutor({
+ scopes: [{ id: "docs-workspace", name: "Docs Workspace" }],
+ plugins: [openApiPlugin()],
+ onElicitation: "accept-all",
+});
+// docs:end create-executor
+
+try {
+ // docs:start add-source
+ await executor.openapi.addSpec({
+ namespace: "inventory",
+ scope: "docs-workspace",
+ spec: JSON.stringify(inventoryApi),
+ });
+ // docs:end add-source
+
+ // docs:start list-tools
+ const tools = await executor.tools.list({ sourceId: "inventory" });
+
+ for (const tool of tools) {
+ console.log(`${tool.id}: ${tool.description}`);
+ }
+ // docs:end list-tools
+
+ // docs:start inspect-schema
+ const schema = await executor.tools.schema("inventory.listItems");
+
+ console.log(schema?.inputTypeScript ?? "No input required");
+ // docs:end inspect-schema
+} finally {
+ // docs:start close-executor
+ await executor.close();
+ // docs:end close-executor
+}
diff --git a/examples/docs-sdk-quickstart/tsconfig.json b/examples/docs-sdk-quickstart/tsconfig.json
new file mode 100644
index 000000000..8cd04d0ac
--- /dev/null
+++ b/examples/docs-sdk-quickstart/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "outDir": "dist",
+ "rootDir": "src",
+ "types": ["node"]
+ },
+ "include": ["src"]
+}
diff --git a/package.json b/package.json
index 12cf236d8..59e3864e3 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,8 @@
"lint:release-notes": "bun run scripts/check-release-notes.ts",
"lint:changelog-stubs": "bun run scripts/check-changelog-stubs.ts",
"lint:fix": "oxlint -c .oxlintrc.jsonc --fix .",
+ "docs:snippets": "bun run scripts/generate-doc-snippets.ts",
+ "docs:smoke:install": "bun run scripts/smoke-docs-install.ts",
"format": "oxfmt .",
"format:check": "oxfmt --check .",
"pull:references": "bun run scripts/pull-references.ts",
diff --git a/packages/core/fumadb/tsup.config.ts b/packages/core/fumadb/tsup.config.ts
index aa74e580d..3cee38869 100644
--- a/packages/core/fumadb/tsup.config.ts
+++ b/packages/core/fumadb/tsup.config.ts
@@ -8,6 +8,7 @@ export default defineConfig({
"adapters/index": "src/adapters/index.ts",
"adapters/drizzle/index": "src/adapters/drizzle/index.ts",
"adapters/kysely/index": "src/adapters/kysely/index.ts",
+ "adapters/memory/index": "src/adapters/memory/index.ts",
"cli/index": "src/cli/index.ts",
cuid: "src/cuid.ts",
},
diff --git a/scripts/generate-doc-snippets.ts b/scripts/generate-doc-snippets.ts
new file mode 100644
index 000000000..cf8fa8d43
--- /dev/null
+++ b/scripts/generate-doc-snippets.ts
@@ -0,0 +1,70 @@
+import { mkdir, writeFile } from "node:fs/promises";
+import { dirname, join } from "node:path";
+
+interface SnippetSource {
+ readonly source: string;
+ readonly outputDir: string;
+ readonly language: string;
+}
+
+const sources: readonly SnippetSource[] = [
+ {
+ source: "examples/docs-sdk-quickstart/src/main.ts",
+ outputDir: "docs/snippets/sdk/quickstart",
+ language: "ts",
+ },
+];
+
+const markerPattern = /^\s*\/\/ docs:(start|end) ([a-z0-9-]+)\s*$/;
+
+const dedent = (lines: readonly string[]): string => {
+ const nonBlank = lines.filter((line) => line.trim().length > 0);
+ const indent = Math.min(
+ ...nonBlank.map((line) => {
+ const match = line.match(/^\s*/);
+ return match?.[0].length ?? 0;
+ }),
+ );
+
+ return lines
+ .map((line) => line.slice(indent))
+ .join("\n")
+ .trim();
+};
+
+for (const source of sources) {
+ const text = await Bun.file(source.source).text();
+ const snippets = new Map();
+ let current: { readonly name: string; readonly lines: string[] } | null = null;
+
+ for (const line of text.split("\n")) {
+ const marker = line.match(markerPattern);
+ if (marker) {
+ const [, kind, name] = marker;
+ if (kind === "start") {
+ if (current) throw new Error(`Nested snippet marker in ${source.source}: ${name}`);
+ current = { name, lines: [] };
+ } else {
+ if (!current || current.name !== name) {
+ throw new Error(`Unmatched snippet end in ${source.source}: ${name}`);
+ }
+ snippets.set(name, current.lines);
+ current = null;
+ }
+ continue;
+ }
+
+ if (current) current.lines.push(line);
+ }
+
+ if (current) throw new Error(`Unclosed snippet marker in ${source.source}: ${current.name}`);
+
+ for (const [name, lines] of snippets) {
+ const output = join(source.outputDir, `${name}.mdx`);
+ await mkdir(dirname(output), { recursive: true });
+ await writeFile(
+ output,
+ `{/*\n This file is generated by scripts/generate-doc-snippets.ts.\n Edit ${source.source} between the docs:start/docs:end markers instead.\n*/}\n\n\`\`\`${source.language}\n${dedent(lines)}\n\`\`\`\n`,
+ );
+ }
+}
diff --git a/scripts/smoke-docs-install.ts b/scripts/smoke-docs-install.ts
new file mode 100644
index 000000000..0a74fcd9a
--- /dev/null
+++ b/scripts/smoke-docs-install.ts
@@ -0,0 +1,97 @@
+#!/usr/bin/env bun
+/**
+ * Verifies the SDK install command shown in docs resolves to a package we can
+ * actually publish and consume.
+ *
+ * This intentionally installs the packed tarball under the documented package
+ * name (`@executor-js/sdk`) instead of relying on workspace resolution.
+ */
+import { $ } from "bun";
+import { existsSync, readdirSync } from "node:fs";
+import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import { dirname, join, resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
+const documentedPackages = ["@executor-js/sdk", "@executor-js/plugin-openapi"] as const;
+const publicPackageDirs = [
+ "packages/core/fumadb",
+ "packages/core/sdk",
+ "packages/core/config",
+ "packages/plugins/openapi",
+] as const;
+
+const readPackageName = async (pkgDir: string): Promise => {
+ const raw = await readFile(join(pkgDir, "package.json"), "utf8");
+ return (JSON.parse(raw) as { name: string }).name;
+};
+
+const findTarball = (pkgDir: string, packageName: string): string => {
+ const tarball = readdirSync(pkgDir).find((entry) => entry.endsWith(".tgz"));
+ if (!tarball) {
+ throw new Error(`No packed tarball found for ${packageName}`);
+ }
+ return join(pkgDir, tarball);
+};
+
+console.log(`[docs-smoke] packing documented SDK packages`);
+await $`bun run scripts/publish-packages.ts --dry-run`.cwd(repoRoot);
+
+const tarballs = new Map();
+for (const relDir of publicPackageDirs) {
+ const pkgDir = join(repoRoot, relDir);
+ const name = await readPackageName(pkgDir);
+ tarballs.set(name, findTarball(pkgDir, name));
+}
+
+const tmp = await mkdtemp(join(tmpdir(), "executor-docs-install-"));
+
+try {
+ const dependencies: Record = {};
+ const overrides: Record = {};
+ for (const [name, tarball] of tarballs) {
+ overrides[name] = `file:${tarball}`;
+ }
+ for (const name of documentedPackages) {
+ const tarball = tarballs.get(name);
+ if (!tarball) {
+ throw new Error(`No packed tarball found for documented package ${name}`);
+ }
+ dependencies[name] = `file:${tarball}`;
+ }
+
+ const fixture = {
+ name: "executor-docs-install-smoke",
+ version: "0.0.0",
+ private: true,
+ type: "module",
+ dependencies,
+ overrides,
+ };
+
+ await writeFile(join(tmp, "package.json"), `${JSON.stringify(fixture, null, 2)}\n`);
+
+ console.log(`[docs-smoke] npm install ${documentedPackages.join(" ")}`);
+ await $`npm install --no-audit --no-fund --legacy-peer-deps`.cwd(tmp);
+
+ for (const packageName of documentedPackages) {
+ const installedManifest = join(tmp, "node_modules", ...packageName.split("/"), "package.json");
+ if (!existsSync(installedManifest)) {
+ throw new Error(`Expected ${packageName} to be installed at ${installedManifest}`);
+ }
+ const manifest = await import(installedManifest, { with: { type: "json" } });
+ if (manifest.default.name !== packageName) {
+ throw new Error(
+ `Expected installed package name to be ${packageName}, got ${manifest.default.name}`,
+ );
+ }
+ }
+
+ console.log(`[docs-smoke] import documented SDK packages`);
+ await $`node --input-type=module --eval ${`const sdk = await import("@executor-js/sdk"); const openapi = await import("@executor-js/plugin-openapi"); if (typeof sdk.createExecutor !== "function") throw new Error("missing createExecutor"); if (typeof openapi.openApiPlugin !== "function") throw new Error("missing openApiPlugin");`}`.cwd(
+ tmp,
+ );
+} finally {
+ await rm(tmp, { recursive: true, force: true });
+}
From 09555421cdad3d549bb07fcfe1a7795cc9206642 Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Sat, 16 May 2026 11:04:08 -0700
Subject: [PATCH 2/2] fix docs ci checks
---
docs/snippets/sdk/quickstart/add-source.mdx | 8 ++--
.../sdk/quickstart/close-executor.mdx | 8 ++--
.../sdk/quickstart/create-executor.mdx | 8 ++--
.../sdk/quickstart/inspect-schema.mdx | 8 ++--
docs/snippets/sdk/quickstart/list-tools.mdx | 8 ++--
examples/docs-sdk-quickstart/CHANGELOG.md | 6 +++
examples/docs-sdk-quickstart/src/main.ts | 44 +++++++++----------
scripts/generate-doc-snippets.ts | 2 +-
8 files changed, 48 insertions(+), 44 deletions(-)
create mode 100644 examples/docs-sdk-quickstart/CHANGELOG.md
diff --git a/docs/snippets/sdk/quickstart/add-source.mdx b/docs/snippets/sdk/quickstart/add-source.mdx
index 82ed0755f..2d004ee75 100644
--- a/docs/snippets/sdk/quickstart/add-source.mdx
+++ b/docs/snippets/sdk/quickstart/add-source.mdx
@@ -1,7 +1,7 @@
-{/*
- This file is generated by scripts/generate-doc-snippets.ts.
- Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
-*/}
+{/_
+This file is generated by scripts/generate-doc-snippets.ts.
+Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+_/}
```ts
await executor.openapi.addSpec({
diff --git a/docs/snippets/sdk/quickstart/close-executor.mdx b/docs/snippets/sdk/quickstart/close-executor.mdx
index aa8513163..34df34ee1 100644
--- a/docs/snippets/sdk/quickstart/close-executor.mdx
+++ b/docs/snippets/sdk/quickstart/close-executor.mdx
@@ -1,7 +1,7 @@
-{/*
- This file is generated by scripts/generate-doc-snippets.ts.
- Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
-*/}
+{/_
+This file is generated by scripts/generate-doc-snippets.ts.
+Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+_/}
```ts
await executor.close();
diff --git a/docs/snippets/sdk/quickstart/create-executor.mdx b/docs/snippets/sdk/quickstart/create-executor.mdx
index 9a4cab682..c9717176e 100644
--- a/docs/snippets/sdk/quickstart/create-executor.mdx
+++ b/docs/snippets/sdk/quickstart/create-executor.mdx
@@ -1,7 +1,7 @@
-{/*
- This file is generated by scripts/generate-doc-snippets.ts.
- Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
-*/}
+{/_
+This file is generated by scripts/generate-doc-snippets.ts.
+Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+_/}
```ts
const executor = await createExecutor({
diff --git a/docs/snippets/sdk/quickstart/inspect-schema.mdx b/docs/snippets/sdk/quickstart/inspect-schema.mdx
index 2674de463..7409b681c 100644
--- a/docs/snippets/sdk/quickstart/inspect-schema.mdx
+++ b/docs/snippets/sdk/quickstart/inspect-schema.mdx
@@ -1,7 +1,7 @@
-{/*
- This file is generated by scripts/generate-doc-snippets.ts.
- Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
-*/}
+{/_
+This file is generated by scripts/generate-doc-snippets.ts.
+Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+_/}
```ts
const schema = await executor.tools.schema("inventory.listItems");
diff --git a/docs/snippets/sdk/quickstart/list-tools.mdx b/docs/snippets/sdk/quickstart/list-tools.mdx
index 15071dac2..3857085d0 100644
--- a/docs/snippets/sdk/quickstart/list-tools.mdx
+++ b/docs/snippets/sdk/quickstart/list-tools.mdx
@@ -1,7 +1,7 @@
-{/*
- This file is generated by scripts/generate-doc-snippets.ts.
- Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
-*/}
+{/_
+This file is generated by scripts/generate-doc-snippets.ts.
+Edit examples/docs-sdk-quickstart/src/main.ts between the docs:start/docs:end markers instead.
+_/}
```ts
const tools = await executor.tools.list({ sourceId: "inventory" });
diff --git a/examples/docs-sdk-quickstart/CHANGELOG.md b/examples/docs-sdk-quickstart/CHANGELOG.md
new file mode 100644
index 000000000..8b69ab6b6
--- /dev/null
+++ b/examples/docs-sdk-quickstart/CHANGELOG.md
@@ -0,0 +1,6 @@
+# @executor-js/example-docs-sdk-quickstart changelog
+
+This file exists for `changesets/action@v1` compatibility (it reads every
+workspace package's `CHANGELOG.md` to build the Version Packages PR).
+Canonical user-facing release notes are at `apps/cli/release-notes/next.md`
+and on the GitHub Releases page.
diff --git a/examples/docs-sdk-quickstart/src/main.ts b/examples/docs-sdk-quickstart/src/main.ts
index 70960a644..2a54a4095 100644
--- a/examples/docs-sdk-quickstart/src/main.ts
+++ b/examples/docs-sdk-quickstart/src/main.ts
@@ -77,30 +77,28 @@ const executor = await createExecutor({
});
// docs:end create-executor
-try {
- // docs:start add-source
- await executor.openapi.addSpec({
- namespace: "inventory",
- scope: "docs-workspace",
- spec: JSON.stringify(inventoryApi),
- });
- // docs:end add-source
+// docs:start add-source
+await executor.openapi.addSpec({
+ namespace: "inventory",
+ scope: "docs-workspace",
+ spec: JSON.stringify(inventoryApi),
+});
+// docs:end add-source
+
+// docs:start list-tools
+const tools = await executor.tools.list({ sourceId: "inventory" });
- // docs:start list-tools
- const tools = await executor.tools.list({ sourceId: "inventory" });
+for (const tool of tools) {
+ console.log(`${tool.id}: ${tool.description}`);
+}
+// docs:end list-tools
- for (const tool of tools) {
- console.log(`${tool.id}: ${tool.description}`);
- }
- // docs:end list-tools
+// docs:start inspect-schema
+const schema = await executor.tools.schema("inventory.listItems");
- // docs:start inspect-schema
- const schema = await executor.tools.schema("inventory.listItems");
+console.log(schema?.inputTypeScript ?? "No input required");
+// docs:end inspect-schema
- console.log(schema?.inputTypeScript ?? "No input required");
- // docs:end inspect-schema
-} finally {
- // docs:start close-executor
- await executor.close();
- // docs:end close-executor
-}
+// docs:start close-executor
+await executor.close();
+// docs:end close-executor
diff --git a/scripts/generate-doc-snippets.ts b/scripts/generate-doc-snippets.ts
index cf8fa8d43..f5b6c9e9f 100644
--- a/scripts/generate-doc-snippets.ts
+++ b/scripts/generate-doc-snippets.ts
@@ -64,7 +64,7 @@ for (const source of sources) {
await mkdir(dirname(output), { recursive: true });
await writeFile(
output,
- `{/*\n This file is generated by scripts/generate-doc-snippets.ts.\n Edit ${source.source} between the docs:start/docs:end markers instead.\n*/}\n\n\`\`\`${source.language}\n${dedent(lines)}\n\`\`\`\n`,
+ `{/_\nThis file is generated by scripts/generate-doc-snippets.ts.\nEdit ${source.source} between the docs:start/docs:end markers instead.\n_/}\n\n\`\`\`${source.language}\n${dedent(lines)}\n\`\`\`\n`,
);
}
}