memoir-cli 3.3.1 → 3.4.0

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
@@ -2,37 +2,27 @@
2
2
 
3
3
  # memoir
4
4
 
5
- **Persistent memory for AI coding tools.**
5
+ **Portable memory for every AI coding tool.**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/memoir-cli.svg?style=flat-square&color=7c6ef0)](https://npmjs.org/package/memoir-cli)
8
8
  [![npm downloads](https://img.shields.io/npm/dm/memoir-cli.svg?style=flat-square&color=7c6ef0)](https://npmjs.org/package/memoir-cli)
9
9
  [![GitHub stars](https://img.shields.io/github/stars/camgitt/memoir?style=flat-square&color=7c6ef0)](https://github.com/camgitt/memoir/stargazers)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
11
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square)](https://nodejs.org)
12
-
13
- Your AI forgets everything between sessions. memoir gives it long-term memory via MCP.
14
-
15
- **11 tools supported** • **E2E encrypted** • **Cross-platform** • **Open source**
16
-
17
- Works with Claude Code, Cursor, Windsurf, Gemini, Copilot, Codex, ChatGPT, Aider, Zed, Cline, and Continue.dev.
18
-
19
- [Website](https://memoir.sh) • [npm](https://npmjs.org/package/memoir-cli) • [Blog](https://memoir.sh/blog) • [Contributing](CONTRIBUTING.md)
20
-
21
- <br />
22
-
23
- <img src="demo.svg" alt="memoir demo — push, restore, and sync AI memory" width="700" />
24
11
 
25
12
  </div>
26
13
 
27
- ## The Problem
14
+ ```bash
15
+ npm install -g memoir-cli
16
+ memoir activate
17
+ ```
28
18
 
29
- You told Claude your project uses Zustand, not Redux. You explained your auth middleware to Cursor. You spent weeks building up context across your AI tools.
19
+ Your AI now remembers across sessions, tools, and machines. Works with Claude Code, Cursor, Windsurf, Gemini, Copilot, and 6 more tools.
30
20
 
31
- Next session? **Gone.** New machine? **Gone.** Switch tools? **Gone.**
21
+ ---
32
22
 
33
- ## How memoir fixes it
23
+ ## What it does
34
24
 
35
- memoir is a **persistent memory layer** that runs via [MCP](https://modelcontextprotocol.io) inside your AI tools. Your AI can search, read, and save memories automatically — across sessions, tools, and machines.
25
+ memoir is an [MCP server](https://modelcontextprotocol.io) that gives your AI tools persistent memory. Your AI can search, save, and recall context automatically.
36
26
 
37
27
  ```
38
28
  you: how does auth work in this project?
@@ -47,38 +37,15 @@ claude: Based on your previous sessions: this project uses JWT auth
47
37
 
48
38
  No re-explaining. memoir remembered.
49
39
 
50
- ## Architecture
51
-
52
- ```mermaid
53
- graph LR
54
- A[Claude Code] --> M[memoir MCP]
55
- B[Cursor] --> M
56
- C[Gemini CLI] --> M
57
- D[Windsurf] --> M
58
- E[+ 7 more] --> M
59
-
60
- M --> R[recall / remember / list / read]
61
- R --> S[(Local Memory Store)]
62
-
63
- S --> P[memoir push]
64
- P --> G[GitHub / Cloud]
65
- G --> Q[memoir restore]
66
- Q --> S2[(New Machine)]
67
- ```
68
-
69
- memoir runs as a local MCP server inside your AI tools. Your AI can search, save, and recall memories automatically. Push to sync across machines.
40
+ ## Setup
70
41
 
71
- ## Quick Start
42
+ ### 1. Install
72
43
 
73
44
  ```bash
74
- # Install
75
45
  npm install -g memoir-cli
76
-
77
- # Setup
78
- memoir init
79
46
  ```
80
47
 
81
- ### Add MCP to your AI tools
48
+ ### 2. Add MCP to your AI tool
82
49
 
83
50
  **Claude Code** — add to `~/.mcp.json`:
84
51
  ```json
@@ -98,7 +65,13 @@ memoir init
98
65
  }
99
66
  ```
100
67
 
101
- That's it. Your AI tools now have 6 memory abilities:
68
+ ### 3. Activate in your project
69
+
70
+ ```bash
71
+ memoir activate
72
+ ```
73
+
74
+ That's it. Your AI now has 6 memory tools:
102
75
 
103
76
  | MCP Tool | What it does |
104
77
  |----------|-------------|
@@ -109,49 +82,28 @@ That's it. Your AI tools now have 6 memory abilities:
109
82
  | `memoir_status` | See which AI tools are detected |
110
83
  | `memoir_profiles` | Switch between work/personal |
111
84
 
112
- ## What Gets Synced
113
-
114
- memoir syncs three layers that no other tool connects:
85
+ ## Why memoir
115
86
 
116
- ### Layer 1: AI Memory (via MCP + CLI)
117
- Configs, instructions, and project knowledge across 11 tools — searchable and writable from inside any AI conversation.
87
+ Your AI forgets everything between sessions. You re-explain your codebase, your conventions, your decisions — every time.
118
88
 
119
- | Tool | What gets synced |
120
- |------|-----------------|
121
- | **Claude Code** | ~/.claude/ settings, memory, CLAUDE.md files |
122
- | **Gemini CLI** | ~/.gemini/ config, GEMINI.md files |
123
- | **ChatGPT** | CHATGPT.md custom instructions |
124
- | **OpenAI Codex** | ~/.codex/ config, AGENTS.md |
125
- | **Cursor** | Settings, keybindings, .cursorrules |
126
- | **GitHub Copilot** | Config, copilot-instructions.md |
127
- | **Windsurf** | Settings, keybindings, .windsurfrules |
128
- | **Zed** | Settings, keymap, tasks |
129
- | **Cline** | Settings, .clinerules |
130
- | **Continue.dev** | Config, .continuerules |
131
- | **Aider** | .aider.conf.yml, system prompt |
89
+ memoir fixes this by giving your AI a shared memory layer that works across **every tool you use**. Tell Claude something once. Cursor knows it too.
132
90
 
133
- ### Layer 2: Session State
134
- What you were **doing** — not just what your AI knows, but the active context.
91
+ **11 tools supported:** Claude Code, Cursor, Windsurf, Gemini CLI, GitHub Copilot, OpenAI Codex, ChatGPT, Aider, Zed, Cline, Continue.dev
135
92
 
136
- - Last coding session captured automatically
137
- - What files you changed, what errors you hit, what decisions you made
138
- - Injected into your AI on restore so it picks up mid-conversation
139
- - Secrets auto-redacted (API keys, tokens, passwords stripped before sync)
93
+ ## Sync across machines
140
94
 
141
- ### Layer 3: Workspace
142
- Your actual projects — code, files, everything.
95
+ ```bash
96
+ # Back up
97
+ memoir push
143
98
 
144
- - **Git projects:** Remote URLs saved, auto-cloned on restore
145
- - **Non-git projects:** Bundled as compressed archives, unpacked on restore
146
- - **Uncommitted work:** Saved as patches, applied after clone
147
- - **Zero git commands needed** — memoir handles it all
99
+ # Restore on any machine
100
+ memoir restore -y
101
+ ```
148
102
 
149
- ## Key Features
103
+ Push syncs AI memory, session context, workspace (git repos + uncommitted work), and project configs. E2E encrypted with AES-256-GCM.
150
104
 
151
- ### Cross-tool memory
152
- Tell Claude something once. Cursor knows it too. memoir is the shared memory layer between all your AI tools.
105
+ ## Translate between AI tools
153
106
 
154
- ### Translate between AI tools
155
107
  ```bash
156
108
  memoir migrate --from chatgpt --to claude
157
109
  # AI-powered — rewrites conventions, not copy-paste
@@ -160,56 +112,25 @@ memoir migrate --from chatgpt --to all
160
112
  # Translate to every tool at once
161
113
  ```
162
114
 
163
- ### Cross-machine sync
164
- ```bash
165
- # On your main machine
166
- memoir push
167
-
168
- # On any other machine
169
- memoir restore -y
170
- # ✔ AI memory restored (Claude, Gemini, Cursor, 11 tools)
171
- # ✔ 44 projects cloned & unpacked
172
- # ✔ Uncommitted changes applied
173
- # ✔ Session context injected — AI picks up mid-conversation
174
- ```
175
-
176
- ### E2E Encryption
177
- ```bash
178
- memoir encrypt # toggle encryption on/off
179
- memoir push # prompted for passphrase, AES-256-GCM encrypted
180
- ```
181
-
182
- Your backup is encrypted before it leaves your machine. Secret scanning auto-redacts API keys, tokens, and passwords.
183
-
184
- ### Profiles (personal / work)
185
- ```bash
186
- memoir profile create work
187
- memoir push --profile work
188
- memoir profile switch personal
189
- ```
115
+ ## Cloud sync
190
116
 
191
- ### Cloud sync
192
117
  ```bash
193
118
  memoir login
194
119
  memoir cloud push # encrypted cloud backup
195
120
  memoir cloud restore # restore from any version
121
+ memoir history # view backup versions
122
+ memoir share # create encrypted shareable link
196
123
  ```
197
124
 
198
- ### Cross-platform (Mac / Windows / Linux)
199
- Paths remap automatically between platforms. Push from Mac, restore on Windows. It just works.
200
-
201
125
  ## All Commands
202
126
 
203
127
  | Command | What it does |
204
128
  |---------|-------------|
205
- | `memoir init` | Setup wizard GitHub or local storage |
129
+ | `memoir activate` | Enable auto-recall in this project |
130
+ | `memoir deactivate` | Remove memoir from this project |
206
131
  | `memoir push` | Back up AI memory + workspace + session |
207
132
  | `memoir restore` | Restore everything on a new machine |
208
- | `memoir mcp` | Start MCP server for editor integration |
209
133
  | `memoir status` | Show detected AI tools |
210
- | `memoir doctor` | Diagnose issues, scan for secrets |
211
- | `memoir view` | Preview what's in your backup |
212
- | `memoir diff` | Show changes since last backup |
213
134
  | `memoir migrate` | Translate memory between tools via AI |
214
135
  | `memoir snapshot` | Capture current coding session |
215
136
  | `memoir resume` | Pick up where you left off |
@@ -217,95 +138,24 @@ Paths remap automatically between platforms. Push from Mac, restore on Windows.
217
138
  | `memoir profile` | Manage profiles (personal/work) |
218
139
  | `memoir cloud push` | Back up to memoir cloud |
219
140
  | `memoir cloud restore` | Restore from memoir cloud |
220
- | `memoir history` | View cloud backup versions |
221
- | `memoir login` | Sign in to memoir cloud |
222
141
  | `memoir share` | Create encrypted shareable link |
223
- | `memoir upgrade` | View plans and upgrade |
142
+ | `memoir doctor` | Diagnose issues |
143
+ | `memoir diff` | Show changes since last backup |
144
+ | `memoir view` | Preview what's in your backup |
224
145
  | `memoir update` | Self-update to latest version |
225
146
 
226
- ## How memoir compares
227
-
228
- | Feature | memoir | dotfiles managers | ai-rulez | memories.sh |
229
- |---------|--------|-------------------|----------|-------------|
230
- | MCP memory layer | **6 tools** | No | No | No |
231
- | AI memory sync | **11 tools** | No | 18 tools | 3 tools |
232
- | Cross-tool recall | **Yes** | No | No | No |
233
- | Workspace sync | **Yes** | No | No | No |
234
- | Session handoff | **Yes** | No | No | No |
235
- | AI-powered migration | **Yes** | No | No | No |
236
- | E2E encryption | **Yes** | No | No | No |
237
- | Secret scanning | **Yes** | Some | No | No |
238
- | Cross-platform remap | **Yes** | Some | No | No |
239
- | Cloud backup | **Yes** | No | No | Yes ($15/mo) |
240
- | Profiles | **Yes** | No | No | No |
241
- | Free & open source | **Yes** | Yes | Yes | No |
242
-
243
- ## Common Workflows
244
-
245
- ### Your AI remembers across sessions
246
- ```
247
- # Monday — you explain your auth setup to Claude
248
- # ...Claude calls memoir_remember to save the decision
249
-
250
- # Thursday — new conversation
251
- you: "add a protected route"
252
- # Claude calls memoir_recall, finds your auth architecture
253
- # No re-explaining needed
254
- ```
255
-
256
- ### New machine setup
257
- ```bash
258
- npm install -g memoir-cli && memoir init && memoir restore -y
259
- # Done. Everything's back.
260
- ```
261
-
262
- ### Switching AI tools
263
- ```bash
264
- memoir migrate --from chatgpt --to claude
265
- # Your custom instructions become a proper CLAUDE.md
266
- ```
267
-
268
- ### Team onboarding
269
- ```bash
270
- # Senior dev pushes team config
271
- memoir push --profile team
272
-
273
- # New hire runs one command
274
- memoir restore --profile team
275
- # Every project cloned. Every AI tool configured. Day one productive.
276
- ```
277
-
278
147
  ## Security
279
148
 
280
149
  - **E2E encryption** — AES-256-GCM with scrypt key derivation
281
- - **Secret scanning** — 20+ patterns detect API keys, tokens, passwords, connection strings
282
- - **Auto-redaction** — secrets stripped from session handoffs before sync
283
- - **No credentials synced** — .env files, auth tokens, and API keys are never included
284
- - **Passphrase verified** — wrong passphrase caught before decrypt attempt
285
- - **Local MCP server** — runs on your machine, no data sent to external services
286
-
287
- ## Requirements
288
-
289
- - Node.js >= 18
290
- - Git (for workspace sync)
291
- - Works on macOS, Windows, Linux
292
-
293
- ## Contributing
294
-
295
- Contributions welcome — especially new tool adapters and MCP improvements.
296
-
297
- 1. Fork the repo
298
- 2. Create your branch (`git checkout -b feature/my-feature`)
299
- 3. Commit and push
300
- 4. Open a PR
150
+ - **Secret scanning** — API keys, tokens, passwords auto-redacted before sync
151
+ - **Local MCP server** — runs on your machine, no data sent externally
152
+ - **Zero-knowledge cloud** — encrypted before upload
301
153
 
302
154
  ## Links
303
155
 
304
156
  - **Website:** [memoir.sh](https://memoir.sh)
305
157
  - **npm:** [memoir-cli](https://npmjs.org/package/memoir-cli)
306
- - **Blog:** [memoir.sh/blog](https://memoir.sh/blog)
307
158
  - **Issues:** [GitHub Issues](https://github.com/camgitt/memoir/issues)
159
+ - **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md)
308
160
 
309
- ## License
310
-
311
- MIT
161
+ MIT Licensed
package/bin/memoir.js CHANGED
@@ -20,6 +20,7 @@ import { shareCommand } from '../src/commands/share.js';
20
20
  import { historyCommand } from '../src/commands/history.js';
21
21
  import { projectsListCommand, projectsTodoCommand } from '../src/commands/projects.js';
22
22
  import { upgradeCommand } from '../src/commands/upgrade.js';
23
+ import { activateCommand, deactivateCommand } from '../src/commands/activate.js';
23
24
  import { createRequire } from 'module';
24
25
 
25
26
  const require = createRequire(import.meta.url);
@@ -66,6 +67,7 @@ if (process.argv.length <= 2) {
66
67
  chalk.cyan(' memoir status ') + chalk.gray('— see detected AI tools') + '\n' +
67
68
  chalk.cyan(' memoir profile ') + chalk.gray('— manage profiles (personal/work)') + '\n' +
68
69
  chalk.cyan(' memoir projects ') + chalk.gray('— see all your projects at a glance') + '\n' +
70
+ chalk.cyan(' memoir activate ') + chalk.gray('— enable auto-recall in this project') + '\n' +
69
71
  chalk.cyan(' memoir encrypt ') + chalk.gray('— toggle E2E encryption') + '\n' +
70
72
  chalk.cyan(' memoir update ') + chalk.gray('— update to latest version') + '\n' +
71
73
  chalk.cyan(' memoir upgrade ') + chalk.gray('— view plans & upgrade') + '\n\n' +
@@ -298,6 +300,30 @@ program
298
300
  }
299
301
  });
300
302
 
303
+ program
304
+ .command('activate')
305
+ .description('Add memoir instructions to this project so your AI uses it automatically')
306
+ .action(async () => {
307
+ try {
308
+ await activateCommand();
309
+ } catch (err) {
310
+ console.error(chalk.red('\n✖ Error:'), err.message);
311
+ process.exit(1);
312
+ }
313
+ });
314
+
315
+ program
316
+ .command('deactivate')
317
+ .description('Remove memoir instructions from this project')
318
+ .action(async () => {
319
+ try {
320
+ await deactivateCommand();
321
+ } catch (err) {
322
+ console.error(chalk.red('\n✖ Error:'), err.message);
323
+ process.exit(1);
324
+ }
325
+ });
326
+
301
327
  program
302
328
  .command('encrypt')
303
329
  .description('Toggle E2E encryption for your backups')
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "memoir-cli",
3
- "version": "3.3.1",
3
+ "version": "3.4.0",
4
4
  "mcpName": "io.github.camgitt/memoir",
5
- "description": "Persistent memory for AI coding tools via MCP. Your AI remembers across sessions, tools, and machines. Works with Claude, Cursor, Gemini, Windsurf, and 7 more tools.",
5
+ "description": "MCP server that gives Claude, Cursor, and Gemini long-term memory across sessions. Your AI remembers your codebase, decisions, and preferences across tools and machines.",
6
6
  "main": "src/index.js",
7
7
  "type": "module",
8
8
  "bin": {
@@ -19,7 +19,8 @@
19
19
  },
20
20
  "scripts": {
21
21
  "start": "node bin/memoir.js",
22
- "test": "bash test-local.sh"
22
+ "test": "bash test-local.sh",
23
+ "postinstall": "node -e \"try{const c='\\x1b[36m',r='\\x1b[0m',g='\\x1b[90m';console.log('\\n '+c+'memoir'+r+' installed.\\n Run '+c+'memoir activate'+r+' in any project to give your AI long-term memory.\\n '+g+'https://memoir.sh'+r+'\\n')}catch{}\""
23
24
  },
24
25
  "keywords": [
25
26
  "mcp",
@@ -1,5 +1,5 @@
1
1
  export const SUPABASE_URL = process.env.MEMOIR_SUPABASE_URL || 'https://oqrkxytbahfwjhcbyzrx.supabase.co';
2
2
  export const SUPABASE_ANON_KEY = process.env.MEMOIR_SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9xcmt4eXRiYWhmd2poY2J5enJ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzMyMTQ4MzMsImV4cCI6MjA4ODc5MDgzM30.jOKOi73OJgIgi1zj0VOIQkGp0xqS3ee4gfCjpdqCnvM';
3
3
  export const STORAGE_BUCKET = 'memoir-backups';
4
- export const MAX_BACKUPS_FREE = 3;
4
+ export const MAX_BACKUPS_FREE = 100;
5
5
  export const MAX_BACKUPS_PRO = 50;
@@ -0,0 +1,232 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import inquirer from 'inquirer';
6
+
7
+ // The instruction files each AI tool reads, in priority order
8
+ const INSTRUCTION_FILES = [
9
+ { file: 'CLAUDE.md', tool: 'Claude' },
10
+ { file: '.cursorrules', tool: 'Cursor' },
11
+ { file: '.windsurfrules', tool: 'Windsurf' },
12
+ { file: '.github/copilot-instructions.md', tool: 'Copilot' },
13
+ { file: '.clinerules', tool: 'Cline' },
14
+ { file: 'GEMINI.md', tool: 'Gemini' },
15
+ { file: '.aider.system-prompt.md', tool: 'Aider' },
16
+ ];
17
+
18
+ const BLOCK_START = '<!-- memoir:start -->';
19
+ const BLOCK_END = '<!-- memoir:end -->';
20
+
21
+ const MEMOIR_BLOCK = `${BLOCK_START}
22
+ # Memoir — Persistent Memory
23
+ <!-- Cross-session memory for AI tools — https://memoir.sh -->
24
+ <!-- Install: npm i -g memoir-cli -->
25
+ Use memoir_recall to search past context before answering project questions.
26
+ Use memoir_remember to save important decisions, architecture choices, or context worth keeping.
27
+ ${BLOCK_END}`;
28
+
29
+ /**
30
+ * Detect which instruction files exist in the current project.
31
+ * Returns array of { file, tool, fullPath, exists }
32
+ */
33
+ function detectInstructionFiles(projectDir) {
34
+ return INSTRUCTION_FILES.map(({ file, tool }) => {
35
+ const fullPath = path.join(projectDir, file);
36
+ return { file, tool, fullPath, exists: fs.existsSync(fullPath) };
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Check if a file already has the memoir block
42
+ */
43
+ function hasMemoir(content) {
44
+ return content.includes(BLOCK_START);
45
+ }
46
+
47
+ /**
48
+ * Inject memoir block into a file (append, or create)
49
+ */
50
+ async function injectBlock(filePath) {
51
+ await fs.ensureDir(path.dirname(filePath));
52
+
53
+ if (await fs.pathExists(filePath)) {
54
+ const content = await fs.readFile(filePath, 'utf-8');
55
+ if (hasMemoir(content)) {
56
+ return 'already';
57
+ }
58
+ // Append with spacing
59
+ const separator = content.endsWith('\n') ? '\n' : '\n\n';
60
+ await fs.writeFile(filePath, content + separator + MEMOIR_BLOCK + '\n');
61
+ return 'appended';
62
+ } else {
63
+ await fs.writeFile(filePath, MEMOIR_BLOCK + '\n');
64
+ return 'created';
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Remove memoir block from a file
70
+ */
71
+ async function removeBlock(filePath) {
72
+ if (!await fs.pathExists(filePath)) return 'not_found';
73
+
74
+ const content = await fs.readFile(filePath, 'utf-8');
75
+ if (!hasMemoir(content)) return 'not_present';
76
+
77
+ const startIdx = content.indexOf(BLOCK_START);
78
+ const endIdx = content.indexOf(BLOCK_END);
79
+ if (startIdx === -1 || endIdx === -1) return 'not_present';
80
+
81
+ const before = content.slice(0, startIdx).replace(/\n+$/, '');
82
+ const after = content.slice(endIdx + BLOCK_END.length).replace(/^\n+/, '');
83
+ const cleaned = (before + (before && after ? '\n\n' : '') + after).trim();
84
+
85
+ if (!cleaned) {
86
+ // File would be empty — delete it
87
+ await fs.remove(filePath);
88
+ return 'deleted';
89
+ }
90
+
91
+ await fs.writeFile(filePath, cleaned + '\n');
92
+ return 'removed';
93
+ }
94
+
95
+ /**
96
+ * Track which projects have been activated
97
+ */
98
+ function getActivatedPath() {
99
+ return path.join(os.homedir(), '.config', 'memoir', 'activated-projects.json');
100
+ }
101
+
102
+ async function loadActivated() {
103
+ const p = getActivatedPath();
104
+ if (await fs.pathExists(p)) {
105
+ const data = await fs.readJson(p);
106
+ return Array.isArray(data) ? data : [];
107
+ }
108
+ return [];
109
+ }
110
+
111
+ async function markActivated(projectDir) {
112
+ const activated = await loadActivated();
113
+ if (!activated.includes(projectDir)) {
114
+ activated.push(projectDir);
115
+ await fs.ensureDir(path.dirname(getActivatedPath()));
116
+ await fs.writeJson(getActivatedPath(), activated);
117
+ }
118
+ }
119
+
120
+ async function markDeactivated(projectDir) {
121
+ let activated = await loadActivated();
122
+ activated = activated.filter(p => p !== projectDir);
123
+ await fs.ensureDir(path.dirname(getActivatedPath()));
124
+ await fs.writeJson(getActivatedPath(), activated);
125
+ }
126
+
127
+ export async function isActivated(projectDir) {
128
+ const activated = await loadActivated();
129
+ return activated.includes(projectDir);
130
+ }
131
+
132
+ /**
133
+ * memoir activate — inject memoir instructions into project AI config files
134
+ */
135
+ export async function activateCommand(options = {}) {
136
+ const projectDir = process.cwd();
137
+ const detected = detectInstructionFiles(projectDir);
138
+ const existing = detected.filter(d => d.exists);
139
+
140
+ if (existing.length === 0) {
141
+ // No instruction files exist — create CLAUDE.md by default
142
+ const result = await injectBlock(path.join(projectDir, 'CLAUDE.md'));
143
+ console.log(chalk.green('\n ✔ Created CLAUDE.md with memoir instructions'));
144
+ console.log(chalk.gray(' Your AI will use memoir_recall and memoir_remember automatically.\n'));
145
+ await markActivated(projectDir);
146
+ return;
147
+ }
148
+
149
+ // Inject into all existing instruction files
150
+ let injected = 0;
151
+ for (const { file, tool, fullPath } of existing) {
152
+ const result = await injectBlock(fullPath);
153
+ if (result === 'appended') {
154
+ console.log(chalk.green(` ✔ Added memoir to ${file}`) + chalk.gray(` (${tool})`));
155
+ injected++;
156
+ } else if (result === 'created') {
157
+ console.log(chalk.green(` ✔ Created ${file} with memoir instructions`) + chalk.gray(` (${tool})`));
158
+ injected++;
159
+ } else if (result === 'already') {
160
+ console.log(chalk.gray(` · ${file} already has memoir`) + chalk.gray(` (${tool})`));
161
+ }
162
+ }
163
+
164
+ if (injected > 0) {
165
+ console.log(chalk.gray('\n Your AI tools will now use memoir automatically.\n'));
166
+ } else {
167
+ console.log(chalk.gray('\n memoir is already active in this project.\n'));
168
+ }
169
+
170
+ await markActivated(projectDir);
171
+ }
172
+
173
+ /**
174
+ * memoir deactivate — remove memoir instructions from project AI config files
175
+ */
176
+ export async function deactivateCommand(options = {}) {
177
+ const projectDir = process.cwd();
178
+ const detected = detectInstructionFiles(projectDir);
179
+
180
+ let removed = 0;
181
+ for (const { file, tool, fullPath } of detected) {
182
+ const result = await removeBlock(fullPath);
183
+ if (result === 'removed') {
184
+ console.log(chalk.yellow(` ✔ Removed memoir from ${file}`) + chalk.gray(` (${tool})`));
185
+ removed++;
186
+ } else if (result === 'deleted') {
187
+ console.log(chalk.yellow(` ✔ Deleted ${file}`) + chalk.gray(' (was only memoir block)'));
188
+ removed++;
189
+ }
190
+ }
191
+
192
+ if (removed === 0) {
193
+ console.log(chalk.gray(' · memoir is not active in this project.\n'));
194
+ } else {
195
+ console.log(chalk.gray('\n memoir instructions removed.\n'));
196
+ }
197
+
198
+ await markDeactivated(projectDir);
199
+ }
200
+
201
+ /**
202
+ * Prompt to activate — called from push on first push per project
203
+ */
204
+ export async function promptActivate() {
205
+ const projectDir = process.cwd();
206
+
207
+ // Don't prompt if already activated or if not in a project directory
208
+ if (await isActivated(projectDir)) return;
209
+
210
+ // Check if we're in a project (has git, or has instruction files, or has package.json etc.)
211
+ const projectSignals = ['.git', 'package.json', 'Cargo.toml', 'go.mod', 'pyproject.toml', 'Makefile'];
212
+ const isProject = projectSignals.some(f => fs.existsSync(path.join(projectDir, f)));
213
+ if (!isProject) {
214
+ await markActivated(projectDir); // Don't ask again for non-projects
215
+ return;
216
+ }
217
+
218
+ console.log('');
219
+ const { activate } = await inquirer.prompt([{
220
+ type: 'confirm',
221
+ name: 'activate',
222
+ message: 'Add memoir instructions to this project so your AI uses it automatically?',
223
+ default: true,
224
+ }]);
225
+
226
+ if (activate) {
227
+ await activateCommand();
228
+ } else {
229
+ await markActivated(projectDir); // Don't ask again
230
+ console.log(chalk.gray(' · Skipped. Run ') + chalk.cyan('memoir activate') + chalk.gray(' anytime to enable.\n'));
231
+ }
232
+ }
@@ -14,6 +14,7 @@ import { scanForSecrets, printSecurityReport } from '../security/scanner.js';
14
14
  import { encryptDirectory, createVerifyToken } from '../security/encryption.js';
15
15
  import { getRawConfig, saveConfig, migrateConfigToV2 } from '../config.js';
16
16
  import { scanWorkspace } from '../workspace/tracker.js';
17
+ import { promptActivate } from './activate.js';
17
18
 
18
19
  export async function pushCommand(options = {}) {
19
20
  const config = await getConfig(options.profile);
@@ -262,6 +263,13 @@ export async function pushCommand(options = {}) {
262
263
  chalk.gray('Restore on another machine with: ') + chalk.cyan('memoir restore'),
263
264
  { padding: 1, borderStyle: 'round', borderColor: 'green', dimBorder: true }
264
265
  ) + '\n');
266
+
267
+ // Prompt to activate memoir in this project (first push only)
268
+ try {
269
+ await promptActivate();
270
+ } catch {
271
+ // Activation prompt is best-effort
272
+ }
265
273
  } catch (error) {
266
274
  spinner.fail(chalk.red('Sync failed: ') + error.message);
267
275
  } finally {
@@ -63,7 +63,7 @@ export async function upgradeCommand() {
63
63
  const sep = chalk.gray('─'.repeat(col1 + col2 + 18));
64
64
 
65
65
  const rows = [
66
- [chalk.gray('3 cloud backups'), chalk.white('50 cloud backups'), chalk.white('Unlimited backups')],
66
+ [chalk.gray('100 cloud backups'), chalk.white('Unlimited backups'), chalk.white('Unlimited backups')],
67
67
  [chalk.gray('Local only'), chalk.white('Unlimited machines'), chalk.white('Shared team context')],
68
68
  [chalk.gray('Manual snapshots'), chalk.white('Auto snapshots'), chalk.white('Team dashboard')],
69
69
  [chalk.gray('Community support'), chalk.white('Priority support'), chalk.white('Audit log')],