llm-wiki-kit 0.2.3 → 0.2.5

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
@@ -16,6 +16,20 @@ llm-wiki doctor --workspace /apps
16
16
 
17
17
  Restart Claude Code and Codex sessions after installation.
18
18
 
19
+ ### Native Windows
20
+
21
+ Native Windows is supported through the npm-generated `llm-wiki.cmd` shim. Use PowerShell or Windows Terminal with Node.js 20+:
22
+
23
+ ```powershell
24
+ npm install -g llm-wiki-kit@latest
25
+ llm-wiki install --workspace C:\path\to\project --profile standard
26
+ llm-wiki doctor --workspace C:\path\to\project
27
+ ```
28
+
29
+ On Windows, `llm-wiki install` does not create a Unix-style `~/.local/bin` symlink. It verifies the npm shim on `PATH`, installs Codex hooks with `commandWindows`, and writes Claude Code hooks with a Windows-safe `node.exe <bin>` command. Restart Codex and Claude Code after installation.
30
+
31
+ Use WSL2 instead when your repository and tooling already live in Linux. Native Windows support is for Windows-hosted projects and the native Codex/Claude Code surfaces.
32
+
19
33
  The default install mode is npm global install. On servers where the global npm prefix is root-owned, use sudo:
20
34
 
21
35
  ```bash
@@ -73,6 +87,7 @@ Use Claude Code or Codex normally.
73
87
  The installed hooks:
74
88
 
75
89
  - inject `wiki/memory.md`, `wiki/index.md`, and relevant wiki context at session start, instructions loaded, prompt submit, and post-compact time
90
+ - remove Codex-facing legacy `oh-my-codex:wiki`/`omx_wiki` surfaces at session start so `llm-wiki/` remains the active wiki implementation
76
91
  - record small redacted raw event envelopes and per-turn state
77
92
  - capture decision points, debugging findings, changed files, and verification notes
78
93
  - allow tool calls to proceed without secret/PII-based hook blocking
@@ -102,7 +117,7 @@ Most users should not need these during daily Claude Code/Codex work. They exist
102
117
 
103
118
  `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.
104
119
 
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.
120
+ `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. The command prints step progress to stderr, including registry lookup, npm install, post-update, and project discovery. Use `--timeout-ms <ms>` to bound external commands and `--max-dirs <n>` to bound project discovery under large or slow roots such as WSL `/mnt/*` trees.
106
121
 
107
122
  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 gives the active agent a Korean update reminder and tells it to offer `llm-wiki update --workspace <project-or-search-root>`. The cache is scoped to the npm command used for lookup so test/fake npm checks do not leak into normal hook sessions. Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` only when diagnosing or suppressing that reminder.
108
123
 
@@ -118,9 +133,13 @@ Installed npm runtimes also perform a cached update notice check from hooks whil
118
133
 
119
134
  `llm-wiki projects --workspace /apps` lists project roots that already have `llm-wiki-kit` state or an older `llm-wiki/wiki/index.md`, and shows the update commands to run. `llm-wiki update --workspace /apps` updates the global runtime once, then reapplies managed templates across every known or discovered project root under `/apps`.
120
135
 
136
+ For `llm-wiki-kit` code releases, source tests are not enough. After code changes, publish the package, install the newly published version, and verify the installed CLI and hooks with `version`, `status`, `doctor`, `update`, `lint`, and hook smoke checks before calling the release complete.
137
+
138
+ Native Windows changes require a real Windows smoke before release. The release gate is: install the packed candidate on a Windows host, run `llm-wiki install`, `llm-wiki status`, and `llm-wiki doctor` against a temporary Windows project, inspect `%USERPROFILE%\.codex\hooks.json` and `%USERPROFILE%\.claude\settings.json`, then repeat the minimal smoke after `npm install -g llm-wiki-kit@latest` once published. Simulated unit tests are not enough for the Windows support claim.
139
+
121
140
  After a plain `npm install -g llm-wiki-kit@latest`, existing hooks keep working when they already point at the global npm package path. The next `SessionStart`/`InstructionsLoaded` hook automatically reapplies safe managed template updates for the active project root. Clearly generated older `llm-wiki/AGENTS.md` and procedure files are refreshed even when old state is missing; user-edited files are not overwritten and are surfaced to the active agent as cleanup work. If hooks point at a source checkout or stale shim, run `llm-wiki post-update --workspace <project>` or `llm-wiki install --workspace <project>` once to reconnect them.
122
141
 
123
- `llm-wiki install` no longer creates a user-local `~/.local/bin/llm-wiki` shim when an npm/nvm global `llm-wiki` command already resolves to the current runtime. If an older kit-managed local shim is shadowing that npm command, install backs it up and removes it.
142
+ On Linux/macOS, `llm-wiki install` no longer creates a user-local `~/.local/bin/llm-wiki` shim when an npm/nvm global `llm-wiki` command already resolves to the current runtime. If an older kit-managed local shim is shadowing that npm command, install backs it up and removes it. On Windows, the npm-generated `llm-wiki.cmd` shim is the supported command entrypoint and no local symlink is created.
124
143
 
125
144
  On PCs that use nvm or user-local npm, prefer the non-sudo global install and make sure the `llm-wiki` command resolves to that npm package:
126
145
 
@@ -16,7 +16,7 @@ The installed hook stores the Node executable and the absolute package binary pa
16
16
 
17
17
  User-local fallback installs may instead point under `$HOME/.local/lib/node_modules`.
18
18
 
19
- Handled events:
19
+ Handled events on compatible Claude Code versions:
20
20
 
21
21
  - `SessionStart`
22
22
  - `InstructionsLoaded`
@@ -30,6 +30,8 @@ Handled events:
30
30
  - `Stop`
31
31
  - `SessionEnd`
32
32
 
33
+ `llm-wiki install` detects `claude --version` and installs a conservative event set when the local Claude Code binary is older or cannot be detected. `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `PreCompact`, `PostCompact`, `SubagentStop`, and `Stop` are treated as the stable set. `InstructionsLoaded`, `PostToolBatch`, and `SessionEnd` are installed only for newer compatible versions, or when `LLM_WIKI_KIT_CLAUDE_MODERN_HOOKS=1` is set. Existing kit-managed hooks for unsupported event keys are removed during install so Claude Code does not skip the entire settings file with an “Invalid key in record” error.
34
+
33
35
  Claude Code reads `CLAUDE.md`. For project compatibility, the kit creates a `CLAUDE.md` stub containing:
34
36
 
35
37
  ```text
@@ -29,7 +29,7 @@ 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`, 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 Korean update notice, and any maintenance note for outdated or customized managed rules.
32
+ - `SessionStart` first attempts a safe managed-template refresh, removes Codex-facing legacy `oh-my-codex:wiki`/`omx_wiki` surfaces when they reappear, 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 Korean update notice, and any maintenance note for outdated or customized managed rules.
33
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. Update notice cache is scoped by npm command, and 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.
package/docs/manual.md CHANGED
@@ -69,6 +69,7 @@ llm-wiki/
69
69
  - 사용자가 명시적으로 문서화/기록을 요청했는데 durable wiki 반영이 없으면 `outputs/maintenance/queue.md`에 정리 후보를 남긴다.
70
70
  - 이전 session이 깨끗하게 종료되지 않았을 때 stale turn state를 maintenance queue로 복구할 수 있다.
71
71
  - 새 runtime이 오래된 project rules/templates를 발견하면 안전하게 갱신 가능한 managed file만 refresh한다.
72
+ - `SessionStart`/`InstructionsLoaded`에서 Codex-facing legacy `oh-my-codex:wiki`/`omx_wiki` 설정과 스킬 표면이 되살아났는지 확인하고 제거한다. wiki 기능은 `llm-wiki/`가 단일 활성 구현이다.
72
73
 
73
74
  매번 저장 여부를 사용자가 고민해야 한다면 잘못 쓰고 있는 것이다. 답변보다 wiki maintenance가 먼저 오면 안 된다. 현재 사용자 요청을 먼저 처리하고, 오래 쓸 지식만 필요한 만큼 정리한다.
74
75
 
@@ -119,6 +120,14 @@ llm-wiki install --workspace /path/to/project --profile standard
119
120
  llm-wiki install --workspace /path/to/project --profile standard --no-project
120
121
  ```
121
122
 
123
+ Native Windows에서는 PowerShell/Windows Terminal에서 npm shim을 사용한다.
124
+
125
+ ```powershell
126
+ npm install -g llm-wiki-kit@latest
127
+ llm-wiki install --workspace C:\path\to\project --profile standard
128
+ llm-wiki doctor --workspace C:\path\to\project
129
+ ```
130
+
122
131
  `standard` profile은 기본 profile이다.
123
132
 
124
133
  - context injection
@@ -129,7 +138,7 @@ llm-wiki install --workspace /path/to/project --profile standard --no-project
129
138
 
130
139
  `--no-project`는 hook/bin 설치만 하고 현재 workspace bootstrap은 하지 않을 때 사용한다.
131
140
 
132
- global npm package 설치 자체는 환경에 따라 `npm install -g` 또는 `sudo npm install -g`로 수행한다. hook 설정 갱신은 보통 일반 사용자 home 아래 파일을 수정하므로 `llm-wiki install`은 해당 user로 실행한다.
141
+ global npm package 설치 자체는 환경에 따라 `npm install -g` 또는 `sudo npm install -g`로 수행한다. hook 설정 갱신은 보통 일반 사용자 home 아래 파일을 수정하므로 `llm-wiki install`은 해당 user로 실행한다. Windows에서는 npm이 만든 `llm-wiki.cmd`를 표준 command shim으로 사용하며 Unix-style `~/.local/bin` symlink를 만들지 않는다. Codex hook에는 Windows 실행용 `commandWindows`가 함께 기록된다.
133
142
 
134
143
  ### `llm-wiki update`
135
144
 
@@ -141,11 +150,14 @@ llm-wiki update --workspace /path/to/search-root
141
150
  llm-wiki update --workspace /path/to/search-root --to 0.2.1
142
151
  llm-wiki update --workspace /path/to/project --current-only
143
152
  llm-wiki update --workspace /path/to/project --dry-run
153
+ llm-wiki update --workspace /path/to/search-root --timeout-ms 120000 --max-dirs 5000
144
154
  ```
145
155
 
146
156
  `--check`는 network를 사용하지만 파일을 변경하지 않는다. installed version보다 registry target이 최신일 때만 update available을 보고한다.
147
157
 
148
- 기본 `update --workspace <search-root>`는 runtime update를 한 번 수행한 뒤, known/discovered project roots의 managed templates를 재적용한다. 기존 wiki contents는 덮어쓰지 않는다.
158
+ 기본 `update --workspace <search-root>`는 runtime update를 한 번 수행한 뒤, known/discovered project roots의 managed templates를 재적용한다. 기존 wiki contents는 덮어쓰지 않는다. `update`는 registry lookup, npm install, post-update, project discovery 진행 상태를 stderr에 출력한다. JSON 모드에서도 stdout은 JSON만 유지하고 progress는 stderr로 분리한다.
159
+
160
+ `--timeout-ms`는 `npm view`, `npm install -g`, internal `post-update` 같은 외부 command timeout을 지정한다. timeout 후 SIGTERM과 짧은 grace period 뒤 SIGKILL을 사용해 child process가 terminal을 계속 붙잡는 hard hang을 방지한다. `--max-dirs`는 search root 아래 project discovery가 검사할 최대 directory 수를 제한한다.
149
161
 
150
162
  `update`는 source checkout에서 self-update하지 않는다. source checkout 개발 중에는 npm package나 local tarball로 global install한 뒤 update behavior를 테스트한다.
151
163
 
@@ -412,16 +424,35 @@ node --test
412
424
  npm pack --dry-run
413
425
  ```
414
426
 
427
+ Native Windows 관련 변경은 publish 전 실제 Windows 설치 검증이 필수다. 후보 tarball을 Windows host에 설치하고 임시 project에서 다음을 확인한다.
428
+
429
+ ```powershell
430
+ npm install -g .\llm-wiki-kit-<version>.tgz
431
+ llm-wiki version
432
+ llm-wiki install --workspace C:\Temp\llm-wiki-kit-smoke --profile standard
433
+ llm-wiki status --workspace C:\Temp\llm-wiki-kit-smoke
434
+ llm-wiki doctor --workspace C:\Temp\llm-wiki-kit-smoke
435
+ ```
436
+
437
+ 검증에는 `%USERPROFILE%\.codex\hooks.json`의 `commandWindows`, `%USERPROFILE%\.claude\settings.json`의 Windows-safe `node.exe` command, project-local `llm-wiki/` 생성, sample hook roundtrip이 포함된다. 원격 자동화는 WinRM을 사용하되 credential은 환경변수나 secret store로만 전달하고 wiki/log에 저장하지 않는다.
438
+
415
439
  publish 후 검증:
416
440
 
417
441
  ```bash
418
442
  npm view llm-wiki-kit version --registry=https://registry.npmjs.org/
443
+ npm install -g llm-wiki-kit@<published-version> --registry=https://registry.npmjs.org/ --prefer-online
419
444
  llm-wiki version
420
445
  llm-wiki manual
421
446
  llm-wiki status --workspace /apps
422
447
  llm-wiki doctor --workspace /apps
448
+ llm-wiki update --workspace /apps --dry-run
449
+ llm-wiki update --workspace /apps --current-only
423
450
  ```
424
451
 
452
+ `llm-wiki-kit` 코드 변경 릴리스는 publish와 새 published version 설치 후 검증까지 끝나야 완료로 본다. root-owned global npm prefix에서는 package install에 `sudo npm install -g`가 필요할 수 있고, user home hook 갱신은 일반 user로 `llm-wiki install` 또는 `post-update`를 실행한다.
453
+
454
+ Windows 지원 변경이 포함된 릴리스는 publish 후에도 같은 Windows host에서 `npm install -g llm-wiki-kit@latest` 후 최소 `version/status/doctor` smoke를 반복한다.
455
+
425
456
  ## Troubleshooting Shortcuts
426
457
 
427
458
  hook이 안 돈다면:
@@ -440,6 +471,14 @@ npm root -g
440
471
  node "$(npm root -g)/llm-wiki-kit/bin/llm-wiki.js" version
441
472
  ```
442
473
 
474
+ Windows에서는 `where llm-wiki`와 npm prefix를 먼저 확인한다.
475
+
476
+ ```powershell
477
+ where llm-wiki
478
+ npm root -g
479
+ node "$(npm root -g)\llm-wiki-kit\bin\llm-wiki.js" version
480
+ ```
481
+
443
482
  local shim이 npm global command를 shadowing하면:
444
483
 
445
484
  ```bash
@@ -24,6 +24,14 @@ npm install -g llm-wiki-kit
24
24
  llm-wiki install --workspace /apps --profile standard
25
25
  ```
26
26
 
27
+ Native Windows:
28
+
29
+ ```powershell
30
+ npm install -g llm-wiki-kit@latest
31
+ llm-wiki install --workspace C:\path\to\project --profile standard
32
+ llm-wiki doctor --workspace C:\path\to\project
33
+ ```
34
+
27
35
  The default install mode is npm global install. On servers where the global npm prefix is root-owned, use sudo:
28
36
 
29
37
  ```bash
@@ -42,8 +50,9 @@ Avoid mixing root-owned and user-local installs unless you intentionally choose
42
50
  The installer:
43
51
 
44
52
  - uses an npm/nvm global `llm-wiki` command when it already resolves to the current runtime
45
- - removes an older kit-managed `~/.local/bin/llm-wiki` shim when it shadows that npm/nvm command
46
- - creates a user-local shim only when no `PATH` command points at the current runtime, such as source checkout development or user-local fallback installs
53
+ - on Linux/macOS, removes an older kit-managed `~/.local/bin/llm-wiki` shim when it shadows that npm/nvm command
54
+ - on Linux/macOS, creates a user-local shim only when no `PATH` command points at the current runtime, such as source checkout development or user-local fallback installs
55
+ - on Windows, relies on the npm-generated `llm-wiki.cmd` shim and does not create a Unix-style local symlink
47
56
  - backs up existing Codex/Claude settings before editing
48
57
  - merges hook entries without removing existing hooks
49
58
  - bootstraps the workspace `llm-wiki/`
@@ -58,6 +67,13 @@ npm install
58
67
  ./install.sh --workspace /apps --profile standard
59
68
  ```
60
69
 
70
+ On Windows source checkouts, run the CLI through Node instead of `install.sh`:
71
+
72
+ ```powershell
73
+ npm install
74
+ node bin\llm-wiki.js install --workspace C:\path\to\project --profile standard
75
+ ```
76
+
61
77
  Pre-publish server smoke tests can use a local tarball:
62
78
 
63
79
  ```bash
@@ -81,6 +97,7 @@ llm-wiki update --check --workspace /path/to/project [--to <version-or-tag>]
81
97
  llm-wiki update --workspace /path/to/search-root
82
98
  llm-wiki update --current-only --workspace /path/to/project
83
99
  llm-wiki update --dry-run --workspace /path/to/project
100
+ llm-wiki update --workspace /path/to/search-root --timeout-ms 120000 --max-dirs 5000
84
101
  llm-wiki post-update --workspace /path/to/project
85
102
  llm-wiki post-update --all --workspace /path/to/search-root
86
103
  llm-wiki context "search phrase" --workspace /path/to/project
@@ -113,8 +130,10 @@ Installed npm runtimes also run a cached hook-side update notice check while the
113
130
  - reinstalls hook entries without duplicating them
114
131
  - patches only managed project files across known or discovered project roots
115
132
  - backs up changed files under `~/.local/share/llm-wiki-kit/backups/`
133
+ - prints update progress to stderr and keeps JSON output parseable on stdout
134
+ - force-kills unresponsive child commands after timeout so slow npm/WSL environments do not wait forever
116
135
 
117
- By default, `update --workspace <search-root>` performs the npm runtime update once, then reapplies managed templates to every known or discovered project root under the search root. Use `update --current-only --workspace <project>` to limit template reapplication to one project.
136
+ By default, `update --workspace <search-root>` performs the npm runtime update once, then reapplies managed templates to every known or discovered project root under the search root. Use `update --current-only --workspace <project>` to limit template reapplication to one project. Use `--max-dirs` when a search root is a very large or slow tree.
118
137
 
119
138
  `post-update --workspace <project>` skips npm installation and reapplies the current runtime's hook entries plus safe managed template updates. `post-update --all --workspace <search-root>` does the same template reapplication across discovered project roots.
120
139
 
@@ -208,6 +227,25 @@ llm-wiki version
208
227
 
209
228
  Do not delete the whole `~/.local/bin` directory. It may contain unrelated user tools.
210
229
 
230
+ ## Updating Native Windows Installs
231
+
232
+ Windows uses npm's command shim. If `llm-wiki` is missing or old after install, inspect the Windows command resolution:
233
+
234
+ ```powershell
235
+ where llm-wiki
236
+ npm root -g
237
+ node "$(npm root -g)\llm-wiki-kit\bin\llm-wiki.js" version
238
+ llm-wiki status --workspace C:\path\to\project
239
+ ```
240
+
241
+ If `where llm-wiki` does not show the npm shim, reinstall the package in the active Node installation:
242
+
243
+ ```powershell
244
+ npm uninstall -g llm-wiki-kit
245
+ npm install -g llm-wiki-kit@latest --registry=https://registry.npmjs.org/ --prefer-online
246
+ llm-wiki install --workspace C:\path\to\project --profile standard
247
+ ```
248
+
211
249
  Use package-name-only uninstall syntax:
212
250
 
213
251
  ```bash
@@ -239,6 +277,18 @@ npm pack --dry-run
239
277
 
240
278
  Check that the tarball includes `bin/`, `src/`, `docs/`, `examples/`, `README.md`, `LICENSE`, `install.sh`, and `package.json`, but does not include project-local `llm-wiki/` contents.
241
279
 
280
+ For Native Windows changes, a real Windows smoke is mandatory before publishing. Install the candidate tarball on a Windows host and verify:
281
+
282
+ ```powershell
283
+ npm install -g .\llm-wiki-kit-<version>.tgz
284
+ llm-wiki version
285
+ llm-wiki install --workspace C:\Temp\llm-wiki-kit-smoke --profile standard
286
+ llm-wiki status --workspace C:\Temp\llm-wiki-kit-smoke
287
+ llm-wiki doctor --workspace C:\Temp\llm-wiki-kit-smoke
288
+ ```
289
+
290
+ Inspect `%USERPROFILE%\.codex\hooks.json` for `commandWindows`, `%USERPROFILE%\.claude\settings.json` for a Windows-safe `node.exe` hook command, and the temporary project for the generated `llm-wiki/` tree. If this is automated from Linux, use WinRM and keep credentials only in environment variables or a secret store.
291
+
242
292
  After publishing:
243
293
 
244
294
  ```bash
@@ -250,6 +300,8 @@ llm-wiki doctor --workspace /apps
250
300
  llm-wiki update --check --workspace /apps
251
301
  ```
252
302
 
303
+ For Native Windows changes, repeat a minimal post-publish smoke on the same Windows host after `npm install -g llm-wiki-kit@latest`.
304
+
253
305
  ## Uninstall
254
306
 
255
307
  ```bash
@@ -36,6 +36,35 @@ llm-wiki update --check --workspace /path/to/project
36
36
 
37
37
  `status` does not contact the network. `update --check` contacts npm but does not change files.
38
38
 
39
+ ## llm-wiki update Appears To Hang
40
+
41
+ `update` runs `npm view`, optional `npm install -g`, project discovery, and `post-update`. It prints progress to stderr while keeping JSON output on stdout parseable. In slow WSL or Windows-mounted trees, start with a bounded dry run:
42
+
43
+ ```bash
44
+ llm-wiki update --dry-run --workspace /path/to/project --current-only --timeout-ms 30000
45
+ llm-wiki update --dry-run --workspace /path/to/search-root --max-dirs 1000 --timeout-ms 30000
46
+ ```
47
+
48
+ If the current project succeeds but the search root is slow, use `--current-only` for that project or raise `--max-dirs` intentionally. If npm itself is slow, compare with:
49
+
50
+ ```bash
51
+ npm view llm-wiki-kit version --registry=https://registry.npmjs.org/
52
+ ```
53
+
54
+ When a child command exceeds `--timeout-ms`, `update` terminates it and then force-kills it after a short grace period.
55
+
56
+ ## Claude Code Settings Error: Invalid Hook Key
57
+
58
+ Some Claude Code versions reject newer hook event keys such as `PostToolBatch`. Run:
59
+
60
+ ```bash
61
+ claude --version
62
+ llm-wiki install --workspace /path/to/project --profile standard
63
+ llm-wiki doctor --workspace /path/to/project
64
+ ```
65
+
66
+ The installer detects the local Claude version, installs only compatible hook events, and removes kit-managed hooks for unsupported event keys. User-defined hooks are preserved when possible.
67
+
39
68
  ## npm Says The Package Is Not Found
40
69
 
41
70
  If `llm-wiki update --check` returns npm 404, the package is not published to the registry being used. Until publish, test npm installation with a local tarball:
@@ -94,6 +123,15 @@ npm root -g
94
123
  node "$(npm root -g)/llm-wiki-kit/bin/llm-wiki.js" version
95
124
  ```
96
125
 
126
+ On Native Windows, use PowerShell:
127
+
128
+ ```powershell
129
+ where llm-wiki
130
+ npm ls -g llm-wiki-kit --depth=0
131
+ npm root -g
132
+ node "$(npm root -g)\llm-wiki-kit\bin\llm-wiki.js" version
133
+ ```
134
+
97
135
  If the direct `node "$(npm root -g)/llm-wiki-kit/bin/llm-wiki.js" version` command prints the latest version but plain `llm-wiki` is old, reconnect through the installer:
98
136
 
99
137
  ```bash
@@ -106,7 +144,7 @@ After a manual `sudo npm install -g llm-wiki-kit@latest`, a normal-user `llm-wik
106
144
 
107
145
  If `readlink -f "$(command -v llm-wiki)"` points at a repository checkout such as `/mnt/d/dev_proj/llm-wiki-kit/bin/llm-wiki.js`, `npm install -g` is not updating that checkout. Either switch the shim to the npm package as above, or update the checkout itself with `git pull` and run it intentionally as source.
108
146
 
109
- Running `llm-wiki post-update --workspace /path/to/project` or `llm-wiki install --workspace /path/to/project --profile standard` also reconnects hook entries to the current runtime. `install` uses an npm/nvm global command when it already resolves to the current runtime, removes an older kit-managed local shim when it shadows that command, and creates a local shim only when no `PATH` command points at the current runtime.
147
+ Running `llm-wiki post-update --workspace /path/to/project` or `llm-wiki install --workspace /path/to/project --profile standard` also reconnects hook entries to the current runtime. On Linux/macOS, `install` uses an npm/nvm global command when it already resolves to the current runtime, removes an older kit-managed local shim when it shadows that command, and creates a local shim only when no `PATH` command points at the current runtime. On Windows, `install` relies on npm's `llm-wiki.cmd` shim and does not create a Unix-style symlink.
110
148
 
111
149
  If `which -a llm-wiki` shows both `~/.local/bin/llm-wiki` and an nvm path such as `~/.nvm/versions/node/v20.20.2/bin/llm-wiki`, the `~/.local/bin` entry usually wins because it appears earlier on `PATH`. Let install handle managed shims first:
112
150
 
@@ -130,6 +168,16 @@ llm-wiki version
130
168
 
131
169
  Use `npm uninstall -g llm-wiki-kit` with the package name only. `npm uninstall -g llm-wiki-kit@latest` is not the correct uninstall syntax and does not remove source checkouts or manually-created command shims.
132
170
 
171
+ If `where llm-wiki` is empty on Windows after npm install, the active Node npm prefix is not on `PATH` or npm did not create the shim. Reinstall with the active Node installation, then restart the terminal:
172
+
173
+ ```powershell
174
+ npm uninstall -g llm-wiki-kit
175
+ npm install -g llm-wiki-kit@latest --registry=https://registry.npmjs.org/ --prefer-online
176
+ where llm-wiki
177
+ llm-wiki install --workspace C:\path\to\project --profile standard
178
+ llm-wiki doctor --workspace C:\path\to\project
179
+ ```
180
+
133
181
  ## npm install -g Fails With EACCES
134
182
 
135
183
  If npm tries to write under `/usr` and fails with `EACCES`, use sudo when the server policy allows system-wide global packages:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-wiki-kit",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Hook-first living LLM Wiki runtime for Codex and Claude Code.",
5
5
  "type": "module",
6
6
  "files": [
@@ -0,0 +1,83 @@
1
+ import { spawnSync } from 'child_process';
2
+
3
+ export const CLAUDE_STABLE_EVENTS = [
4
+ 'SessionStart',
5
+ 'UserPromptSubmit',
6
+ 'PreToolUse',
7
+ 'PostToolUse',
8
+ 'PreCompact',
9
+ 'PostCompact',
10
+ 'SubagentStop',
11
+ 'Stop',
12
+ ];
13
+
14
+ export const CLAUDE_MODERN_EVENTS = [
15
+ 'InstructionsLoaded',
16
+ 'PostToolBatch',
17
+ 'SessionEnd',
18
+ ];
19
+
20
+ export const CLAUDE_MODERN_MIN_VERSION = '2.1.138';
21
+
22
+ function parseVersion(value) {
23
+ return String(value || '')
24
+ .replace(/^v/, '')
25
+ .split('.', 3)
26
+ .map((part) => {
27
+ const parsed = Number.parseInt(part, 10);
28
+ return Number.isFinite(parsed) ? parsed : 0;
29
+ });
30
+ }
31
+
32
+ export function compareClaudeVersions(a, b) {
33
+ const left = parseVersion(a);
34
+ const right = parseVersion(b);
35
+ for (let i = 0; i < 3; i += 1) {
36
+ const diff = (left[i] || 0) - (right[i] || 0);
37
+ if (diff !== 0) return diff > 0 ? 1 : -1;
38
+ }
39
+ return 0;
40
+ }
41
+
42
+ export function parseClaudeVersionOutput(output) {
43
+ return String(output || '').match(/\b(\d+\.\d+\.\d+)\b/)?.[1] || '';
44
+ }
45
+
46
+ export function detectClaudeVersion(options = {}) {
47
+ if (process.env.LLM_WIKI_KIT_CLAUDE_VERSION) {
48
+ const version = process.env.LLM_WIKI_KIT_CLAUDE_VERSION;
49
+ return {
50
+ available: true,
51
+ version,
52
+ raw: version,
53
+ modern: compareClaudeVersions(version, CLAUDE_MODERN_MIN_VERSION) >= 0,
54
+ };
55
+ }
56
+
57
+ const command = options.command || process.env.LLM_WIKI_KIT_CLAUDE || 'claude';
58
+ const result = spawnSync(command, ['--version'], {
59
+ encoding: 'utf8',
60
+ timeout: options.timeout || 5000,
61
+ });
62
+ const raw = `${result.stdout || ''}${result.stderr || ''}`.trim();
63
+ const version = parseClaudeVersionOutput(raw);
64
+ return {
65
+ available: result.status === 0 && !result.error,
66
+ version,
67
+ raw,
68
+ modern: Boolean(version) && compareClaudeVersions(version, CLAUDE_MODERN_MIN_VERSION) >= 0,
69
+ error: result.error?.message || null,
70
+ };
71
+ }
72
+
73
+ export function supportedClaudeEvents(detection = detectClaudeVersion()) {
74
+ if (process.env.LLM_WIKI_KIT_CLAUDE_MODERN_HOOKS === '1') {
75
+ return [...CLAUDE_STABLE_EVENTS, ...CLAUDE_MODERN_EVENTS];
76
+ }
77
+ if (process.env.LLM_WIKI_KIT_CLAUDE_MODERN_HOOKS === '0') {
78
+ return [...CLAUDE_STABLE_EVENTS];
79
+ }
80
+ return detection.modern
81
+ ? [...CLAUDE_STABLE_EVENTS, ...CLAUDE_MODERN_EVENTS]
82
+ : [...CLAUDE_STABLE_EVENTS];
83
+ }
package/src/cli.js CHANGED
@@ -32,6 +32,22 @@ function parseOptions(args) {
32
32
  } else if (arg === '--to') {
33
33
  options.to = optionValue(arg, i);
34
34
  i += 1;
35
+ } else if (arg === '--timeout-ms') {
36
+ const value = optionValue(arg, i);
37
+ const timeout = Number(value);
38
+ if (!Number.isInteger(timeout) || timeout < 1000) {
39
+ throw new Error('--timeout-ms must be an integer >= 1000');
40
+ }
41
+ options.timeout = timeout;
42
+ i += 1;
43
+ } else if (arg === '--max-dirs') {
44
+ const value = optionValue(arg, i);
45
+ const maxDirs = Number(value);
46
+ if (!Number.isInteger(maxDirs) || maxDirs < 1) {
47
+ throw new Error('--max-dirs must be a positive integer');
48
+ }
49
+ options.maxDirs = maxDirs;
50
+ i += 1;
35
51
  } else if (arg === '--no-codex') {
36
52
  options.codex = false;
37
53
  } else if (arg === '--no-claude') {
@@ -88,7 +104,7 @@ export async function runCli(args) {
88
104
 
89
105
  Usage:
90
106
  llm-wiki install --workspace /apps [--profile standard]
91
- llm-wiki update --workspace <project-or-search-root> [--check|--dry-run|--current-only|--to <version-or-tag>]
107
+ llm-wiki update --workspace <project-or-search-root> [--check|--dry-run|--current-only|--to <version-or-tag>] [--timeout-ms 120000] [--max-dirs 5000]
92
108
  llm-wiki post-update --workspace <project> [--all]
93
109
  llm-wiki doctor --workspace <project>
94
110
  llm-wiki projects --workspace /apps
@@ -115,7 +131,7 @@ Usage:
115
131
  `- workspace: ${value.workspace}`,
116
132
  `- runtime bin: ${value.binPath}`,
117
133
  `- command: ${value.commandPath || 'not found on PATH'}`,
118
- `- local shim: ${value.localBin} (${value.localBinAction})`,
134
+ `- command shim: ${value.localBin || value.commandPath || 'not found'} (${value.localBinAction})`,
119
135
  `- changed hooks: ${value.changed.length ? value.changed.join(', ') : 'none (already installed)'}`,
120
136
  'Restart Codex/Claude Code sessions so new hooks are loaded.',
121
137
  ].join('\n'));
@@ -156,12 +172,21 @@ Usage:
156
172
  }
157
173
 
158
174
  if (command === 'update') {
159
- printJsonOrText(await update(options), options, formatUpdate);
175
+ printJsonOrText(await update({
176
+ ...options,
177
+ onProgress: (message) => console.error(`[llm-wiki update] ${message}`),
178
+ }), options, formatUpdate);
160
179
  return;
161
180
  }
162
181
 
163
182
  if (command === 'post-update') {
164
- printJsonOrText(await postUpdate(options), options, formatPostUpdate);
183
+ const postOptions = process.env.LLM_WIKI_KIT_PROGRESS === '1'
184
+ ? {
185
+ ...options,
186
+ onProgress: (message) => console.error(`[llm-wiki post-update] ${message}`),
187
+ }
188
+ : options;
189
+ printJsonOrText(await postUpdate(postOptions), options, formatPostUpdate);
165
190
  return;
166
191
  }
167
192
 
@@ -226,7 +251,7 @@ Usage:
226
251
 
227
252
  async function listProjects(options) {
228
253
  const workspace = resolve(options.workspace || process.cwd());
229
- const roots = await knownProjectRoots({ workspace });
254
+ const roots = await knownProjectRoots({ workspace, maxDirs: options.maxDirs });
230
255
  const projects = [];
231
256
  for (const root of roots) {
232
257
  let state = null;
@@ -256,14 +281,17 @@ function formatStatus(value) {
256
281
  return [
257
282
  'llm-wiki-kit status',
258
283
  `- version: ${value.runtimeVersion}`,
284
+ `- platform: ${value.platform || process.platform}`,
259
285
  `- runtime: ${value.runtimeVersion} (${value.installSource})`,
260
286
  `- bin: ${value.binPath}`,
261
287
  `- command: ${value.commandPath || 'not found'}`,
262
288
  `- command matches runtime: ${value.commandMatchesRuntime ? 'yes' : 'no'}`,
263
- `- local shim: ${value.localBin?.path || 'unknown'} (${value.localBin?.exists ? (value.localBin.managed ? 'managed' : 'unmanaged') : 'absent'}${value.localBin?.matchesRuntime ? ', current' : ''})`,
289
+ `- command shim: ${value.localBin?.path || 'unknown'} (${value.localBin?.exists ? (value.localBin.managed ? 'managed' : 'unmanaged') : 'absent'}${value.localBin?.matchesRuntime ? ', current' : ''})`,
264
290
  `- hooks current: ${value.hooksCurrent ? 'yes' : 'no'}`,
265
291
  `- codex hook: ${value.codexInstalled ? 'current' : 'missing/outdated'}`,
266
292
  `- claude hook: ${value.claudeInstalled ? 'current' : 'missing/outdated'}`,
293
+ `- claude version: ${value.claudeVersion || 'unknown'} (${value.claudeModernHooks ? 'modern hooks' : 'compatible hooks'})`,
294
+ `- claude unsupported kit hooks: ${(value.claudeUnsupportedKitEvents || []).join(', ') || 'none'}`,
267
295
  `- project applied runtime: ${project.lastRuntimeVersionApplied || 'unknown'}`,
268
296
  `- project templates current: ${project.managedFilesCurrent ? 'yes' : 'no'}`,
269
297
  `- project auto-updateable rules: ${autoUpdateCount}`,
package/src/doctor.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { spawnSync } from 'child_process';
2
- import { join } from 'path';
2
+ import { dirname, join } from 'path';
3
3
  import { mkdtemp } from 'fs/promises';
4
4
  import { tmpdir } from 'os';
5
+ import { fileURLToPath } from 'url';
5
6
  import { exists, kitDataDir } from './fs-utils.js';
6
7
  import { status } from './install.js';
8
+ import { isWindows } from './platform.js';
7
9
 
8
10
  function nodeMajor() {
9
11
  return Number.parseInt(process.versions.node.split('.')[0], 10);
@@ -21,9 +23,15 @@ export async function runDoctor(options = {}) {
21
23
  add('command-path', 'llm-wiki command resolves to current runtime', stat.commandMatchesRuntime, stat.commandPath ? `command=${stat.commandPath}; runtime=${stat.binPath}` : 'command not found on PATH');
22
24
  add('codex-hook', 'Codex hook installed', stat.codexInstalled, stat.codexHooksPath);
23
25
  add('claude-hook', 'Claude hook installed', stat.claudeInstalled, stat.claudeSettingsPath);
26
+ add(
27
+ 'claude-settings-compatible',
28
+ 'Claude hook settings compatible',
29
+ (stat.claudeUnsupportedKitEvents || []).length === 0,
30
+ `version=${stat.claudeVersion || 'unknown'}; unsupported=${(stat.claudeUnsupportedKitEvents || []).join(', ') || 'none'}`
31
+ );
24
32
  add('project-templates', 'project templates current', stat.project.managedFilesCurrent, stat.project.statePath);
25
- add('codex-command', 'codex command available', spawnSync('codex', ['--version'], { encoding: 'utf8' }).status === 0, 'codex --version');
26
- add('claude-command', 'claude command available', spawnSync('claude', ['--version'], { encoding: 'utf8' }).status === 0, 'claude --version');
33
+ add('codex-command', 'codex command available', commandVersionAvailable('codex'), 'codex --version');
34
+ add('claude-command', 'claude command available', commandVersionAvailable('claude'), 'claude --version');
27
35
  add('state-writable', 'state directory writable', await canWrite(join(kitDataDir(), '.doctor')), kitDataDir());
28
36
  add('docs', 'docs present', await docsPresent(), 'README.md and docs/');
29
37
  add('sample-hook', 'sample hook roundtrip', await sampleHookRoundtrip(stat.binPath), 'UserPromptSubmit fixture');
@@ -32,8 +40,17 @@ export async function runDoctor(options = {}) {
32
40
  return { ok: allOk, checks, workspace: stat.workspace, status: stat };
33
41
  }
34
42
 
43
+ function commandVersionAvailable(command) {
44
+ const result = spawnSync(command, ['--version'], {
45
+ encoding: 'utf8',
46
+ shell: isWindows(),
47
+ timeout: 10000,
48
+ });
49
+ return result.status === 0;
50
+ }
51
+
35
52
  async function docsPresent() {
36
- const root = new URL('..', import.meta.url).pathname;
53
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
37
54
  return (await exists(join(root, 'README.md'))) &&
38
55
  (await exists(join(root, 'docs', 'concepts.md'))) &&
39
56
  (await exists(join(root, 'docs', 'security.md')));
@@ -99,19 +116,24 @@ function failed(result, id) {
99
116
 
100
117
  function doctorRemediation(result) {
101
118
  const workspace = result.workspace || process.cwd();
119
+ const windows = isWindows({ platform: result.status?.platform });
102
120
  const suggestions = [];
103
121
  if (failed(result, 'install-source')) {
104
122
  suggestions.push(`normal install: npm install -g llm-wiki-kit@latest && llm-wiki install --workspace ${workspace} --profile standard`);
105
- suggestions.push(`source checkout development: ./install.sh --workspace ${workspace} --profile standard`);
123
+ suggestions.push(windows
124
+ ? `source checkout development: node bin\\llm-wiki.js install --workspace ${workspace} --profile standard`
125
+ : `source checkout development: ./install.sh --workspace ${workspace} --profile standard`);
106
126
  }
107
127
  if (failed(result, 'command-path')) {
108
128
  const local = result.status?.localBin;
109
- if (result.status?.installSource === 'npm' && local?.exists && local.managed) {
129
+ if (!windows && result.status?.installSource === 'npm' && local?.exists && local.managed) {
110
130
  suggestions.push(`remove stale managed local shim if it still shadows npm: rm -f ${local.path} && hash -r`);
111
131
  }
112
- suggestions.push(`reconnect command and hooks: llm-wiki install --workspace ${workspace} --profile standard`);
132
+ suggestions.push(windows
133
+ ? `reinstall npm shim and hooks: npm install -g llm-wiki-kit@latest && llm-wiki install --workspace ${workspace} --profile standard`
134
+ : `reconnect command and hooks: llm-wiki install --workspace ${workspace} --profile standard`);
113
135
  }
114
- if (failed(result, 'codex-hook') || failed(result, 'claude-hook')) {
136
+ if (failed(result, 'codex-hook') || failed(result, 'claude-hook') || failed(result, 'claude-settings-compatible')) {
115
137
  suggestions.push(`install hooks: llm-wiki install --workspace ${workspace} --profile standard, then restart Codex/Claude Code sessions`);
116
138
  }
117
139
  if (failed(result, 'project-templates')) {