metame-cli 1.4.15 → 1.4.18

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
@@ -64,7 +64,7 @@ Claude: ✏️ Edit: api/login.ts
64
64
  ✅ Fixed. 3 tests passing.
65
65
  ```
66
66
 
67
- Start on your laptop, continue on the train. `/stop` to interrupt, `/undo` to rollback, `/sh ls` for raw shell access when everything else breaks.
67
+ Start on your laptop, continue on the train. `/stop` to interrupt, `/undo` to rollback, `/mac check` for macOS automation diagnostics, and `/sh ls` for raw shell access when everything else breaks.
68
68
 
69
69
  ### 3. Layered Memory That Works While You Sleep
70
70
 
@@ -124,7 +124,8 @@ projects:
124
124
  heartbeat_tasks:
125
125
  - name: "daily-draft"
126
126
  prompt: "Research top AI news and write an article"
127
- interval: "24h"
127
+ at: "09:30"
128
+ days: "weekdays"
128
129
  model: "sonnet"
129
130
  notify: true
130
131
 
@@ -132,7 +133,7 @@ heartbeat:
132
133
  tasks:
133
134
  - name: "morning-brief"
134
135
  prompt: "Summarize my git activity from yesterday"
135
- interval: "24h"
136
+ at: "09:00"
136
137
  notify: true
137
138
  ```
138
139
 
@@ -150,7 +151,7 @@ Chain skills into multi-step workflows — research → write → publish — fu
150
151
  prompt: "Publish it"
151
152
  ```
152
153
 
153
- Task options: `require_idle` (defer when you're active, retry on next heartbeat tick), `precondition` (shell guard — skip if false, zero tokens), `notify` (push result to phone), `model`, `cwd`, `allowedTools`, `timeout`.
154
+ Task options: `interval` (every N seconds/minutes/hours/days), `at` (fixed local `HH:MM`), `days` (optional day filter), `require_idle` (defer when you're active, retry on next heartbeat tick), `precondition` (shell guard — skip if false, zero tokens), `notify` (push result to phone), `model`, `cwd`, `allowedTools`, `timeout`.
154
155
 
155
156
  ### 5. Skills That Evolve Themselves
156
157
 
@@ -208,7 +209,7 @@ npm install -g metame-cli && metame
208
209
  | **Browser Automation** | Built-in Playwright MCP. Browser control out of the box for every user. |
209
210
  | **Provider Relay** | Route through any Anthropic-compatible API. Use GPT-4, DeepSeek, Gemini — zero config file mutation. |
210
211
  | **Metacognition** | Detects behavioral patterns (decision style, comfort zones, goal drift) and injects mirror observations. Zero extra API cost. |
211
- | **Emergency Tools** | `/doctor` diagnostics, `/sh` raw shell, `/fix` config restore, `/undo` git-based rollback. |
212
+ | **Emergency Tools** | `/doctor` diagnostics, `/mac` macOS control helpers, `/sh` raw shell, `/fix` config restore, `/undo` git-based rollback. |
212
213
 
213
214
  ## Defining Your Agents
214
215
 
@@ -263,7 +264,8 @@ projects:
263
264
  heartbeat_tasks:
264
265
  - name: "daily-review"
265
266
  prompt: "Review yesterday's commits and flag any issues"
266
- interval: "24h"
267
+ at: "20:30"
268
+ days: [mon, tue, wed, thu, fri]
267
269
  notify: true
268
270
 
269
271
  feishu:
@@ -294,6 +296,7 @@ All agents share your cognitive profile (`~/.claude_profile.yaml`) — they all
294
296
  | `/list` | Browse & download project files |
295
297
  | `/model` | Switch model (sonnet/opus/haiku) |
296
298
  | `/agent bind <name> [dir]` | Register group as dedicated agent |
299
+ | `/mac` | macOS control helper: permissions check/open + AppleScript/JXA execution |
297
300
  | `/sh <cmd>` | Raw shell — bypasses Claude |
298
301
  | `/memory` | Memory stats: fact count, session tags, DB size |
299
302
  | `/memory <keyword>` | Search long-term facts by keyword |
package/index.js CHANGED
@@ -30,7 +30,7 @@ if (!fs.existsSync(METAME_DIR)) {
30
30
  // Auto-deploy bundled scripts to ~/.metame/
31
31
  // IMPORTANT: daemon.yaml is USER CONFIG — never overwrite it. Only daemon-default.yaml (template) is synced.
32
32
  const scriptsDir = path.join(__dirname, 'scripts');
33
- const BUNDLED_BASE_SCRIPTS = ['signal-capture.js', 'distill.js', 'schema.js', 'pending-traits.js', 'migrate-v2.js', 'daemon.js', 'telegram-adapter.js', 'feishu-adapter.js', 'daemon-default.yaml', 'providers.js', 'session-analytics.js', 'resolve-yaml.js', 'utils.js', 'skill-evolution.js', 'memory.js', 'memory-extract.js', 'qmd-client.js', 'session-summarize.js'];
33
+ const BUNDLED_BASE_SCRIPTS = ['signal-capture.js', 'distill.js', 'schema.js', 'pending-traits.js', 'migrate-v2.js', 'daemon.js', 'telegram-adapter.js', 'feishu-adapter.js', 'daemon-default.yaml', 'providers.js', 'session-analytics.js', 'resolve-yaml.js', 'utils.js', 'skill-evolution.js', 'memory.js', 'memory-extract.js', 'memory-search.js', 'qmd-client.js', 'session-summarize.js', 'check-macos-control-capabilities.sh'];
34
34
  const DAEMON_MODULE_SCRIPTS = (() => {
35
35
  try {
36
36
  return fs.readdirSync(scriptsDir).filter((f) => /^daemon-[\w-]+\.js$/.test(f));
@@ -1755,15 +1755,22 @@ if (!isKnownUser) {
1755
1755
  // RAG: inject relevant facts based on current project (desktop-side equivalent of daemon RAG)
1756
1756
  try {
1757
1757
  const memory = require(path.join(__dirname, 'scripts', 'memory.js'));
1758
- // Derive project key from git repo name or cwd basename
1759
- let projectQuery = path.basename(process.cwd());
1758
+ const { projectScopeFromCwd } = require(path.join(__dirname, 'scripts', 'utils.js'));
1759
+ // Keep cwd basename as authoritative project filter for legacy rows (scope IS NULL).
1760
+ const cwdProject = path.basename(process.cwd());
1761
+ let repoProject = cwdProject;
1760
1762
  try {
1761
1763
  const { execSync } = require('child_process');
1762
1764
  const remote = execSync('git remote get-url origin 2>/dev/null || true', { encoding: 'utf8', stdio: 'pipe' }).trim();
1763
- if (remote) projectQuery = path.basename(remote, '.git');
1765
+ if (remote) repoProject = path.basename(remote, '.git');
1764
1766
  } catch { /* not a git repo, use dirname */ }
1765
1767
 
1766
- const facts = memory.searchFacts(projectQuery, { limit: 5 });
1768
+ const factQuery = repoProject === cwdProject ? cwdProject : `${repoProject} ${cwdProject}`;
1769
+ const facts = memory.searchFacts(factQuery, {
1770
+ limit: 5,
1771
+ project: cwdProject || undefined,
1772
+ scope: projectScopeFromCwd(process.cwd()) || undefined,
1773
+ });
1767
1774
  if (facts.length > 0) {
1768
1775
  const factBlock = facts.map(f => `- [${f.relation}] ${f.value}`).join('\n');
1769
1776
  launchArgs.push(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metame-cli",
3
- "version": "1.4.15",
3
+ "version": "1.4.18",
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,7 @@
13
13
  "scripts": {
14
14
  "test": "node --test scripts/*.test.js",
15
15
  "start": "node index.js",
16
- "sync:plugin": "cp scripts/schema.js scripts/pending-traits.js scripts/signal-capture.js scripts/distill.js scripts/daemon.js scripts/daemon-agent-commands.js scripts/daemon-session-commands.js scripts/daemon-admin-commands.js scripts/daemon-exec-commands.js scripts/daemon-ops-commands.js scripts/daemon-session-store.js scripts/daemon-checkpoints.js scripts/daemon-bridges.js scripts/daemon-file-browser.js scripts/daemon-runtime-lifecycle.js scripts/daemon-notify.js scripts/daemon-claude-engine.js scripts/daemon-command-router.js scripts/daemon-agent-tools.js scripts/daemon-task-scheduler.js scripts/telegram-adapter.js scripts/feishu-adapter.js scripts/daemon-default.yaml scripts/providers.js scripts/utils.js scripts/resolve-yaml.js scripts/memory.js scripts/memory-extract.js scripts/qmd-client.js scripts/session-summarize.js scripts/session-analytics.js scripts/skill-evolution.js plugin/scripts/ && echo '✅ Plugin scripts synced'",
16
+ "sync:plugin": "cp scripts/schema.js scripts/pending-traits.js scripts/signal-capture.js scripts/distill.js scripts/daemon.js scripts/daemon-agent-commands.js scripts/daemon-session-commands.js scripts/daemon-admin-commands.js scripts/daemon-exec-commands.js scripts/daemon-ops-commands.js scripts/daemon-session-store.js scripts/daemon-checkpoints.js scripts/daemon-bridges.js scripts/daemon-file-browser.js scripts/daemon-runtime-lifecycle.js scripts/daemon-notify.js scripts/daemon-claude-engine.js scripts/daemon-command-router.js scripts/daemon-agent-tools.js scripts/daemon-task-scheduler.js scripts/daemon-task-envelope.js scripts/task-board.js scripts/telegram-adapter.js scripts/feishu-adapter.js scripts/daemon-default.yaml scripts/providers.js scripts/utils.js scripts/usage-classifier.js scripts/resolve-yaml.js scripts/memory.js scripts/memory-extract.js scripts/qmd-client.js scripts/session-summarize.js scripts/session-analytics.js scripts/skill-evolution.js scripts/check-macos-control-capabilities.sh plugin/scripts/ && echo '✅ Plugin scripts synced'",
17
17
  "restart:daemon": "node index.js stop 2>/dev/null; sleep 1; node index.js start 2>/dev/null || echo '⚠️ Daemon not running or restart failed'",
18
18
  "precommit": "npm run sync:plugin && npm run restart:daemon"
19
19
  },
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+ set -u
3
+ set -o pipefail
4
+
5
+ PASS=0
6
+ FAIL=0
7
+ WARN=0
8
+
9
+ print_line() {
10
+ printf '%s\n' "$1"
11
+ }
12
+
13
+ run_check() {
14
+ local name="$1"
15
+ local mode="$2"
16
+ local cmd="$3"
17
+
18
+ local output
19
+ output="$(bash -o pipefail -lc "$cmd" 2>&1)"
20
+ local code=$?
21
+
22
+ if [ "$mode" = "pass_on_zero" ]; then
23
+ if [ $code -eq 0 ]; then
24
+ PASS=$((PASS + 1))
25
+ print_line "[PASS] $name"
26
+ [ -n "$output" ] && print_line " $output"
27
+ else
28
+ FAIL=$((FAIL + 1))
29
+ print_line "[FAIL] $name"
30
+ [ -n "$output" ] && print_line " $output"
31
+ fi
32
+ return
33
+ fi
34
+
35
+ if [ "$mode" = "warn_on_nonzero" ]; then
36
+ if [ $code -eq 0 ]; then
37
+ PASS=$((PASS + 1))
38
+ print_line "[PASS] $name"
39
+ [ -n "$output" ] && print_line " $output"
40
+ else
41
+ WARN=$((WARN + 1))
42
+ print_line "[WARN] $name"
43
+ [ -n "$output" ] && print_line " $output"
44
+ fi
45
+ return
46
+ fi
47
+
48
+ FAIL=$((FAIL + 1))
49
+ print_line "[FAIL] $name"
50
+ print_line " invalid mode: $mode"
51
+ }
52
+
53
+ print_line "MetaMe macOS control capability check"
54
+ print_line "Timestamp: $(date '+%Y-%m-%d %H:%M:%S %z')"
55
+ print_line ""
56
+
57
+ run_check "osascript binary available" "pass_on_zero" "which osascript"
58
+ run_check "AppleScript baseline" "pass_on_zero" "osascript -e 'return \"ok\"'"
59
+ run_check "Finder automation" "pass_on_zero" "osascript -e 'tell application \"Finder\" to get name of startup disk'"
60
+ run_check "System Events accessibility" "pass_on_zero" "osascript -e 'tell application \"System Events\" to get UI elements enabled'"
61
+ run_check "GUI app launch/control (Calculator)" "pass_on_zero" "open -a Calculator >/dev/null 2>&1; sleep 1; osascript -e 'tell application \"System Events\" to tell process \"Calculator\" to return {frontmost, (count of windows)}'; osascript -e 'tell application \"Calculator\" to quit' >/dev/null 2>&1"
62
+
63
+ SHOT_PATH="/tmp/metame_gui_test_$$.png"
64
+ run_check "Screenshot capability (screencapture)" "pass_on_zero" "screencapture -x '$SHOT_PATH' && ls -lh '$SHOT_PATH'"
65
+ rm -f "$SHOT_PATH" >/dev/null 2>&1
66
+
67
+ run_check "Full Disk probe: read ~/Library/Mail" "warn_on_nonzero" "ls '$HOME/Library/Mail' | head -n 3"
68
+ run_check "Full Disk probe: query Safari History.db" "warn_on_nonzero" "sqlite3 '$HOME/Library/Safari/History.db' 'select count(*) from history_items;'"
69
+
70
+ print_line ""
71
+ print_line "Summary: pass=$PASS warn=$WARN fail=$FAIL"
72
+
73
+ if [ $FAIL -gt 0 ]; then
74
+ exit 1
75
+ fi
76
+
77
+ exit 0