metame-cli 1.3.8 → 1.3.9
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 +39 -12
- package/index.js +41 -15
- package/package.json +3 -2
- package/scripts/daemon.js +23 -17
package/README.md
CHANGED
|
@@ -6,15 +6,27 @@
|
|
|
6
6
|
|
|
7
7
|
> **The Cognitive Profile Layer for Claude Code.**
|
|
8
8
|
>
|
|
9
|
-
> *
|
|
9
|
+
> *Knows how you think. Works wherever you are.*
|
|
10
10
|
|
|
11
11
|
## 📖 Introduction
|
|
12
12
|
|
|
13
|
-
**Claude Code** is
|
|
13
|
+
**Claude Code** is powerful, but it has two pain points:
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
1. **Project Amnesia** — Switch folders, and it forgets who you are. Your communication style, coding preferences, constraints — gone. Every project, you start from scratch.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
2. **Desktop-Bound** — Leave your computer, work stops. You can't continue that debugging session on your phone. You can't vibe with Claude on the train, in bed, or waiting in line.
|
|
18
|
+
|
|
19
|
+
**MetaMe** solves both — and more:
|
|
20
|
+
|
|
21
|
+
**🧠 Cognitive Profile** — A persistent "Global Brain" (`~/.claude_profile.yaml`) that travels with you across every project. Unlike ChatGPT/Claude's built-in memory (which stores *facts* like "user lives in X"), MetaMe captures *how you think* — your decision style, cognitive load preferences, and communication traits. It's not a memory system; it's a **Cognitive Mirror**.
|
|
22
|
+
|
|
23
|
+
**📱 Mobile Bridge** — Full Claude Code from your phone via Telegram or Feishu. Same tools, same files, same conversation history. Start on your computer, continue anywhere. `/cd last` syncs you to exactly where you left off.
|
|
24
|
+
|
|
25
|
+
**🔔 Remote Wake** — Daemon runs in the background on your computer. Send a message from your phone, and it wakes up Claude Code to do real work — edit files, run commands, commit code — even while you're away from your desk.
|
|
26
|
+
|
|
27
|
+
**📂 File Transfer** — Send files from your computer to your phone (ask Claude to send any project file). Send files from your phone to your computer (just attach them in chat). Seamless both ways.
|
|
28
|
+
|
|
29
|
+
**⏰ Heartbeat Tasks** — Schedule Claude to run automatically. Daily summaries, automated workflows, multi-step skill chains — all running on your machine, pushing results to your phone.
|
|
18
30
|
|
|
19
31
|
## ✨ Key Features
|
|
20
32
|
|
|
@@ -34,15 +46,19 @@ MetaMe is a wrapper around **Claude Code**. You must have Node.js and the offici
|
|
|
34
46
|
|
|
35
47
|
## 📦 Installation
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
**Bash**
|
|
49
|
+
**Option A: NPM (recommended)** — full CLI with daemon, mobile bridge, interview
|
|
40
50
|
|
|
41
|
-
```
|
|
51
|
+
```bash
|
|
42
52
|
npm install -g metame-cli
|
|
43
53
|
```
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
**Option B: Claude Code Plugin** — lightweight, profile injection + slash commands
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude plugin install github:Yaron9/MetaMe/plugin
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
*(NPM note: If you encounter permission errors on Mac/Linux, use `sudo npm install -g metame-cli`)*
|
|
46
62
|
|
|
47
63
|
## 🚀 Usage
|
|
48
64
|
|
|
@@ -170,7 +186,6 @@ metame daemon install-launchd # macOS auto-start (RunAtLoad + KeepAlive)
|
|
|
170
186
|
| `/cd` | Change working directory — with directory browser |
|
|
171
187
|
| `/cd last` | **Sync to computer** — jump to the most recent session's directory |
|
|
172
188
|
| `/session` | Current session info |
|
|
173
|
-
| `/continue` | Continue the most recent terminal session |
|
|
174
189
|
|
|
175
190
|
Just type naturally for conversation — every message stays in the same Claude Code session with full context.
|
|
176
191
|
|
|
@@ -190,7 +205,9 @@ Each chat gets a persistent session via `claude -p --resume <session-id>`. This
|
|
|
190
205
|
💻 Bash: 「git status」
|
|
191
206
|
```
|
|
192
207
|
|
|
193
|
-
**File
|
|
208
|
+
**File transfer (v1.3.8):** Seamlessly move files between your phone and computer.
|
|
209
|
+
|
|
210
|
+
*Computer → Phone (download):* Ask Claude to send any project file:
|
|
194
211
|
|
|
195
212
|
```
|
|
196
213
|
You: Send me report.md
|
|
@@ -200,8 +217,18 @@ Claude: Here you go!
|
|
|
200
217
|
|
|
201
218
|
Works for documents, audio, images, etc. Click button to download. Links valid for 30 minutes.
|
|
202
219
|
|
|
220
|
+
*Phone → Computer (upload):* Send files directly to your project:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
[📎 You send a PDF, image, or any file]
|
|
224
|
+
Claude: 📥 Saved: document.pdf
|
|
225
|
+
File is in your project's upload/ folder.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Uploaded files are saved to `<project>/upload/`. Claude won't read large files automatically — just tell it when you want it to process them.
|
|
229
|
+
|
|
203
230
|
- **Telegram:** Works out of the box
|
|
204
|
-
- **Feishu:** Requires `im:resource`
|
|
231
|
+
- **Feishu:** Requires `im:resource` + `im:message` permissions in app settings
|
|
205
232
|
|
|
206
233
|
**Other commands:**
|
|
207
234
|
|
package/index.js
CHANGED
|
@@ -598,10 +598,15 @@ if (isDaemon) {
|
|
|
598
598
|
|
|
599
599
|
// --- Telegram Setup ---
|
|
600
600
|
console.log("━━━ 📱 Telegram Setup ━━━");
|
|
601
|
-
console.log("
|
|
602
|
-
console.log("
|
|
603
|
-
console.log("
|
|
604
|
-
console.log("
|
|
601
|
+
console.log("");
|
|
602
|
+
console.log("Step 1: Create a Bot");
|
|
603
|
+
console.log(" • Open Telegram app on your phone or desktop");
|
|
604
|
+
console.log(" • Search for @BotFather (official Telegram bot)");
|
|
605
|
+
console.log(" • Send /newbot command");
|
|
606
|
+
console.log(" • Enter a display name (e.g., 'My MetaMe Bot')");
|
|
607
|
+
console.log(" • Enter a username (must end in 'bot', e.g., 'my_metame_bot')");
|
|
608
|
+
console.log(" • BotFather will reply with your bot token");
|
|
609
|
+
console.log(" (looks like: 123456789:ABCdefGHI-jklMNOpqrSTUvwxYZ)");
|
|
605
610
|
console.log("");
|
|
606
611
|
|
|
607
612
|
const tgToken = (await ask("Paste your Telegram bot token (Enter to skip): ")).trim();
|
|
@@ -652,17 +657,38 @@ if (isDaemon) {
|
|
|
652
657
|
|
|
653
658
|
// --- Feishu Setup ---
|
|
654
659
|
console.log("━━━ 📘 Feishu (Lark) Setup ━━━");
|
|
655
|
-
console.log("
|
|
656
|
-
console.log("
|
|
657
|
-
console.log("
|
|
658
|
-
console.log("
|
|
659
|
-
console.log("
|
|
660
|
-
console.log("
|
|
661
|
-
console.log("
|
|
662
|
-
console.log("
|
|
663
|
-
console.log("
|
|
664
|
-
console.log("
|
|
665
|
-
console.log("
|
|
660
|
+
console.log("");
|
|
661
|
+
console.log("Step 1: Create an App");
|
|
662
|
+
console.log(" • Go to: https://open.feishu.cn/app");
|
|
663
|
+
console.log(" • Click '创建企业自建应用' (Create Enterprise App)");
|
|
664
|
+
console.log(" • Fill in app name and description");
|
|
665
|
+
console.log("");
|
|
666
|
+
console.log("Step 2: Get Credentials");
|
|
667
|
+
console.log(" • In left sidebar → '凭证与基础信息' (Credentials)");
|
|
668
|
+
console.log(" • Copy App ID and App Secret");
|
|
669
|
+
console.log("");
|
|
670
|
+
console.log("Step 3: Enable Bot");
|
|
671
|
+
console.log(" • In left sidebar → '应用能力' → '机器人' (Bot)");
|
|
672
|
+
console.log(" • Enable the bot capability");
|
|
673
|
+
console.log("");
|
|
674
|
+
console.log("Step 4: Configure Events");
|
|
675
|
+
console.log(" • In left sidebar → '事件订阅' (Event Subscription)");
|
|
676
|
+
console.log(" • Choose '使用长连接接收事件' (Long Connection mode) — important!");
|
|
677
|
+
console.log(" • Add event: im.message.receive_v1 (接收消息)");
|
|
678
|
+
console.log("");
|
|
679
|
+
console.log("Step 5: Add Permissions");
|
|
680
|
+
console.log(" • In left sidebar → '权限管理' (Permissions)");
|
|
681
|
+
console.log(" • Search and enable these 5 permissions:");
|
|
682
|
+
console.log(" → im:message (获取与发送单聊、群组消息)");
|
|
683
|
+
console.log(" → im:message.p2p_msg:readonly (读取用户发给机器人的单聊消息)");
|
|
684
|
+
console.log(" → im:message.group_at_msg:readonly (接收群聊中@机器人消息事件)");
|
|
685
|
+
console.log(" → im:message:send_as_bot (以应用的身份发消息)");
|
|
686
|
+
console.log(" → im:resource (文件上传下载 - for file transfer)");
|
|
687
|
+
console.log("");
|
|
688
|
+
console.log("Step 6: Publish");
|
|
689
|
+
console.log(" • In left sidebar → '版本管理与发布' (Version Management)");
|
|
690
|
+
console.log(" • Click '创建版本' → fill version (e.g., 1.0.0)");
|
|
691
|
+
console.log(" • Click '申请发布' (Apply for Release)");
|
|
666
692
|
console.log("");
|
|
667
693
|
|
|
668
694
|
const feishuAppId = (await ask("Paste your Feishu App ID (Enter to skip): ")).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metame-cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.9",
|
|
4
4
|
"description": "The Cognitive Profile Layer for Claude Code. Knows how you think, not just what you said.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "node index.js",
|
|
15
15
|
"sync:plugin": "cp scripts/schema.js scripts/pending-traits.js scripts/signal-capture.js scripts/distill.js scripts/daemon.js scripts/telegram-adapter.js scripts/feishu-adapter.js scripts/daemon-default.yaml plugin/scripts/ && echo '✅ Plugin scripts synced'",
|
|
16
|
-
"
|
|
16
|
+
"restart:daemon": "node index.js daemon stop 2>/dev/null; sleep 1; node index.js daemon start 2>/dev/null || echo '⚠️ Daemon not running or restart failed'",
|
|
17
|
+
"precommit": "npm run sync:plugin && npm run restart:daemon"
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"claude",
|
package/scripts/daemon.js
CHANGED
|
@@ -669,22 +669,6 @@ async function handleCommand(bot, chatId, text, config, executeTaskByName) {
|
|
|
669
669
|
return;
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
-
if (text === '/continue') {
|
|
673
|
-
// Continue the most recent conversation in current workdir
|
|
674
|
-
const session = getSession(chatId);
|
|
675
|
-
const cwd = session ? session.cwd : HOME;
|
|
676
|
-
const state2 = loadState();
|
|
677
|
-
state2.sessions[chatId] = {
|
|
678
|
-
id: '__continue__',
|
|
679
|
-
cwd,
|
|
680
|
-
created: new Date().toISOString(),
|
|
681
|
-
started: true,
|
|
682
|
-
};
|
|
683
|
-
saveState(state2);
|
|
684
|
-
await bot.sendMessage(chatId, `Resuming last conversation in ${cwd}`);
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
672
|
// /file <shortId> — send cached file (from button callback)
|
|
689
673
|
if (text.startsWith('/file ')) {
|
|
690
674
|
const shortId = text.slice(6).trim();
|
|
@@ -1006,7 +990,7 @@ async function handleCommand(bot, chatId, text, config, executeTaskByName) {
|
|
|
1006
990
|
'/cd <path> — 切换工作目录',
|
|
1007
991
|
'/session — 查看当前会话',
|
|
1008
992
|
'',
|
|
1009
|
-
'⚙️ /status /tasks /budget /reload',
|
|
993
|
+
'⚙️ /status /tasks /run <name> /budget /reload',
|
|
1010
994
|
'',
|
|
1011
995
|
'直接打字即可对话 💬',
|
|
1012
996
|
].join('\n'));
|
|
@@ -1904,6 +1888,27 @@ async function main() {
|
|
|
1904
1888
|
}, 1000);
|
|
1905
1889
|
});
|
|
1906
1890
|
|
|
1891
|
+
// Auto-restart: watch daemon.js for code changes (hot restart)
|
|
1892
|
+
const DAEMON_SCRIPT = path.join(METAME_DIR, 'daemon.js');
|
|
1893
|
+
let _restartDebounce = null;
|
|
1894
|
+
fs.watchFile(DAEMON_SCRIPT, { interval: 3000 }, (curr, prev) => {
|
|
1895
|
+
if (curr.mtimeMs === prev.mtimeMs) return;
|
|
1896
|
+
if (_restartDebounce) clearTimeout(_restartDebounce);
|
|
1897
|
+
_restartDebounce = setTimeout(async () => {
|
|
1898
|
+
log('INFO', 'daemon.js changed on disk — auto-restarting...');
|
|
1899
|
+
await notifyFn('🔄 Code updated, daemon restarting...').catch(() => {});
|
|
1900
|
+
// Spawn new daemon process, then exit
|
|
1901
|
+
const { spawn } = require('child_process');
|
|
1902
|
+
const newDaemon = spawn(process.execPath, [DAEMON_SCRIPT], {
|
|
1903
|
+
detached: true,
|
|
1904
|
+
stdio: 'ignore',
|
|
1905
|
+
env: { ...process.env, METAME_ROOT: process.env.METAME_ROOT || path.dirname(__dirname) },
|
|
1906
|
+
});
|
|
1907
|
+
newDaemon.unref();
|
|
1908
|
+
setTimeout(() => process.exit(0), 500);
|
|
1909
|
+
}, 2000);
|
|
1910
|
+
});
|
|
1911
|
+
|
|
1907
1912
|
// Start bridges (both can run simultaneously)
|
|
1908
1913
|
telegramBridge = await startTelegramBridge(config, executeTaskByName);
|
|
1909
1914
|
feishuBridge = await startFeishuBridge(config, executeTaskByName);
|
|
@@ -1912,6 +1917,7 @@ async function main() {
|
|
|
1912
1917
|
const shutdown = () => {
|
|
1913
1918
|
log('INFO', 'Daemon shutting down...');
|
|
1914
1919
|
fs.unwatchFile(CONFIG_FILE);
|
|
1920
|
+
fs.unwatchFile(DAEMON_SCRIPT);
|
|
1915
1921
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
1916
1922
|
if (telegramBridge) telegramBridge.stop();
|
|
1917
1923
|
if (feishuBridge) feishuBridge.stop();
|