@fugui200/llmwiki 0.1.2-beta.0 → 0.1.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,9 +51,9 @@ llmwiki push "archive: update project notes"
51
51
 
52
52
  ## Agents
53
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.
54
+ - `codex`: writes `.llmwiki.json`, installs a global Codex hook, and installs `llmwiki-connector` to `$HOME/.codex/skills/`.
55
+ - `claude-code`: writes `.claude/settings.json` plus a lightweight `CLAUDE.md` block, and installs `llmwiki-connector` to `$HOME/.claude/skills/`.
56
+ - `gemini`: writes a lightweight `GEMINI.md` block, and installs `llmwiki-connector` to `$HOME/.gemini/skills/`.
57
57
  - `all`: configures all supported agents.
58
58
 
59
59
  Agent integrations only inject routing metadata and recall rules. They do not
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fugui200/llmwiki",
3
- "version": "0.1.2-beta.0",
3
+ "version": "0.1.2-beta.1",
4
4
  "description": "Project-scoped LLM wiki CLI for Codex, Claude Code, and Gemini",
5
5
  "bin": {
6
6
  "llmwiki": "bin/llmwiki.js"
@@ -77,6 +77,7 @@ function buildAdditionalContext(cwd) {
77
77
  'Use this as routing metadata only. Do not read or load global LLM Wiki pages at startup, after /clear, or for ordinary prompts.',
78
78
  'Search/read wiki pages only when the user asks to recall/archive knowledge, or when the current task clearly needs prior project context.',
79
79
  'When recall is needed, prefer current archiveProjects first; use shared patterns/tools/concepts only after keyword matching.',
80
+ 'When the user asks to archive to llmwiki or 沉淀到 llmwiki, use the llmwiki-connector skill and the configured wikiRoot; do not route that task to OMX wiki.',
80
81
  ];
81
82
 
82
83
  if (legacyTargets.length) {
@@ -16,10 +16,11 @@
16
16
  const fs = require('fs');
17
17
  const os = require('os');
18
18
  const path = require('path');
19
- const { writeProjectConfig, writeWorkspaceConfig } = require('./classify-project');
19
+ const { resolveWikiRoot, writeProjectConfig, writeWorkspaceConfig } = require('./classify-project');
20
20
 
21
21
  const LLMWIKI_CONTEXT_BLOCK_START = '<!-- LLMWIKI:START -->';
22
22
  const LLMWIKI_CONTEXT_BLOCK_END = '<!-- LLMWIKI:END -->';
23
+ const CONNECTOR_SKILL_NAME = 'llmwiki-connector';
23
24
  const STOP_HOOK_COMMAND = [
24
25
  'if [ -d ~/.llmwiki/.git ]; then',
25
26
  'echo \'[LLM Wiki] 如果本次工作产出了新知识',
@@ -99,9 +100,9 @@ function showInitHelp() {
99
100
  console.log(' 为当前项目导入指定 Agent 的 LLM Wiki 接入配置。');
100
101
  console.log('');
101
102
  console.log('Agent:');
102
- console.log(' claude-code 写入 .claude/settings.json hooks');
103
- console.log(' codex 写入 .llmwiki.json 项目标记,并安装全局 Codex hooks');
104
- console.log(' gemini 写入 GEMINI.md 项目上下文入口');
103
+ console.log(' claude-code 写入 .claude/settings.json hooks,并安装 $HOME/.claude/skills/llmwiki-connector');
104
+ console.log(' codex 写入 .llmwiki.json、全局 hook,并安装 $HOME/.codex/skills/llmwiki-connector');
105
+ console.log(' gemini 写入 GEMINI.md,并安装 $HOME/.gemini/skills/llmwiki-connector');
105
106
  console.log(' all 同时导入 claude-code、codex、gemini');
106
107
  console.log('');
107
108
  console.log('选项:');
@@ -348,6 +349,14 @@ function defaultWikiRootForProfile(profile) {
348
349
  return '~/.llmwiki';
349
350
  }
350
351
 
352
+ function ensureTeamWikiRoot(config, configDir) {
353
+ if (config.profile !== 'team') return null;
354
+
355
+ const wikiRoot = resolveWikiRoot(config, configDir);
356
+ fs.mkdirSync(wikiRoot, { recursive: true });
357
+ return wikiRoot;
358
+ }
359
+
351
360
  async function promptInteractiveConfig(args, input = process.stdin, output = process.stdout) {
352
361
  if (!input.isTTY || !output.isTTY) return args;
353
362
 
@@ -470,6 +479,7 @@ function installClaudeCode(projectRoot) {
470
479
  const claudeDir = path.join(projectRoot, '.claude');
471
480
  const settingsPath = path.join(claudeDir, 'settings.json');
472
481
  const claudePath = path.join(projectRoot, 'CLAUDE.md');
482
+ const skillResult = installConnectorSkill(path.join(resolveClaudeHome(), 'skills'));
473
483
  fs.mkdirSync(claudeDir, { recursive: true });
474
484
 
475
485
  let settings = {};
@@ -486,10 +496,12 @@ function installClaudeCode(projectRoot) {
486
496
 
487
497
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, '\t') + '\n');
488
498
  console.log(`✓ Claude Code hook/context 已${stopStatus === 'updated' ? '更新' : '导入'}: .claude/settings.json, CLAUDE.md`);
499
+ logSkillResult('Claude Code', skillResult);
489
500
  }
490
501
 
491
502
  function installCodex(projectRoot) {
492
503
  const result = installCodexGlobalHooks();
504
+ const skillResult = installCodexSkill();
493
505
  console.log('✓ Codex 接入已标记: .llmwiki.json');
494
506
  if (result.status === 'installed') {
495
507
  console.log(`✓ Codex 全局 hook 已写入: ${result.hooksPath}`);
@@ -500,13 +512,85 @@ function installCodex(projectRoot) {
500
512
  } else {
501
513
  console.log(`⚠ Codex 全局 hook 未写入: ${result.reason}`);
502
514
  }
515
+ if (skillResult.status === 'installed') {
516
+ console.log(`✓ Codex skill 已安装: ${skillResult.skillPath}`);
517
+ } else if (skillResult.status === 'updated') {
518
+ console.log(`✓ Codex skill 已更新: ${skillResult.skillPath}`);
519
+ } else {
520
+ console.log(`⚠ Codex skill 未安装: ${skillResult.reason}`);
521
+ }
503
522
  console.log(' Codex hook 只注入项目归属元数据;需要召回时再按需读取 wiki。');
504
523
  }
505
524
 
506
525
  function resolveCodexHome() {
507
- return process.env.CODEX_HOME
508
- ? path.resolve(process.env.CODEX_HOME)
509
- : path.join(os.homedir(), '.codex');
526
+ return path.join(resolveUserHome(), '.codex');
527
+ }
528
+
529
+ function resolveClaudeHome() {
530
+ return path.join(resolveUserHome(), '.claude');
531
+ }
532
+
533
+ function resolveGeminiHome() {
534
+ return path.join(resolveUserHome(), '.gemini');
535
+ }
536
+
537
+ function resolveUserHome() {
538
+ return process.env.HOME ? path.resolve(process.env.HOME) : os.homedir();
539
+ }
540
+
541
+ function copyDirectory(src, dest) {
542
+ fs.mkdirSync(dest, { recursive: true });
543
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
544
+ const from = path.join(src, entry.name);
545
+ const to = path.join(dest, entry.name);
546
+ if (entry.isDirectory()) {
547
+ copyDirectory(from, to);
548
+ } else if (entry.isFile()) {
549
+ fs.copyFileSync(from, to);
550
+ }
551
+ }
552
+ }
553
+
554
+ function installConnectorSkill(skillsRoot) {
555
+ const skillSource = path.join(__dirname, '..', 'skill', CONNECTOR_SKILL_NAME);
556
+ const skillPath = path.join(skillsRoot, CONNECTOR_SKILL_NAME);
557
+
558
+ try {
559
+ if (!fs.existsSync(skillSource)) {
560
+ return {
561
+ status: 'failed',
562
+ skillPath,
563
+ reason: `skill 源目录不存在: ${skillSource}`,
564
+ };
565
+ }
566
+
567
+ const existed = fs.existsSync(skillPath);
568
+ copyDirectory(skillSource, skillPath);
569
+ return {
570
+ status: existed ? 'updated' : 'installed',
571
+ skillPath,
572
+ };
573
+ } catch (error) {
574
+ return {
575
+ status: 'failed',
576
+ skillPath,
577
+ reason: error.message,
578
+ };
579
+ }
580
+ }
581
+
582
+ function installCodexSkill() {
583
+ return installConnectorSkill(path.join(resolveCodexHome(), 'skills'));
584
+ }
585
+
586
+ function logSkillResult(agentName, result) {
587
+ if (result.status === 'installed') {
588
+ console.log(`✓ ${agentName} skill 已安装: ${result.skillPath}`);
589
+ } else if (result.status === 'updated') {
590
+ console.log(`✓ ${agentName} skill 已更新: ${result.skillPath}`);
591
+ } else {
592
+ console.log(`⚠ ${agentName} skill 未安装: ${result.reason}`);
593
+ }
510
594
  }
511
595
 
512
596
  function buildCodexHookCommand() {
@@ -585,8 +669,10 @@ function installCodexGlobalHooks() {
585
669
 
586
670
  function installGemini(projectRoot) {
587
671
  const geminiPath = path.join(projectRoot, 'GEMINI.md');
672
+ const skillResult = installConnectorSkill(path.join(resolveGeminiHome(), 'skills'));
588
673
  upsertContextBlock(geminiPath);
589
674
  console.log('✓ Gemini context 已导入: GEMINI.md');
675
+ logSkillResult('Gemini', skillResult);
590
676
  }
591
677
 
592
678
  function expandAgent(agent) {
@@ -634,22 +720,26 @@ async function main() {
634
720
 
635
721
  if (args.workspace) {
636
722
  const { configPath, config } = writeWorkspaceConfig(projectRoot, configOptions);
723
+ const createdWikiRoot = ensureTeamWikiRoot(config, projectRoot);
637
724
  console.log(`✓ workspace 配置已写入 ${path.relative(projectRoot, configPath)}`);
638
725
  console.log(` - workspace: ${config.name}`);
639
726
  console.log(` - profile: ${config.profile}`);
640
727
  console.log(` - wikiRoot: ${config.wikiRoot}`);
641
728
  console.log(` - sync: ${config.sync.type}${config.sync.branch ? ` ${config.sync.branch}` : ''}`);
642
729
  console.log(` - projects: ${Object.keys(config.projectRoots).join(', ') || '(none detected)'}`);
730
+ if (createdWikiRoot) console.log(`✓ team wikiRoot 已创建: ${createdWikiRoot}`);
643
731
  wikiConfigWritten = true;
644
732
  return;
645
733
  }
646
734
 
647
735
  const { configPath, config } = writeProjectConfig(projectRoot, configOptions);
736
+ const createdWikiRoot = ensureTeamWikiRoot(config, projectRoot);
648
737
  console.log(`✓ project 配置已写入 ${path.relative(projectRoot, configPath)}`);
649
738
  console.log(` - project: ${config.name}`);
650
739
  console.log(` - profile: ${config.profile}`);
651
740
  console.log(` - wikiRoot: ${config.wikiRoot}`);
652
741
  console.log(` - sync: ${config.sync.type}${config.sync.branch ? ` ${config.sync.branch}` : ''}`);
742
+ if (createdWikiRoot) console.log(`✓ team wikiRoot 已创建: ${createdWikiRoot}`);
653
743
  wikiConfigWritten = true;
654
744
  };
655
745
 
@@ -113,7 +113,7 @@ llmwiki init --agent gemini
113
113
  llmwiki init --agent all
114
114
  ```
115
115
 
116
- `llmwiki init` 在交互终端中会依次询问 agent、是否 workspace、profile(personal/team/local)和 wikiRoot;非交互环境必须显式传参。`claude-code` 写入 `.claude/settings.json` 归档提醒 hook,并在 `CLAUDE.md` 写入按需召回规则;`codex` 写入 `.llmwiki.json` 项目标记并安装全局 Codex hooks;`gemini` 写入 `GEMINI.md` 项目上下文入口;`all` 同时导入三者。三种接入默认只使用项目归属元数据和按需召回规则,不在启动、`/clear` 或普通提问时自动加载全局 wiki 页面。
116
+ `llmwiki init` 在交互终端中会依次询问 agent、是否 workspace、profile(personal/team/local)和 wikiRoot;非交互环境必须显式传参。`claude-code` 写入 `.claude/settings.json` 归档提醒 hook、`CLAUDE.md` 按需召回规则,并安装 `$HOME/.claude/skills/llmwiki-connector`;`codex` 写入 `.llmwiki.json` 项目标记、全局 Codex hooks,并安装 `$HOME/.codex/skills/llmwiki-connector`;`gemini` 写入 `GEMINI.md` 项目上下文入口,并安装 `$HOME/.gemini/skills/llmwiki-connector`;`all` 同时导入三者。三种接入默认只使用项目归属元数据和按需召回规则,不在启动、`/clear` 或普通提问时自动加载全局 wiki 页面。
117
117
 
118
118
  ## 注意事项
119
119