@fugui200/llmwiki 0.1.2-beta.0

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,60 @@
1
+ # llmwiki
2
+
3
+ CLI for connecting AI coding agents to a project-scoped markdown knowledge base.
4
+
5
+ `llmwiki` does not upload or index your files. It writes local project markers and
6
+ agent context so Codex CLI, Claude Code, and Gemini CLI can decide when to recall
7
+ or archive wiki knowledge.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install -g @fugui200/llmwiki@beta
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Initialize the current project:
18
+
19
+ ```bash
20
+ llmwiki init
21
+ ```
22
+
23
+ Non-interactive examples:
24
+
25
+ ```bash
26
+ llmwiki init --profile personal --agent codex
27
+ llmwiki init --profile local --agent claude-code
28
+ llmwiki init --workspace --profile team --wiki-root /path/to/team-wiki --agent all
29
+ ```
30
+
31
+ Check the current project routing:
32
+
33
+ ```bash
34
+ llmwiki status
35
+ llmwiki classify
36
+ llmwiki classify path/to/file path/to/another-file
37
+ ```
38
+
39
+ Sync a git-backed wiki root:
40
+
41
+ ```bash
42
+ llmwiki pull
43
+ llmwiki push "archive: update project notes"
44
+ ```
45
+
46
+ ## Profiles
47
+
48
+ - `personal`: defaults to `~/.llmwiki`.
49
+ - `team`: requires an explicit `--wiki-root`.
50
+ - `local`: defaults to `.llmwiki-local` and disables `push`/`pull`.
51
+
52
+ ## Agents
53
+
54
+ - `codex`: writes `.llmwiki.json` and installs a global Codex hook.
55
+ - `claude-code`: writes `.claude/settings.json` plus a lightweight `CLAUDE.md` block.
56
+ - `gemini`: writes a lightweight `GEMINI.md` block.
57
+ - `all`: configures all supported agents.
58
+
59
+ Agent integrations only inject routing metadata and recall rules. They do not
60
+ load the whole wiki on every prompt.
package/bin/llmwiki.js ADDED
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { execFileSync, execSync } = require('child_process');
7
+
8
+ const HOME = require('os').homedir();
9
+ const LLMWIKI_DIR = process.env.LLMWIKI_DIR
10
+ ? path.resolve(process.env.LLMWIKI_DIR)
11
+ : path.join(HOME, '.llmwiki');
12
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
13
+ const PKG_JSON = path.resolve(__dirname, '..', 'package.json');
14
+
15
+ function resolveRuntimeRoot() {
16
+ if (fs.existsSync(path.join(PACKAGE_ROOT, 'scripts', 'init-project.js'))) return PACKAGE_ROOT;
17
+ if (fs.existsSync(path.join(LLMWIKI_DIR, 'scripts', 'init-project.js'))) return LLMWIKI_DIR;
18
+ return LLMWIKI_DIR;
19
+ }
20
+
21
+ const RUNTIME_ROOT = resolveRuntimeRoot();
22
+
23
+ async function main() {
24
+ const args = process.argv.slice(2);
25
+
26
+ if (args[0] === '--version' || args[0] === '-v') {
27
+ const pkg = JSON.parse(fs.readFileSync(PKG_JSON, 'utf8'));
28
+ console.log(pkg.version);
29
+ } else if (!args[0] || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
30
+ showHelp();
31
+ } else if (args[0] === 'init') {
32
+ if (isHelpArg(args[1])) {
33
+ showInitHelp();
34
+ } else {
35
+ await initProject();
36
+ }
37
+ } else if (args[0] === 'classify') {
38
+ classifyProject(args.slice(1));
39
+ } else if (args[0] === 'status') {
40
+ showStatus();
41
+ } else if (args[0] === 'push') {
42
+ pushWiki(args.slice(1).join(' '));
43
+ } else if (args[0] === 'pull') {
44
+ pullWiki();
45
+ } else {
46
+ showHelp();
47
+ }
48
+ }
49
+
50
+ function isHelpArg(arg) {
51
+ return arg === 'help' || arg === '--help' || arg === '-h';
52
+ }
53
+
54
+ function showHelp() {
55
+ console.log('用法: llmwiki <command>');
56
+ console.log('');
57
+ console.log('命令:');
58
+ console.log(' init [options] 交互式导入 Agent、workspace/profile/wikiRoot 配置');
59
+ console.log(' classify [paths...] 根据 .llmwiki.json 判断归档项目归属');
60
+ console.log(' status 显示当前项目的 wiki 同步边界');
61
+ console.log(' push [msg] 提交并推送当前 wikiRoot 的变更');
62
+ console.log(' pull 拉取当前 wikiRoot 的最新内容');
63
+ console.log(' help 显示帮助信息');
64
+ console.log('');
65
+ console.log('Profile:');
66
+ console.log(' personal 个人知识库,默认 wikiRoot=~/.llmwiki');
67
+ console.log(' team 公司或团队共享知识库,必须显式指定 --wiki-root');
68
+ console.log(' local 仅本地沉淀,不允许 push/pull');
69
+ console.log('');
70
+ console.log('选项:');
71
+ console.log(' --version, -v 显示版本号');
72
+ }
73
+
74
+ function showInitHelp() {
75
+ console.log('用法: llmwiki init [--workspace] [--profile personal|team|local] [--wiki-root <path>] [--agent <agent>]');
76
+ console.log('');
77
+ console.log('说明:');
78
+ console.log(' 为当前项目导入指定 Agent 的 LLM Wiki 接入配置。');
79
+ console.log('');
80
+ console.log('Agent:');
81
+ console.log(' claude-code 写入 .claude/settings.json hooks');
82
+ console.log(' codex 写入 .llmwiki.json 项目标记,并安装全局 Codex hooks');
83
+ console.log(' gemini 写入 GEMINI.md 项目上下文入口');
84
+ console.log(' all 同时导入 claude-code、codex、gemini');
85
+ console.log('');
86
+ console.log('选项:');
87
+ console.log(' --workspace 生成 workspace 配置 .llmwiki.json,用于多子项目归属判断');
88
+ console.log(' --profile 设置知识库同步边界: personal | team | local');
89
+ console.log(' --wiki-root 设置当前项目使用的物理 wiki 根目录');
90
+ console.log(' --branch 设置 git 同步分支,默认 main');
91
+ console.log(' --help, -h 显示 init 帮助信息');
92
+ }
93
+
94
+ function loadClassifier() {
95
+ const classifier = path.join(RUNTIME_ROOT, 'scripts', 'classify-project.js');
96
+ if (!fs.existsSync(classifier)) {
97
+ console.error('错误: classify-project.js 不存在');
98
+ console.error(`期望路径: ${classifier}`);
99
+ process.exit(1);
100
+ }
101
+ return require(classifier);
102
+ }
103
+
104
+ function classifyProject(paths) {
105
+ const { classifyFromCwd } = loadClassifier();
106
+ const result = classifyFromCwd({ paths });
107
+ console.log(JSON.stringify(result, null, 2));
108
+ }
109
+
110
+ function defaultWikiContext(cwd = process.cwd()) {
111
+ const config = {
112
+ type: 'project',
113
+ name: 'default',
114
+ profile: 'personal',
115
+ wikiRoot: '~/.llmwiki',
116
+ sync: {
117
+ type: 'git',
118
+ branch: 'main',
119
+ },
120
+ };
121
+ return {
122
+ cwd,
123
+ config,
124
+ configDir: cwd,
125
+ configPath: null,
126
+ classification: {
127
+ workspace: null,
128
+ matchedProjects: [],
129
+ archiveProjects: [],
130
+ archiveType: 'unconfigured',
131
+ suggestedPath: null,
132
+ },
133
+ wikiRoot: LLMWIKI_DIR,
134
+ };
135
+ }
136
+
137
+ function getWikiContext(cwd = process.cwd()) {
138
+ const {
139
+ classifyConfig,
140
+ findEffectiveConfig,
141
+ resolveWikiRoot,
142
+ } = loadClassifier();
143
+ const match = findEffectiveConfig(cwd);
144
+ if (!match) return defaultWikiContext(cwd);
145
+
146
+ return {
147
+ cwd,
148
+ config: match.config,
149
+ configDir: match.dir,
150
+ configPath: match.path,
151
+ classification: classifyConfig(match.config, match.dir, { cwd }),
152
+ wikiRoot: resolveWikiRoot(match.config, match.dir),
153
+ };
154
+ }
155
+
156
+ function formatSync(sync = {}) {
157
+ if (sync.type === 'none') return 'none';
158
+ return `${sync.type || 'git'} ${sync.branch || 'main'}`;
159
+ }
160
+
161
+ function showStatus() {
162
+ const context = getWikiContext();
163
+ const { config, classification } = context;
164
+ const project = (classification.archiveProjects || [])[0] || config.name || '(none)';
165
+ console.log(`project: ${project}`);
166
+ console.log(`profile: ${config.profile || 'personal'}`);
167
+ console.log(`wikiRoot: ${context.wikiRoot}`);
168
+ console.log(`sync: ${formatSync(config.sync)}`);
169
+ console.log(`archiveTarget: ${classification.suggestedPath || '(none)'}`);
170
+ }
171
+
172
+ function ensureGitSync(context) {
173
+ const sync = context.config.sync || { type: 'git', branch: 'main' };
174
+ if (sync.type === 'none') {
175
+ console.error('错误: 当前 wiki 实例未启用 git 同步');
176
+ console.error(`wikiRoot: ${context.wikiRoot}`);
177
+ console.error(`profile: ${context.config.profile || 'personal'}`);
178
+ process.exit(1);
179
+ }
180
+ return {
181
+ type: sync.type || 'git',
182
+ branch: sync.branch || 'main',
183
+ };
184
+ }
185
+
186
+ function pullWiki() {
187
+ const context = getWikiContext();
188
+ const sync = ensureGitSync(context);
189
+ if (!fs.existsSync(path.join(context.wikiRoot, '.git'))) {
190
+ console.error(`错误: ${context.wikiRoot} 不是 git 仓库`);
191
+ process.exit(1);
192
+ }
193
+ console.log(`wikiRoot: ${context.wikiRoot}`);
194
+ console.log(`profile: ${context.config.profile || 'personal'}`);
195
+ console.log(`sync: ${formatSync(sync)}`);
196
+ execFileSync('git', ['pull', '--rebase', 'origin', sync.branch], { cwd: context.wikiRoot, stdio: 'inherit' });
197
+ }
198
+
199
+ function pushWiki(msg) {
200
+ const context = getWikiContext();
201
+ const sync = ensureGitSync(context);
202
+ if (!fs.existsSync(path.join(context.wikiRoot, '.git'))) {
203
+ console.error(`错误: ${context.wikiRoot} 不是 git 仓库`);
204
+ process.exit(1);
205
+ }
206
+
207
+ const status = execSync('git status --porcelain', { cwd: context.wikiRoot, encoding: 'utf8' });
208
+ if (!status.trim()) {
209
+ console.log('没有需要提交的变更。');
210
+ return;
211
+ }
212
+
213
+ const commitMsg = msg || '[archive] wiki update';
214
+ console.log(`wikiRoot: ${context.wikiRoot}`);
215
+ console.log(`profile: ${context.config.profile || 'personal'}`);
216
+ console.log(`sync: ${formatSync(sync)}`);
217
+ console.log(`变更文件:\n${status}`);
218
+ console.log(`提交信息: ${commitMsg}`);
219
+
220
+ execFileSync('git', ['add', '-A'], { cwd: context.wikiRoot, stdio: 'inherit' });
221
+ execFileSync('git', ['commit', '-m', commitMsg], { cwd: context.wikiRoot, stdio: 'inherit' });
222
+ execFileSync('git', ['push', 'origin', sync.branch], { cwd: context.wikiRoot, stdio: 'inherit' });
223
+
224
+ console.log('推送完成。');
225
+ }
226
+
227
+ async function initProject() {
228
+ if (!fs.existsSync(RUNTIME_ROOT)) {
229
+ console.error('错误: ~/.llmwiki 不存在');
230
+ console.error('');
231
+ console.error('解决方法:');
232
+ console.error(' npm install -g llmwiki@beta');
233
+ console.error(' 或设置 LLMWIKI_DIR=/path/to/llmwiki-runtime');
234
+ process.exit(1);
235
+ }
236
+
237
+ const initScript = path.join(RUNTIME_ROOT, 'scripts', 'init-project.js');
238
+ if (fs.existsSync(initScript)) {
239
+ const init = require(initScript);
240
+ await init.main();
241
+ } else {
242
+ console.error('错误: init-project.js 不存在');
243
+ console.error(`期望路径: ${initScript}`);
244
+ process.exit(1);
245
+ }
246
+ }
247
+
248
+ main().catch(error => {
249
+ console.error(error.message);
250
+ process.exit(1);
251
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@fugui200/llmwiki",
3
+ "version": "0.1.2-beta.0",
4
+ "description": "Project-scoped LLM wiki CLI for Codex, Claude Code, and Gemini",
5
+ "bin": {
6
+ "llmwiki": "bin/llmwiki.js"
7
+ },
8
+ "scripts": {
9
+ "test": "node --test test/*.test.js",
10
+ "wiki:lint": "node scripts/wiki-lint.js",
11
+ "wiki:overview": "node scripts/wiki-build-overview.js",
12
+ "wiki:graph": "node scripts/wiki-build-graph.js"
13
+ },
14
+ "files": [
15
+ "bin/llmwiki.js",
16
+ "scripts/classify-project.js",
17
+ "scripts/codex-hook.js",
18
+ "scripts/init-project.js",
19
+ "skill/llmwiki-connector/"
20
+ ],
21
+ "publishConfig": {
22
+ "registry": "https://registry.npmjs.org/",
23
+ "access": "public"
24
+ },
25
+ "license": "MIT",
26
+ "private": false,
27
+ "type": "commonjs"
28
+ }