metame-cli 1.1.3 → 1.2.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.
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MetaMe Pending Traits Manager
5
+ *
6
+ * Manages the accumulation and promotion of observed preferences.
7
+ * T3 fields need confidence threshold before writing to profile:
8
+ * - high confidence (strong directive / correction) → direct write
9
+ * - normal confidence → accumulate in pending, promote at count >= 3
10
+ *
11
+ * File: ~/.metame/pending_traits.yaml
12
+ * This file is system-internal, NOT injected into prompts.
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const os = require('os');
18
+
19
+ const PENDING_FILE = path.join(os.homedir(), '.metame', 'pending_traits.yaml');
20
+ const PROMOTION_THRESHOLD = 3;
21
+ const EXPIRY_DAYS = 30;
22
+
23
+ /**
24
+ * Load pending traits from disk.
25
+ * Returns plain object { 'dotted.key': { value, count, first_seen, last_seen, confidence, source_quote } }
26
+ */
27
+ function loadPending() {
28
+ try {
29
+ if (!fs.existsSync(PENDING_FILE)) return {};
30
+ const yaml = require('js-yaml');
31
+ return yaml.load(fs.readFileSync(PENDING_FILE, 'utf8')) || {};
32
+ } catch {
33
+ return {};
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Save pending traits to disk.
39
+ */
40
+ function savePending(pending) {
41
+ const yaml = require('js-yaml');
42
+ const dir = path.dirname(PENDING_FILE);
43
+ if (!fs.existsSync(dir)) {
44
+ fs.mkdirSync(dir, { recursive: true });
45
+ }
46
+ fs.writeFileSync(PENDING_FILE, yaml.dump(pending, { lineWidth: -1 }), 'utf8');
47
+ }
48
+
49
+ /**
50
+ * Upsert a trait observation into pending.
51
+ * If the value matches existing, increment count.
52
+ * If the value differs, start a new counter (contradiction).
53
+ */
54
+ function upsertPending(pending, key, value, confidence, sourceQuote) {
55
+ const today = new Date().toISOString().slice(0, 10);
56
+ const existing = pending[key];
57
+
58
+ if (existing && existing.value === value) {
59
+ // Same value observed again — increment
60
+ existing.count += 1;
61
+ existing.last_seen = today;
62
+ if (confidence === 'high') existing.confidence = 'high';
63
+ if (sourceQuote) existing.source_quote = sourceQuote;
64
+ } else if (existing && existing.value !== value) {
65
+ // Contradiction — track it but don't delete old
66
+ if (!existing.contradictions) existing.contradictions = 0;
67
+ existing.contradictions += 1;
68
+ // If contradictions outnumber original observations, replace
69
+ if (existing.contradictions >= existing.count) {
70
+ pending[key] = {
71
+ value: value,
72
+ count: 1,
73
+ first_seen: today,
74
+ last_seen: today,
75
+ confidence: confidence || 'normal',
76
+ source_quote: sourceQuote || null
77
+ };
78
+ }
79
+ } else {
80
+ // New trait
81
+ pending[key] = {
82
+ value: value,
83
+ count: 1,
84
+ first_seen: today,
85
+ last_seen: today,
86
+ confidence: confidence || 'normal',
87
+ source_quote: sourceQuote || null
88
+ };
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Get traits ready for promotion (count >= threshold OR confidence === 'high').
94
+ * Returns array of { key, value, source_quote }
95
+ */
96
+ function getPromotable(pending) {
97
+ const ready = [];
98
+ for (const [key, meta] of Object.entries(pending)) {
99
+ if (meta.count >= PROMOTION_THRESHOLD || meta.confidence === 'high') {
100
+ ready.push({ key, value: meta.value, source_quote: meta.source_quote });
101
+ }
102
+ }
103
+ return ready;
104
+ }
105
+
106
+ /**
107
+ * Remove promoted traits from pending.
108
+ */
109
+ function removePromoted(pending, keys) {
110
+ for (const key of keys) {
111
+ delete pending[key];
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Expire stale pending traits (not observed for > EXPIRY_DAYS).
117
+ * Returns number of expired entries.
118
+ */
119
+ function expireStale(pending) {
120
+ const now = Date.now();
121
+ const cutoff = EXPIRY_DAYS * 24 * 60 * 60 * 1000;
122
+ let expired = 0;
123
+
124
+ for (const [key, meta] of Object.entries(pending)) {
125
+ const lastSeen = new Date(meta.last_seen).getTime();
126
+ if (now - lastSeen > cutoff) {
127
+ delete pending[key];
128
+ expired++;
129
+ }
130
+ }
131
+ return expired;
132
+ }
133
+
134
+ module.exports = {
135
+ PENDING_FILE,
136
+ loadPending,
137
+ savePending,
138
+ upsertPending,
139
+ getPromotable,
140
+ removePromoted,
141
+ expireStale,
142
+ PROMOTION_THRESHOLD,
143
+ EXPIRY_DAYS,
144
+ };
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MetaMe Profile Schema — Field Whitelist
5
+ *
6
+ * Defines every allowed field in the profile, its tier, data type,
7
+ * and constraints. The distiller can ONLY write keys listed here.
8
+ * This is the #1 anti-bloat measure.
9
+ *
10
+ * Tiers:
11
+ * T1 — Identity (LOCKED, never auto-modify)
12
+ * T2 — Core Values (LOCKED, deep personality)
13
+ * T3 — Preferences (auto-writable, needs confidence)
14
+ * T4 — Context (free overwrite, current state)
15
+ * T5 — Evolution (system-managed, strict limits)
16
+ */
17
+
18
+ const SCHEMA = {
19
+ // === T1: Identity ===
20
+ 'identity.nickname': { tier: 'T1', type: 'string', locked: true },
21
+ 'identity.role': { tier: 'T1', type: 'string', locked: false },
22
+ 'identity.locale': { tier: 'T1', type: 'string', locked: true },
23
+
24
+ // === T2: Core Values / Traits ===
25
+ 'core_values.*': { tier: 'T2', type: 'string', locked: true },
26
+ 'core_traits.crisis_reflex': { tier: 'T2', type: 'enum', locked: true, values: ['Action', 'Analysis', 'Delegation', 'Freeze'] },
27
+ 'core_traits.flow_trigger': { tier: 'T2', type: 'enum', locked: true, values: ['Ideation', 'Execution', 'Teaching', 'Debugging'] },
28
+ 'core_traits.shadow_self': { tier: 'T2', type: 'string', locked: true, maxChars: 80 },
29
+ 'core_traits.learning_style': { tier: 'T2', type: 'enum', locked: true, values: ['Hands-on', 'Conceptual', 'Social', 'Reflective'] },
30
+ 'core_traits.north_star.aspiration': { tier: 'T2', type: 'string', locked: true, maxChars: 80 },
31
+ 'core_traits.north_star.realistic': { tier: 'T2', type: 'string', locked: true, maxChars: 80 },
32
+
33
+ // === T3: Preferences ===
34
+ 'preferences.code_style': { tier: 'T3', type: 'enum', values: ['concise', 'verbose', 'documented'] },
35
+ 'preferences.communication': { tier: 'T3', type: 'enum', values: ['direct', 'gentle', 'socratic'] },
36
+ 'preferences.language_mix': { tier: 'T3', type: 'enum', values: ['zh-only', 'en-only', 'zh-main-en-term', 'code-switch'] },
37
+ 'preferences.tech_terms_language': { tier: 'T3', type: 'enum', values: ['zh', 'en'] },
38
+ 'preferences.code_comments_language': { tier: 'T3', type: 'enum', values: ['zh', 'en', null] },
39
+ 'preferences.explanation_depth': { tier: 'T3', type: 'enum', values: ['result_only', 'brief_rationale', 'deep_dive'] },
40
+ 'preferences.interaction_tempo': { tier: 'T3', type: 'enum', values: ['batch', 'incremental'] },
41
+ 'preferences.tools': { tier: 'T3', type: 'array', maxItems: 10 },
42
+ 'preferences.anti_patterns': { tier: 'T3', type: 'array', maxItems: 5 },
43
+
44
+ // === T3b: Cognition ===
45
+ 'cognition.decision_style': { tier: 'T3', type: 'enum', values: ['intuitive', 'analytical', 'adaptive'] },
46
+ 'cognition.info_processing.entry_point': { tier: 'T3', type: 'enum', values: ['big_picture', 'details', 'examples'] },
47
+ 'cognition.info_processing.preferred_format': { tier: 'T3', type: 'enum', values: ['structured', 'narrative', 'visual_metaphor'] },
48
+ 'cognition.abstraction.default_level': { tier: 'T3', type: 'enum', values: ['strategic', 'architectural', 'implementation', 'operational'] },
49
+ 'cognition.abstraction.range': { tier: 'T3', type: 'enum', values: ['narrow', 'wide'] },
50
+ 'cognition.cognitive_load.chunk_size': { tier: 'T3', type: 'enum', values: ['small', 'medium', 'large'] },
51
+ 'cognition.cognitive_load.preferred_response_length': { tier: 'T3', type: 'enum', values: ['concise', 'moderate', 'comprehensive'] },
52
+ 'cognition.motivation.primary_driver': { tier: 'T3', type: 'enum', values: ['autonomy', 'competence', 'meaning', 'social_proof'] },
53
+ 'cognition.motivation.energy_source': { tier: 'T3', type: 'enum', values: ['creation', 'optimization', 'problem_solving', 'teaching'] },
54
+ 'cognition.metacognition.self_awareness': { tier: 'T3', type: 'enum', values: ['high', 'medium', 'low'] },
55
+ 'cognition.metacognition.receptive_to_challenge': { tier: 'T3', type: 'enum', values: ['yes', 'sometimes', 'no'] },
56
+
57
+ // === T4: Context ===
58
+ 'context.focus': { tier: 'T4', type: 'string', maxChars: 80 },
59
+ 'context.focus_since': { tier: 'T4', type: 'string' },
60
+ 'context.active_projects': { tier: 'T4', type: 'array', maxItems: 5 },
61
+ 'context.blockers': { tier: 'T4', type: 'array', maxItems: 3 },
62
+ 'context.energy': { tier: 'T4', type: 'enum', values: ['high', 'medium', 'low', null] },
63
+ 'status.focus': { tier: 'T4', type: 'string', maxChars: 80 },
64
+ 'status.language': { tier: 'T4', type: 'string' },
65
+
66
+ // === T5: Evolution (system-managed) ===
67
+ 'evolution.last_distill': { tier: 'T5', type: 'string' },
68
+ 'evolution.distill_count': { tier: 'T5', type: 'number' },
69
+ 'evolution.recent_changes': { tier: 'T5', type: 'array', maxItems: 5 },
70
+ 'evolution.auto_distill': { tier: 'T5', type: 'array', maxItems: 10 },
71
+ };
72
+
73
+ /**
74
+ * Check if a dotted key matches the schema.
75
+ * Supports wildcard entries like 'core_values.*'
76
+ */
77
+ function hasKey(key) {
78
+ if (SCHEMA[key]) return true;
79
+ // Check wildcard patterns
80
+ const parts = key.split('.');
81
+ for (let i = parts.length - 1; i >= 1; i--) {
82
+ const wildcard = parts.slice(0, i).join('.') + '.*';
83
+ if (SCHEMA[wildcard]) return true;
84
+ }
85
+ return false;
86
+ }
87
+
88
+ /**
89
+ * Get schema definition for a key (or its wildcard parent).
90
+ */
91
+ function getDefinition(key) {
92
+ if (SCHEMA[key]) return SCHEMA[key];
93
+ const parts = key.split('.');
94
+ for (let i = parts.length - 1; i >= 1; i--) {
95
+ const wildcard = parts.slice(0, i).join('.') + '.*';
96
+ if (SCHEMA[wildcard]) return SCHEMA[wildcard];
97
+ }
98
+ return null;
99
+ }
100
+
101
+ /**
102
+ * Get the tier for a key.
103
+ */
104
+ function getTier(key) {
105
+ const def = getDefinition(key);
106
+ return def ? def.tier : null;
107
+ }
108
+
109
+ /**
110
+ * Check if a key is locked.
111
+ */
112
+ function isLocked(key) {
113
+ const def = getDefinition(key);
114
+ return def ? !!def.locked : false;
115
+ }
116
+
117
+ /**
118
+ * Validate a value against its schema definition.
119
+ * Returns { valid: boolean, reason?: string }
120
+ */
121
+ function validate(key, value) {
122
+ const def = getDefinition(key);
123
+ if (!def) return { valid: false, reason: 'Key not in schema' };
124
+
125
+ if (def.type === 'enum') {
126
+ if (!def.values.includes(value)) {
127
+ return { valid: false, reason: `Value must be one of: ${def.values.join(', ')}` };
128
+ }
129
+ }
130
+
131
+ if (def.type === 'string' && typeof value === 'string') {
132
+ if (def.maxChars && value.length > def.maxChars) {
133
+ return { valid: false, reason: `String exceeds ${def.maxChars} chars` };
134
+ }
135
+ }
136
+
137
+ if (def.type === 'array' && Array.isArray(value)) {
138
+ if (def.maxItems && value.length > def.maxItems) {
139
+ return { valid: false, reason: `Array exceeds ${def.maxItems} items` };
140
+ }
141
+ }
142
+
143
+ return { valid: true };
144
+ }
145
+
146
+ /**
147
+ * Get all allowed keys as a formatted list (for injection into prompts).
148
+ */
149
+ function getAllowedKeysForPrompt() {
150
+ const lines = [];
151
+ let currentTier = '';
152
+ for (const [key, def] of Object.entries(SCHEMA)) {
153
+ if (def.tier !== currentTier) {
154
+ currentTier = def.tier;
155
+ lines.push(`\n# ${currentTier}${def.locked ? ' (LOCKED — do NOT write)' : ''}:`);
156
+ }
157
+ let desc = ` ${key}: ${def.type}`;
158
+ if (def.values) desc += ` [${def.values.join('|')}]`;
159
+ if (def.maxChars) desc += ` (max ${def.maxChars} chars)`;
160
+ if (def.maxItems) desc += ` (max ${def.maxItems} items)`;
161
+ if (def.locked) desc += ' [LOCKED]';
162
+ lines.push(desc);
163
+ }
164
+ return lines.join('\n');
165
+ }
166
+
167
+ /**
168
+ * Estimate token count for a YAML string (conservative for mixed zh/en).
169
+ */
170
+ function estimateTokens(yamlString) {
171
+ return Math.ceil(yamlString.length / 3);
172
+ }
173
+
174
+ const TOKEN_BUDGET = 800;
175
+
176
+ module.exports = {
177
+ SCHEMA,
178
+ hasKey,
179
+ getDefinition,
180
+ getTier,
181
+ isLocked,
182
+ validate,
183
+ getAllowedKeysForPrompt,
184
+ estimateTokens,
185
+ TOKEN_BUDGET,
186
+ };
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MetaMe Signal Capture Hook
5
+ *
6
+ * Runs as a Claude Code UserPromptSubmit hook.
7
+ * Receives user prompt via stdin JSON, filters for potential
8
+ * persistent preferences/identity signals, appends to buffer.
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const os = require('os');
14
+
15
+ const BUFFER_FILE = path.join(os.homedir(), '.metame', 'raw_signals.jsonl');
16
+ const MAX_BUFFER_LINES = 50; // Safety cap to avoid unbounded growth
17
+
18
+ // === CONFIDENCE PATTERNS ===
19
+
20
+ // Strong directive signals → high confidence (direct write to T3)
21
+ // Allow up to 6 chars between key words (e.g. "以后代码一律" = "以后" + "代码" + "一律")
22
+ const STRONG_SIGNAL_ZH = /以后.{0,6}(都|一律|每次|全部|统一)|永远.{0,4}(不要|别|不能|要)|千万.{0,4}(别|不要)|记住|一定.{0,4}(要|得)|一律|统一用/;
23
+ const STRONG_SIGNAL_EN = /(from now on|always|never|don't ever|remember to|every time)/i;
24
+
25
+ // Implicit preference signals → normal confidence (needs accumulation)
26
+ const IMPLICIT_ZH = /我(喜欢|偏好|习惯|讨厌|不喜欢|一般都|通常|总是|倾向于)/;
27
+ const IMPLICIT_EN = /I (prefer|like|hate|usually|tend to|always)/i;
28
+
29
+ // Correction signals → high confidence (user is teaching us)
30
+ const CORRECTION_ZH = /不是.*我(要|想|说)的|我说的不是|你理解错了|不对.*应该/;
31
+ const CORRECTION_EN = /(no,? I meant|that's not what I|you misunderstood|wrong.+should be)/i;
32
+
33
+ // Read JSON from stdin
34
+ let input = '';
35
+ process.stdin.setEncoding('utf8');
36
+ process.stdin.on('data', (chunk) => { input += chunk; });
37
+ process.stdin.on('end', () => {
38
+ try {
39
+ const data = JSON.parse(input);
40
+ const prompt = (data.prompt || '').trim();
41
+
42
+ // === LAYER 1: Hard filters (definitely not preferences) ===
43
+
44
+ // Skip empty or very short messages
45
+ // Chinese chars carry more info per char, so use weighted length
46
+ const weightedLen = [...prompt].reduce((sum, ch) => sum + (ch.charCodeAt(0) > 0x2e80 ? 3 : 1), 0);
47
+ if (weightedLen < 15) {
48
+ process.exit(0);
49
+ }
50
+
51
+ // Skip messages that are purely code or file paths
52
+ if (/^(```|\/[\w/]+\.\w+$)/.test(prompt)) {
53
+ process.exit(0);
54
+ }
55
+
56
+ // Skip common non-preference commands
57
+ if (/^(\/\w+|!metame|git |npm |pnpm |yarn |brew |sudo |cd |ls |cat |mkdir )/.test(prompt)) {
58
+ process.exit(0);
59
+ }
60
+
61
+ // Skip pure task instructions (fix/add/delete/refactor/debug/deploy/test/run/build)
62
+ if (/^(帮我|请你|麻烦)?\s*(fix|add|delete|remove|refactor|debug|deploy|test|run|build|create|update|implement|write|generate|make)/i.test(prompt)) {
63
+ process.exit(0);
64
+ }
65
+ if (/^(帮我|请你|麻烦)?\s*(修|加|删|重构|调试|部署|测试|运行|构建|创建|更新|实现|写|生成|做)/.test(prompt)) {
66
+ process.exit(0);
67
+ }
68
+
69
+ // Skip pasted error logs / stack traces
70
+ if (/^(Error|TypeError|SyntaxError|ReferenceError|at\s+\w+|Traceback|FATAL|WARN|ERR!)/i.test(prompt)) {
71
+ process.exit(0);
72
+ }
73
+ if (prompt.split('\n').length > 10) {
74
+ // Multi-line pastes are usually code or logs, not preferences
75
+ process.exit(0);
76
+ }
77
+
78
+ // Skip pure questions with no preference signal
79
+ if (/^(what|how|why|where|when|which|can you|could you|is there|are there|does|do you)\s/i.test(prompt) &&
80
+ !/prefer|like|hate|always|never|style|习惯|偏好|喜欢|讨厌/.test(prompt)) {
81
+ process.exit(0);
82
+ }
83
+ if (/^(什么|怎么|为什么|哪|能不能|可以|是不是)\s/.test(prompt) &&
84
+ !/偏好|喜欢|讨厌|习惯|以后|一律|总是|永远|记住/.test(prompt)) {
85
+ process.exit(0);
86
+ }
87
+
88
+ // === LAYER 2: Confidence tagging ===
89
+ const isStrong = STRONG_SIGNAL_ZH.test(prompt) || STRONG_SIGNAL_EN.test(prompt);
90
+ const isCorrection = CORRECTION_ZH.test(prompt) || CORRECTION_EN.test(prompt);
91
+ const confidence = (isStrong || isCorrection) ? 'high' : 'normal';
92
+
93
+ // Append to buffer
94
+ const entry = {
95
+ ts: new Date().toISOString(),
96
+ prompt: prompt,
97
+ confidence: confidence,
98
+ session: data.session_id || null,
99
+ cwd: data.cwd || null
100
+ };
101
+
102
+ // Append to buffer, drop oldest if over cap
103
+ let existingLines = [];
104
+ try {
105
+ existingLines = fs.readFileSync(BUFFER_FILE, 'utf8')
106
+ .split('\n').filter(l => l.trim());
107
+ } catch {
108
+ // File doesn't exist yet, that's fine
109
+ }
110
+
111
+ existingLines.push(JSON.stringify(entry));
112
+
113
+ // Keep only the most recent entries (drop oldest)
114
+ if (existingLines.length > MAX_BUFFER_LINES) {
115
+ existingLines = existingLines.slice(-MAX_BUFFER_LINES);
116
+ }
117
+
118
+ fs.writeFileSync(BUFFER_FILE, existingLines.join('\n') + '\n');
119
+
120
+ } catch {
121
+ // Silently ignore parse errors — never block the user's workflow
122
+ }
123
+
124
+ process.exit(0);
125
+ });
@@ -1,175 +0,0 @@
1
- # 🔮 MetaMe
2
-
3
- <p align="center">
4
- <img src="./logo.png" alt="MetaMe Logo" width="200"/>
5
- </p>
6
-
7
- > **Claude Code 的“元认知”层 (The Meta-Cognitive Layer)**
8
- >
9
- > *将你的 AI 助手变成一面心理镜像:它了解你,随你进化,并时刻守护你的核心原则。*
10
-
11
- ## 📖 简介 (Introduction)
12
-
13
- **Claude Code** 是一个强大的工具,但它患有“项目失忆症”。每当你切换文件夹时,它就会忘记你是谁、你的沟通风格以及你的具体限制。
14
-
15
- **MetaMe** 通过为 Claude 包裹一层 **“元认知层”** 来解决这个问题。它创建了一个跟随你穿梭于所有项目的 **“全局大脑”** 。它了解你的心理画像,监控你的压力状态,并尊重你的核心原则——无需你每次重复强调。
16
-
17
- 它不仅仅是一个启动器;它是你的 **元分身 (Meta Avatar)** 。
18
-
19
- ## ✨ 核心特性 (Key Features)
20
-
21
- * **🧠 全局大脑 (`~/.claude_profile.yaml`):** 关于你身份的“唯一真理来源”。存储你的昵称、压力状态和认知特征,跨项目共享。
22
- * **🧬 进化机制 (Evolution Mechanism):** 你掌握控制权。使用 `!metame evolve` 手动教导 Claude 你的新偏好或限制,确保它在每次交互中变得更聪明。
23
- * **🤝 动态握手协议 (Dynamic Handshake):** 即“金丝雀测试”。MetaMe 会强制 AI 在回复的第一句话中通过你的 **代号 (Codename)** 来称呼你。如果它没叫你的名字,你就知道元认知连接已断开。
24
- * **🛡️ 自动锁定机制 (Auto-Lock):** 在配置文件中为任何值添加 `# [LOCKED]`,MetaMe 就会将其视为不可动摇的“宪法”,防止 AI 随意修改。
25
- * **🔌 智能注入 (Smart Injection):** 自动将你的个人档案注入到你进入的任何项目的 `CLAUDE.md` 中,实现无缝的上下文切换。
26
-
27
- ## 🛠 前置要求 (Prerequisites)
28
-
29
- MetaMe 是 **Claude Code** 的外壳。你必须先安装 Node.js 和官方的 Claude Code 工具。
30
-
31
- 1. **Node.js** : 版本 14 或更高。
32
- 2. **Claude Code** :
33
- **Bash**
34
-
35
- ```
36
- npm install -g @anthropic-ai/claude-code
37
- ```
38
-
39
- 1. **认证** : 确保你已经运行过 `claude login` 并登录成功。
40
-
41
- ## 📦 安装 (Installation)
42
-
43
- 通过 NPM 全局安装 MetaMe:
44
-
45
- **Bash**
46
-
47
- ```
48
- npm install -g metame-cli
49
- ```
50
-
51
- *(注意:如果你在 Mac/Linux 上遇到权限错误,请使用 `sudo npm install -g metame-cli`)*
52
-
53
- ## 🚀 使用指南 (Usage)
54
-
55
- 忘掉 `claude` 命令吧。从现在起,只需输入:
56
-
57
- **Bash**
58
-
59
- ```
60
- metame
61
- ```
62
-
63
- 或者,如果你喜欢混合大小写(效果一样):
64
-
65
- **Bash**
66
-
67
- ```
68
- MetaMe
69
- ```
70
-
71
- ### 初次运行:创世纪 (The First Run)
72
-
73
- 当你第一次运行 MetaMe 时,它会检测到你的档案为空。它会暂停 AI 并进入 **校准模式 (Calibration Mode)** :
74
-
75
- 1. 它会询问你的 **代号 (Codename/Nickname)**。
76
- 2. 它会开启一场 **深度认知访谈**,探索你的天赋领域、思维模式和潜在焦虑。
77
- 3. **请务必诚实**:它是一面镜子。你越坦诚(即便是关于你的恐惧),它就越能成为你的完美分身。
78
- 4. 完成后,它会保存你的“源代码”并启动 Claude。
79
-
80
- ### 日常工作流
81
-
82
- 1. `cd` 进入任何项目文件夹。
83
- 2. 运行 `metame`。
84
- 3. Claude 启动并立即说:*“Ready, [你的名字]...”*
85
- 4. 开始写代码。MetaMe 会在后台自动管理上下文。
86
-
87
- ### 热重载 (Hot Reload)
88
-
89
- 如果你更新了个人档案,或者需要修复断开的上下文连接,而**不想重启会话**:
90
-
91
- * **在 Claude 内部**:运行 `!metame refresh`
92
- * **在外部终端**:运行 `metame refresh`
93
-
94
- 这会立即将你最新的档案重新注入 `CLAUDE.md`。
95
-
96
- ## ⚙️ 配置与“全局大脑”
97
-
98
- 你的个人档案存储在你用户主目录下的一个隐藏 YAML 文件中。
99
-
100
- **位置:** `~/.claude_profile.yaml`
101
-
102
- 你可以手动编辑此文件来更新你的状态或锁定你的价值观。
103
-
104
- **档案示例:**
105
-
106
- **YAML**
107
-
108
- ```
109
- identity:
110
- role: Senior Architect
111
- nickname: Neo
112
- status:
113
- focus: Refactoring Legacy Code
114
- pressure: High
115
- cognition:
116
- crisis_reflex: Strategic_Analysis
117
- blind_spot: Perfectionism # [LOCKED]
118
- values:
119
- core: "User Experience First" # [LOCKED]
120
- ```
121
-
122
- * **`# [LOCKED]`** :添加此注释可确保即使 AI 随着时间推移进化你的档案,这些特定的行也 **永远不会** 被覆盖。
123
-
124
- ## 🗑️ 卸载 (Uninstallation)
125
-
126
- 如果你希望从系统中彻底移除 MetaMe,请按照以下步骤操作:
127
-
128
- ### 1. 移除软件包
129
-
130
- 卸载 CLI 工具:
131
-
132
- **Bash**
133
-
134
- ```
135
- npm uninstall -g metame-cli
136
- ```
137
-
138
- ### 2. 移除全局大脑(可选)
139
-
140
- 如果你想删除存储的个人档案数据:
141
-
142
- **Bash**
143
-
144
- ```
145
- rm ~/.claude_profile.yaml
146
- ```
147
-
148
- ### 3. 清理项目文件(可选)
149
-
150
- MetaMe 会在项目的 `CLAUDE.md` 文件头部添加一段协议。如果你想恢复原状,可以用文本编辑器删除以 `## 🧠 SYSTEM KERNEL` 开头的块。
151
-
152
- ## ⚡ 性能与成本 (Performance & Cost)
153
-
154
- 你可能会担心:*“这会吃掉我的上下文窗口吗?”*
155
-
156
- **简短回答:不会。它甚至通过减少废话为你省钱。**
157
-
158
- * **上下文占用**:整个 MetaMe 内核 + 你的完整档案仅占用 **约 800 - 1000 tokens**。
159
- * **占比**:在 Claude 的 200k 上下文窗口中,这仅占 **0.5%**。
160
- * **投资回报**:通过预加载你的完整背景,它避免了每个新会话开头的“磨合期”和重复指令修正,而那些通常会浪费数千 tokens。
161
-
162
- ## ❓ 常见问题 (FAQ)
163
-
164
- **Q: 这会覆盖我原本的 `CLAUDE.md` 吗?**
165
- A: 不会。它只是将元认知协议 *插入* 到你现有 `CLAUDE.md` 的最顶部。你原本的项目笔记会保持原样。
166
-
167
- **Q: 如果 Claude 突然不再叫我的昵称了怎么办?**
168
- A: 这就是“金丝雀测试”失败了。这意味着上下文窗口被压缩了,或者文件链接断开了。在 Claude 中运行 `/compact` 或重启 `metame` 即可修复。
169
-
170
- **Q: 我的数据会被发送给第三方吗?**
171
- A: 不会。你的档案只保存在本地的 `~/.claude_profile.yaml` 中。MetaMe 只是将文本传递给官方的 Claude Code 工具。
172
-
173
- ## 📄 许可证 (License)
174
-
175
- MIT License. 欢迎 Fork、修改并进化你自己的元认知系统。
package/logo.png DELETED
Binary file