@hippo-memo/cli 1.0.2 → 1.0.4

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.
@@ -0,0 +1,21 @@
1
+ # 🧠 Hippo Memory
2
+
3
+ **hippo-memory** 是项目的持久记忆层 skill,用于存储用户偏好、项目上下文、技术决策等跨会话信息。
4
+
5
+ ## ⚡ 会话启动
6
+
7
+ **每次新会话必须检索系统引导记忆,了解用户偏好、项目上下文和核心配置。**
8
+
9
+ ## 🎯 调用指南
10
+
11
+ **触发场景:**
12
+ - 用户询问或提及任何可被记忆的信息(偏好、配置、决策、历史、上下文等)
13
+ - 关键词命中:我/我的/习惯/喜欢/选择/决定/记住/保存/my/I prefer/remember/save/previous/architecture/config/settings/架构/配置/规范
14
+ - 用户透露任何可存储的信息(新的偏好、决策、习惯、技术选型等)
15
+ - 回答涉及用户私有信息时需要验证
16
+
17
+ **核心原则:**
18
+ - 涉及用户私有信息时,必须先检索记忆,禁止猜测
19
+ - 用户透露新信息时,立即存储到记忆
20
+
21
+ ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hippo-memory
3
- description: 【必须主动判定触发】每当用户透露偏好、约定、决策时立即存储。主动触发场景:①用户说"记住"、"记录"、"我习惯" ②发现项目决策/架构约定 ③用户表达偏好"我喜欢/我不用/我不喜欢" ④重复出现的信息应缓存。
3
+ description: "🧠 Persistent memory layer. ALWAYS ACTIVE: (1) SEARCH when user asks about memorable info, (2) STORE when user reveals storable info. Keywords: 我/我的/习惯/喜欢/选择/决定/记住/保存/my/I prefer/remember/save/previous/architecture/config/架构/配置. Never guess without searching."
4
4
  ---
5
5
 
6
6
  # Hippo Memory Skill
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hippo-memo/cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "hippo": "./dist/index.js"
package/src/api/server.ts CHANGED
@@ -1,4 +1,5 @@
1
- import path, { join } from "node:path";
1
+ import { dirname, join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
2
3
  import type { MemoryStore } from "@hippo-memo/core";
3
4
  import { serve } from "@hono/node-server";
4
5
  import { serveStatic } from "@hono/node-server/serve-static";
@@ -7,7 +8,8 @@ import { setupApiRoutes } from "./router";
7
8
 
8
9
  export function createServer(store: MemoryStore) {
9
10
  const app = new Hono();
10
- const webDist = process.env.WEB_DIST || join(__dirname, "../../dist");
11
+ const currentDir = dirname(fileURLToPath(import.meta.url));
12
+ const webDist = process.env.WEB_DIST || currentDir;
11
13
  setupApiRoutes(app, store);
12
14
  app.get("/*", serveStatic({ root: webDist }));
13
15
  app.get("*", serveStatic({ path: join(webDist, "index.html") }));
@@ -7,15 +7,21 @@ import {
7
7
  writeFile
8
8
  } from "node:fs/promises";
9
9
  import { EOL } from "node:os";
10
- import { join } from "node:path";
10
+ import { dirname, join } from "node:path";
11
+ import { fileURLToPath } from "node:url";
11
12
  import { createConfig, createStore } from "@hippo-memo/core";
12
13
  import { MEMORY_DIR_NAME } from "@hippo-memo/shared";
13
14
  import prompts from "prompts";
14
15
 
15
- const __dirname = import.meta.dirname;
16
- const TEMPLATE_DIR = join(__dirname, "../../template/system");
17
- const AGENTS_TEMPLATE_PATH = join(__dirname, "../../template/mcp/AGENTS.md");
18
- const SKILL_TEMPLATE_DIR = join(__dirname, "../../template/skill");
16
+ const currentDir = dirname(fileURLToPath(import.meta.url));
17
+ const TEMPLATE_DIR = join(currentDir, "./template/system");
18
+ const MCP_AGENTS_TEMPLATE_PATH = join(currentDir, "./template/mcp/AGENTS.md");
19
+ const SKILL_AGENTS_TEMPLATE_PATH = join(
20
+ currentDir,
21
+ "./template/skill/AGENTS.md"
22
+ );
23
+
24
+ const SKILL_TEMPLATE_DIR = join(currentDir, "./template/skill");
19
25
 
20
26
  const TEMPLATE_URIS = {
21
27
  agent: "system://agent",
@@ -87,7 +93,11 @@ async function injectToTopOfFile(
87
93
  /**
88
94
  * 检测并处理 AGENTS.md 和 CLAUDE.md 文件
89
95
  */
90
- async function handleAgentsAndClaudeFiles(directory: string): Promise<void> {
96
+ async function handleAgentsAndClaudeFiles(
97
+ directory: string,
98
+ templatePath: string,
99
+ mode: InitMode
100
+ ): Promise<void> {
91
101
  const agentsPath = join(directory, "AGENTS.md");
92
102
  const claudePath = join(directory, "CLAUDE.md");
93
103
 
@@ -108,7 +118,8 @@ async function handleAgentsAndClaudeFiles(directory: string): Promise<void> {
108
118
  // CLAUDE.md 不存在
109
119
  }
110
120
 
111
- const agentsContent = await readFile(AGENTS_TEMPLATE_PATH, "utf-8");
121
+ const agentsContent = await readFile(templatePath, "utf-8");
122
+ const configName = mode === "mcp" ? "MCP" : "Skill";
112
123
 
113
124
  if (hasClaude) {
114
125
  console.log("› Found: CLAUDE.md");
@@ -121,10 +132,15 @@ async function handleAgentsAndClaudeFiles(directory: string): Promise<void> {
121
132
  const response = await prompts({
122
133
  type: "confirm",
123
134
  name: "inject",
124
- message: "Inject MCP configuration to CLAUDE.md?",
135
+ message: `Inject ${configName} configuration to CLAUDE.md?`,
125
136
  initial: true
126
137
  });
127
138
 
139
+ if (response.inject === undefined) {
140
+ // 用户按下 Ctrl+C 取消
141
+ process.exit(0);
142
+ }
143
+
128
144
  if (response.inject) {
129
145
  await injectToTopOfFile(claudePath, agentsContent);
130
146
  } else {
@@ -143,10 +159,15 @@ async function handleAgentsAndClaudeFiles(directory: string): Promise<void> {
143
159
  const response = await prompts({
144
160
  type: "confirm",
145
161
  name: "inject",
146
- message: "Inject MCP configuration to AGENTS.md?",
162
+ message: `Inject ${configName} configuration to AGENTS.md?`,
147
163
  initial: true
148
164
  });
149
165
 
166
+ if (response.inject === undefined) {
167
+ // 用户按下 Ctrl+C 取消
168
+ process.exit(0);
169
+ }
170
+
150
171
  if (response.inject) {
151
172
  await injectToTopOfFile(agentsPath, agentsContent);
152
173
  } else {
@@ -156,7 +177,7 @@ async function handleAgentsAndClaudeFiles(directory: string): Promise<void> {
156
177
  console.log("› Skipped: content already exists");
157
178
  }
158
179
  } else {
159
- console.log("✔ Created: AGENTS.md");
180
+ console.log(`✔ Created: AGENTS.md`);
160
181
  await writeFile(agentsPath, agentsContent, "utf-8");
161
182
  }
162
183
  }
@@ -200,6 +221,11 @@ async function copySkillTemplates(directory: string): Promise<void> {
200
221
  initial: false
201
222
  });
202
223
 
224
+ if (response.overwrite === undefined) {
225
+ // 用户按下 Ctrl+C 取消
226
+ process.exit(0);
227
+ }
228
+
203
229
  if (!response.overwrite) {
204
230
  console.log(`› Skipped: ${skill}`);
205
231
  continue;
@@ -237,7 +263,12 @@ async function askInitMode(): Promise<InitMode> {
237
263
  initial: 1
238
264
  });
239
265
 
240
- return (response.mode as InitMode) || "skill";
266
+ if (!response.mode) {
267
+ // 用户取消输入(Ctrl+C 或 Esc)
268
+ process.exit(0);
269
+ }
270
+
271
+ return response.mode as InitMode;
241
272
  }
242
273
 
243
274
  export async function init(directory: string): Promise<void> {
@@ -270,7 +301,7 @@ export async function init(directory: string): Promise<void> {
270
301
  // 处理 MCP 配置 (注入到 AGENTS.md/CLAUDE.md)
271
302
  if (mode === "mcp") {
272
303
  console.log(`${EOL}◇ Setting up MCP integration...`);
273
- await handleAgentsAndClaudeFiles(directory);
304
+ await handleAgentsAndClaudeFiles(directory, MCP_AGENTS_TEMPLATE_PATH, mode);
274
305
  console.log(`${EOL}✨ Setup complete!${EOL}`);
275
306
  console.log("📌 Next steps:");
276
307
  console.log(" 1. Configure MCP server in Claude Code settings");
@@ -281,12 +312,18 @@ export async function init(directory: string): Promise<void> {
281
312
  // 处理 Skill 配置
282
313
  if (mode === "skill") {
283
314
  console.log(`${EOL}◇ Installing Claude Code Skills...`);
315
+ await handleAgentsAndClaudeFiles(
316
+ directory,
317
+ SKILL_AGENTS_TEMPLATE_PATH,
318
+ mode
319
+ );
284
320
  await copySkillTemplates(directory);
285
321
  console.log(`${EOL}✨ Setup complete!${EOL}`);
286
322
  console.log("📌 Next steps:");
287
323
  console.log(" 1. Skills installed in .claude/skills/");
288
- console.log(" 2. LLM will automatically trigger when needed");
289
- console.log(" 3. Commit to Git to share with your team");
324
+ console.log(" 2. Configuration injected to CLAUDE.md");
325
+ console.log(" 3. LLM will automatically trigger when needed");
326
+ console.log(" 4. Commit to Git to share with your team");
290
327
  console.log("");
291
328
  }
292
329
  }