`createCopilotNodeListener` now mirrors `createCopilotRuntimeHandler`'s branded
overload pair, so a runtime with at least one declared Channel yields a listener
whose `.channels` is non-optional and the documented `listener.channels.ready()`
call type-checks with no `!` and no `?.`. `activateChannels: false` and
channel-less runtimes keep the optional shape. Both listener types are exported
from `@copilotkit/runtime/v2/node`.
Corrects TSDoc on the node, express, and hono wrappers that still claimed
activation happens "at creation time" and labelled `ready()` as optional — stale
since activation was deferred to make the Fetch handler serverless-safe. On a
long-running host that call is required, not optional.
Fixes a live consequence of that stale model: `examples/slack/app/managed.ts`
never called `ready()`, so it mounted a listener, logged "started managed
Channel", and connected nothing. Covered by a regression assertion.
Drops the now-unnecessary `?.` from the examples, READMEs, and channel docs, and
adds compile-time contracts for the listener shape alongside the existing
handler ones. The examples compile with `strict: true`, so they prove the
`?.`-free call under strict null checks, which the runtime package (strict:
false) cannot.
Fixes the Channels docs/examples pointing at an Intelligence host that
does not serve the API, and the websocket URL guidance that can never
produce a working prod value. Linear:
[OSS-621](https://linear.app/copilotkit/issue/OSS-621).
## The two bugs
**1. The documented host does not serve the API.** Probed every
plausible path, not just `/`:
| URL | Result |
| --- | --- |
| `api.copilotkit.ai` — `/`, `/api`, `/api/health`, `/health`,
`/api/threads`, `/api/v1/threads` | **404 on all**, `server:
awselb/2.0`, `content-length: 0` — an ALB with no target-group rule
behind it |
| `realtime.copilotkit.ai` | **no DNS record at all** |
| `api.intelligence.copilotkit.ai/` and `/api/health` | 200,
`x-powered-by: Express` |
| `api.intelligence.copilotkit.ai/api/threads` | **401** — a real,
auth-gated endpoint |
| `realtime.intelligence.copilotkit.ai/runner/websocket` | **403** —
mounted and auth-gated (a 404 would mean unmounted) |
So the documented host is not merely returning 404 at the root — nothing
is routed there on any path, and it is not the app (no `x-powered-by`).
The working pair, matching the CLI's baked-in prod defaults and
`gitops/environments/prod/values.yaml`, is
`https://api.intelligence.copilotkit.ai` +
`wss://realtime.intelligence.copilotkit.ai`.
**2. `wsUrl` was documented as derivable from `apiUrl`.** Prod splits
the API and realtime planes across *different hosts*, so a scheme-only
swap yields `wss://api.intelligence.copilotkit.ai` — wrong host. That
failure is silent: a wrong `apiUrl` returns a clean HTTP error, but a
wrong `wsUrl` sits in `connecting` until the settle timeout and reports
only "did not settle in time". The derive is not even correct locally,
where the API and gateway are on different ports (4201 vs 4401) and the
swap preserves the port. It is essentially never right, so it is deleted
rather than relabelled.
Demonstrated end to end rather than asserted — running `examples/teams`
with the WS URL unset:
```
# on main: derive(https://api.intelligence.copilotkit.ai) -> wss://api.intelligence.copilotkit.ai (wrong host, 30s hang)
# on this branch:
exit code: 1
Missing COPILOTKIT_INTELLIGENCE_WS_URL.
export COPILOTKIT_INTELLIGENCE_URL=https://api.intelligence.copilotkit.ai
export COPILOTKIT_INTELLIGENCE_WS_URL=wss://realtime.intelligence.copilotkit.ai
The API and websocket URLs are DIFFERENT hosts (api.… vs realtime.…), so
the websocket URL cannot be derived from the API URL — set both.
```
## Scope note
The ticket listed 8 sites; the actual blast radius was 30 across 22
files. Beyond the ticket's list:
- **Five more channels package READMEs** — `channels`, `channels-core`,
`channels-discord`, `channels-slack`, `channels-teams` (the ticket named
only telegram + whatsapp).
- **The live product docs** —
`showcase/shell-docs/src/content/docs/channels/` taught the broken
derive in 8 files. These escaped the ticket's grep because their host
was already a `your-intelligence-url` placeholder; only bug 2 was
present. This is the surface developers actually read.
- **A generated skills mirror** — `skills/runtime/` is produced from
`packages/runtime/skills/runtime/` by `pnpm sync:plugin-skills`; fixing
one without the other leaves the bug live and fails the
`check-plugin-skills` gate.
- `skills/copilotkit-debug/references/runtime-debugging.md` and a third
occurrence in `client.ts`.
## Acceptance item 4 — resolved, chain verified
The ticket flagged a contradiction: `realtime-gateway.ts` documented
`wss://gateway.example/socket` while the runtime skill listed `/socket`
as a mistake. **The skill is right**, confirmed by tracing the real
runtime path rather than inferring it:
1. `channel-activation-config.ts:145` — `const wsUrl =
intelligence.ɵgetRunnerWsUrl()`, i.e. base + `/runner`.
2. → `channel-manager.ts:237` `wsUrl: config.wsUrl` →
`startChannelsOverRealtimeGateway` → `connectRealtimeGateway`.
3. `realtime-gateway.ts:253` hands that to Phoenix's `Socket`, which
appends `/websocket`.
4. The gateway mounts exactly `/runner` and `/client`
(`realtime_gateway/endpoint.ex:10,17`). There is no `/socket`.
The two docs survived contradicting each other because they describe
**different layers**: the public `wsUrl` is a bare base, while
`connectRealtimeGateway` receives the already-derived runner URL. Its
doc comment and the test fixtures move to `/runner` and now name the
layer. Independently, `get-runtime-info.ts:93` uses `ɵgetClientWsUrl()`,
which confirms the `/info` sample in the debug skill correctly keeps its
`/client` suffix — only the host there was wrong.
## Acceptance item 3 — split out
Failing loudly instead of hanging is a behavior change in the launcher's
connect path that overlaps OSS-622's error classification, so it is
[OSS-623](https://linear.app/copilotkit/issue/OSS-623) rather than
smuggled into a docs fix.
## Verification
- 44/44 gateway tests in `packages/channels-intelligence`;
`examples/slack/app/managed.test.ts` passes; `examples/teams` typechecks
clean.
- `nx run-many -t test,publint,attw` across the 15 affected projects
passed via the pre-commit hook; full CI green (38 checks, including
`build-check (shell-docs)`).
- Behavior proven by running the example, not by mocks (above).
- 45 commits behind `main` at time of review with **zero overlap** on
changed files, and the diff covers every dead-host and derive site
present on *current* `main`.
- No logic changes in either published package — `client.ts` and
`realtime-gateway.ts` are JSDoc/field-comment only. Behavior changes are
confined to the three example apps.
## Self-review pass
An adversarial pass over this PR tried to falsify its central claim
(that `api.copilotkit.ai` does not serve the API) by probing non-root
paths — the evidence got stronger, not weaker. It also cleared a
suspected regression: three `channels-intelligence` files read
`COPILOTKIT_INTELLIGENCE_URL` without the WS var, but they are the
HTTP-only transport path and need no socket URL. Two genuine gaps it
*did* find are fixed in the last commit: the five platform pages had
lost deployment neutrality (managed hosts now carry a self-hosted note),
and `index.mdx`/`mcp.mdx` referenced the new variable without telling
the reader where it comes from.
**One product decision for the reviewer:** `api.copilotkit.ai` is a live
ALB that routes nothing. If it is meant to become the public API alias,
this PR is documenting the wrong long-term string and the ALB wants a
listener rule instead. I used the host the product actually hands users
today (CLI prod defaults + gitops).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Two gaps from the previous commit, found reviewing it.
The five platform pages previously carried a `your-intelligence-url`
placeholder, which was neutral about where Intelligence runs. Replacing it with
the managed hosts read as "this is the endpoint" to a self-hosted reader, and
only the quickstart said otherwise; every env block now notes that self-hosted
deployments substitute their own two hosts.
index.mdx and mcp.mdx are code-only pages with no env block, so after requiring
a second variable they referenced COPILOTKIT_INTELLIGENCE_WS_URL without ever
telling the reader where it comes from. Both now point at the dashboard and the
quickstart's env block.
Refs OSS-621
The published Channels docs configured the Intelligence client with
`wsUrl: apiUrl.replace(/^http/, "ws")` in all eight pages. Because the API and
realtime planes are separate hosts, that yields a URL serving no socket, and
the failure is a silent 30s hang rather than an error — so this was the most
harmful copy of the bug: it is the surface developers actually read.
Every page now reads COPILOTKIT_INTELLIGENCE_WS_URL from the environment
alongside the API URL, and the six env blocks that previously showed only a
`your-intelligence-url` placeholder document both hosts with the values that
work against the managed service. The quickstart gains a short paragraph on why
the second host is required and what going wrong looks like.
Refs OSS-621
Independent re-verification against packages/react-native source found the
page overstated polyfill auto-install: only /headless (and the root barrel,
via its /headless re-export) side-effect-imports the polyfill barrel.
src/components/index.ts imports no polyfills, so a consumer importing only
from @copilotkit/react-native/components does not get them auto-installed;
it relies on the provider imported alongside it. Corrects the 'all three
surfaces auto-install' and 'every entry point installs these automatically'
statements accordingly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the code samples from create_react_agent(middleware=..., prompt=...)
to create_agent/createAgent with system_prompt/systemPrompt, matching the
current pinned langchain 1.x API used elsewhere in the docs. Wire
copilotkitMiddleware into the TypeScript example's middleware array (it was
imported but never attached). Point the "Imperatively emitting tool calls"
link at the correct /integrations/langgraph/ prefixed route.
Addresses review feedback on #5469.
Point "See also" links at the /integrations/langgraph/ prefixed routes
(the bare /langgraph/... links 404), drop the dead Python SDK reference
link (no target page), and swap the placeholder "gpt-5.4" model string
for a real one (gpt-4o) in both code samples.
Addresses review feedback on #5483. The unrelated use-agent.tsx isReady
change was dropped by rebasing this branch onto upstream/main and
carrying forward only the docs commit — isReady already ships on main
via #6041.
Adds a new page under integrations/langgraph/advanced/ explaining how
LangGraph SDK backend emit functions (copilotkit_emit_tool_call,
copilotkit_customize_config) connect to React v2 frontend hooks
(useFrontendTool, useComponent). Includes a mapping table, two
concrete end-to-end examples, and a decision guide.
Closes#3301
Rewrites the React Native page into a production guide (Metro, polyfills,
provider options, runtime/model wiring, device + bench connectivity, frontend
tools, run lifecycle, voice), and corrects the source-backed inaccuracies found
in review. Every claim below was re-verified against the package source on main
(@copilotkit/react-native 1.63.2), not inferred.
Import surfaces (was "What's included" + "Headless imports")
- Documents all THREE entry points separately with the native peers each forces
Metro to resolve: /headless (none), root (expo-document-picker,
expo-file-system via useAttachments), /components (@gorhom/bottom-sheet,
react-native-streamdown).
- Removes the claim that the root barrel pulls @gorhom/bottom-sheet. It does
not -- the only import is src/components/CopilotModal.tsx, reachable solely
from /components. (The package's own source comments state this incorrectly;
that is what the previous draft was written from.)
- Warns that root's CopilotChat/CopilotModal are HEADLESS wrappers rendering
only children, while the same-named /components exports are the rendered
chat -- a silent blank-screen trap.
- The quickstart now imports from /headless throughout, matching its own advice
and keeping readers out of the release-bundle failure the page warns about.
- Corrects "the provider re-exports hooks" to the package, enumerates the
shared hooks, and drops "behave identically to the web SDK": React Native
ships its OWN useRenderTool (requires parameters, accepts handler, returns
ReactElement | null, no wildcard) and omits the web-only rendering hooks.
Metro
- Corrects the cause: jose is not a JWT/license dependency. It arrives via
telemetry (@copilotkit/shared -> @segment/analytics-node -> jose).
- Replaces the global unstable_conditionNames array with resolveRequest scoped
to jose (Metro's own documented recipe). unstable_conditionNames is an
UNORDERED SET of asserted conditions -- target priority comes from each
package's own exports key order, so reordering that array does nothing. The
previous config also applied browser globally and dropped Metro's default
react-native condition.
- Fixes version bounds: package exports arrived opt-in in RN 0.72 / Metro
0.76.1 and is default-on from Metro 0.82 / RN 0.79 (not "0.70+").
Polyfills
- Makes the quickstart canonical instead of correcting it later. Drops
"optional belt-and-suspenders".
- Documents the crypto ordering as a HARD requirement: CopilotKit's polyfill
and react-native-get-random-values are both first-writer-wins, so any
CopilotKit import evaluated first permanently locks in the non-cryptographic
Math.random fallback and silently no-ops the secure library.
Provider / runtime
- headers: a function form is evaluated when the PROVIDER RENDERS, memoized,
and pushed to the core -- never per request. Adds rotating-token guidance
(drive from state, or call copilotkit.setHeaders on refresh).
- cors: corrects the causal claim. CORS is browser-enforced; React Native's
native stack sends no Origin and never consults Access-Control-Allow-Origin,
so cors:true is irrelevant to native reachability (it matters for Expo Web).
Device connectivity
- Labels the adb reverse row Android-only and adds an iOS device row.
- Adds the missing `npx expo install expo-build-properties` step.
- Adds the iOS path, which was absent: ATS applies to debug and release alike,
expo-build-properties has no iOS ATS option, and since iOS 17 ATS rejects
raw IPs unless listed in NSExceptionDomains -- plus
NSLocalNetworkUsageDescription for the local-network permission gate. Notes
why NSAllowsLocalNetworking alone is insufficient.
Frontend tools
- Replaces the incorrect "useFrontendTool can carry a render function drawn as
the tool runs". The rendered RN chat reads a registry populated only by RN's
useRenderTool; a render passed to useFrontendTool is never drawn there and
yields the fallback "Called: <toolName>" stub.
Other
- Removes the useAgent({ threadId }) example: unsupported on main, does not
typecheck (TS2353), silently ignored. Recorded as a known limitation
pointing at #6141 instead, so this page no longer depends on that PR.
- Known limitations: drops the "No pre-built UI is required" positioning line;
corrects the markdown entry (the rendered chat DOES render markdown via
CopilotMarkdown/react-native-streamdown -- the old entry recommended the
wrong library); adds the threadId and web-only-hooks entries.
- Broadens the frontmatter description, which still promised only "get started".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
## What does this PR do?
Adds documentation for the **`@copilotkit/channels` SDK** — running a
CopilotKit agent as a bot inside Slack, Teams, WhatsApp, Telegram, and
Discord. New `---Channels---` nav group under `showcase/shell-docs`.
**Guides**
- Overview (agent + JSX + channel, end to end), Quickstart (TanStack
factory agent on the Intelligence adapter)
- UI Library (JSX component rendering, callbacks, component
registration, `{ raw }` escape hatch)
- Interactive flows: Human-in-the-loop (+ agent-initiated
`onInterrupt`), Reactions (+ emoji helpers), Modals
- Commands & global reactions, Files & multimodality, MCP (agent-side),
Channel configuration, Tools & context
- Platforms: overview of what Intelligence handles for you, plus
per-adapter pages (Teams / WhatsApp / Slack / Telegram / Discord) with
built-in tools/context
**API reference** (signatures pulled from the installed `0.2.1` type
definitions): Channel, Thread, JSX callbacks.
All examples use the Intelligence adapter except the platform-specific
pages, which use each platform's own adapter. Every internal link
resolves; MDX validated.
## Related PRs and Issues
- N/A
## Checklist
- [x] I have read the Contribution Guide
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Adversarial pass caught that every new CopilotRuntime({...}) snippet omitted the
required non-optional `agents` field (TS2741 on copy-paste) — added `agents: {}`
matching examples/slack/app/managed.ts. Also noted that the managed index/mcp
snippets end at ready() with no server, so a reader's process would exit — added a
keep-alive pointer to the Quickstart's full listener mount.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Channels run only through the Intelligence runtime now (PR #6145): public
channel.start()/stop()/addAdapter() are removed. Updated the run path to
new CopilotRuntime({ intelligence, channels }) + handler/listener.channels.ready()/stop()
across quickstart, index, mcp, configuration, the 5 platform pages, and the
channel reference; reframed the managed-vs-direct table (both require an
Intelligence key — the difference is who holds the platform credentials);
name is now required (the runtime keys lifecycle by it); surfaced the
Intelligence-key (free tier) prerequisite. Standardized the managed pattern on
zero-adapter createChannel({ name }) (runtime attaches the managed transport),
matching examples/slack/app/managed.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Response to docs audit. Real gaps fixed; false 'wrong scaffold'/'missing
content' findings verified against the rendered DOM and not acted on.
- Add ADK wrapper-limitations callout (no multimodal, last-message-only,
no live/voice, text-only output, no intermediate events,
LangsmithSessionService required, no LangGraph interrupts) quoted from
the canonical LangChain ADK guide.
- Add ADK prerequisites (Python 3.11+, deployments-wrap-sdk[google-adk],
Google AI API key for Gemini).
- Add a 'verify locally first' (langgraph dev) callout before deploy.
- Add a deployment-models callout (Cloud serverless/dedicated vs
self-hosted / hybrid / standalone) and soften the serverless-only intro.
- Register LangGraphPlatformDeploymentTabs in SNIPPET_MAP so inlineSnippets
resolves it and no longer logs a spurious 'snippet missing' warning;
drop the now-redundant STUB_PARTIAL_MAP + stub registration.
Not changed: per-route framework-tab defaulting is not feasible from the
shared partial (the Content 'framework' scope does not thread through the
base-docs render path, same pre-existing limitation AgentCore has), so both
framework tabs are shown with clear labels. Full split into separate
per-framework guides rejected (single shared snippet is by design).
Ticket: GROW-540
Self-contained agent-side deploy guide: deploy a LangGraph or Google ADK
agent to the LangSmith Platform, then point the CopilotKit Runtime at it.
- New canonical page deploy/langsmith.mdx (Overview > Deploy).
- Per-framework wrappers integrations/{langgraph,adk}/deploy-langsmith.mdx,
registered in each meta.json under a new Deploy section.
- Shared walkthrough snippet integrations/langsmith/index.mdx, framework
aware via the Content loader; reuses the existing
langgraph-platform-deployment-tabs snippet for deployment-URL sources.
- Generalize the Content MDX component to accept a partial path and add a
LangGraphPlatformDeploymentTabs stub.
- Also surfaces the previously orphaned langgraph deploy-agentcore wrapper
in the LangGraph Deploy section.
Commands and the ADK wrap SDK (deployments-wrap-sdk / saf_sdk) verified
against live LangChain docs.
Ticket: GROW-540
## Mastra Partner Refresh — showcase finalization (OSS-381)
Bumps the showcase Mastra integration onto the **v1 bridge alpha** and
flips the
features it unblocks out of `not_supported`. Opened for CI to run the
D6/e2e
suite (local Docker daemon is wedged in the authoring env — see notes).
### Landed
- **OSS-382 (gate):** `@ag-ui/mastra` `0.2.1-beta.2` →
**`1.1.0-alpha.0`**.
- Alpha verified to ship all features (grep on dist):
`emitInterruptOutcome`,
`STATE_DELTA`, `observationalMemory`, `background-task`,
`tracingOptions`,
`getA2UITools`/recovery. Peers satisfied (`@mastra/core` 1.41,
`client-js`
1.23.2, runtime 1.61.2).
- `next build` passes (40 routes). Unit tests **identical to the beta.2
baseline** (13 pre-existing failures in `route.test.ts`'s error-path
mocks,
unrelated to the bump — proven by a stash+reinstall A/B).
- **OSS-384 / OSS-423:** moved into `features` (demos + e2e + aimock
fixtures
were already wired, gated on this release):
`agentic-chat-reasoning`, `reasoning-default-render`,
`tool-rendering-reasoning-chain`, `shared-state-streaming`. Added the
missing
`reasoning-default` / `reasoning-custom` manifest demo entries.
- **Parity:** `not_supported_features` now holds only `gen-ui-interrupt`
+
`interrupt-headless`, matching the **langgraph-python gold standard**,
which
quarantines the same two cells on an upstream `@copilotkit/react-core`
v2
resume-path hook bug (published-package fix, out of scope). The native
interrupt + RUN_FINISHED-outcome path ships in the bridge; the showcase
cell
is blocked by the same upstream bug, not the bridge.
- **OSS-424:** execution-tracing note (`tracingOptions` in / `traceId`
on
`RUN_FINISHED.result` out) added to the Mastra Copilot Runtime doc.
- **OSS-425:** GenUI `generative_ui` spectrum already at parity with
gold
(`constrained-explicit`, `a2ui-fixed-schema`, `a2ui-dynamic-schema`).
### Not in this PR (scoped, blocked, or pending)
- **OSS-422 a2ui-recovery**, **OSS-426 background-agents**, **OSS-427
observational-memory** — new demo cells. Reference material + build
plans
ready. OM additionally needs `@mastra/memory` ≥1.21.2 (repo pins
`1.0.1-alpha.1`; the on-stream async-buffering path won't fire below
that).
- **OSS-91 browser-use** — Mastra-only, non-deterministic (no clean
aimock
replay), needs a Browserbase key not present in the env. Blocked.
- **OSS-392 input.context** — owner exception; only if langgraph
showcases it.
### Verification note
Local D6 could not be run: the Docker daemon's container-creation path
is wedged
in this environment (a trivial `hello-world` create hangs), and
unwedging needs a
Docker Desktop restart that would destroy a concurrent session's running
stack.
Relying on CI for D6/e2e. Everything above is build-level verified +
committed.
generate-registry.ts imports the catalog cross-join/flatten fold from
../harness/src/shared/catalog/catalog-flatten.ts, which does
`import yaml from "js-yaml"`. The generator's build/test environments did
not stage that file (or its module-resolution scope), so the fold could
not resolve.
- Dockerfiles (shell, shell-dashboard, shell-docs, shell-dojo): COPY the
shared catalog source + harness/package.json (its `"type":"module"` is
required so catalog-flatten resolves as ESM and its named exports bind)
and provide a node_modules for js-yaml resolution.
- generate-registry-pattern.test.ts (makeHarness): stage catalog-flatten.ts
and harness/package.json at the exact relative path the generator
resolves, and symlink the scripts node_modules onto the harness tree so
the ESM `import yaml from "js-yaml"` resolves.
- js-yaml + @types/js-yaml added to showcase/scripts (package.json and the
npm package-lock.json), and the root pnpm-lock.yaml regenerated to add
the matching importer entries for showcase/scripts (js-yaml >=4.1.1 via
the root override, @types/js-yaml ^4.0.9) so `pnpm install
--frozen-lockfile` stays in sync.
## What & why
Three independent documentation-accuracy fixes, batched into one PR.
### 1. Dead spec links + gen-ui page gaps (Closes#3975)
`generative-ui-specs-overview.mdx` (rendered at
`/whats-new/generative-ui-spec-support`) linked to the retired
`/generative-ui/specs/<spec>` subgroup. Repointed to canonical
destinations and added the frameworks list the issue asked for.
**Verified live (HTTP status against docs.copilotkit.ai):**
| Link | Before | After |
| --- | --- | --- |
| A2UI | `/generative-ui/specs/a2ui` (301 hop) | `/generative-ui/a2ui` →
**200** |
| MCP Apps | `/generative-ui/specs/mcp-apps` (301 hop) |
`/generative-ui/mcp-apps` → **200** |
| Open Generative UI (new) | — | `/generative-ui/open-generative-ui` →
**200** |
- **Supported Frameworks** list added — all 12 `/<slug>/quickstart`
targets return **200** live (LangGraph Py/TS, Google ADK, MS Agent, AWS
Strands, Mastra, PydanticAI, CrewAI, Agno, AG2, LlamaIndex, Claude Agent
SDK, Deep Agents).
- **Open-JSON-UI is intentionally NOT linked:**
`/generative-ui/open-json-ui` is a placeholder pulled from the nav and
redirected to `/generative-ui` on purpose (`next.config.ts` — `//
AI-slop placeholder pulled from nav until properly authored`). Linking
only the two specs that have live detail pages avoids sending readers to
a redirect. Open-JSON-UI is still described in the comparison table on
the page.
- Open Generative UI is a CopilotKit capability (not an external spec),
so it sits under "related capabilities."
> Note: the issue/support-bot suggested a `/learn/...` path — there is
no `/learn/` tree in shell-docs; the canonical homes are the flat
`/generative-ui/<spec>` pages.
### 2. CLI `init` vs. existing app (Closes#2525)
Maintainer resolution was "fix the docs." The original "`init`
bootstraps your existing Next.js app" claim was already removed in the
shell-docs migration (the reported `/direct-to-llm/guides/quickstart`
now resolves to the Built-in Agent quickstart, which is fully manual).
To remove the remaining ambiguity:
- **Built-in Agent quickstart:** added an "Already have an app?" callout
— existing apps skip `create-next-app`.
- **CLI guide (`cli.mdx`):** clarified that `create` (aliased `init`)
scaffolds a brand-new project in its own directory and does not
detect/bootstrap an existing app; points to the manual install in the
Quickstart.
Verified against `copilotkit@latest` (4.3.0): `init --help` →
*"Initialize a **new** CopilotKit project … before scaffolding"*, `-n,
--name` *"names the local app **and its directory**"*, and
`init`/`create` are aliases.
### 3. Codex setup for the MCP guide (Closes#2526)
Added a **Codex** section to `mcp-server-setup.mdx` using the stdio
`mcp-remote` bridge in `~/.codex/config.toml`, matching the page's
existing command-based pattern (Cursor / Windsurf / Claude Desktop),
plus the `codex mcp add` shortcut.
Verified against the installed Codex CLI: `codex mcp --help` lists
`add`/`list`/`get`/`remove`, and the `[mcp_servers.<name>]` table with
`command`/`args` matches OpenAI's Codex config reference. Per the issue
thread, the macOS `mcp-remote` port-blocking concern is **not** claimed
to be solved — only the Codex config is documented.
## Testing
- **#3975 (links):** curled every added/changed URL against the live
docs — A2UI, MCP Apps, Open Generative UI, and all 12 framework
quickstarts return **200**; confirmed `/generative-ui/open-json-ui` is a
deliberate redirect (hence unlinked). Pre-existing `/ag-ui-protocol` and
`/generative-ui` links are stable 301→200 and left as-is.
- **#2525 (CLI):** ran `npx copilotkit@latest init --help` on the
published `latest` (4.3.0) — confirmed new-directory scaffolding, no
existing-app detection; verified `[Quickstart](/quickstart)` serves the
manual-install page live (`create-next-app` + "Install CopilotKit
packages").
- **#2526 (Codex):** ran `codex mcp --help` to confirm subcommands; new
section reuses the file's existing `<Steps>`/fenced-code structure.
`<Callout>` is a registered global MDX component
(`src/lib/mdx-registry.tsx`), already used unimported on the Built-in
Agent quickstart.
- Docs-only; no code paths affected.
Closes#3975Closes#2525Closes#2526🤖 Generated with [Claude Code](https://claude.com/claude-code)
CR: /generative-ui/open-json-ui is a deliberately-unpublished placeholder
(next.config.ts redirects it to /generative-ui, pulled from nav until
authored), so link only the two specs with live detail pages (A2UI, MCP
Apps). Open Generative UI is a CopilotKit capability rather than an
external spec, so it moves under related capabilities.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>