blume 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +28 -0
  3. package/README.md +2 -2
  4. package/dist/cli/{chunk-f7t03s3g.js → chunk-27g6wdth.js} +2 -2
  5. package/dist/cli/{chunk-mnqj32sj.js → chunk-2hn4b8z7.js} +13 -13
  6. package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
  7. package/dist/cli/{chunk-by2290sx.js → chunk-5shv93fd.js} +2 -2
  8. package/dist/cli/{chunk-a9kptbw5.js → chunk-6crbhc3x.js} +3 -3
  9. package/dist/cli/{chunk-a9kptbw5.js.map → chunk-6crbhc3x.js.map} +1 -1
  10. package/dist/cli/{chunk-mwt1k8n7.js → chunk-6hsn950k.js} +20 -20
  11. package/dist/cli/chunk-6hsn950k.js.map +10 -0
  12. package/dist/cli/{chunk-11j0384y.js → chunk-6vm74dry.js} +13 -13
  13. package/dist/cli/{chunk-11j0384y.js.map → chunk-6vm74dry.js.map} +3 -3
  14. package/dist/cli/{chunk-j8mw0za6.js → chunk-79jhk4py.js} +8 -8
  15. package/dist/cli/{chunk-j8mw0za6.js.map → chunk-79jhk4py.js.map} +2 -2
  16. package/dist/cli/{chunk-nk3ts2xk.js → chunk-82bbrxdn.js} +2 -2
  17. package/dist/cli/{chunk-2q1dwty4.js → chunk-ah61y8py.js} +8 -8
  18. package/dist/cli/{chunk-2q1dwty4.js.map → chunk-ah61y8py.js.map} +4 -4
  19. package/dist/cli/{chunk-zxccj738.js → chunk-ce574jw2.js} +1 -1
  20. package/dist/cli/{chunk-y3e45rc8.js → chunk-ch6g3ar0.js} +3 -3
  21. package/dist/cli/{chunk-beat36xx.js → chunk-dh8cwk36.js} +5 -5
  22. package/dist/cli/{chunk-beat36xx.js.map → chunk-dh8cwk36.js.map} +2 -2
  23. package/dist/cli/{chunk-1w8dp3qb.js → chunk-epjnccmv.js} +13 -13
  24. package/dist/cli/{chunk-ernrthtr.js → chunk-f2z5v128.js} +13 -13
  25. package/dist/cli/{chunk-zg2gtj10.js → chunk-fs23ddbb.js} +2 -2
  26. package/dist/cli/{chunk-7ez8ny0t.js → chunk-fxypxtvm.js} +2 -2
  27. package/dist/cli/{chunk-tzne8qfq.js → chunk-fz5wtpmh.js} +13 -13
  28. package/dist/cli/{chunk-b5aj94ah.js → chunk-hdpx1tax.js} +4 -4
  29. package/dist/cli/{chunk-d80hr03s.js → chunk-jwyddg7y.js} +9 -9
  30. package/dist/cli/{chunk-d80hr03s.js.map → chunk-jwyddg7y.js.map} +2 -2
  31. package/dist/cli/{chunk-fh5hj5jt.js → chunk-kdp5q7ke.js} +15 -15
  32. package/dist/cli/{chunk-6k8vp3ta.js → chunk-kpf8rrjc.js} +9 -9
  33. package/dist/cli/{chunk-6k8vp3ta.js.map → chunk-kpf8rrjc.js.map} +3 -3
  34. package/dist/cli/{chunk-5a2z0198.js → chunk-m3vmjgmq.js} +9 -9
  35. package/dist/cli/{chunk-5a2z0198.js.map → chunk-m3vmjgmq.js.map} +2 -2
  36. package/dist/cli/{chunk-bctazmbk.js → chunk-mb2919y2.js} +4 -4
  37. package/dist/cli/{chunk-79njf86q.js → chunk-q5163e60.js} +13 -13
  38. package/dist/cli/{chunk-xaz13gwg.js → chunk-qkqwkpte.js} +196 -208
  39. package/dist/cli/{chunk-xaz13gwg.js.map → chunk-qkqwkpte.js.map} +48 -48
  40. package/dist/cli/{chunk-sqn5t4q0.js → chunk-qs4q5p4e.js} +3 -3
  41. package/dist/cli/{chunk-bw22s759.js → chunk-qwsrynx5.js} +1 -1
  42. package/dist/cli/{chunk-z01ze5c1.js → chunk-s1p84fyh.js} +15 -15
  43. package/dist/cli/{chunk-pnnvybbk.js → chunk-s6jhgk0q.js} +5 -5
  44. package/dist/cli/{chunk-pnnvybbk.js.map → chunk-s6jhgk0q.js.map} +2 -2
  45. package/dist/cli/{chunk-f2972sbt.js → chunk-vtk4a6dg.js} +1 -1
  46. package/dist/cli/{chunk-z1f5arsg.js → chunk-wgm7m9qk.js} +21 -21
  47. package/dist/cli/{chunk-z1f5arsg.js.map → chunk-wgm7m9qk.js.map} +4 -4
  48. package/dist/cli/{chunk-bnbmcwfb.js → chunk-wm7js3j9.js} +5 -5
  49. package/dist/cli/{chunk-bnbmcwfb.js.map → chunk-wm7js3j9.js.map} +3 -3
  50. package/dist/cli/{chunk-d1tadaw7.js → chunk-yt5n7ppj.js} +3 -3
  51. package/dist/cli/{chunk-pat2zzwc.js → chunk-yw7dm696.js} +1 -1
  52. package/dist/cli/{chunk-pat2zzwc.js.map → chunk-yw7dm696.js.map} +1 -1
  53. package/dist/cli/{chunk-88cpgt6h.js → chunk-zxcczpyx.js} +1 -1
  54. package/dist/cli/{chunk-41za066z.js → chunk-zxh4d9vy.js} +4 -4
  55. package/dist/cli/index.js +17 -17
  56. package/dist/types/ai/agent-readability.d.ts +1 -1
  57. package/dist/types/ai/api/paths.d.ts +1 -1
  58. package/dist/types/ai/ask-context.d.ts +7 -7
  59. package/dist/types/ai/ask.d.ts +43 -43
  60. package/dist/types/ai/index.d.ts +3 -3
  61. package/dist/types/ai/openapi-components.d.ts +1 -1
  62. package/dist/types/ai/serializers.d.ts +1 -1
  63. package/dist/types/ai/visibility.d.ts +1 -1
  64. package/dist/types/core/config-input.d.ts +17 -17
  65. package/dist/types/core/config.d.ts +3 -3
  66. package/dist/types/core/data.d.ts +3 -3
  67. package/dist/types/core/i18n-ui.d.ts +6 -8
  68. package/dist/types/core/schema.d.ts +5 -5
  69. package/dist/types/core/unrecognized-keys.d.ts +1 -1
  70. package/dist/types/search/documents.d.ts +1 -1
  71. package/dist/types/search/orama-index.d.ts +1 -1
  72. package/docs/02-deployment.mdx +4 -4
  73. package/docs/03-upgrading.mdx +22 -9
  74. package/docs/04-migrating.mdx +4 -4
  75. package/docs/08-faq.mdx +3 -3
  76. package/docs/advanced/custom-pages.mdx +2 -2
  77. package/docs/advanced/skills.mdx +1 -1
  78. package/docs/cli/audit.mdx +3 -3
  79. package/docs/cli/doctor.mdx +3 -3
  80. package/docs/cli/evals.mdx +7 -7
  81. package/docs/cli/index.mdx +2 -2
  82. package/docs/cli/translate.mdx +8 -8
  83. package/docs/configuration/{ask-ai.mdx → assistant.mdx} +19 -19
  84. package/docs/configuration/customization.mdx +2 -2
  85. package/docs/configuration/index.mdx +2 -2
  86. package/docs/configuration/meta.ts +1 -1
  87. package/docs/configuration/search.mdx +1 -1
  88. package/docs/content/i18n.mdx +2 -2
  89. package/docs/content/islands.mdx +1 -1
  90. package/docs/discoverability/agent-discovery.mdx +1 -1
  91. package/docs/discoverability/index.mdx +1 -1
  92. package/docs/index.mdx +2 -2
  93. package/package.json +1 -1
  94. package/skills/blume/SKILL.md +5 -5
  95. package/skills/blume-migrate/SKILL.md +2 -2
  96. package/src/ai/agent-readability.ts +4 -4
  97. package/src/ai/api/paths.ts +1 -1
  98. package/src/ai/ask-context.ts +7 -7
  99. package/src/ai/ask-data.ts +2 -2
  100. package/src/ai/ask.ts +84 -71
  101. package/src/ai/cors.ts +3 -3
  102. package/src/ai/index.ts +16 -16
  103. package/src/ai/openapi-components.ts +1 -1
  104. package/src/ai/serializers.ts +1 -1
  105. package/src/ai/visibility.ts +1 -1
  106. package/src/astro/generate.ts +19 -18
  107. package/src/astro/module-types.ts +1 -1
  108. package/src/astro/runtime-deps.ts +6 -6
  109. package/src/astro/templates.ts +26 -26
  110. package/src/blume-modules.d.ts +2 -2
  111. package/src/cli/commands/audit.ts +1 -1
  112. package/src/cli/commands/doctor.ts +7 -5
  113. package/src/cli/commands/eval.ts +3 -3
  114. package/src/cli/commands/migrate.ts +2 -2
  115. package/src/cli/commands/translate.ts +3 -3
  116. package/src/cli/commands/upgrade.ts +2 -2
  117. package/src/cli/required-secrets.ts +3 -3
  118. package/src/components/copy-feedback.ts +1 -1
  119. package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
  120. package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
  121. package/src/components/islands/hooks.ts +14 -12
  122. package/src/components/layout/Header.astro +10 -10
  123. package/src/components/layout/PageLayout.astro +6 -6
  124. package/src/components/layout/Pagination.astro +7 -7
  125. package/src/components/layout/ReferenceLayout.astro +1 -1
  126. package/src/components/layout/RootLayout.astro +6 -6
  127. package/src/components/layout/Search.astro +13 -13
  128. package/src/components/layout/analytics-client.ts +1 -1
  129. package/src/components/layout/drawer-inert.ts +1 -1
  130. package/src/components/openapi/description.ts +2 -2
  131. package/src/core/code-fences.ts +1 -1
  132. package/src/core/config-input.ts +19 -19
  133. package/src/core/config.ts +3 -3
  134. package/src/core/data.ts +3 -3
  135. package/src/core/i18n-ui.ts +35 -9
  136. package/src/core/request-body.ts +1 -1
  137. package/src/core/schema.ts +25 -20
  138. package/src/core/server-features.ts +2 -2
  139. package/src/core/ui-packs/ar.ts +4 -5
  140. package/src/core/ui-packs/bg.ts +4 -5
  141. package/src/core/ui-packs/bn.ts +4 -5
  142. package/src/core/ui-packs/ca.ts +4 -5
  143. package/src/core/ui-packs/cs.ts +4 -5
  144. package/src/core/ui-packs/da.ts +4 -5
  145. package/src/core/ui-packs/de.ts +4 -5
  146. package/src/core/ui-packs/el.ts +4 -5
  147. package/src/core/ui-packs/es.ts +4 -5
  148. package/src/core/ui-packs/fa.ts +4 -5
  149. package/src/core/ui-packs/fi.ts +4 -5
  150. package/src/core/ui-packs/fr.ts +4 -5
  151. package/src/core/ui-packs/he.ts +4 -5
  152. package/src/core/ui-packs/hi.ts +4 -5
  153. package/src/core/ui-packs/hr.ts +4 -5
  154. package/src/core/ui-packs/hu.ts +4 -5
  155. package/src/core/ui-packs/id.ts +4 -5
  156. package/src/core/ui-packs/it.ts +4 -5
  157. package/src/core/ui-packs/ja.ts +4 -5
  158. package/src/core/ui-packs/ko.ts +4 -5
  159. package/src/core/ui-packs/nl.ts +4 -5
  160. package/src/core/ui-packs/no.ts +4 -5
  161. package/src/core/ui-packs/pl.ts +4 -5
  162. package/src/core/ui-packs/pt-br.ts +4 -5
  163. package/src/core/ui-packs/pt.ts +4 -5
  164. package/src/core/ui-packs/ro.ts +4 -5
  165. package/src/core/ui-packs/ru.ts +4 -5
  166. package/src/core/ui-packs/sk.ts +4 -5
  167. package/src/core/ui-packs/sr.ts +4 -5
  168. package/src/core/ui-packs/sv.ts +4 -5
  169. package/src/core/ui-packs/th.ts +4 -5
  170. package/src/core/ui-packs/tr.ts +4 -5
  171. package/src/core/ui-packs/uk.ts +4 -5
  172. package/src/core/ui-packs/vi.ts +4 -5
  173. package/src/core/ui-packs/zh-tw.ts +4 -5
  174. package/src/core/ui-packs/zh.ts +4 -5
  175. package/src/core/unrecognized-keys.ts +1 -1
  176. package/src/registry/eject.ts +19 -18
  177. package/src/search/documents.ts +2 -2
  178. package/src/search/orama-index.ts +1 -1
  179. package/src/translate/report.ts +1 -1
  180. package/src/upgrade/upgrade.ts +1 -1
  181. package/dist/cli/chunk-mnqj32sj.js.map +0 -12
  182. package/dist/cli/chunk-mwt1k8n7.js.map +0 -10
  183. /package/dist/cli/{chunk-f7t03s3g.js.map → chunk-27g6wdth.js.map} +0 -0
  184. /package/dist/cli/{chunk-by2290sx.js.map → chunk-5shv93fd.js.map} +0 -0
  185. /package/dist/cli/{chunk-nk3ts2xk.js.map → chunk-82bbrxdn.js.map} +0 -0
  186. /package/dist/cli/{chunk-zxccj738.js.map → chunk-ce574jw2.js.map} +0 -0
  187. /package/dist/cli/{chunk-y3e45rc8.js.map → chunk-ch6g3ar0.js.map} +0 -0
  188. /package/dist/cli/{chunk-1w8dp3qb.js.map → chunk-epjnccmv.js.map} +0 -0
  189. /package/dist/cli/{chunk-ernrthtr.js.map → chunk-f2z5v128.js.map} +0 -0
  190. /package/dist/cli/{chunk-zg2gtj10.js.map → chunk-fs23ddbb.js.map} +0 -0
  191. /package/dist/cli/{chunk-7ez8ny0t.js.map → chunk-fxypxtvm.js.map} +0 -0
  192. /package/dist/cli/{chunk-tzne8qfq.js.map → chunk-fz5wtpmh.js.map} +0 -0
  193. /package/dist/cli/{chunk-b5aj94ah.js.map → chunk-hdpx1tax.js.map} +0 -0
  194. /package/dist/cli/{chunk-fh5hj5jt.js.map → chunk-kdp5q7ke.js.map} +0 -0
  195. /package/dist/cli/{chunk-bctazmbk.js.map → chunk-mb2919y2.js.map} +0 -0
  196. /package/dist/cli/{chunk-79njf86q.js.map → chunk-q5163e60.js.map} +0 -0
  197. /package/dist/cli/{chunk-sqn5t4q0.js.map → chunk-qs4q5p4e.js.map} +0 -0
  198. /package/dist/cli/{chunk-bw22s759.js.map → chunk-qwsrynx5.js.map} +0 -0
  199. /package/dist/cli/{chunk-z01ze5c1.js.map → chunk-s1p84fyh.js.map} +0 -0
  200. /package/dist/cli/{chunk-f2972sbt.js.map → chunk-vtk4a6dg.js.map} +0 -0
  201. /package/dist/cli/{chunk-d1tadaw7.js.map → chunk-yt5n7ppj.js.map} +0 -0
  202. /package/dist/cli/{chunk-88cpgt6h.js.map → chunk-zxcczpyx.js.map} +0 -0
  203. /package/dist/cli/{chunk-41za066z.js.map → chunk-zxh4d9vy.js.map} +0 -0
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  title: Upgrade to Blume 2
3
- description: Move a Blume 1 site to Blume 2 with one command, then use this guide for each config change — or hand the whole upgrade to Claude Code or Codex.
3
+ description: Move a Blume 1 site to Blume 2 with one command, then use this guide for each config change — or hand the whole upgrade to Codex or Claude Code.
4
4
  sidebar:
5
5
  label: Upgrade to Blume 2
6
6
  order: 2.5
7
7
  ---
8
8
 
9
- Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits, unless one sets the removed `search.boost` frontmatter field (see [Frontmatter](#frontmatter)). Settings that used to be a named string or a keyed block — the search provider, the deployment target, content sources, API references, analytics, and the Ask AI backend — are now **adapters** you import from a `blume/*` subpath and call. The machine-readable settings move from `ai` to a new `agents` key, and `components.ts` overrides are checked before the build. A zero-config site, or one that sets none of these, only needs the version bump.
9
+ Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits, unless one sets the removed `search.boost` frontmatter field (see [Frontmatter](#frontmatter)). Settings that used to be a named string or a keyed block — the search provider, the deployment target, content sources, API references, analytics, and the assistant's model backend — are now **adapters** you import from a `blume/*` subpath and call. Ask AI is renamed the assistant, so `ai.ask` becomes `ai.assistant`. The machine-readable settings move from `ai` to a new `agents` key, and `components.ts` overrides are checked before the build. A zero-config site, or one that sets none of these, only needs the version bump.
10
10
 
11
11
  ## Upgrade with one command
12
12
 
@@ -18,10 +18,10 @@ npx blume@latest upgrade
18
18
 
19
19
  It bumps `blume` in your `package.json` to 2, installs it with the package manager your project uses, then checks your config and `components.ts` against Blume 2. Every change that's still needed is listed with its file, line, and replacement — including `package.json` scripts that still pass the removed `blume build` flags — and the command exits non-zero until none are left. Run from a folder with neither a config nor a `blume` dependency, it stops with an error instead. Run it through `npx blume@latest` rather than `blume`: the command ships in Blume 2, so a project still on 1 doesn't have it yet. On pnpm 12, add `--allow-build=esbuild` after `pnpm dlx`, since pnpm 12 won't run esbuild's install script unapproved.
20
20
 
21
- To hand the changes to a coding agent instead, add `--claude` or `--codex`:
21
+ To hand the changes to a coding agent instead, add `--codex` or `--claude`:
22
22
 
23
23
  ```package-install
24
- npx blume@latest upgrade --claude
24
+ npx blume@latest upgrade --codex
25
25
  ```
26
26
 
27
27
  The agent opens interactively with the findings and this guide, applies each change, and runs `blume doctor` and `blume build` until both pass, so you review every edit through its own permission flow. Pass `--no-install` to bump `package.json` without installing.
@@ -201,9 +201,9 @@ export default defineConfig({
201
201
 
202
202
  `cloudflare: { token }` becomes `cloudflare({ token })`, and each `scripts[]` entry becomes `script({ … })`.
203
203
 
204
- ## Ask AI
204
+ ## Assistant
205
205
 
206
- `ai.ask.provider` takes an adapter from `blume/ai`, which owns the model and the fields that went with it.
206
+ Ask AI is now called the assistant, and its config moves with the name: `ai.ask` becomes `ai.assistant`. Its `provider` takes an adapter from `blume/ai`, which owns the model and the fields that went with it.
207
207
 
208
208
  <CodeGroup>
209
209
 
@@ -226,7 +226,7 @@ import { openrouter } from "blume/ai";
226
226
 
227
227
  export default defineConfig({
228
228
  ai: {
229
- ask: {
229
+ assistant: {
230
230
  enabled: true,
231
231
  provider: openrouter({
232
232
  model: "anthropic/claude-sonnet-4-5",
@@ -239,7 +239,20 @@ export default defineConfig({
239
239
 
240
240
  </CodeGroup>
241
241
 
242
- The adapters are `gateway()`, `openrouter()`, `llmgateway()`, `inkeep()`, and `openaiCompatible({ baseUrl, name, model, apiKeyEnv })`. `model`, `apiKeyEnv`, `baseUrl`, `headers`, and `reasoning` move into the adapter; `enabled`, `instructions`, `retrieval`, `suggestions`, `cors`, and `endpoint` stay on `ai.ask`. Leaving `provider` unset still uses the AI Gateway.
242
+ The adapters are `gateway()`, `openrouter()`, `llmgateway()`, `inkeep()`, and `openaiCompatible({ baseUrl, name, model, apiKeyEnv })`. `model`, `apiKeyEnv`, `baseUrl`, `headers`, and `reasoning` move into the adapter; `enabled`, `instructions`, `retrieval`, `suggestions`, `cors`, and `endpoint` move to `ai.assistant` unchanged. Leaving `provider` unset still uses the AI Gateway.
243
+
244
+ The rename reaches every name that said Ask AI:
245
+
246
+ - `i18n.ui` overrides: the `ask` group becomes `assistant`, and `search.askAi` and `search.askAiHint` become `search.assistant` and `search.assistantHint`.
247
+ - `useAskAI` from `blume/hooks` becomes `useAssistant`, with its `UseAssistant` and `UseAssistantOptions` types.
248
+ - The `askEnabled` prop on `PageLayout`, `RootLayout`, `Header`, and a `Search` override becomes `assistantEnabled`.
249
+ - In the [`blume:data`](/docs/advanced/custom-pages) module, `config.ask` becomes `config.assistant` and `ui.ask` becomes `ui.assistant`, and the `UIStrings` type from `blume` follows.
250
+ - The adapter types from `blume/ai` swap their `Ask` prefix for `Assistant` (`AskAdapter` becomes `AssistantAdapter`, `AskGatewayOptions` becomes `AssistantGatewayOptions`), and `askReasoningLevels` and `AskReasoning` from `blume/schema` become `assistantReasoningLevels` and `AssistantReasoning`.
251
+ - The `blume:open-ask-ai` window event becomes `blume:open-assistant`, and the `data-blume-ask` attribute on `<body>` becomes `data-blume-assistant`.
252
+
253
+ The generated `/api/ask` route and the `ask`, `ask_answer`, and `ask_error` [analytics events](/docs/configuration/assistant#analytics) keep their names, so callers and dashboards need no change. `blume upgrade` and `blume doctor` name each old config key they find, `ai.ask` and the `i18n.ui` keys alike, with its replacement.
254
+
255
+ Upgraded to Blume 2.0.0 already? It still read `ai.ask`, so update `blume` as usual and make the same rename.
243
256
 
244
257
  ## Agents and other config moves
245
258
 
@@ -270,7 +283,7 @@ export default defineConfig({
270
283
 
271
284
  </CodeGroup>
272
285
 
273
- - `ai.api`, `ai.catalog`, `ai.llmsTxt`, `ai.markdownComponents`, `ai.mcp`, `ai.skills`, `ai.webBotAuth`, and `ai.webmcp` become `agents.*`, and so do `seo.agentReadability` and `seo.contentSignals`. `ai` keeps only `ask` and `openInChat`.
286
+ - `ai.api`, `ai.catalog`, `ai.llmsTxt`, `ai.markdownComponents`, `ai.mcp`, `ai.skills`, `ai.webBotAuth`, and `ai.webmcp` become `agents.*`, and so do `seo.agentReadability` and `seo.contentSignals`. `ai` keeps only `assistant` (formerly `ask`) and `openInChat`.
274
287
  - `lastModified` is a flat value: `true` becomes `"git"`, and `{ type: "git" }` or `{ type: "frontmatter" }` becomes the bare string.
275
288
  - `markdown.codeBlocks` merges into `markdown.code`.
276
289
  - `theme.layout` is gone. Nothing read it, so delete it.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Migrate to Blume
3
- description: Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with one command that hands the migration to Claude Code or Codex.
3
+ description: Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with one command that hands the migration to Codex or Claude Code.
4
4
  sidebar:
5
5
  label: Migrate to Blume
6
6
  order: 2.4
@@ -13,10 +13,10 @@ Moving a docs site to idiomatic Blume takes judgment a codemod can't make: which
13
13
  Run it from the root of the docs project you're migrating:
14
14
 
15
15
  ```package-install
16
- npx blume migrate fumadocs --claude
16
+ npx blume migrate fumadocs --codex
17
17
  ```
18
18
 
19
- Swap `fumadocs` for your framework, and `--claude` for `--codex` to use Codex. With pnpm 12, add `--allow-build=esbuild` after `pnpm dlx`, since pnpm 12 won't run esbuild's install script unapproved. The agent opens interactively in your terminal, so every edit goes through its own permission flow. It works in place, so start from a clean working tree and review the whole migration as one diff.
19
+ Swap `fumadocs` for your framework, and `--codex` for `--claude` to use Claude Code. With pnpm 12, add `--allow-build=esbuild` after `pnpm dlx`, since pnpm 12 won't run esbuild's install script unapproved. The agent opens interactively in your terminal, so every edit goes through its own permission flow. It works in place, so start from a clean working tree and review the whole migration as one diff.
20
20
 
21
21
  ## Sources
22
22
 
@@ -47,7 +47,7 @@ It finishes with a summary of what it migrated, dropped, or approximated, such a
47
47
 
48
48
  ## Other agents
49
49
 
50
- Without `--claude` or `--codex`, the command reports the source it detected, prints the path to the playbook — the `blume-migrate` [skill](/docs/advanced/skills) bundled in the package — and exits without changing anything. Point any other agent at that `SKILL.md`, or install the skill where your agent looks for skills, with the command it prints:
50
+ Without `--codex` or `--claude`, the command reports the source it detected, prints the path to the playbook — the `blume-migrate` [skill](/docs/advanced/skills) bundled in the package — and exits without changing anything. Point any other agent at that `SKILL.md`, or install the skill where your agent looks for skills, with the command it prints:
51
51
 
52
52
  ```bash
53
53
  npx skills add haydenbleasel/blume --skill blume-migrate
package/docs/08-faq.mdx CHANGED
@@ -20,13 +20,13 @@ Blume takes a third path: **the framework is the template.** You point it at a f
20
20
  | **Hosting** | Anywhere — static or a server function | Their managed infrastructure | Anywhere; you build and deploy |
21
21
  | **You maintain** | Your Markdown | Your Markdown + platform config | Your Markdown + the app around it |
22
22
  | **Rendering** | Astro; core theme ships zero client JS | Their runtime | React/Next.js runtime |
23
- | **AI features** | `llms.txt`, raw Markdown, Ask AI, MCP — built in, no hosted service | Built in (hosted) | Bring your own |
23
+ | **AI features** | `llms.txt`, raw Markdown, an in-page assistant, MCP — built in, no hosted service | Built in (hosted) | Bring your own |
24
24
 
25
25
  A few consequences worth calling out:
26
26
 
27
27
  - **You own the output.** `blume build` produces a plain site you host on Vercel, Netlify, Cloudflare, S3, or your own box. Nothing phones home.
28
28
  - **No lock-in, two ways out.** Your content is portable Markdown, and `blume eject` turns the project into a standalone Astro app that still uses the `blume` package when you want full control.
29
- - **Fast by default.** The core theme is React-free and renders static HTML, so pages score well on Core Web Vitals without tuning. You opt into server features (Ask AI, MCP) only when you need them.
29
+ - **Fast by default.** The core theme is React-free and renders static HTML, so pages score well on Core Web Vitals without tuning. You opt into server features (the assistant, MCP) only when you need them.
30
30
  - **Type-safe configuration.** `blume.config.ts` and every `meta.ts` are real TypeScript validated by a schema — not loosely-typed YAML.
31
31
 
32
32
  :::note
@@ -49,7 +49,7 @@ Yes. Any page can be `.md` or `.mdx`, and MDX lets you drop in the [built-in com
49
49
 
50
50
  ## Where can I deploy it?
51
51
 
52
- Anywhere. `blume build` outputs static HTML by default, which you can serve from any static host or CDN — Vercel, Netlify, Cloudflare Pages, GitHub Pages, S3, or your own server. Server-only features (Ask AI, the MCP server, on-demand rendering) need server output: name a host adapter from `blume/deploy` — `vercel()`, `netlify()`, `cloudflare()`, or `node()` — as `deployment`. See [Deployment](/docs/deployment).
52
+ Anywhere. `blume build` outputs static HTML by default, which you can serve from any static host or CDN — Vercel, Netlify, Cloudflare Pages, GitHub Pages, S3, or your own server. Server-only features (the assistant, the MCP server, on-demand rendering) need server output: name a host adapter from `blume/deploy` — `vercel()`, `netlify()`, `cloudflare()`, or `node()` — as `deployment`. See [Deployment](/docs/deployment).
53
53
 
54
54
  ## Does search need a hosted service?
55
55
 
@@ -76,7 +76,7 @@ The module exposes:
76
76
  type: "BlumeDataConfig",
77
77
  required: true,
78
78
  description:
79
- "Resolved site settings: title, description, logo, favicon, appleIcon, banner, theme, site, repoUrl, github (owner, repo, host, and the REST api base — null when unset), search, i18n, mcp, ask, og, analytics, feedback, structuredData, toc, codeThemes, codeWrap, and imageZoom.",
79
+ "Resolved site settings: title, description, logo, favicon, appleIcon, banner, theme, site, repoUrl, github (owner, repo, host, and the REST api base — null when unset), search, i18n, mcp, assistant, og, analytics, feedback, structuredData, toc, codeThemes, codeWrap, and imageZoom.",
80
80
  },
81
81
  navigation: {
82
82
  type: "Navigation",
@@ -230,7 +230,7 @@ const { config } = data;
230
230
  </PageLayout>
231
231
  ```
232
232
 
233
- The header a custom page gets is the same one the docs pages get, so the chrome that lives in it comes along: search, the theme toggle, the language switcher, and — when [Ask AI](/docs/configuration/ask-ai) is configured — the Ask AI trigger. None of it needs wiring up per page. Pass `askEnabled={false}` to leave the Ask trigger off one page while keeping it everywhere else.
233
+ The header a custom page gets is the same one the docs pages get, so the chrome that lives in it comes along: search, the theme toggle, the language switcher, and — when the [assistant](/docs/configuration/assistant) is configured — its trigger. None of it needs wiring up per page. Pass `assistantEnabled={false}` to leave the assistant trigger off one page while keeping it everywhere else.
234
234
 
235
235
  The [agent-discovery head links](/docs/discoverability/agent-discovery#discovery-link-header) come along too: the layout reads the resolved config, so a custom page carries the same `describedby`, `ai-catalog`, and `ard` links the docs pages do without passing a prop. The homepage also advertises its `/index.md` Markdown mirror as a `text/markdown` alternate, since that mirror always exists; other custom pages have none, so none is advertised. Pass `discovery={null}` to drop the links from one page.
236
236
 
@@ -15,7 +15,7 @@ npx skills add haydenbleasel/blume
15
15
 
16
16
  ## Migration
17
17
 
18
- `blume-migrate` moves an existing docs site to Blume: Mintlify, Fumadocs, Docusaurus, Starlight, Nextra, or any other framework. It targets idiomatic Blume rather than a line-by-line port, with a mapping reference for each named framework, a redirect for every URL that moves, and a report of anything it drops. The quickest way to run it is [`blume migrate`](/docs/migrating), which detects your framework and opens Claude Code or Codex on the copy bundled in the package. To use it from another agent, install it:
18
+ `blume-migrate` moves an existing docs site to Blume: Mintlify, Fumadocs, Docusaurus, Starlight, Nextra, or any other framework. It targets idiomatic Blume rather than a line-by-line port, with a mapping reference for each named framework, a redirect for every URL that moves, and a report of anything it drops. The quickest way to run it is [`blume migrate`](/docs/migrating), which detects your framework and opens Codex or Claude Code on the copy bundled in the package. To use it from another agent, install it:
19
19
 
20
20
  ```bash
21
21
  npx skills add haydenbleasel/blume --skill blume-migrate
@@ -31,7 +31,7 @@ Findings are grouped by check rather than listed per page, so the report reads a
31
31
  - `--list-checks` — print every check the audit can report, then exit.
32
32
  - `--verbose` — list every affected page with each finding's full detail, instead of the first few.
33
33
  - `--json` — emit the report as JSON on stdout.
34
- - `--claude` / `--codex` — hand the findings to Claude Code or Codex to fix interactively.
34
+ - `--codex` / `--claude` — hand the findings to Codex or Claude Code to fix interactively.
35
35
 
36
36
  ## Failing CI
37
37
 
@@ -55,10 +55,10 @@ Outbound links are graded rather than flatly failed: a 404 is a broken link you
55
55
 
56
56
  ## Fixing the findings with an agent
57
57
 
58
- If you use [Claude Code](https://claude.com/claude-code) or [Codex](https://developers.openai.com/codex/cli), the audit can hand its findings straight to it:
58
+ If you use [Codex](https://developers.openai.com/codex/cli) or [Claude Code](https://claude.com/claude-code), the audit can hand its findings straight to it:
59
59
 
60
60
  ```bash
61
- blume audit --claude # or --codex
61
+ blume audit --codex # or --claude
62
62
  ```
63
63
 
64
64
  This writes the complete JSON report — every affected page, not the terminal's three-page preview — to a file and opens the agent interactively with a prompt that walks it through the findings: edit the source file each finding names, apply its suggested fix, then run `blume build` and `blume audit` again until the report is clean. The session is interactive by design: you review the edits through the agent's own permission flow, and the agent is told never to fix a finding by deleting content.
@@ -14,15 +14,15 @@ blume doctor
14
14
  - **The Node version** against the range the installed `blume` package supports, read from its own `engines` field. A version outside it is a warning: things may work, but it isn't a combination Blume tests.
15
15
  - **`blume.config.ts`**, with the same validation a build runs. A removed or renamed key fails with a hint naming its replacement rather than a bare "unrecognized key".
16
16
  - **Every content page and folder meta**: the diagnostics `blume dev` and `blume build` print as they load the project — invalid frontmatter, navigation problems, missing include targets, and the rest — collected in one report.
17
- - **Features that need a server** on a site configured for static output — Ask AI, the MCP server, or the Try it playground's built-in proxy: an error naming the feature, with the deployment adapter to switch to (or, when a host adapter is set to `output: "static"`, telling you to drop that option).
18
- - **Packages your config needs** that aren't installed — the SDK a search, content source, or Ask AI adapter imports, a deployment adapter's `@astrojs/*` package, or the renderer for Vue or Svelte islands: an error naming each package, with the install command for your package manager. `blume build` stops on the same check.
17
+ - **Features that need a server** on a site configured for static output — the assistant, the MCP server, or the Try it playground's built-in proxy: an error naming the feature, with the deployment adapter to switch to (or, when a host adapter is set to `output: "static"`, telling you to drop that option).
18
+ - **Packages your config needs** that aren't installed — the SDK a search, content source, or assistant adapter imports, a deployment adapter's `@astrojs/*` package, or the renderer for Vue or Svelte islands: an error naming each package, with the install command for your package manager. `blume build` stops on the same check.
19
19
  - **`components.ts` overrides** Blume can't plan — an inline or computed entry, or an import whose file doesn't exist: an error for each, at its line.
20
20
  - **A version-shaped folder** (`v1.0/`) on a site with no `versions` configured, which would otherwise build as ordinary content: a warning pointing at [`blume version`](/docs/cli/version).
21
21
  - **Secrets an enabled feature reads** that aren't set, such as `ALGOLIA_ADMIN_API_KEY` or `OPENROUTER_API_KEY`: a warning naming the variable. Doctor loads `.env` and `.env.local` first, like `blume dev` and `blume build`.
22
22
 
23
23
  ## The summary
24
24
 
25
- After the diagnostics, doctor prints what the project resolved to, so a mismatch between what you think is configured and what Blume sees is visible at a glance: the page count, the output mode and deployment adapter, the search provider, the configured reference, analytics, and content source adapters, and whether Ask AI is on and which backend it uses.
25
+ After the diagnostics, doctor prints what the project resolved to, so a mismatch between what you think is configured and what Blume sees is visible at a glance: the page count, the output mode and deployment adapter, the search provider, the configured reference, analytics, and content source adapters, and whether the assistant is on and which backend it uses.
26
26
 
27
27
  ## Exit code and JSON
28
28
 
@@ -10,22 +10,22 @@ blume eval
10
10
  ```
11
11
 
12
12
  ```
13
- blume eval 4 question(s) · Claude Code
13
+ blume eval 4 question(s) · Codex
14
14
 
15
- ✔ install-node-version pass 1.00 14.2s $0.14
16
- ✔ custom-domain pass 0.92 21.3s $0.19
17
- ✖ deploy-vercel fail 0.40 38.9s $0.31
15
+ ✔ install-node-version pass 1.00 14.2s
16
+ ✔ custom-domain pass 0.92 21.3s
17
+ ✖ deploy-vercel fail 0.40 38.9s
18
18
  missing: deployment: vercel() from blume/deploy
19
19
  ⊘ search-providers skipped
20
20
 
21
21
  fix: content/docs/deployment.mdx Docs could not answer: "How do I deploy to Vercel?" — missing: deployment: vercel() from blume/deploy
22
22
 
23
- 2 passed · 1 failed · 1 skipped · 1m 42s · $0.64
23
+ 2 passed · 1 failed · 1 skipped · 1m 42s
24
24
  ```
25
25
 
26
26
  ## How it works
27
27
 
28
- Each question runs through two agent sessions, using an agent CLI you already have installed — [Claude Code](https://claude.com/claude-code) by default, or [Codex](https://developers.openai.com/codex/cli) with `--agent codex`. Blume holds no API keys and calls no model itself. With `--agent codex`, both sessions also run without Codex's shell, command, and image tools, and inherit none of your environment variables.
28
+ Each question runs through two agent sessions, using an agent CLI you already have installed — [Codex](https://developers.openai.com/codex/cli) by default, or [Claude Code](https://claude.com/claude-code) with `--agent claude`. Blume holds no API keys and calls no model itself. With Codex, both sessions also run without Codex's shell, command, and image tools, and inherit none of your environment variables.
29
29
 
30
30
  1. **The reader** answers the question using _only_ your documentation. It runs in an empty directory with its file, shell, and web tools disabled, connected to a private [MCP server](/docs/discoverability/mcp) that serves your docs — the same `search_docs`/`get_page` tools a real agent uses against your deployed site. It cannot read your repo, so it experiences the docs exactly like a fresh user: what isn't written doesn't exist.
31
31
  2. **The judge** grades the answer against the facts you listed, with no tools at all. Paraphrase passes; a missing or contradicted fact fails — and so does "the documentation doesn't say."
@@ -98,7 +98,7 @@ This writes the full JSON report to a file and opens the agent interactively wit
98
98
 
99
99
  ## Flags
100
100
 
101
- - `--agent claude|codex` — which agent CLI runs the reader and judge. Defaults to `claude`.
101
+ - `--agent codex|claude` — which agent CLI runs the reader and judge. Defaults to `codex`.
102
102
  - `--file <path>` — the evals file. Defaults to `evals.yaml`.
103
103
  - `--threshold <0..1>` — minimum passing fraction before the run exits non-zero. Defaults to `1`.
104
104
  - `--timeout <seconds>` — reader time limit per question. Defaults to `180`.
@@ -25,8 +25,8 @@ blume <command> [options]
25
25
  | [`blume eval`](/docs/cli/evals) | Test the docs: an agent answers your questions using only the documentation. |
26
26
  | [`blume translate`](/docs/cli/translate) | Translate docs into the configured locales with a local agent CLI. |
27
27
  | [`blume version [id]`](/docs/cli/version) | Freeze the current docs as an archived version (no id lists configured versions). |
28
- | [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with Claude Code or Codex. |
29
- | [`blume upgrade`](/docs/upgrading) | Move to a new major: bump `blume`, then list the config changes left or hand them to Claude Code or Codex. |
28
+ | [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with Codex or Claude Code. |
29
+ | [`blume upgrade`](/docs/upgrading) | Move to a new major: bump `blume`, then list the config changes left or hand them to Codex or Claude Code. |
30
30
 
31
31
  ## Common flags
32
32
 
@@ -6,22 +6,22 @@ description: blume translate fills in your locales with an AI agent — it finds
6
6
  Once [i18n](/docs/content/i18n) is on, every edit to a source page quietly outdates its translations. `blume translate` closes that loop: it computes exactly which pages are missing or stale in each locale, translates them headlessly with a local agent CLI, and records what it did in a committed ledger so the next run — and CI — knows what's current.
7
7
 
8
8
  ```bash
9
- blume translate --claude
9
+ blume translate --codex
10
10
  ```
11
11
 
12
12
  ```
13
- blume translate 3 item(s) · 2 locale(s) · Claude Code
13
+ blume translate 3 item(s) · 2 locale(s) · Codex
14
14
 
15
- ✔ docs/guides/install.mdx → fr 24.2s $0.11
16
- ✔ docs/guides/install.mdx → de 22.8s $0.10
17
- ✔ meta titles (2) → de 4.1s $0.01
15
+ ✔ docs/guides/install.mdx → fr 24.2s
16
+ ✔ docs/guides/install.mdx → de 22.8s
17
+ ✔ meta titles (2) → de 4.1s
18
18
 
19
- Translated 3 files into 2 locales · 1 adopted · 14 already up to date · 51.1s · $0.22
19
+ Translated 3 files into 2 locales · 1 adopted · 14 already up to date · 51.1s
20
20
  ```
21
21
 
22
22
  ## How it works
23
23
 
24
- Blume owns the pipeline; the agent only translates text. For each file that needs work, Blume builds a translation prompt, runs the agent CLI headlessly with its file, shell, and web tools disabled, validates the reply's structure, and writes the target file itself — [Claude Code](https://claude.com/claude-code) with `--claude`, or [Codex](https://developers.openai.com/codex/cli) with `--codex`. Blume holds no API keys and calls no model itself.
24
+ Blume owns the pipeline; the agent only translates text. For each file that needs work, Blume builds a translation prompt, runs the agent CLI headlessly with its file, shell, and web tools disabled, validates the reply's structure, and writes the target file itself — [Codex](https://developers.openai.com/codex/cli) with `--codex`, or [Claude Code](https://claude.com/claude-code) with `--claude`. Blume holds no API keys and calls no model itself.
25
25
 
26
26
  Every validated write is recorded in `blume.translations.json` at the project root: for each source file and locale, a hash of the source at the moment it was translated. **Commit this file.** It's how a rerun knows the difference between "already translated" and "translated, but the source changed since" — and it's what makes the CI gate possible.
27
27
 
@@ -72,7 +72,7 @@ The JSON report carries the same `diagnostics` + `summary` shape as `blume valid
72
72
 
73
73
  ## Flags
74
74
 
75
- - `--claude` / `--codex` — which agent CLI translates. Exactly one is required (except with `--check`).
75
+ - `--codex` / `--claude` — which agent CLI translates. Exactly one is required (except with `--check`).
76
76
  - `--check` — report drift and exit non-zero, without writing anything.
77
77
  - `--concurrency <n>` — parallel agent sessions. Defaults to `4`, max `16`.
78
78
  - `--locale <codes>` — comma-separated target locales (defaults to every non-default locale).
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: Ask AI
2
+ title: Assistant
3
3
  description: An in-page assistant grounded in your docs — suggested questions, custom instructions, retrieval sizing, provider adapters from the Vercel AI Gateway to any OpenAI-compatible endpoint, and the server output it needs.
4
4
  ---
5
5
 
@@ -7,7 +7,7 @@ Add an assistant that answers reader questions in an in-page chat panel, backed
7
7
 
8
8
  ```ts blume.config.ts lineNumbers
9
9
  ai: {
10
- ask: {
10
+ assistant: {
11
11
  enabled: true,
12
12
  },
13
13
  }
@@ -21,7 +21,7 @@ Seed the empty state with a few starter prompts. Each renders as a clickable sug
21
21
 
22
22
  ```ts blume.config.ts lineNumbers
23
23
  ai: {
24
- ask: {
24
+ assistant: {
25
25
  enabled: true,
26
26
  suggestions: [
27
27
  { label: "What is Blume?", icon: "rocket" },
@@ -40,7 +40,7 @@ Add your own system-prompt text with `instructions` — identity, language, tone
40
40
 
41
41
  ```ts blume.config.ts lineNumbers
42
42
  ai: {
43
- ask: {
43
+ assistant: {
44
44
  enabled: true,
45
45
  instructions:
46
46
  "You are Bloomy, the Acme docs assistant. Answer in the language the question was asked in, and keep answers under three paragraphs.",
@@ -52,7 +52,7 @@ Your text is **appended to** the built-in instructions rather than replacing the
52
52
 
53
53
  ## Grounding
54
54
 
55
- Ask AI is **grounded in your docs**. For each question it retrieves the most relevant pages — using the same lexical [Orama](/docs/configuration/search) index that powers on-page search — and injects them into the model's system prompt, so answers come from your content instead of the model's own knowledge. The assistant is told to answer only from the retrieved pages, to say when something isn't covered, and to cite the pages it drew from.
55
+ The assistant is **grounded in your docs**. For each question it retrieves the most relevant pages — using the same lexical [Orama](/docs/configuration/search) index that powers on-page search — and injects them into the model's system prompt, so answers come from your content instead of the model's own knowledge. The assistant is told to answer only from the retrieved pages, to say when something isn't covered, and to cite the pages it drew from.
56
56
 
57
57
  The page the reader is currently on is added to the context first and used to scope retrieval to that page's language, so answers stay relevant to where they are in the docs. Retrieval runs at request time from a snapshot baked into the build, so it works regardless of your [search](/docs/configuration/search) provider — even with `search: false` — and needs no configuration.
58
58
 
@@ -64,7 +64,7 @@ How much documentation a question carries is the biggest lever on how long the r
64
64
 
65
65
  ```ts blume.config.ts lineNumbers
66
66
  ai: {
67
- ask: {
67
+ assistant: {
68
68
  enabled: true,
69
69
  retrieval: {
70
70
  maxResults: 3, // fewer pages retrieved per question
@@ -91,7 +91,7 @@ Already have an API backend for AI? Point the panel at it and keep the docs buil
91
91
 
92
92
  ```ts blume.config.ts lineNumbers
93
93
  ai: {
94
- ask: {
94
+ assistant: {
95
95
  enabled: true,
96
96
  endpoint: "https://api.example.com/v1/docs/ask",
97
97
  },
@@ -115,7 +115,7 @@ The generated endpoint answers the in-page assistant on its own origin. To call
115
115
 
116
116
  ```ts blume.config.ts lineNumbers
117
117
  ai: {
118
- ask: {
118
+ assistant: {
119
119
  enabled: true,
120
120
  cors: ["https://www.example.com"],
121
121
  },
@@ -142,7 +142,7 @@ The content type matters: Astro's cross-site request check rejects a cross-origi
142
142
 
143
143
  ## Server output required
144
144
 
145
- Blume's built-in Ask AI backend is a server route (`POST /api/ask`), so it can't run on a static build. Name a host adapter from `blume/deploy` to switch to server output:
145
+ Blume's built-in assistant backend is a server route (`POST /api/ask`), so it can't run on a static build. Name a host adapter from `blume/deploy` to switch to server output:
146
146
 
147
147
  ```ts blume.config.ts lineNumbers
148
148
  import { vercel } from "blume/deploy";
@@ -152,7 +152,7 @@ export default defineConfig({
152
152
  });
153
153
  ```
154
154
 
155
- A static build with Ask AI enabled and no external `endpoint` fails fast with a message telling you to set a host adapter. See [Deployment](/docs/deployment) for the adapters.
155
+ A static build with the assistant enabled and no external `endpoint` fails fast with a message telling you to set a host adapter. See [Deployment](/docs/deployment) for the adapters.
156
156
 
157
157
  ## Adapters
158
158
 
@@ -164,7 +164,7 @@ import { openrouter } from "blume/ai";
164
164
 
165
165
  export default defineConfig({
166
166
  ai: {
167
- ask: {
167
+ assistant: {
168
168
  enabled: true,
169
169
  provider: openrouter({ model: "anthropic/claude-sonnet-4-5" }),
170
170
  },
@@ -194,7 +194,7 @@ import { gateway } from "blume/ai";
194
194
 
195
195
  export default defineConfig({
196
196
  ai: {
197
- ask: {
197
+ assistant: {
198
198
  enabled: true,
199
199
  provider: gateway({ model: "anthropic/claude-sonnet-4-5" }),
200
200
  },
@@ -214,7 +214,7 @@ import { openrouter } from "blume/ai";
214
214
 
215
215
  export default defineConfig({
216
216
  ai: {
217
- ask: {
217
+ assistant: {
218
218
  enabled: true,
219
219
  provider: openrouter({
220
220
  model: "anthropic/claude-sonnet-4-5",
@@ -235,7 +235,7 @@ import { llmgateway } from "blume/ai";
235
235
 
236
236
  export default defineConfig({
237
237
  ai: {
238
- ask: {
238
+ assistant: {
239
239
  enabled: true,
240
240
  provider: llmgateway({ model: "openai/gpt-5.5" }),
241
241
  },
@@ -255,7 +255,7 @@ import { inkeep } from "blume/ai";
255
255
 
256
256
  export default defineConfig({
257
257
  ai: {
258
- ask: {
258
+ assistant: {
259
259
  enabled: true,
260
260
  provider: inkeep({ model: "inkeep-qa-expert" }),
261
261
  },
@@ -275,7 +275,7 @@ import { openaiCompatible } from "blume/ai";
275
275
 
276
276
  export default defineConfig({
277
277
  ai: {
278
- ask: {
278
+ assistant: {
279
279
  enabled: true,
280
280
  provider: openaiCompatible({
281
281
  baseUrl: "https://my-gateway.example.com/v1",
@@ -314,7 +314,7 @@ provider: gateway({
314
314
  }),
315
315
  ```
316
316
 
317
- Blume maps only the options it names (`model`, `reasoning`, `apiKeyEnv`, `headers`) and forwards `providerOptions` verbatim, so it has to be JSON — it's inlined into the route — and it has to use the key the underlying provider expects (`openai` for an OpenAI model behind the gateway, `openrouter` on OpenRouter). Enabling Ask AI also turns on React for the in-page island — see [Customization](/docs/configuration/customization#interactive-islands).
317
+ Blume maps only the options it names (`model`, `reasoning`, `apiKeyEnv`, `headers`) and forwards `providerOptions` verbatim, so it has to be JSON — it's inlined into the route — and it has to use the key the underlying provider expects (`openai` for an OpenAI model behind the gateway, `openrouter` on OpenRouter). Enabling the assistant also turns on React for the in-page island — see [Customization](/docs/configuration/customization#interactive-islands).
318
318
 
319
319
  ## Reasoning
320
320
 
@@ -324,7 +324,7 @@ Reasoning models think before they answer, and how much they do so by default va
324
324
  provider: gateway({ model: "openai/gpt-5.5", reasoning: "none" }),
325
325
  ```
326
326
 
327
- Each adapter sends the level as its backend's own reasoning control, which is why it lives on the adapter rather than on `ask`:
327
+ Each adapter sends the level as its backend's own reasoning control, which is why it lives on the adapter rather than on `assistant`:
328
328
 
329
329
  | Adapter | What the level becomes |
330
330
  | --- | --- |
@@ -348,7 +348,7 @@ With an [analytics provider](/docs/configuration/analytics) configured, the assi
348
348
 
349
349
  `path` is the page the reader asked from (the served pathname, so it matches the feedback widget and your pageviews under a `base`), `questionChars` the question's length, `ms` the time from sending the question to the last chunk, and `chars` the answer's length. `status` is the HTTP status: `0` when no response arrived at all (offline, DNS, CORS), and `200` when the response was fine but its stream broke mid-answer — how a provider or credential error surfaces, since the backend has already sent its headers — or delivered nothing. Clearing the conversation mid-answer reports neither outcome.
350
350
 
351
- The question's text never reaches a provider: it is free-form reader input (pasted keys, error logs, names) that would breach most providers' terms and per-value size limits. It travels only on the `blume:track` DOM event, as `question` in `detail.props`, so a listener you write can forward it wherever you decide it belongs. A custom chat UI built on `useAskAI` from `blume/hooks` reports the same events. With no provider configured the built-in provider calls are no-ops, but the `blume:track` event still fires, so a custom integration listening for it receives them.
351
+ The question's text never reaches a provider: it is free-form reader input (pasted keys, error logs, names) that would breach most providers' terms and per-value size limits. It travels only on the `blume:track` DOM event, as `question` in `detail.props`, so a listener you write can forward it wherever you decide it belongs. A custom chat UI built on `useAssistant` from `blume/hooks` reports the same events. With no provider configured the built-in provider calls are no-ops, but the `blume:track` event still fires, so a custom integration listening for it receives them.
352
352
 
353
353
  ## Rate limiting
354
354
 
@@ -91,7 +91,7 @@ Wired slots:
91
91
  | `Layout` | The entire page shell (`RootLayout`) | Everything the built-in layout receives, plus the `layout` map |
92
92
  | `Header` | The top navigation bar | `site`, `logo`, `navigation`, `route`, `searchEnabled`, … |
93
93
  | `Logo` | The brand link (mark + title) in the header | `site`, `logo`, `locale` |
94
- | `Search` | The header search trigger + modal | `navigation`, `strings`, `locale`, `askEnabled` |
94
+ | `Search` | The header search trigger + modal | `navigation`, `strings`, `locale`, `assistantEnabled` |
95
95
  | `Sidebar` | The primary navigation tree | `items`, `currentRoute` |
96
96
  | `MobileNav` | The nav inside the mobile drawer (defaults to `Sidebar`) | `items`, `currentRoute` |
97
97
  | `Breadcrumbs` | The breadcrumb trail | `crumbs` |
@@ -184,7 +184,7 @@ npx blume eject --yes
184
184
 
185
185
  Eject is a one-way step: the hidden `.blume/` runtime becomes a normal Astro app you own and can modify directly. The `blume` package stays importable, so you keep its components, theme, and Markdown processors.
186
186
 
187
- Eject points your `package.json` scripts at `astro dev` and `astro build`, and adds the packages the Astro app imports by name — `astro`, `@tailwindcss/vite`, the search client, integrations, and adapter the config wires in, React when an island, example, or Ask AI uses it, `ai` for the Ask AI route, and `epub-gen-memory` for EPUB export — at the ranges Blume itself uses. Run an install before `dev` or `build`; eject lists what it added. Every path in the ejected app is relative, so it builds from any checkout, CI included.
187
+ Eject points your `package.json` scripts at `astro dev` and `astro build`, and adds the packages the Astro app imports by name — `astro`, `@tailwindcss/vite`, the search client, integrations, and adapter the config wires in, React when an island, example, or the assistant uses it, `ai` for the assistant route, and `epub-gen-memory` for EPUB export — at the ranges Blume itself uses. Run an install before `dev` or `build`; eject lists what it added. Every path in the ejected app is relative, so it builds from any checkout, CI included.
188
188
 
189
189
  From then on, run the app through its own scripts (`npm run dev`, `npm run build`): `blume dev` and `blume build` stop in an ejected project and point you there. Running `blume eject` again refuses too, since it would overwrite your edits; pass `--force` to regenerate the app anyway.
190
190
 
@@ -366,7 +366,7 @@ dateFormat: { year: "numeric", month: "2-digit", day: "2-digit" },
366
366
 
367
367
  ## SEO and agents
368
368
 
369
- Metadata, Open Graph images, RSS feeds, JSON-LD, the sitemap, and `robots.txt` live under `seo`; `llms.txt`, raw Markdown, the JSON API, the MCP server, and the discovery manifests live under `agents`. Both are covered page by page in the [Discoverability](/docs/discoverability) section, which treats search engines and AI agents as two audiences for the same machine-readable layer. The reader-facing model features — the Ask AI assistant and the Open in chat action — live under `ai`.
369
+ Metadata, Open Graph images, RSS feeds, JSON-LD, the sitemap, and `robots.txt` live under `seo`; `llms.txt`, raw Markdown, the JSON API, the MCP server, and the discovery manifests live under `agents`. Both are covered page by page in the [Discoverability](/docs/discoverability) section, which treats search engines and AI agents as two audiences for the same machine-readable layer. The reader-facing model features — the assistant and the Open in chat action — live under `ai`.
370
370
 
371
371
  ```ts blume.config.ts lineNumbers
372
372
  seo: {
@@ -431,7 +431,7 @@ Each of these has its own guide. The config field is the entry point:
431
431
  | `search` | Provider (Orama, Pagefind, Algolia, and more) and indexing | [Search](/docs/configuration/search) |
432
432
  | `markdown` | Markdown rendering options — code blocks, heading anchors, image zoom | [Syntax](/docs/content/syntax) |
433
433
  | `agents` | `llms.txt`, Markdown mirrors, the JSON API, the hosted MCP server, skills, and discovery manifests for coding agents | [SEO and AEO](/docs/discoverability) |
434
- | `ai` | The in-page Ask AI assistant and the Open in chat action | [Ask AI](/docs/configuration/ask-ai) |
434
+ | `ai` | The in-page assistant and the Open in chat action | [Assistant](/docs/configuration/assistant) |
435
435
  | `reference` | API references: `openapi()`, `asyncapi()`, `graphql()`, and `scalar()` adapters from `blume/reference` | [OpenAPI](/docs/references/openapi), [AsyncAPI](/docs/references/asyncapi), [GraphQL](/docs/references/graphql), [Scalar](/docs/references/scalar) |
436
436
  | `analytics` | Adapters from `blume/analytics` — PostHog, Google Analytics, Plausible, Mixpanel, Segment, and more — plus custom scripts | [Analytics](/docs/configuration/analytics) |
437
437
  | `seo` | Metadata, OG images, feeds, structured data, sitemap, robots | [SEO and AEO](/docs/discoverability) |
@@ -6,7 +6,7 @@ export default defineMeta({
6
6
  "theming",
7
7
  "customization",
8
8
  "search",
9
- "ask-ai",
9
+ "assistant",
10
10
  "analytics",
11
11
  "export",
12
12
  ],
@@ -115,7 +115,7 @@ i18n: {
115
115
  }
116
116
  ```
117
117
 
118
- The same tokenizer serves the search dialog, the MCP server's `search_docs` tool, and Ask AI grounding. The script is what decides, not the language name — `az-Cyrl` is segmented while `sr-Latn` is not — and it is the default locale that decides for the whole index: on a mixed-language site every page shares the default locale's tokenizer. With a non-Latin default that's safe, because Latin words survive segmentation intact, so pages in English stay searchable alongside the default language. The reverse doesn't hold: non-Latin translations on a Latin-default site aren't searchable. Latin-script languages that lean heavily on diacritics (Vietnamese, or Serbian in Latin script) also fare worse on the standard tokenizer, which folds only a few accented vowels and splits words on the rest.
118
+ The same tokenizer serves the search dialog, the MCP server's `search_docs` tool, and assistant grounding. The script is what decides, not the language name — `az-Cyrl` is segmented while `sr-Latn` is not — and it is the default locale that decides for the whole index: on a mixed-language site every page shares the default locale's tokenizer. With a non-Latin default that's safe, because Latin words survive segmentation intact, so pages in English stay searchable alongside the default language. The reverse doesn't hold: non-Latin translations on a Latin-default site aren't searchable. Latin-script languages that lean heavily on diacritics (Vietnamese, or Serbian in Latin script) also fare worse on the standard tokenizer, which folds only a few accented vowels and splits words on the rest.
119
119
 
120
120
  Japanese and Chinese go one step further. Segmenting alone indexes a compound term as its parts — 資金決済法 as 資金, 決済 and 法 — which lets a page mentioning each part somewhere outrank the page the term is actually about. Han, Hiragana and Katakana are therefore indexed as overlapping character pairs, and queries on those indexes prefer pages carrying a term's pairs together, loosening to any-pair matching when no page carries them all, so typing a whole sentence still returns its closest pages. Korean and Thai keep their segmented words.
121
121
 
@@ -112,10 +112,10 @@ Anchors travel with the link, so heading ids have to agree across languages. [`b
112
112
 
113
113
  ## Translating with an agent
114
114
 
115
- You don't have to fill in the locales by hand. [`blume translate`](/docs/cli/translate) finds every page that's missing or outdated in each locale and translates it with a local agent CLI ([Claude Code](https://claude.com/claude-code) or [Codex](https://developers.openai.com/codex/cli)):
115
+ You don't have to fill in the locales by hand. [`blume translate`](/docs/cli/translate) finds every page that's missing or outdated in each locale and translates it with a local agent CLI ([Codex](https://developers.openai.com/codex/cli) or [Claude Code](https://claude.com/claude-code)):
116
116
 
117
117
  ```bash
118
- blume translate --claude
118
+ blume translate --codex
119
119
  ```
120
120
 
121
121
  Blume validates each result's structure — frontmatter, code fences, links — and writes the files itself; the agent only translates text. A committed ledger (`blume.translations.json`) tracks which source revision each translation came from, so reruns only touch what changed, and translations you wrote by hand are adopted as-is, never overwritten. In CI, `blume translate --check` fails when a source page has drifted ahead of its translations.
@@ -143,7 +143,7 @@ export default function PageInfo() {
143
143
  | `useBlume()` | `{ config, navigation }` for the site, or `null` before mount |
144
144
  | `usePage()` | `{ route, title }` for the current page, or `null` before mount |
145
145
  | `useSearch()` | `{ search, results, loading }` — query the configured search provider |
146
- | `useAskAI()` | `{ ask, messages, loading, reset }` — stream from the Ask AI endpoint |
146
+ | `useAssistant()` | `{ ask, messages, loading, reset }` — stream from the assistant endpoint |
147
147
 
148
148
  `useBlume()` and `usePage()` return `null` until the island mounts (so server and client render the same first frame) — guard for it. The snapshot is emitted only on pages that ship React, so a fully static site pays nothing.
149
149
 
@@ -15,7 +15,7 @@ agents: {
15
15
  }
16
16
  ```
17
17
 
18
- The manifest lists only what you've enabled — the [raw Markdown](/docs/discoverability/markdown) mirror pattern, the [JSON API](/docs/discoverability/json-api) and its OpenAPI description, [`llms.txt`](/docs/discoverability/llms-txt) and `llms-full.txt`, the [MCP server](/docs/discoverability/mcp) and its discovery document, the [Ask AI](/docs/configuration/ask-ai) endpoint, the [sitemap](/docs/discoverability/sitemap-and-robots#sitemap), and [RSS feeds](/docs/discoverability/rss) — alongside your site name, description, source repository, and the [content-signal](/docs/discoverability/sitemap-and-robots#content-signals) usage policy. URLs are absolute when [`deployment.site`](/docs/deployment) is set and root-relative otherwise:
18
+ The manifest lists only what you've enabled — the [raw Markdown](/docs/discoverability/markdown) mirror pattern, the [JSON API](/docs/discoverability/json-api) and its OpenAPI description, [`llms.txt`](/docs/discoverability/llms-txt) and `llms-full.txt`, the [MCP server](/docs/discoverability/mcp) and its discovery document, the [assistant](/docs/configuration/assistant) endpoint, the [sitemap](/docs/discoverability/sitemap-and-robots#sitemap), and [RSS feeds](/docs/discoverability/rss) — alongside your site name, description, source repository, and the [content-signal](/docs/discoverability/sitemap-and-robots#content-signals) usage policy. URLs are absolute when [`deployment.site`](/docs/deployment) is set and root-relative otherwise:
19
19
 
20
20
  ```json agent-readability.json
21
21
  {
@@ -41,7 +41,7 @@ Most of this is sharper with an absolute site URL — set [`deployment.site`](/d
41
41
 
42
42
  Every generated file yields to one you ship yourself: drop a `robots.txt`, `sitemap.xml`, `llms.txt`, `openapi.json`, or `agent-readability.json` in `public/` and Blume serves yours in its place.
43
43
 
44
- The in-page **Ask AI** assistant is the one AI feature documented elsewhere: it's a reader-facing product feature rather than a discovery surface, so it's configured under `ai` and lives under [Configuration](/docs/configuration/ask-ai).
44
+ The in-page **assistant** is the one AI feature documented elsewhere: it's a reader-facing product feature rather than a discovery surface, so it's configured under `ai` and lives under [Configuration](/docs/configuration/assistant).
45
45
 
46
46
  ## Checking your work
47
47
 
package/docs/index.mdx CHANGED
@@ -31,7 +31,7 @@ Blume builds on Astro and Vite and renders static HTML by default — fast, cach
31
31
 
32
32
  ### AI-ready out of the box
33
33
 
34
- Every Blume site speaks fluent machine. It emits [`llms.txt` and `llms-full.txt`](/docs/discoverability/llms-txt), serves any page's raw Markdown by appending `.md` to its URL, exposes a [JSON API described by OpenAPI](/docs/discoverability/json-api), and gives readers **Copy as Markdown** and **Open in chat** actions on every page. Add an optional in-page **Ask AI** assistant, or host an [**MCP server**](/docs/discoverability/mcp) so coding agents like Claude Code and Cursor can search and read your docs directly — no scraping, no hosted service. Your Markdown is the source of truth for both humans and models.
34
+ Every Blume site speaks fluent machine. It emits [`llms.txt` and `llms-full.txt`](/docs/discoverability/llms-txt), serves any page's raw Markdown by appending `.md` to its URL, exposes a [JSON API described by OpenAPI](/docs/discoverability/json-api), and gives readers **Copy as Markdown** and **Open in chat** actions on every page. Add an optional in-page **assistant**, or host an [**MCP server**](/docs/discoverability/mcp) so coding agents like Claude Code and Cursor can search and read your docs directly — no scraping, no hosted service. Your Markdown is the source of truth for both humans and models.
35
35
 
36
36
  ### Zero configuration — even the template
37
37
 
@@ -45,7 +45,7 @@ Your [`blume.config.ts`](/docs/configuration) and every [`meta.ts`](/docs/conten
45
45
 
46
46
  - **Components** — callouts, cards, steps, tabs, accordions, badges, file trees, and parameter tables, usable in MDX with [no imports](/docs/content/components).
47
47
  - **Local search** — Orama works in dev and production; for large sites, Pagefind is one adapter away (`search: pagefind()`). No hosted index.
48
- - **AI** — [`llms.txt`, raw Markdown URLs, a JSON API with an OpenAPI description, Copy as Markdown, Open in chat, and a hosted MCP server](/docs/discoverability), plus an optional [Ask AI assistant](/docs/configuration/ask-ai).
48
+ - **AI** — [`llms.txt`, raw Markdown URLs, a JSON API with an OpenAPI description, Copy as Markdown, Open in chat, and a hosted MCP server](/docs/discoverability), plus an optional [in-page assistant](/docs/configuration/assistant).
49
49
  - **Navigation** — inferred from files, refined with `meta.ts` or config.
50
50
  - **SEO** — metadata, Open Graph images, RSS feeds, and JSON-LD, [built in](/docs/discoverability).
51
51
  - **Customization** — component overrides, React islands, custom pages, theme tokens, and a source-component registry via `blume add`.