The packaged runtime skill up to v1.62.2 prescribed `api.copilotkit.ai` /
`realtime.copilotkit.ai`. The first host is a CNAME onto the legacy Copilot
Cloud ALB, where no listener rule matches it, so every request gets the ALB
default action: a 404 with an empty body. The second has no DNS record at all.
A reader who followed that page converted a working OSS install into a 502.
The hosts themselves were corrected in v1.64.0, but two shipped surfaces still
carried stale claims about the same step, and nothing stopped the hosts from
coming back a third time:
- The debug skill said Intelligence "requires ... `apiUrl`, `wsUrl`, `apiKey`,
`tenantId`". Three errors in one line: `apiUrl`/`wsUrl` have been optional
with managed defaults since v1.64.0, and `tenantId` has never existed on
`CopilotKitIntelligenceConfig` — the API key carries the project (its token
format is `cpk-{projectId}_...`) and the platform resolves the organization
server-side, so there is no org or tenant field for a caller to pass.
- `CopilotKitIntelligence`'s own TSDoc showed only `*.internal` placeholders,
so the class's hover docs never named the pair that actually serves prod.
`validate-intelligence-env-names` — already the unfiltered guard for this same
config surface (OSS-881) — now also fails on either dead host. The
channels-intelligence realtime test is allowlisted: it needs a hostname that
genuinely does not resolve, since `getaddrinfo ENOTFOUND` is the condition
under test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three names for one value were live in CopilotKit's own documentation, and
following the wrong one with a CLI-provisioned project yields an undefined
key:
- `INTELLIGENCE_API_KEY` — what `copilotkit project select` writes, used by
all 34 integration examples and the docs site.
- `COPILOTKIT_INTELLIGENCE_API_KEY` — the seven Channels package READMEs and
the packaged skills. Nothing ever read it.
- `COPILOTKIT_API_KEY` — the Slack and Teams examples, and the TSDoc on
`CopilotKitIntelligence` itself, which is what an IDE shows on hover.
`INTELLIGENCE_API_KEY` wins, because it is the name the CLI provisions and
changing it would break every scaffolded project in the wild.
`COPILOTKIT_INTELLIGENCE_API_KEY` is retired outright — no code read it.
`COPILOTKIT_API_KEY` stays readable as a deprecated alias in the two
examples that consume it, so an existing `.env` keeps working, and is
documented as deprecated everywhere it appears.
The skills reference also documented `organizationId`, sourced from a fourth
and fifth env name, as a `CopilotKitIntelligence` option. It is not one:
`CopilotKitIntelligenceConfig` has no such field, so the copy-pasteable
sample it appeared in would not compile. Removed from the samples, and the
prose that told readers to fetch a value for it corrected.
The Intelligence wiring itself was published only inside
`node_modules/@copilotkit/runtime/skills/`, and the only docs pages showing
`CopilotKitIntelligence` were the two Channels frontends — so a developer on
the plain web path had no page to reach it from. Adds
`/premium/connect-your-runtime`, which covers the wiring, how to confirm the
credential is actually consumed, and the self-hosted two-URL rule.
`scripts/validate-intelligence-env-names.ts` keeps this from drifting back.
It runs unfiltered in CI on purpose: the two workflows that would otherwise
cover it filter paths, and static/quality ignores `examples/**` — exactly
where the deprecated alias lives.
## Summary
- remove the retired top-level `docs/` Next app and the disabled
docs-sync workflow/script
- add `docs -> showcase/shell-docs` as a top-level symlink for `cd docs`
muscle memory without restoring the old docs tree
- move the docs model allowlist into `showcase/shell-docs/` and retarget
docs validation/doctest extraction to shell-docs content
- update docs/agent guidance and CI path filters so `docs/` is treated
as an alias, not an active separate docs surface
- tighten the pre-commit package check so non-package docs/tooling
changes do not fan out into the full package matrix
## Validation
- `pnpm exec tsx scripts/validate-doc-model-names.ts`
- `pnpm exec tsx scripts/doc-tests/extract.ts`
- `pnpm exec vitest run
scripts/__tests__/validate-doc-model-names.test.ts
scripts/doc-tests/__tests__/extract.test.ts
showcase/harness/src/cli/eval/scope.test.ts`
- `pnpm exec oxlint showcase/harness/src/cli/eval/scope.test.ts
scripts/doc-tests/extract.ts`
- `git diff --cached --check` before follow-up commit
- `test "$(readlink docs)" = "showcase/shell-docs"`
- `test -f docs/package.json`
- `pnpm exec oxfmt --check .claude/docs/documentation.md
.claude/docs/hooks.md AGENTS.md CLAUDE.md CONTRIBUTING.md
showcase/shell-docs/README.md`
- commit hooks passed
## Notes
- historical docs remain recoverable from
`archive/docs-save-do-not-prune` and `archive/docs-retired-2026-06-17`
- I intentionally left Vercel/project teardown out of this PR; this is
repo cleanup only
The plugin version pins to packages/runtime/package.json, but neither the
lefthook glob nor the plugin-skills-check workflow path filters watched
that file. A routine release bump to the runtime version therefore matched
no trigger and the pin silently rotted between releases (the root cause of
the version drift). Add packages/runtime/package.json to the lefthook glob
and to both the push and pull_request path filters so a version bump
re-runs check:plugin-skills.
lefthook invokes a multi-line `run` as `sh -c "<script>"` and (in lefthook
2.1.1 / Windows git-sh) does not escape the script's embedded double quotes,
so `"$@"` / `[ "$#" ]` / `x=""` close the `-c` string early and the shell
aborts with "unexpected EOF", failing every commit. Rewrite the lint-fix
script double-quote-free (unquoted $@/$# — staged paths have no spaces; JSON
is already glob-excluded so oxfmt never sees package.json; ruff scoped to .py
via case).
Add showcase/scripts/sync-promote-service-options.ts: generates the
promote workflow's service `choice` options from the SSOT
(railway-envs.ts), spliced between BEGIN/END markers in
showcase_promote.yml. Fail-loud throughout — every emitted token must
resolve to exactly one service under the resolve-step predicate
(name|dispatchName match AND probe.prod), tokens are YAML-safe, args are
strict (a typo'd flag cannot trigger a destructive write), and markers
are validated before any rewrite.
Wire it into a lefthook pre-commit hook (regenerate + restage; set -e so
a failed regen blocks the commit) and an advisory (never-failing) drift
check in showcase_validate.yml. Vitest coverage for ordering, exclusion,
collision/ambiguity guards, marker errors, exit codes, idempotency, and
the import-side-effect guard.
Adds two CI signals for keeping the published packages small and broadly compatible:
- Bundle size: size-limit file-mode config across packages plus a
CopilotChat import-size regression signal (gzip) so growth in the
headline consumer entrypoint is visible on every PR. A bundle-size
workflow comments results on the PR (Phase 1: no hard-fail).
- ES compatibility: a compat-check (es-check) script across 9 packages
with a root .browserslistrc, validating built .mjs/.cjs against the
es2022 build target.
The measure script is importable (measureBundle) and unit-tested. Dev
docs live under dev-docs/ (bundle-size.md, browser-compat.md). All
action refs are pinned to full commit SHAs for supply-chain safety.
The lint-fix pre-commit step runs `oxlint --fix` + `oxfmt --write` over
staged files. When `package.json` is part of the staged set, oxfmt
rewrites the file into JSON5 syntax (4-space indent, trailing commas
after the last key in every object, compacted single-line objects).
The result is invalid strict JSON that pnpm rejects with
`ERR_PNPM_JSON_PARSE` at line 8 column 5, blocking every commit that
touches any `package.json`.
This was bypassed in PRs #5054 and #5055 via `LEFTHOOK_EXCLUDE=lint-fix`;
this commit fixes it at the source by removing `json,jsonc,json5` from
the lint-fix glob.
Reproduction (with the buggy glob):
- Apply PR #5055's edit to packages/voice/package.json
- git add + run `lefthook run pre-commit --command lint-fix`
- oxfmt logs "1 file reformatted"
- JSON.parse / pnpm install now fail on the rewritten file
After the fix:
- JSON-only staged sets cause lefthook to skip lint-fix ("no files for
inspection") rather than mangle the JSON
- TS/JS/etc. continue to flow through oxlint --fix + oxfmt --write
unchanged
- JSON formatting is left to pnpm and manual editing, both of which
produce strict 2-space JSON
oxfmt 0.36.0 exposes no per-file-type knob (printWidth/proseWrap/
ignorePatterns only); excluding json/jsonc/json5 from the glob is the
minimal correct fix. A future oxfmt upgrade that ships a json formatter
configurable via `.oxfmtrc.json` can re-add these extensions.
This commit itself is being landed with `LEFTHOOK_EXCLUDE=lint-fix`
because the bug being fixed currently blocks any path that exercises the
lint-fix hook. The change touches only `lefthook.yml`, which is not a
JSON file and would not be mangled — the exclude is purely defensive.
The release-PR workflow's pre-commit hook ran the full test suite and
failed because @tanstack/virtual-core 3.13.18 has a latent bug — its
scrollToIndex schedules a nested rAF that calls
`this.targetWindow.requestAnimationFrame(verify)` with no null-check.
The virtualizer's cleanup nulls `targetWindow` on React unmount, so the
queued rAF fires post-unmount and throws. All 1170 tests passed, but
vitest exited non-zero from the unhandled error.
Wrap rAF on both globalThis and window (separate bindings in
vitest+jsdom; tanstack uses `targetWindow.rAF` which resolves to
`window.rAF`) so callbacks hitting this specific error are swallowed.
Also fix the lint-fix lefthook command — `[ -n "{staged_files}" ]`
broke on multi-file expansion ("[: <path>: unexpected operator")
because lefthook interpolates files as space-separated words, not a
quoted string. Use `set --` to put them in positional args.
Pre-commit lint-fix now covers json, md, css, yml, yaml, html, vue, py
in addition to js/ts. Adds ruff format for Python files. Local
formatting coverage now matches CI.
A docs-only commit expanded {staged_files} to a docs/** path; oxlint
silently processed 0 files (both configs ignore docs/**) and then
oxfmt exited 2 with "Expected at least one target file", blocking the
commit. Adding an exclude entry in lefthook.yml lets the existing
empty-{staged_files} guard skip the hook cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The inline check-binaries hook broke on Windows Git Bash because lefthook invoked
it via sh.exe -c with the multi-line YAML script as a single argument, and the
nested quotes inside (`echo "$STAGED" | grep -iE '...'`) got mangled during
Windows command-line argument escaping. Move it to scripts/hooks/check-binaries.sh
so lefthook just invokes bash against a file, avoiding the escaping issue.
Also scope the root test script (and test:coverage) to --projects=packages/**,
mirroring check:packages. The previous unscoped nx run-many -t test triggered
showcase starter generation tests that fail on leftover state from prior runs;
these aren't relevant to the pre-commit gate, which is about verifying shipped
packages.
Replace eslint and prettier with oxlint and oxfmt for faster linting
and formatting across the monorepo. Remove all eslint and prettier
configs, dependencies, and related packages. Add .oxlintrc.json and
.oxfmtrc.json for the new tooling. Update CI workflows and lefthook
hooks accordingly. Reformat codebase with oxfmt.
https://claude.ai/code/session_01GMkSf29p78HuMR1mbXn8He
Mirrors the CI workflow check locally — catches binary extensions,
build directories, dSYM directories, and files over 1 MB at commit
time instead of waiting for CI.
Add glob filter to the sync-lockfile pre-commit command so it only
triggers when a package.json file is staged. Previously it ran on every
commit, causing unnecessary lockfile diffs that conflicted with main.
- Replace husky with lefthook for git hooks management
- Pre-commit runs lint --fix, format, test, and check:packages in parallel
with auto-staging of fixes via stage_fixed
- Commit-msg runs commitlint
- Add dependsOn ^build to test target in nx.json so dependencies are
built before tests run
- Upgrade @analogjs/vite-plugin-angular and @analogjs/vitest-angular
from ^1.20.2 to ^2.2.3 for vite 7 compatibility
- Add pnpm packageExtensions to declare missing vite peer dependency
on @analogjs/vite-plugin-angular
- Fix lint issues: let -> const in agent and react packages
- Disable nx TUI in pre-commit hooks via NX_TUI env var