@dotdrelle/wiki-manager 0.6.17

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.
package/README.md ADDED
@@ -0,0 +1,693 @@
1
+ # llm-wiki-manager
2
+
3
+ [![License: PolyForm Noncommercial 1.0.0](https://img.shields.io/badge/license-PolyForm%20Noncommercial%201.0.0-blue)](LICENSE)
4
+
5
+ `llm-wiki-manager` is the local cockpit for several `llm-wiki` workspaces. It
6
+ creates workspace folders, assigns ports, starts Docker services, exposes MCP
7
+ endpoints, and provides the `donna` shell: an agent-first terminal UI that can
8
+ inspect workspaces, run safe manager commands, call MCP tools, guide production
9
+ jobs, and run one-shot headless tasks.
10
+
11
+ The manager does not implement the wiki engine or the external agents. It
12
+ **orchestrates** them.
13
+
14
+ ---
15
+
16
+ ## What it's for, in one sentence
17
+
18
+ wikiLLM turns a pile of scattered documents (Confluence pages, files, notes…)
19
+ into a **clean, up-to-date wiki**, and can then **regenerate deliverables** from
20
+ it (reports, pages, exports). The **manager** is the control deck: it keeps each
21
+ project in its own corner, starts the right services, and lets you drive
22
+ everything — either with the mouse in a browser, or by talking to an assistant.
23
+
24
+ A **workspace** = a project. Each project is isolated: its documents, settings,
25
+ and results never get mixed up with the others.
26
+
27
+ ## The 4 ways to use it
28
+
29
+ The same system has four faces depending on what you want to do.
30
+
31
+ ### 1. The web interface — to explore with the mouse
32
+
33
+ You open a site in your browser and work visually. This is the most accessible
34
+ mode, with nothing technical to type. It brings together four facets:
35
+
36
+ - **Browse the wiki** — read, search, navigate pages. A **graph** visualizes the
37
+ **interdependencies** between pages: at a glance you see which documents rely on
38
+ which others, and the impact of a change.
39
+ - **The interface** — buttons, menus, everything is clickable.
40
+ - **Chat with an assistant** — an integrated chat that answers about the content,
41
+ but above all an **agent** able to **act**. When a request involves several
42
+ tools (MCP) that depend on each other, it **organizes them into a workflow**:
43
+ it chains the tasks in the right order, waits for one step to finish before
44
+ launching the next, and coordinates everything for you.
45
+ - **Plug in tools** — the interface can call external services (Confluence
46
+ export, sending e-mail…) without you having to deal with them.
47
+
48
+ ### 2. Scripting mode — to let it run on its own
49
+
50
+ The same tool can run **with nobody in front of the screen**: you write the task
51
+ as a **script** (one command, or a sequence of commands), launched on demand or
52
+ **scheduled** (for example "update the wiki every morning"). Ideal for repetitive,
53
+ automated tasks.
54
+
55
+ ### 3. The driver assistant (shell) — to talk in plain language
56
+
57
+ It's a **shell that works like Claude**: you write your request in plain language,
58
+ and the `donna` assistant chains the steps for you. It's the **agentic
59
+ orchestrator**: it understands the request, picks the right tools, and acts. Under
60
+ the hood it relies on its **internal agentic building blocks** (what it can drive
61
+ itself).
62
+
63
+ ### 4. The shared external agents — the common toolbox
64
+
65
+ Some services live apart and serve **all projects** at once: Confluence export,
66
+ sending e-mails, heavy production jobs. You start them once, and they stay
67
+ available for any workspace.
68
+
69
+ ## The journey: from first launch to first result
70
+
71
+ Follow this little story in order. By the end you'll have seen it all: the
72
+ interface, the assistant, the tools, and scripting.
73
+
74
+ **Step 1 — Create your workspace with `wiki-workspace`.**
75
+ Everything starts here: `wiki-workspace` creates your project, e.g. `my-project`.
76
+ It's the folder that will hold its documents, settings, and results, all on its
77
+ own. It ships **pre-filled with an example** (the "basic" scaffold): enough to
78
+ have a working use case from the start.
79
+
80
+ **Step 2 — Configure the MCPs and the environment.**
81
+ Fill in the **services (MCP)** and the **environment file**: the keys, URLs, and
82
+ tokens the project needs (Confluence, e-mail, production…). It's like plugging in
83
+ the cables before switching on.
84
+
85
+ **Step 3 — Start the shared external agents.**
86
+ Start the common toolbox once and for all (Confluence, documents, e-mail,
87
+ production). These agents run in the background and serve **all your projects**:
88
+
89
+ ```bash
90
+ wiki-workspace agents up # start cme, documents, mailer…
91
+ wiki-workspace agents status # check they respond
92
+ ```
93
+
94
+ **Step 4 — Move to `wiki-manager` or `serve`.**
95
+ Two entry doors, your choice:
96
+
97
+ ```bash
98
+ wiki-workspace up my-project --open # open the web interface (serve) in the browser
99
+ ```
100
+
101
+ - **`serve`** → the **web interface**: you **browse the wiki** (with its
102
+ **interdependency graph**), click around, and **chat with the built-in
103
+ assistant**.
104
+ - **`wiki-manager`** (the `donna` shell) → you **talk in plain language**; it
105
+ **organizes the steps into a workflow** and calls the tools for you.
106
+
107
+ 👉 From this step you already have a concrete result: your wiki is in front of you.
108
+ *(If the stack is already running, `wiki-workspace wiki my-project serve --open`
109
+ just reopens the web page.)*
110
+
111
+ **Step 5 — Discover the shipped use case via the `wiki-manager` commands.**
112
+ The scaffold ships **ready-to-use examples**. In the shell, explore them:
113
+
114
+ ```text
115
+ /skills list the bundled examples (diagnose, pipeline, status, wiki-sync…)
116
+ /skills show <name> see what an example does
117
+ /skills run <name> run it to see the result
118
+ ```
119
+
120
+ It's the best way to **discover every facet** without building anything yourself:
121
+ you start from a working case, then adapt it.
122
+
123
+ **Step 6 — Let it run on its own (optional).**
124
+ Once comfortable, turn a task into a **script** and **schedule it** (e.g. every
125
+ morning) — that's **scripting mode**. No need to think about it anymore.
126
+
127
+ ## Understanding a project's structure
128
+
129
+ A workspace keeps everything in five folders. The easiest way is to see them as a
130
+ **production line**, from raw materials to finished product:
131
+
132
+ | Folder | Role | Image |
133
+ | --- | --- | --- |
134
+ | `raw/` | The **raw sources** you provide (Confluence exports, converted docs). They land in `raw/untracked/`, then are archived into `raw/ingested/` once processed. | Raw material |
135
+ | `wiki/` | The **knowledge base**: clean markdown pages, linked together, created and kept up to date from the sources. The consultable core. | The organized warehouse |
136
+ | `templates/` | The **deliverable templates**: the shape of the final document, with slots to fill. | The mold |
137
+ | `build-context/` | The **rules and references** guiding generation: style, citation rules, expected structure, quality checks. | The build instructions |
138
+ | `deliverables/` | The **final deliverables** generated from the `templates`, fed by the `wiki` and the `build-context`. | The finished product |
139
+
140
+ In one sentence: you **ingest** the sources into the **wiki**, then **generate**
141
+ the **deliverables** by filling the **templates** with wiki content, according to
142
+ the rules in the **build-context**.
143
+
144
+ ## How a deliverable is generated
145
+
146
+ The process always follows the same chain. Two entry points depending on your
147
+ starting source.
148
+
149
+ Everything is driven **in plain language** (the web interface chat or the `donna`
150
+ shell), or by running a ready-made **skill**. No command line needed.
151
+
152
+ ### Entry point A — from a wiki / Confluence export
153
+
154
+ At each step, either you **ask for it in plain language**, or you **run the skill**.
155
+
156
+ 1. **Export** Confluence (via the CME agent) → the markdown lands in
157
+ `raw/untracked/`.
158
+ → *"Export the KEY Confluence space into my-project"*
159
+ 2. **Ingest** — the sources become clean pages in `wiki/` (the originals are
160
+ archived in `raw/ingested/`).
161
+ → *"Ingest the project's sources"*
162
+ 3. **Index** — builds the search index so the AI finds the right passage.
163
+ → *"Update the index"*
164
+ 4. **Build** — fills the `templates/` with the wiki + the `build-context/` → the
165
+ `deliverables/`.
166
+ → *"Generate the deliverables"*
167
+ 5. **Export / polish** — expands citations into their source and refines the
168
+ rendering.
169
+ → *"Export and polish the deliverables"*
170
+
171
+ > 💡 Even simpler: `/skills run wiki-sync` chains export + ingestion, and
172
+ > `/skills run pipeline` runs the whole chain end to end.
173
+
174
+ ### Entry point B — from a simple PDF (the fastest)
175
+
176
+ Ingestion only reads **markdown**. For a PDF (or a Word file, HTML…), the
177
+ **documents agent** does the conversion (it even reads scanned PDFs thanks to OCR,
178
+ in French and English). Two ways to hand it the file:
179
+
180
+ - **Simplest — via chat**: drag/attach the PDF directly into the conversation and
181
+ ask *"Convert this PDF into my-project"*. The agent turns it into markdown and
182
+ **drops it into `raw/untracked/` by itself**.
183
+ - **Via folder**: put the PDF in the documents agent's input folder
184
+ (`.agents-data/documents/input/`), then ask *"Convert the file my-doc.pdf into
185
+ my-project"*.
186
+
187
+ Then it's the **same path** as entry point A: ingest → index → build → export. The
188
+ shortest route for a first try: hand over a PDF, then `/skills run pipeline`.
189
+
190
+ ### Exploring the example data
191
+
192
+ The scaffold ships with a working case. To discover it, in the chat or the `donna`
193
+ shell:
194
+
195
+ ```text
196
+ /skills list the examples (diagnose, pipeline, status, wiki-sync)
197
+ /skills show pipeline show what the end-to-end example does
198
+ /skills run pipeline run the full chain on the example sources
199
+ /wiki inspect the project's wiki
200
+ ```
201
+
202
+ You can also simply **open the folders** `raw/`, `wiki/`, `templates/`, and
203
+ `deliverables/` of the workspace to see, at each step, what goes in and what comes
204
+ out.
205
+
206
+ > ⚙️ *Advanced (later)*: the same steps exist on the command line via
207
+ > `wiki-workspace wiki …` (`doctor`, `ingest`, `build`, `logs`). Keep these for
208
+ > automation and debugging — for everyday use, stay in the chat or the skills.
209
+
210
+ ## In short
211
+
212
+ | You want to… | You use… |
213
+ | --- | --- |
214
+ | Explore and click | The **web interface** (`up … --open`) |
215
+ | Let it run on its own | **Scripting mode** (script + scheduler) |
216
+ | Talk in plain language | The **`donna` assistant** (shell, agentic) |
217
+ | The shared services | The **external agents** (Confluence, e-mail, production) |
218
+
219
+ The right reflex to get started: **steps 1 → 4**, and your wiki is already in front
220
+ of you in the browser (create → configure → start the agents → open).
221
+
222
+ ---
223
+
224
+ # Technical reference
225
+
226
+ ## Toolchain
227
+
228
+ | Repository | Role |
229
+ | --- | --- |
230
+ | [`llm-wiki`](https://github.com/dotdrelle/llm-wiki) | Workspace engine: CLI, web UI, MCP server, retrieval, deliverables, skills |
231
+ | [`llm-wiki-manager`](https://github.com/dotdrelle/llm-wiki-manager) | Multi-workspace cockpit, Docker orchestration, `donna` shell |
232
+ | [`agent-cme`](https://github.com/dotdrelle/agent-cme) | Global Confluence to Markdown MCP exporter; workspace injected automatically by Donna |
233
+ | [`agent-wiki-production`](https://github.com/dotdrelle/agent-wiki-production) | Workspace-scoped production jobs: ingest, build, export, polish, pipeline |
234
+ | [`agent-wiki-documents`](https://github.com/dotdrelle/agent-wiki-documents) | Document conversion MCP: PDF/Office/HTML/images → Markdown (OCR-capable) |
235
+ | [`agent-mailer-api`](https://github.com/dotdrelle/agent-mailer-api) | Optional external mailer MCP endpoint |
236
+
237
+ ## Workspace Model
238
+
239
+ Each managed workspace is a normal `llm-wiki` workspace plus manager metadata:
240
+
241
+ ```text
242
+ workspaces/<name>/
243
+ .env # ports, tokens, workspace path
244
+ .wikirc.yaml # LLM/vector config for this workspace
245
+ raw/
246
+ wiki/
247
+ templates/
248
+ build-context/
249
+ deliverables/
250
+ .wiki/
251
+ ```
252
+
253
+ The `.env` file is manager-owned. The `.wikirc.yaml` file is workspace-owned and
254
+ stores provider/model/baseUrl/apiKey/retrieval settings.
255
+
256
+ Confluence exports land directly in:
257
+
258
+ ```text
259
+ raw/untracked/
260
+ ```
261
+
262
+ The normal production pipeline starts at ingest:
263
+
264
+ ```text
265
+ ingest -> build -> export -> polish
266
+ ```
267
+
268
+ The legacy copy step is only for deployments that explicitly configure external
269
+ import mappings.
270
+
271
+ ## Initial Setup
272
+
273
+ ```bash
274
+ corepack enable
275
+ pnpm install
276
+ ```
277
+
278
+ When installed through `npm`/`npx`/`bun`, `wiki-manager` keeps its state outside
279
+ the package, in the directory where the command is launched:
280
+
281
+ ```text
282
+ ./workspaces/ # workspace registry
283
+ ./.env # local configuration (gitignored; copy from .env.example)
284
+ ./mcp.endpoints.json # external MCP endpoints (gitignored; copy from .env.example)
285
+ ```
286
+
287
+ `WIKI_WORKSPACES_DIR` is available as an explicit override for the workspaces
288
+ directory, but not required for normal usage.
289
+
290
+ ### Local `.env`
291
+
292
+ Copy `.env.example` to `.env` and fill in your values:
293
+
294
+ ```bash
295
+ cp .env.example .env
296
+ ```
297
+
298
+ The `.env` file is loaded automatically by both `wiki-manager` (Node/Bun process)
299
+ and `wiki-workspace` (Docker Compose). It sets `WORKSPACES_ROOT`, per-agent auth
300
+ tokens, mailer credentials, and optional port overrides.
301
+
302
+ ### External MCP endpoints
303
+
304
+ `mcp.endpoints.json` declares external agents for the shell, TUI, headless, and
305
+ the served chat UI. Values support `${VAR}` interpolation resolved from the
306
+ process environment (including the `.env` loaded at startup):
307
+
308
+ ```json
309
+ {
310
+ "mcpServers": {
311
+ "cme": {
312
+ "url": "http://host.docker.internal:${CME_MCP_PORT:-3336}/mcp/",
313
+ "headers": { "Authorization": "Bearer ${CME_MCP_AUTH_TOKEN}" }
314
+ },
315
+ "documents": {
316
+ "url": "http://host.docker.internal:${DOCUMENTS_MCP_PORT:-3337}/mcp/",
317
+ "headers": { "Authorization": "Bearer ${DOCUMENTS_MCP_AUTH_TOKEN}" }
318
+ }
319
+ }
320
+ }
321
+ ```
322
+
323
+ Copy `mcp.endpoints.example.json` to `mcp.endpoints.json` and set the matching
324
+ token variables in `.env`.
325
+
326
+ ### Starting external agents
327
+
328
+ Start CME, documents, and mailer once for all workspaces:
329
+
330
+ ```bash
331
+ wiki-workspace agents up
332
+ ```
333
+
334
+ This uses the packaged `agents.docker-compose.yml`. `WORKSPACES_ROOT` is resolved
335
+ automatically from the manager workspaces directory. Agent state is stored under
336
+ `./.agents-data/` unless `AGENTS_DATA_DIR` is set.
337
+
338
+ Workspace-native MCP servers (`llm-wiki`, `production`) stay configured through
339
+ each workspace `.env`. External agents are workspace-agnostic: the active
340
+ `/use <workspace>` is injected automatically on every CME and documents tool
341
+ call — no need to pass `workspace` explicitly.
342
+
343
+ CME data is isolated per workspace:
344
+
345
+ ```text
346
+ .agents-data/cme/<workspace>/cme/app_data.json # Confluence credentials
347
+ .agents-data/cme/<workspace>/sources-manifest.yaml # export sources
348
+ workspaces/<workspace>/raw/untracked/ # exported Markdown
349
+ ```
350
+
351
+ Create a workspace:
352
+
353
+ ```bash
354
+ wiki-workspace config my-project [path]
355
+ ```
356
+
357
+ Start it:
358
+
359
+ ```bash
360
+ wiki-workspace up my-project
361
+ ```
362
+
363
+ Run wiki commands:
364
+
365
+ ```bash
366
+ wiki-workspace wiki my-project doctor
367
+ wiki-workspace wiki my-project ingest
368
+ wiki-workspace wiki my-project build --plan
369
+ wiki-workspace wiki my-project build
370
+ ```
371
+
372
+ ## Services
373
+
374
+ The shared `docker-compose.yml` starts one workspace stack:
375
+
376
+ | Service | Role | Port variable |
377
+ | --- | --- | --- |
378
+ | `serve` | Wiki web UI and browser chat | `WIKI_SERVE_PORT` |
379
+ | `mcp-http` | llm-wiki MCP endpoint | `WIKI_MCP_PORT` |
380
+ | `production-mcp` | Production job MCP endpoint | `PRODUCTION_MCP_PORT` |
381
+
382
+ Use `wiki-workspace` whenever possible so Compose receives the right project
383
+ name, env file, ports, and volume mounts.
384
+
385
+ ```bash
386
+ wiki-workspace list
387
+ wiki-workspace agents up
388
+ wiki-workspace agents status
389
+ wiki-workspace up my-project
390
+ wiki-workspace wiki my-project logs
391
+ ```
392
+
393
+ ### Document uploads
394
+
395
+ The shell can deposit local documents into the documents agent input volume and
396
+ convert them when the `documents` MCP endpoint is connected:
397
+
398
+ ```bash
399
+ /upload /path/to/rapport.pdf
400
+ /uploads
401
+ /upload convert pending
402
+ /uploads clean --older-than 30d
403
+ ```
404
+
405
+ Original files are stored under
406
+ `.agents-data/documents/input/<workspace>/`. Converted Markdown is written by
407
+ the documents agent to `<workspace>/raw/untracked/`. If the documents agent is
408
+ down, the upload remains stored and can be converted later.
409
+ Image files, scanned PDFs, and images detected inside PDF or Office documents
410
+ are sent through LLM OCR automatically.
411
+
412
+ ## The `donna` Shell
413
+
414
+ Start the agent shell:
415
+
416
+ ```bash
417
+ bun start # full OpenTUI shell (requires Bun ≥ 1.2)
418
+ pnpm start # alias for bun start
419
+ pnpm run start:node # fallback: legacy repl.js shell under Node
420
+ ```
421
+
422
+ The interactive shell is agentic by default:
423
+
424
+ - input starting with `/` runs a deterministic shell primitive;
425
+ - by default, any other input goes to the LangGraph orchestrator with MCP tools;
426
+ - `/chat` switches free text to direct LLM chat without tools;
427
+ - `/agent` switches free text back to the LangGraph orchestrator;
428
+ - the visible agent name is `donna`;
429
+ - conversation history is separated per workspace;
430
+ - Ctrl+C interrupts active LLM/MCP calls; Ctrl+C twice exits when idle.
431
+
432
+ Direct chat requires an active workspace config with `llm.apiKey`, `llm.model`,
433
+ and `llm.baseUrl`. If those are missing, the shell reports the missing fields
434
+ and points to `/use`, `/config list`, `/config use`, or `/config edit`.
435
+
436
+ The TUI uses a two-pane layout:
437
+
438
+ - **Left** — scrollable conversation thread with a chat input at the bottom.
439
+ Typing `/` opens a slash-command completion overlay just above the input.
440
+ Mouse wheel scrolls the conversation, and selecting text copies it through the
441
+ TUI clipboard bridge. Message headers also expose a `[ copy ]` target for
442
+ copying one message. PageUp/PageDown remain available for keyboard scrolling.
443
+ - **Right** — Plan/Queue tabs, active MCP jobs, plus a live log/trace panel.
444
+ `Ctrl+Q` toggles the tabs; clicking `Plan` or `Queue (N)` selects that tab
445
+ directly. MCP connection details remain available through `/mcp status`.
446
+
447
+ Useful primitives:
448
+
449
+ ```text
450
+ /workspaces
451
+ /new <name> [path]
452
+ /use <workspace>
453
+ /config list
454
+ /config use <name>
455
+ /config status
456
+ /services
457
+ /start [service]
458
+ /stop [service]
459
+ /logs <service>
460
+ /mcp endpoints
461
+ /mcp status
462
+ /mcp tools [mcp]
463
+ /mcp call <mcp> <tool> [json]
464
+ /queue
465
+ /queue cancel <id>
466
+ /queue clear
467
+ /wiki
468
+ /wiki run <args...>
469
+ /skills
470
+ /skills show <name>
471
+ /skills run <name>
472
+ /chat
473
+ /agent
474
+ /clear
475
+ ```
476
+
477
+ Skills are loaded only from the active workspace. The manager itself has no root
478
+ `SKILL.md` and no root `skills/` directory.
479
+
480
+ Workspace switching is isolated. When you run `/use my-project`, the shell
481
+ switches both the displayed conversation and the LLM history to `my-project`.
482
+ Returning to another workspace restores that workspace's in-memory conversation
483
+ for the current shell process.
484
+
485
+ ## Agent Tooling
486
+
487
+ The `donna` agent uses a LangGraph (`@langchain/langgraph`) ReAct loop (max 80
488
+ tool-use iterations). The LLM client is the `openai` SDK against any
489
+ OpenAI-compatible endpoint. Each agent turn makes a single streaming LLM call via
490
+ Server-Sent Events. Text tokens appear in the TUI as they arrive. When the LLM decides to call tools, the stream
491
+ switches to tool-call accumulation; tool results feed back into the next LLM call
492
+ until the agent produces a final text response.
493
+
494
+ The LLM can call:
495
+
496
+ - **connected MCP tools** — discovered at `/use` time and re-discovered on
497
+ `/mcp status`, `/start`, and `/stop`;
498
+ - **`shell__run_command`** — restricted internal tool for safe manager primitives
499
+ only.
500
+
501
+ For actionable requests, the orchestrator must not answer with future intent only.
502
+ If a connected MCP tool or safe primitive can perform the action, it must call the
503
+ tool in the same turn. If required arguments are missing, ask for the exact
504
+ missing values. If the tool/server is unavailable, name the concrete blocker.
505
+
506
+ `shell__run_command` is limited to safe manager primitives and does not expose
507
+ arbitrary system commands, `/mcp call`, `/wiki run`, `/start`, `/stop`, `/logs`,
508
+ or `/exit`.
509
+
510
+ ### Tool naming
511
+
512
+ LLM-facing tool names use `<server>__<tool>`. For the llm-wiki MCP server this
513
+ means remote tools are intentionally named with both the server namespace and the
514
+ canonical llm-wiki tool name:
515
+
516
+ ```text
517
+ wiki__wiki_list_pages
518
+ wiki__wiki_read_page
519
+ wiki__wiki_collect_context
520
+ ```
521
+
522
+ The only internal manager tools under the `wiki__*` namespace are `wiki__plan_set`
523
+ and `wiki__plan_done`. All other `wiki__*` calls are routed to the remote `wiki`
524
+ MCP endpoint.
525
+
526
+ ### Production job queue
527
+
528
+ `production_start_job` remains protected by the production MCP workspace lock.
529
+ When a production job is already active, or when the production MCP returns
530
+ `workspace_busy`, the manager stores the new request in an in-memory local queue
531
+ instead of dropping it.
532
+
533
+ The queue is intentionally narrow in this version: only `production_start_job` is
534
+ queueable; the production MCP lock remains the source of truth; queue items are
535
+ scoped to the workspace that created them; switching workspaces freezes queued
536
+ items from the previous workspace until you switch back.
537
+
538
+ Use the Queue tab in the right pane, or `/queue`, `/queue cancel <id>`, and
539
+ `/queue clear`. `/queue cancel <id>` removes waiting/starting items locally; for a
540
+ running production queue item, it calls `production_cancel_job(jobId)`.
541
+
542
+ ## Non-Interactive Mode
543
+
544
+ The `--once` mode runs one agent turn:
545
+
546
+ ```bash
547
+ node ./bin/wiki-manager.js --once "list configured workspaces"
548
+ ```
549
+
550
+ It is intentionally lightweight and does not preload a workspace, LLM config, or
551
+ MCP endpoints.
552
+
553
+ Scheduled unattended execution uses headless mode, not `--once`:
554
+
555
+ ```bash
556
+ node ./bin/wiki-manager.js --headless --workspace my-project --skill pipeline
557
+ node ./bin/wiki-manager.js --headless --workspace my-project --prompt "check production status"
558
+ ```
559
+
560
+ Headless mode creates a normal session, runs `/use`, and writes a log under
561
+ `.wiki/logs/` by default. `--prompt` runs one agent turn unless `--wait` is passed.
562
+ `--skill` uses the agentic loop by default: agent turn, wait for active MCP jobs
563
+ declared through `_activity.poll`, then re-invoke the agent with the completed job
564
+ summary so it can start the next required step.
565
+
566
+ Useful headless controls:
567
+
568
+ ```bash
569
+ node ./bin/wiki-manager.js --headless --workspace my-project --skill pipeline --timeout 3600 --max-turns 20
570
+ node ./bin/wiki-manager.js --headless --workspace my-project --skill pipeline --no-wait
571
+ node ./bin/wiki-manager.js --headless --workspace my-project --prompt "check production status" --wait
572
+ ```
573
+
574
+ `--timeout` applies per wave of active jobs, not to the whole run. `--max-turns`
575
+ limits the number of LLM turns in a skill run. The process exits non-zero on
576
+ failed/cancelled activities, activity timeout, max-turn exhaustion, or setup
577
+ failure. Use `--log-file <path>` to choose a specific log path.
578
+
579
+ ## MCP Activity Contract
580
+
581
+ The manager is MCP-agnostic for job tracking. Any MCP response can opt into
582
+ automatic shell/headless monitoring by including `_activity`:
583
+
584
+ ```json
585
+ {
586
+ "_activity": {
587
+ "id": "job-123",
588
+ "source": "production",
589
+ "kind": "pipeline",
590
+ "label": "Production pipeline",
591
+ "status": "running",
592
+ "progress": { "percent": 42, "step": "build" },
593
+ "poll": {
594
+ "server": "production",
595
+ "tool": "production_job_status",
596
+ "args": { "jobId": "job-123" },
597
+ "intervalMs": 2500
598
+ },
599
+ "startedAt": "2026-06-05T12:00:00Z",
600
+ "updatedAt": "2026-06-05T12:03:00Z",
601
+ "error": null,
602
+ "terminal": false
603
+ }
604
+ }
605
+ ```
606
+
607
+ The existing native payload should stay intact. `_activity` is additive metadata
608
+ for the manager. When `poll` is present, the shell/TUI and headless loop call the
609
+ declared MCP tool until the activity becomes terminal.
610
+
611
+ ## Local Compose Overrides
612
+
613
+ Do not put machine-specific settings in the shared `docker-compose.yml`.
614
+
615
+ For example, if a VPN/proxy requires a custom CA bundle, create a local ignored
616
+ override such as `docker-compose.ca.local.yml` and run:
617
+
618
+ ```bash
619
+ docker compose \
620
+ -p wiki-my-project \
621
+ -f docker-compose.yml \
622
+ -f docker-compose.ca.local.yml \
623
+ --env-file workspaces/my-project/.env \
624
+ up -d serve production-mcp
625
+ ```
626
+
627
+ Files matching `docker-compose*.local.yml` are ignored by Git.
628
+
629
+ ## Security Model
630
+
631
+ - Workspace names created by `/workspace init` are path-safe identifiers:
632
+ alphanumeric at both ends, only letters/digits/underscore/dot/dash inside, and
633
+ no `..` sequence.
634
+ - Manager MCP tokens are local coordination secrets. They are stored in memory
635
+ for local calls and are not displayed by status commands.
636
+ - Provider API keys belong in the workspace `.wikirc.yaml` or in the owning
637
+ service environment, not in manager-level docs.
638
+ - Clipboard copy uses `execFileSync`, not shell-string execution.
639
+ - `.wikirc.yaml` is parsed as YAML `core` schema and must be an object.
640
+ - `.env` quoted values support basic escapes such as `\"`, `\\`, `\n`, `\r`, and
641
+ `\t`.
642
+
643
+ ## Development
644
+
645
+ ```bash
646
+ pnpm install
647
+ pnpm start
648
+ pnpm run check
649
+ ```
650
+
651
+ When bumping the package version, update both `package.json` and the Streamable
652
+ HTTP MCP `clientInfo.version` in `src/core/mcp.js`. They are kept explicit so
653
+ remote MCP server logs show the manager build that initiated the handshake.
654
+
655
+ `pnpm run check` verifies the CLI version, help output, and limited `--once` mode.
656
+ For headless changes, also test a controlled error path, for example:
657
+
658
+ ```bash
659
+ node ./bin/wiki-manager.js --headless --workspace __missing__ --prompt test
660
+ ```
661
+
662
+ ## Repository Layout
663
+
664
+ ```text
665
+ llm-wiki-manager/
666
+ ├── bin/wiki-manager.js
667
+ ├── bunfig.toml # Bun preload for @opentui/solid
668
+ ├── tsconfig.json # TSX compilation (jsxImportSource = @opentui/solid)
669
+ ├── src/
670
+ │ ├── agent/ # agentic orchestration: @langchain/langgraph (ReAct loop) + openai SDK (OpenAI-compatible LLM client, SSE streaming)
671
+ │ ├── cli/ # CLI entrypoint
672
+ │ ├── commands/ # slash commands
673
+ │ ├── core/ # compose, env, MCP, activity, agentEvents, plan, skills, workspace registry
674
+ │ └── shell/
675
+ │ ├── repl.js # legacy TUI and pipe shell (Node fallback)
676
+ │ ├── tui.tsx # OpenTUI shell root (Bun)
677
+ │ ├── LeftPane.tsx # conversation view + chat input
678
+ │ ├── RightPane.tsx # plan, activity, and log panel
679
+ │ ├── SlashDialog.tsx # completion overlay
680
+ │ ├── useSession.ts # reactive session state
681
+ │ ├── useAgent.ts # agent call wrapper (drives the @langchain/langgraph run)
682
+ │ └── renderer.ts # markdown stripping and line coloring
683
+ ├── docker-compose.yml # workspace-scoped stack (serve, mcp-http, production-mcp)
684
+ ├── agents.docker-compose.yml # global external agents (cme, documents, mailer)
685
+ ├── wiki-workspace
686
+ ├── .env.example # template for local .env (WORKSPACES_ROOT, agent tokens, …)
687
+ ├── mcp.endpoints.example.json
688
+ └── workspaces/.env.example
689
+ ```
690
+
691
+ ## License
692
+
693
+ Released under the PolyForm Noncommercial License 1.0.0. See [`LICENSE`](LICENSE).