llm-wiki-kit 0.2.0 → 0.2.2

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 CHANGED
@@ -92,15 +92,20 @@ Most users should not need these during daily Claude Code/Codex work. They exist
92
92
 
93
93
  - Install/update: `llm-wiki install`, `llm-wiki update`, `llm-wiki post-update`, `llm-wiki projects`
94
94
  - Diagnostics: `llm-wiki doctor`, `llm-wiki status`, `llm-wiki version`
95
+ - Manual: `llm-wiki manual`
95
96
  - Agent maintenance helpers: `llm-wiki context`, `llm-wiki lint`, `llm-wiki consolidate`, `llm-wiki maintenance`
96
97
  - Cleanup: `llm-wiki uninstall`
97
98
 
99
+ `llm-wiki manual` prints the full package manual from `docs/manual.md`. Keep that document current when adding public commands, options, hook behavior, directory conventions, security policy, or update flows.
100
+
98
101
  `llm-wiki status` is an offline consistency check. It reports the installed runtime version, hook targets, whether the `llm-wiki` command on `PATH` resolves to the current runtime, whether the current workspace has the current managed templates applied, how many rules are auto-updateable, how many managed-looking rules need agent cleanup, and how many wiki maintenance items are pending.
99
102
 
100
103
  `llm-wiki update --check [--to <version-or-tag>]` is the online update check. It compares the installed package version with the npm registry target without changing files, and reports an available update only when the target version is newer than the installed version.
101
104
 
102
105
  `llm-wiki update` upgrades the global npm package when npm has a newer target, reinstalls the hook entries, and reapplies safe managed template updates across known project roots. If the installed runtime already satisfies the registry target, it skips `npm install -g` and still runs post-update maintenance. Use `--current-only` when you intentionally want to update only the supplied workspace. Existing wiki content is not overwritten.
103
106
 
107
+ Installed npm runtimes also perform a cached update notice check from hooks while the user works. This does not install anything automatically. When a newer npm release is detected, the injected hook context tells the active agent to mention the available update and offer `llm-wiki update --workspace <project-or-search-root>`. Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` only when diagnosing or suppressing that reminder.
108
+
104
109
  `llm-wiki post-update --workspace <project>` reapplies the current runtime's hook entries and safe managed template updates without running `npm install -g`. Use `post-update --all --workspace <search-root>` to reapply templates across discovered project roots.
105
110
 
106
111
  `llm-wiki context "<query>"` prints the same layered context used by hooks. It is mainly for debugging what Codex/Claude Code will see; daily use should rely on hook injection. By default, episodic `wiki/queries/` pages are excluded from search unless they were promoted with `memory_type: semantic` or `procedural` and `importance >= 4`; use `--include-episodic` only when debugging old automatic query records.
@@ -40,11 +40,12 @@ when no project `CLAUDE.md` exists. Existing `CLAUDE.md` files are not overwritt
40
40
 
41
41
  The hook records redacted turn summaries but does not deny tool calls only because an input looks sensitive. Hook payloads are stored as small redacted event envelopes rather than full transcripts, and context output is redacted field by field before it is returned to Claude Code.
42
42
 
43
- At `SessionStart`/`InstructionsLoaded`, the hook first attempts a safe managed-template refresh, recovers stale turn state into `outputs/maintenance/queue.md`, then injects `llm-wiki/wiki/memory.md`, `llm-wiki/wiki/index.md`, recent log context, operating rules, a one-item maintenance summary when needed, and any maintenance note for outdated or customized managed rules. At `UserPromptSubmit`, it recovers stale turn state, searches wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, and injects the smallest useful context set. Maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
43
+ At `SessionStart`/`InstructionsLoaded`, the hook first attempts a safe managed-template refresh, recovers stale turn state into `outputs/maintenance/queue.md`, performs a cached npm update notice check for npm installs, then injects `llm-wiki/wiki/memory.md`, `llm-wiki/wiki/index.md`, recent log context, operating rules, a one-item maintenance summary when needed, any update notice, and any maintenance note for outdated or customized managed rules. At `UserPromptSubmit`, it recovers stale turn state, searches wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, performs the same cached update notice check, and injects the smallest useful context set. Maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
44
44
 
45
45
  `PostToolUse` and `PostToolBatch` record redacted tool summaries in the same turn buffer. `PreCompact` records a compaction note, and `PostCompact` records the note and returns fresh wiki context. In the default `answer-first` mode, `SubagentStop` does not create live Q&A, query, decision, or maintenance files. `Stop` and `SessionEnd` append live Q&A only for meaningful work turns and do not auto-create `wiki/queries/` or `wiki/decisions/`. If the user explicitly asked to record or document durable knowledge and no durable wiki update is detected, `Stop`/`SessionEnd` queue a pending maintenance item for agent review. `Stop` and `SessionEnd` then clear the per-session turn buffer; `SubagentStop` does not.
46
46
 
47
47
  Set `LLM_WIKI_KIT_AUTO_PROJECT_UPDATE=0` only while diagnosing automatic managed-template refresh behavior.
48
+ Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` only while suppressing the cached npm update reminder.
48
49
  Set `LLM_WIKI_KIT_CAPTURE_MODE=legacy-eager` only as deprecated compatibility mode for the old eager query/decision capture behavior.
49
50
 
50
51
  After installation or update, run:
@@ -29,8 +29,8 @@ Handled events:
29
29
 
30
30
  Expected behavior:
31
31
 
32
- - `SessionStart` first attempts a safe managed-template refresh, recovers stale turn state into `outputs/maintenance/queue.md`, then injects `llm-wiki/wiki/memory.md`, `llm-wiki/wiki/index.md`, recent log context, operating rules, a one-item maintenance summary when needed, and any maintenance note for outdated or customized managed rules.
33
- - `UserPromptSubmit` recovers stale turn state, searches project wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, and injects the smallest useful context set. Maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
32
+ - `SessionStart` first attempts a safe managed-template refresh, recovers stale turn state into `outputs/maintenance/queue.md`, performs a cached npm update notice check for npm installs, then injects `llm-wiki/wiki/memory.md`, `llm-wiki/wiki/index.md`, recent log context, operating rules, a one-item maintenance summary when needed, any update notice, and any maintenance note for outdated or customized managed rules.
33
+ - `UserPromptSubmit` recovers stale turn state, searches project wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, performs the same cached update notice check, and injects the smallest useful context set. Maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
34
34
  - `PreToolUse` records redacted tool summaries without blocking tool calls.
35
35
  - `PostToolUse` records redacted tool summaries in a turn buffer.
36
36
  - `PreCompact` records a compaction note; `PostCompact` records the note and returns fresh wiki context.
@@ -41,6 +41,7 @@ Expected behavior:
41
41
  Hook payloads are stored as small redacted event envelopes rather than full transcripts. Context output is also redacted field by field before it is returned to Codex.
42
42
 
43
43
  Set `LLM_WIKI_KIT_AUTO_PROJECT_UPDATE=0` only while diagnosing automatic managed-template refresh behavior.
44
+ Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` only while suppressing the cached npm update reminder.
44
45
  Set `LLM_WIKI_KIT_CAPTURE_MODE=legacy-eager` only as deprecated compatibility mode for the old eager query/decision capture behavior.
45
46
 
46
47
  Run these after install:
package/docs/manual.md ADDED
@@ -0,0 +1,463 @@
1
+ # llm-wiki-kit Manual
2
+
3
+ `llm-wiki-kit`은 Codex와 Claude Code를 평소처럼 사용하는 동안 프로젝트 안에 living Markdown wiki를 유지하는 hook-first runtime이다.
4
+
5
+ 핵심 원칙은 단순하다. 사용자는 별도 기록 명령을 외워서 매번 실행하지 않는다. 평소처럼 질문하고, 구현하고, 검증한다. 내부적으로는 hook이 필요한 context를 주입하고, 안전하게 요약을 남기고, 오래 쓸 지식을 agent가 `llm-wiki/` Markdown에 정리할 수 있도록 돕는다.
6
+
7
+ ## Mental Model
8
+
9
+ LLM Wiki는 세 층으로 움직인다.
10
+
11
+ ```text
12
+ raw evidence -> curated wiki -> rules and retrieval
13
+ ```
14
+
15
+ - `raw/`: 원본 또는 redacted 근거 저장소다. 기본 hook은 작은 redacted event envelope만 저장한다.
16
+ - `wiki/`: agent가 관리하는 정식 지식층이다. 결정, 구조, 디버깅, 개념, 절차, 맥락을 Markdown으로 보존한다.
17
+ - `outputs/`: live Q&A, 보고서, maintenance queue 같은 일회성 또는 작업 산출물을 둔다.
18
+ - `AGENTS.md`, `CLAUDE.md`, `procedures/`: agent가 wiki를 다루는 규칙과 절차다.
19
+
20
+ 채팅 history는 임시 context다. 오래 남길 지식은 repository Markdown으로 이동해야 다음 세션, 다른 agent, compact 이후에도 검색 가능하다.
21
+
22
+ ## What Gets Created
23
+
24
+ 프로젝트를 bootstrap하거나 install하면 보통 다음 구조가 생긴다.
25
+
26
+ ```text
27
+ llm-wiki/
28
+ ├── .kit-state.json
29
+ ├── raw/
30
+ │ ├── inbox/
31
+ │ ├── sessions/
32
+ │ ├── sources/
33
+ │ └── assets/
34
+ ├── wiki/
35
+ │ ├── index.md
36
+ │ ├── memory.md
37
+ │ ├── log.md
38
+ │ ├── sources/
39
+ │ ├── concepts/
40
+ │ ├── entities/
41
+ │ ├── decisions/
42
+ │ ├── architecture/
43
+ │ ├── debugging/
44
+ │ ├── context/
45
+ │ └── queries/
46
+ ├── outputs/
47
+ │ ├── questions/
48
+ │ ├── reports/
49
+ │ └── maintenance/
50
+ └── procedures/
51
+ ```
52
+
53
+ `wiki/memory.md`는 hook context에 들어가는 짧은 hot index다. 긴 설명을 복사하지 말고 중요한 entry point만 둔다.
54
+
55
+ `wiki/index.md`는 wiki 전체의 navigation map이다. agent는 넓은 질문을 받으면 여기와 `memory.md`에서 시작한다.
56
+
57
+ `.kit-state.json`은 현재 project rules/templates가 어느 runtime version으로 적용되었는지 기록한다. runtime update와 project knowledge는 별개다. npm package update가 기존 wiki 내용을 덮어쓰지 않는다.
58
+
59
+ ## Normal Use
60
+
61
+ 평소처럼 Codex 또는 Claude Code를 사용한다.
62
+
63
+ 설치된 hook은 다음 일을 자동으로 수행한다.
64
+
65
+ - session start, prompt submit, post compact 시점에 `wiki/memory.md`, `wiki/index.md`, 관련 wiki 검색 결과를 context로 주입한다.
66
+ - prompt/tool/result summary를 redaction한 뒤 turn buffer에 기록한다.
67
+ - 의미 있는 작업 turn만 `outputs/questions/YYYY-MM-DD-live-qa.md`에 live Q&A로 남긴다.
68
+ - 기본 answer-first mode에서는 `wiki/queries/`와 `wiki/decisions/`를 매 turn 자동 생성하지 않는다.
69
+ - 사용자가 명시적으로 문서화/기록을 요청했는데 durable wiki 반영이 없으면 `outputs/maintenance/queue.md`에 정리 후보를 남긴다.
70
+ - 이전 session이 깨끗하게 종료되지 않았을 때 stale turn state를 maintenance queue로 복구할 수 있다.
71
+ - 새 runtime이 오래된 project rules/templates를 발견하면 안전하게 갱신 가능한 managed file만 refresh한다.
72
+
73
+ 매번 저장 여부를 사용자가 고민해야 한다면 잘못 쓰고 있는 것이다. 답변보다 wiki maintenance가 먼저 오면 안 된다. 현재 사용자 요청을 먼저 처리하고, 오래 쓸 지식만 필요한 만큼 정리한다.
74
+
75
+ ## Capture Modes
76
+
77
+ 기본값은 다음과 같다.
78
+
79
+ ```bash
80
+ LLM_WIKI_KIT_CAPTURE_MODE=answer-first
81
+ ```
82
+
83
+ `answer-first` mode는 현재 답변을 우선한다.
84
+
85
+ - 단순 Q&A나 상태 확인은 durable wiki로 승격하지 않는다.
86
+ - 의미 있는 작업 turn은 live Q&A archive에 남길 수 있다.
87
+ - explicit durable request가 빠졌을 때만 selective maintenance queue를 만든다.
88
+ - reusable fact는 active agent가 기존 wiki 문서에 병합한다.
89
+
90
+ 과거 호환용 eager mode도 남아 있다.
91
+
92
+ ```bash
93
+ LLM_WIKI_KIT_CAPTURE_MODE=legacy-eager
94
+ ```
95
+
96
+ `legacy-eager`는 old query/decision auto-promotion 흐름을 유지하기 위한 deprecated compatibility mode다. 새 project는 answer-first mode를 사용한다.
97
+
98
+ ## Command Reference
99
+
100
+ 대부분의 사용자는 일상 작업 중 이 명령들을 직접 실행할 필요가 없다. 설치, 업데이트, 진단, agent-side maintenance용 interface다.
101
+
102
+ ### `llm-wiki manual`
103
+
104
+ 이 문서를 출력한다.
105
+
106
+ ```bash
107
+ llm-wiki manual
108
+ ```
109
+
110
+ 새 기능이나 명령이 추가되면 `docs/manual.md`를 함께 갱신한다. 이 문서가 CLI manual의 단일 원본이다.
111
+
112
+ ### `llm-wiki install`
113
+
114
+ Codex/Claude Code hook을 설치하고 workspace를 bootstrap한다.
115
+
116
+ ```bash
117
+ llm-wiki install --workspace /apps --profile standard
118
+ llm-wiki install --workspace /path/to/project --profile standard
119
+ llm-wiki install --workspace /path/to/project --profile standard --no-project
120
+ ```
121
+
122
+ `standard` profile은 기본 profile이다.
123
+
124
+ - context injection
125
+ - redacted summary recording
126
+ - tool call allow with storage redaction
127
+ - project-local `llm-wiki/` bootstrap
128
+ - hook entry merge
129
+
130
+ `--no-project`는 hook/bin 설치만 하고 현재 workspace bootstrap은 하지 않을 때 사용한다.
131
+
132
+ global npm package 설치 자체는 환경에 따라 `npm install -g` 또는 `sudo npm install -g`로 수행한다. hook 설정 갱신은 보통 일반 사용자 home 아래 파일을 수정하므로 `llm-wiki install`은 해당 user로 실행한다.
133
+
134
+ ### `llm-wiki update`
135
+
136
+ npm registry target과 installed runtime을 비교하고, 필요하면 global package를 업데이트한 뒤 hook과 managed project templates를 갱신한다.
137
+
138
+ ```bash
139
+ llm-wiki update --check --workspace /path/to/project
140
+ llm-wiki update --workspace /path/to/search-root
141
+ llm-wiki update --workspace /path/to/search-root --to 0.2.1
142
+ llm-wiki update --workspace /path/to/project --current-only
143
+ llm-wiki update --workspace /path/to/project --dry-run
144
+ ```
145
+
146
+ `--check`는 network를 사용하지만 파일을 변경하지 않는다. installed version보다 registry target이 최신일 때만 update available을 보고한다.
147
+
148
+ 기본 `update --workspace <search-root>`는 runtime update를 한 번 수행한 뒤, known/discovered project roots의 managed templates를 재적용한다. 기존 wiki contents는 덮어쓰지 않는다.
149
+
150
+ `update`는 source checkout에서 self-update하지 않는다. source checkout 개발 중에는 npm package나 local tarball로 global install한 뒤 update behavior를 테스트한다.
151
+
152
+ global npm runtime으로 설치된 경우 hook은 사용 흐름 중 cached update notice check를 수행한다. 자동 설치는 하지 않는다. 새 npm release가 감지되면 hook context가 active agent에게 “업데이트 가능”을 짧게 알리고 `llm-wiki update --workspace <project-or-search-root>` 실행을 제안하게 한다. `LLM_WIKI_KIT_UPDATE_NOTICE=0`으로 이 reminder만 끌 수 있다.
153
+
154
+ ### `llm-wiki post-update`
155
+
156
+ npm install 없이 현재 runtime으로 hook entries와 managed project templates를 다시 적용한다.
157
+
158
+ ```bash
159
+ llm-wiki post-update --workspace /path/to/project
160
+ llm-wiki post-update --all --workspace /path/to/search-root
161
+ ```
162
+
163
+ plain `npm install -g llm-wiki-kit@latest` 후 hook/template을 다시 맞출 때 사용한다.
164
+
165
+ ### `llm-wiki projects`
166
+
167
+ search root 아래의 project roots를 찾고 update 상태를 요약한다.
168
+
169
+ ```bash
170
+ llm-wiki projects --workspace /apps
171
+ ```
172
+
173
+ `llm-wiki/.kit-state.json`이 있거나 older `llm-wiki/wiki/index.md`가 있는 root를 찾는다. 출력 끝에는 전체 update, current-only update, post-update command 예시가 함께 나온다.
174
+
175
+ ### `llm-wiki status`
176
+
177
+ offline consistency check다.
178
+
179
+ ```bash
180
+ llm-wiki status --workspace /path/to/project
181
+ llm-wiki status
182
+ ```
183
+
184
+ 보고 항목:
185
+
186
+ - runtime version과 install source
187
+ - binary path와 `PATH` command가 current runtime을 가리키는지
188
+ - Codex/Claude hook이 current runtime인지
189
+ - project applied runtime
190
+ - managed templates current 여부
191
+ - auto-updateable rules count
192
+ - agent cleanup이 필요한 managed-looking rules count
193
+ - pending maintenance count
194
+
195
+ network를 사용하지 않는다.
196
+
197
+ ### `llm-wiki version`
198
+
199
+ installed runtime version만 출력한다.
200
+
201
+ ```bash
202
+ llm-wiki version
203
+ llm-wiki --version
204
+ llm-wiki -v
205
+ ```
206
+
207
+ script나 smoke test에서 가장 가볍게 runtime version을 확인할 때 쓴다.
208
+
209
+ ### `llm-wiki doctor`
210
+
211
+ 설치와 hook roundtrip을 진단한다.
212
+
213
+ ```bash
214
+ llm-wiki doctor --workspace /path/to/project
215
+ ```
216
+
217
+ 확인 항목:
218
+
219
+ - Node version
220
+ - docs presence
221
+ - Codex/Claude command availability
222
+ - state directory writability
223
+ - hook target 상태
224
+ - sample hook roundtrip
225
+ - status summary
226
+
227
+ 문제가 있으면 remediation hint를 출력한다.
228
+
229
+ ### `llm-wiki bootstrap`
230
+
231
+ project-local `llm-wiki/` 구조와 root policy block을 생성한다.
232
+
233
+ ```bash
234
+ llm-wiki bootstrap --workspace /path/to/project
235
+ ```
236
+
237
+ 직접 bootstrap할 수 있지만 보통 `install`이 함께 처리한다. 기존 wiki content는 덮어쓰지 않는다.
238
+
239
+ ### `llm-wiki migrate`
240
+
241
+ legacy wiki material을 current `llm-wiki/` 구조로 copy-only migration한다.
242
+
243
+ ```bash
244
+ llm-wiki migrate --workspace /path/to/project
245
+ ```
246
+
247
+ older OMX/OMC/`omx_wiki/` material은 migration input일 뿐이다. 현재 project knowledge는 `llm-wiki-kit`과 `llm-wiki/` 아래에서 유지한다.
248
+
249
+ ### `llm-wiki context`
250
+
251
+ hook이 주입하는 layered context를 수동으로 확인한다.
252
+
253
+ ```bash
254
+ llm-wiki context "auth architecture" --workspace /path/to/project
255
+ llm-wiki context "auth architecture" --workspace /path/to/project --json
256
+ llm-wiki context "auth architecture" --workspace /path/to/project --limit 8
257
+ llm-wiki context "auth architecture" --workspace /path/to/project --no-expand
258
+ llm-wiki context "auth architecture" --workspace /path/to/project --include-episodic
259
+ ```
260
+
261
+ 읽는 자료:
262
+
263
+ - `wiki/memory.md`
264
+ - `wiki/index.md`
265
+ - recent `wiki/log.md` excerpt
266
+ - MiniSearch 또는 substring fallback 결과
267
+ - strong match의 one-hop wikilink neighbors
268
+
269
+ 기본 검색은 episodic `wiki/queries/`를 제외한다. 오래된 automatic query record까지 보고 싶을 때만 `--include-episodic`을 쓴다.
270
+
271
+ ### `llm-wiki lint`
272
+
273
+ wiki health check를 수행한다. 파일을 수정하지 않는다.
274
+
275
+ ```bash
276
+ llm-wiki lint --workspace /path/to/project
277
+ ```
278
+
279
+ 점검 항목:
280
+
281
+ - missing `index.md`, `memory.md`, `log.md`
282
+ - missing/invalid frontmatter
283
+ - broken or ambiguous `[[wikilinks]]`
284
+ - broken relative Markdown links
285
+ - invalid or unsafe `source_ids`
286
+ - missing source files
287
+ - secret-like content
288
+ - duplicate aliases/titles
289
+ - stale pages and orphan candidates
290
+ - outdated managed rules/templates
291
+ - stale or oversized maintenance queue
292
+
293
+ broken links, invalid source IDs, secret-like content는 error이며 exit code 1을 반환한다. metadata/discoverability gap은 warning이다.
294
+
295
+ ### `llm-wiki consolidate`
296
+
297
+ generated marker block만 보수적으로 갱신한다.
298
+
299
+ ```bash
300
+ llm-wiki consolidate --workspace /path/to/project
301
+ llm-wiki consolidate --workspace /path/to/project --dry-run
302
+ ```
303
+
304
+ 갱신 대상:
305
+
306
+ - `wiki/memory.md`의 generated memory map
307
+ - `wiki/index.md`의 generated page map
308
+
309
+ handwritten content는 보존한다. malformed marker block은 덮어쓰지 않고 건너뛴다. 기본 `query`, `context`, `session-log` page는 explicit durable metadata가 없으면 generated map에서 제외한다.
310
+
311
+ ### `llm-wiki maintenance`
312
+
313
+ maintenance queue summary를 출력한다.
314
+
315
+ ```bash
316
+ llm-wiki maintenance --workspace /path/to/project
317
+ llm-wiki maintenance --workspace /path/to/project --json
318
+ ```
319
+
320
+ 이 명령은 page merge를 자동 수행하지 않는다. active agent가 pending item을 읽고, 가장 가까운 durable wiki 문서에 병합한 뒤 queue item을 `done` 또는 `skipped`로 표시한다.
321
+
322
+ ### `llm-wiki uninstall`
323
+
324
+ kit이 설치한 hook entries를 제거한다.
325
+
326
+ ```bash
327
+ llm-wiki uninstall
328
+ ```
329
+
330
+ project-local `llm-wiki/` contents는 남긴다. 지식 저장소를 삭제하는 명령이 아니다.
331
+
332
+ ### `llm-wiki hook`
333
+
334
+ Codex/Claude Code hook target으로 쓰는 내부 runtime command다.
335
+
336
+ ```bash
337
+ llm-wiki hook codex SessionStart
338
+ llm-wiki hook codex UserPromptSubmit
339
+ llm-wiki hook codex Stop
340
+ llm-wiki hook claude InstructionsLoaded
341
+ llm-wiki hook claude Stop
342
+ ```
343
+
344
+ 일반 사용자가 직접 호출할 필요는 거의 없다. hook integration이나 smoke test를 디버깅할 때만 사용한다.
345
+
346
+ ## Hook Events
347
+
348
+ Codex handled events:
349
+
350
+ - `SessionStart`
351
+ - `UserPromptSubmit`
352
+ - `PreToolUse`
353
+ - `PostToolUse`
354
+ - `PreCompact`
355
+ - `PostCompact`
356
+ - `SubagentStop`
357
+ - `Stop`
358
+
359
+ Claude Code handled events:
360
+
361
+ - `SessionStart`
362
+ - `InstructionsLoaded`
363
+ - `UserPromptSubmit`
364
+ - `PreToolUse`
365
+ - `PostToolUse`
366
+ - `PostToolBatch`
367
+ - `PreCompact`
368
+ - `PostCompact`
369
+ - `SubagentStop`
370
+ - `Stop`
371
+ - `SessionEnd`
372
+
373
+ Hook payload는 full transcript가 아니라 작은 redacted event envelope다. context output도 field별 redaction을 거친다.
374
+
375
+ ## Security Defaults
376
+
377
+ 기본 정책은 aggressive blocking보다 useful local work wiki를 우선한다.
378
+
379
+ - input이 민감해 보인다는 이유만으로 tool call을 막지 않는다.
380
+ - token, password, bearer credential, private key, `.env` 원문 같은 authentication value는 durable summary에 쓰기 전 redaction한다.
381
+ - phone number, email, date, business identifier는 local work context로 유용할 수 있어 기본 보존한다.
382
+ - full raw transcript capture는 기본 기능이 아니다.
383
+ - `llm-wiki lint`는 wiki 안의 secret-like content를 error로 보고한다.
384
+
385
+ 민감한 raw command output, log, screenshot, transcript를 저장해야 할 때는 먼저 redaction한다. 인증값은 wiki, report, live Q&A, command history에 남기지 않는다.
386
+
387
+ ## Updating Existing Installs
388
+
389
+ 일반 흐름:
390
+
391
+ ```bash
392
+ npm install -g llm-wiki-kit@latest --registry=https://registry.npmjs.org/ --prefer-online
393
+ llm-wiki post-update --all --workspace /apps
394
+ llm-wiki status --workspace /apps
395
+ llm-wiki doctor --workspace /apps
396
+ ```
397
+
398
+ system global npm prefix가 root-owned인 서버에서는 package install에 `sudo npm install -g`가 필요할 수 있다. 단, user home의 Codex/Claude hook 설정을 갱신하는 `llm-wiki install` 또는 `llm-wiki post-update`는 해당 user로 실행하는 것이 일반적으로 맞다.
399
+
400
+ source checkout 개발 중 pre-publish smoke:
401
+
402
+ ```bash
403
+ npm pack --pack-destination /tmp
404
+ npm install -g /tmp/llm-wiki-kit-<version>.tgz
405
+ llm-wiki install --workspace /apps --profile standard
406
+ ```
407
+
408
+ publish 전 검증:
409
+
410
+ ```bash
411
+ node --test
412
+ npm pack --dry-run
413
+ ```
414
+
415
+ publish 후 검증:
416
+
417
+ ```bash
418
+ npm view llm-wiki-kit version --registry=https://registry.npmjs.org/
419
+ llm-wiki version
420
+ llm-wiki manual
421
+ llm-wiki status --workspace /apps
422
+ llm-wiki doctor --workspace /apps
423
+ ```
424
+
425
+ ## Troubleshooting Shortcuts
426
+
427
+ hook이 안 돈다면:
428
+
429
+ ```bash
430
+ llm-wiki status --workspace /path/to/project
431
+ llm-wiki doctor --workspace /path/to/project
432
+ ```
433
+
434
+ `npm install -g` 후에도 old command가 실행된다면:
435
+
436
+ ```bash
437
+ which -a llm-wiki
438
+ readlink -f "$(command -v llm-wiki)"
439
+ npm root -g
440
+ node "$(npm root -g)/llm-wiki-kit/bin/llm-wiki.js" version
441
+ ```
442
+
443
+ local shim이 npm global command를 shadowing하면:
444
+
445
+ ```bash
446
+ llm-wiki install --workspace /path/to/project --profile standard
447
+ hash -r
448
+ llm-wiki version
449
+ ```
450
+
451
+ wiki page가 중복되거나 오래된 것 같다면:
452
+
453
+ ```bash
454
+ llm-wiki lint --workspace /path/to/project
455
+ llm-wiki maintenance --workspace /path/to/project
456
+ llm-wiki consolidate --workspace /path/to/project
457
+ ```
458
+
459
+ ## Manual Maintenance Rule
460
+
461
+ 이 문서는 `llm-wiki manual`의 출력 원본이다.
462
+
463
+ 새 public command, option, hook behavior, directory convention, security policy, update flow가 생기면 구현과 같은 change set에서 `docs/manual.md`를 갱신한다. README는 빠른 시작과 요약을 담고, 자세한 기능 설명은 이 manual에 둔다.
@@ -101,6 +101,8 @@ llm-wiki maintenance --workspace /path/to/project
101
101
 
102
102
  `update --check [--to <version-or-tag>]` is online and asks npm for the target version. It reports `update available` only when that registry target is newer than the installed version, so it does not suggest downgrades.
103
103
 
104
+ Installed npm runtimes also run a cached hook-side update notice check while the user works. It never installs automatically. If npm has a newer release, `SessionStart`/`InstructionsLoaded`/`UserPromptSubmit` context tells the active agent to mention the available update and offer `llm-wiki update --workspace <project-or-search-root>`. Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` to suppress this reminder while diagnosing.
105
+
104
106
  `projects --workspace <search-root>` lists discovered project roots that have `llm-wiki/.kit-state.json` or an older `llm-wiki/wiki/index.md`, reports whether their managed templates are current, and prints the update commands for the search root.
105
107
 
106
108
  `update` applies changes explicitly only when the user runs it:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-wiki-kit",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Hook-first living LLM Wiki runtime for Codex and Claude Code.",
5
5
  "type": "module",
6
6
  "files": [
package/src/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { readFile } from 'fs/promises';
1
2
  import { resolve } from 'path';
2
3
  import { formatConsolidateResult, runConsolidate } from './consolidate.js';
3
4
  import { handleHook } from './hook.js';
@@ -93,6 +94,7 @@ Usage:
93
94
  llm-wiki projects --workspace /apps
94
95
  llm-wiki status
95
96
  llm-wiki version
97
+ llm-wiki manual
96
98
  llm-wiki uninstall
97
99
  llm-wiki hook codex <EventName>
98
100
  llm-wiki hook claude <EventName>
@@ -141,6 +143,12 @@ Usage:
141
143
  return;
142
144
  }
143
145
 
146
+ if (command === 'manual') {
147
+ const manual = await readFile(new URL('../docs/manual.md', import.meta.url), 'utf8');
148
+ process.stdout.write(manual.endsWith('\n') ? manual : `${manual}\n`);
149
+ return;
150
+ }
151
+
144
152
  if (command === 'projects') {
145
153
  const result = await listProjects(options);
146
154
  printJsonOrText(result, options, formatProjects);
@@ -271,6 +279,7 @@ function formatUpdate(value) {
271
279
  `- installed: ${value.installedVersion}`,
272
280
  `- latest: ${value.latestVersion}`,
273
281
  `- update available: ${value.updateAvailable ? 'yes' : 'no'}`,
282
+ ...(value.updateAvailable ? [`- recommended action: ${commandForProject('update', value.workspace)}`] : []),
274
283
  `- project applied runtime: ${value.project?.lastRuntimeVersionApplied || 'unknown'}`,
275
284
  ].join('\n');
276
285
  }
@@ -287,6 +296,7 @@ function formatUpdate(value) {
287
296
  `- installed: ${value.installedVersion}`,
288
297
  `- latest: ${value.latestVersion}`,
289
298
  `- update available: ${value.updateAvailable ? 'yes' : 'no'}`,
299
+ ...(value.updateAvailable ? [`- recommended action: ${commandForProject('update', value.workspace)}`] : []),
290
300
  `- scope: ${value.scope || 'current'}`,
291
301
  ...(projects.length > 0 ? [`- projects checked: ${projects.length}`] : []),
292
302
  `- project template changes: ${changed}`,
package/src/hook.js CHANGED
@@ -6,6 +6,7 @@ import { applyProjectTemplateUpdate, inspectProjectState } from './project-state
6
6
  import { recordProject } from './projects.js';
7
7
  import { summarizeForStorage } from './redaction.js';
8
8
  import { buildEntryFromState, clearTurnState, rememberQuestion, rememberTool } from './state.js';
9
+ import { updateNoticeContext } from './update-notice.js';
9
10
  import { relative } from 'path';
10
11
 
11
12
  async function readStdinJson() {
@@ -42,6 +43,13 @@ function contextOutput(eventName, context) {
42
43
  };
43
44
  }
44
45
 
46
+ async function hookContext(projectRoot, eventName, context, payload) {
47
+ const notice = await updateNoticeContext(projectRoot, eventName, {
48
+ session: payload.session_id || payload.sessionId,
49
+ });
50
+ return [context, notice].filter(Boolean).join('\n\n');
51
+ }
52
+
45
53
  async function handleLegacyEagerStop(projectRoot, eventName, payload, entry) {
46
54
  if (entry.question !== '(not captured)' || entry.result !== '(not captured)') {
47
55
  const liveQaPath = await appendLiveQa(projectRoot, entry);
@@ -111,7 +119,7 @@ export async function handleHook(provider, explicitEvent) {
111
119
  }
112
120
 
113
121
  if (eventName === 'SessionStart' || eventName === 'InstructionsLoaded') {
114
- const context = await buildContextBrief(projectRoot, 'SessionStart');
122
+ const context = await hookContext(projectRoot, eventName, await buildContextBrief(projectRoot, 'SessionStart'), payload);
115
123
  return contextOutput(eventName, context);
116
124
  }
117
125
 
@@ -119,7 +127,12 @@ export async function handleHook(provider, explicitEvent) {
119
127
  const prompt = promptText(payload);
120
128
  await rememberQuestion(projectRoot, payload, prompt);
121
129
  const guidance = formatDurableCaptureGuidance(prompt);
122
- const context = [await buildContextBrief(projectRoot, eventName, prompt), guidance].filter(Boolean).join('\n\n');
130
+ const context = await hookContext(
131
+ projectRoot,
132
+ eventName,
133
+ [await buildContextBrief(projectRoot, eventName, prompt), guidance].filter(Boolean).join('\n\n'),
134
+ payload
135
+ );
123
136
  return contextOutput(eventName, context);
124
137
  }
125
138
 
@@ -0,0 +1,120 @@
1
+ import { spawnSync } from 'child_process';
2
+ import { join, resolve } from 'path';
3
+ import { cacheHome, readJson, writeJson } from './fs-utils.js';
4
+ import { commandForProject } from './projects.js';
5
+ import { compareVersions, parseRegistryVersion } from './update.js';
6
+ import { detectInstallSource, packageName, runtimeVersion } from './version.js';
7
+
8
+ const NOTICE_SCHEMA_VERSION = 1;
9
+ const DEFAULT_INTERVAL_MS = 24 * 60 * 60 * 1000;
10
+ const DEFAULT_TIMEOUT_MS = 3000;
11
+
12
+ function noticeCachePath() {
13
+ return join(cacheHome(), 'llm-wiki-kit', 'update-notice.json');
14
+ }
15
+
16
+ function npmCommand() {
17
+ return process.env.LLM_WIKI_KIT_NPM || 'npm';
18
+ }
19
+
20
+ function numberEnv(name, fallback) {
21
+ const raw = process.env[name];
22
+ if (!raw) return fallback;
23
+ const parsed = Number(raw);
24
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
25
+ }
26
+
27
+ function intervalMs() {
28
+ if (process.env.LLM_WIKI_KIT_UPDATE_NOTICE_INTERVAL_MS) {
29
+ return numberEnv('LLM_WIKI_KIT_UPDATE_NOTICE_INTERVAL_MS', DEFAULT_INTERVAL_MS);
30
+ }
31
+ return numberEnv('LLM_WIKI_KIT_UPDATE_NOTICE_INTERVAL_HOURS', 24) * 60 * 60 * 1000;
32
+ }
33
+
34
+ function timeoutMs() {
35
+ return numberEnv('LLM_WIKI_KIT_UPDATE_NOTICE_TIMEOUT_MS', DEFAULT_TIMEOUT_MS);
36
+ }
37
+
38
+ function noticeEnabled() {
39
+ if (process.env.LLM_WIKI_KIT_UPDATE_NOTICE === '0') return false;
40
+ if (detectInstallSource() === 'source' && process.env.LLM_WIKI_KIT_UPDATE_NOTICE_ALLOW_SOURCE !== '1') {
41
+ return false;
42
+ }
43
+ return true;
44
+ }
45
+
46
+ function freshEnough(record, now = Date.now()) {
47
+ const checkedAt = Date.parse(record?.checkedAt || '');
48
+ return Number.isFinite(checkedAt) && now - checkedAt < intervalMs();
49
+ }
50
+
51
+ function cacheMatches(record, target, installedVersion) {
52
+ return record?.schemaVersion === NOTICE_SCHEMA_VERSION &&
53
+ record.target === target &&
54
+ record.installedVersion === installedVersion;
55
+ }
56
+
57
+ function trimDetail(value) {
58
+ return String(value || '').trim().slice(0, 500);
59
+ }
60
+
61
+ function checkRegistry(target) {
62
+ const result = spawnSync(npmCommand(), ['view', `${packageName()}@${target}`, 'version'], {
63
+ encoding: 'utf8',
64
+ timeout: timeoutMs(),
65
+ });
66
+ if (result.status !== 0 || result.error) {
67
+ return {
68
+ latestVersion: null,
69
+ updateAvailable: false,
70
+ error: trimDetail(result.stderr) || trimDetail(result.stdout) || result.error?.message || 'unknown npm registry check error',
71
+ };
72
+ }
73
+ const latestVersion = parseRegistryVersion(result.stdout);
74
+ return {
75
+ latestVersion,
76
+ updateAvailable: compareVersions(latestVersion, runtimeVersion()) > 0,
77
+ error: null,
78
+ };
79
+ }
80
+
81
+ export async function checkUpdateNotice(options = {}) {
82
+ if (!noticeEnabled()) return null;
83
+ const target = options.to || process.env.LLM_WIKI_KIT_UPDATE_NOTICE_TARGET || 'latest';
84
+ const installedVersion = runtimeVersion();
85
+ const cachePath = noticeCachePath();
86
+ const cached = await readJson(cachePath, null);
87
+ if (!options.force && cacheMatches(cached, target, installedVersion) && freshEnough(cached)) {
88
+ return cached;
89
+ }
90
+
91
+ const checkedAt = new Date().toISOString();
92
+ const registry = checkRegistry(target);
93
+ const record = {
94
+ schemaVersion: NOTICE_SCHEMA_VERSION,
95
+ checkedAt,
96
+ target,
97
+ installedVersion,
98
+ ...registry,
99
+ };
100
+ await writeJson(cachePath, record).catch(() => {});
101
+ return record;
102
+ }
103
+
104
+ export async function updateNoticeContext(projectRoot, eventName, options = {}) {
105
+ if (!['SessionStart', 'InstructionsLoaded', 'UserPromptSubmit'].includes(eventName)) return '';
106
+ const notice = await checkUpdateNotice(options).catch(() => null);
107
+ if (!notice?.updateAvailable) return '';
108
+
109
+ const workspace = resolve(projectRoot || process.cwd());
110
+ const updateCommand = commandForProject('update', workspace);
111
+ return [
112
+ 'LLM Wiki update notice:',
113
+ `- Installed llm-wiki-kit: ${notice.installedVersion}`,
114
+ `- Latest npm release: ${notice.latestVersion}`,
115
+ `- A newer llm-wiki-kit release was detected automatically while the user was using the hooks.`,
116
+ `- Briefly tell the user an update is available and offer to run: \`${updateCommand}\``,
117
+ '- If the user wants every known project root updated, use the broader search root in the same command, for example `--workspace /apps`.',
118
+ '- Do not install automatically unless the user asks for the update.',
119
+ ].join('\n');
120
+ }