memoir-cli 2.5.0 → 2.5.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.
- package/README.md +123 -86
- package/package.json +1 -1
- package/src/adapters/restore.js +48 -3
package/README.md
CHANGED
|
@@ -1,88 +1,129 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
# memoir
|
|
4
|
-
**Your AI Remembers Everything. Sync It Everywhere.**
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
**Sync your AI memory across every device and every tool.**
|
|
6
|
+
|
|
7
|
+
[](https://npmjs.org/package/memoir-cli)
|
|
8
|
+
[](https://npmjs.org/package/memoir-cli)
|
|
7
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+
|
|
12
|
+
Your AI tools forget you on every new machine. memoir fixes that.
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
[Website](https://memoir.sh) • [npm](https://npmjs.org/package/memoir-cli) • [Blog](https://memoir.sh/blog)
|
|
15
|
+
|
|
16
|
+
<br />
|
|
10
17
|
|
|
11
18
|

|
|
12
19
|
|
|
13
20
|
</div>
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
## Why memoir
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
You spend weeks teaching your AI tools how you code. Your CLAUDE.md is dialed in. Your .cursorrules are perfect. Your ChatGPT custom instructions know your stack.
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
Then you get a new laptop. **Everything is gone.**
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
memoir backs up, restores, and **translates** your AI memory across any machine and any tool. One command to save. One command to restore.
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g memoir-cli
|
|
32
|
+
```
|
|
24
33
|
|
|
25
|
-
##
|
|
34
|
+
## Supported Tools (11)
|
|
35
|
+
|
|
36
|
+
| Tool | What gets synced |
|
|
37
|
+
|------|-----------------|
|
|
38
|
+
| **ChatGPT** | CHATGPT.md custom instructions |
|
|
39
|
+
| **Claude Code** | ~/.claude/ settings, memory, CLAUDE.md files |
|
|
40
|
+
| **Gemini CLI** | ~/.gemini/ config, GEMINI.md files |
|
|
41
|
+
| **OpenAI Codex** | ~/.codex/ config, AGENTS.md, codex.md |
|
|
42
|
+
| **Cursor** | Settings, keybindings, .cursorrules |
|
|
43
|
+
| **GitHub Copilot** | Config, copilot-instructions.md |
|
|
44
|
+
| **Windsurf** | Settings, keybindings, .windsurfrules |
|
|
45
|
+
| **Zed** | Settings, keymap, tasks |
|
|
46
|
+
| **Cline** | Settings, .clinerules |
|
|
47
|
+
| **Continue.dev** | Config, .continuerules |
|
|
48
|
+
| **Aider** | .aider.conf.yml, system prompt |
|
|
26
49
|
|
|
27
|
-
|
|
50
|
+
Plus **per-project configs** — memoir scans your filesystem for CLAUDE.md, GEMINI.md, CHATGPT.md, .cursorrules, and AGENTS.md across all your projects.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
28
53
|
|
|
29
54
|
```bash
|
|
55
|
+
# Install
|
|
30
56
|
npm install -g memoir-cli
|
|
57
|
+
|
|
58
|
+
# First-time setup (GitHub repo or local)
|
|
59
|
+
memoir init
|
|
60
|
+
|
|
61
|
+
# Back up all your AI configs
|
|
62
|
+
memoir push
|
|
63
|
+
|
|
64
|
+
# Restore on a new machine
|
|
65
|
+
memoir restore
|
|
31
66
|
```
|
|
32
67
|
|
|
33
|
-
|
|
34
|
-
| Tool | Config synced |
|
|
35
|
-
|------|--------------|
|
|
36
|
-
| **ChatGPT** | `CHATGPT.md` — custom instructions, preferences |
|
|
37
|
-
| **Claude Code** | `~/.claude/` — settings, projects, memory files |
|
|
38
|
-
| **Gemini CLI** | `~/.gemini/` — settings, GEMINI.md |
|
|
39
|
-
| **OpenAI Codex** | `~/.codex/` — config, instructions |
|
|
40
|
-
| **Cursor** | Settings, keybindings, rules |
|
|
41
|
-
| **GitHub Copilot** | Config, settings |
|
|
42
|
-
| **Windsurf** | Settings, keybindings, rules |
|
|
43
|
-
| **Zed** | Settings, keymap, tasks |
|
|
44
|
-
| **Cline** | Settings, rules |
|
|
45
|
-
| **Continue.dev** | Config, rules |
|
|
46
|
-
| **Aider** | `.aider.conf.yml`, system prompt |
|
|
68
|
+
That's it. Every AI tool gets its memory back.
|
|
47
69
|
|
|
48
|
-
|
|
70
|
+
## Key Features
|
|
49
71
|
|
|
50
|
-
|
|
72
|
+
### Translate between AI tools
|
|
73
|
+
```bash
|
|
74
|
+
memoir migrate --from chatgpt --to claude
|
|
75
|
+
# AI-powered — rewrites conventions, not copy-paste
|
|
76
|
+
```
|
|
51
77
|
|
|
52
|
-
|
|
78
|
+
Works between any combination: ChatGPT, Claude, Gemini, Cursor, Copilot, Codex, Windsurf, Aider, and more. Translate to one tool or all at once:
|
|
53
79
|
|
|
54
|
-
### 1. Initialize
|
|
55
80
|
```bash
|
|
56
|
-
memoir
|
|
57
|
-
# Walks you through setup — GitHub repo or local folder
|
|
58
|
-
# Auto-creates a private repo if you have gh CLI
|
|
81
|
+
memoir migrate --from chatgpt --to all
|
|
59
82
|
```
|
|
60
83
|
|
|
61
|
-
###
|
|
84
|
+
### Session handoff
|
|
62
85
|
```bash
|
|
63
|
-
|
|
86
|
+
# Laptop dying? Capture your session
|
|
87
|
+
memoir snapshot
|
|
88
|
+
|
|
89
|
+
# Pick up on another machine
|
|
90
|
+
memoir resume --inject --to claude
|
|
64
91
|
```
|
|
65
92
|
|
|
66
|
-
###
|
|
93
|
+
### Profiles (personal / work)
|
|
67
94
|
```bash
|
|
68
|
-
memoir
|
|
95
|
+
memoir profile create work
|
|
96
|
+
memoir push --profile work
|
|
97
|
+
memoir profile switch personal
|
|
69
98
|
```
|
|
70
99
|
|
|
71
|
-
|
|
100
|
+
Each profile has its own repo and tool filters. Work configs never mix with personal.
|
|
101
|
+
|
|
102
|
+
### Cloud sync (Pro)
|
|
72
103
|
```bash
|
|
73
|
-
memoir
|
|
74
|
-
|
|
104
|
+
memoir login
|
|
105
|
+
memoir cloud push # encrypted cloud backup
|
|
106
|
+
memoir cloud restore # restore from any version
|
|
107
|
+
memoir history # view all backup versions
|
|
75
108
|
```
|
|
76
109
|
|
|
77
|
-
|
|
110
|
+
Free tier: 3 cloud backups. Pro ($5/mo): unlimited + version history.
|
|
111
|
+
|
|
112
|
+
### Security
|
|
113
|
+
```bash
|
|
114
|
+
memoir doctor
|
|
115
|
+
# Scans for secrets, API keys, .env files before pushing
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
memoir **never** syncs credentials, API keys, .env files, or auth tokens.
|
|
78
119
|
|
|
79
120
|
## All Commands
|
|
80
121
|
|
|
81
122
|
| Command | What it does |
|
|
82
123
|
|---------|-------------|
|
|
83
|
-
| `memoir init` | Setup wizard — GitHub or local
|
|
124
|
+
| `memoir init` | Setup wizard — GitHub or local storage |
|
|
84
125
|
| `memoir push` | Back up all AI configs |
|
|
85
|
-
| `memoir restore` | Restore on a new machine
|
|
126
|
+
| `memoir restore` | Restore on a new machine |
|
|
86
127
|
| `memoir status` | Show detected AI tools |
|
|
87
128
|
| `memoir doctor` | Diagnose issues, scan for secrets |
|
|
88
129
|
| `memoir view` | Preview what's in your backup |
|
|
@@ -91,28 +132,27 @@ memoir migrate --from claude --to gemini
|
|
|
91
132
|
| `memoir snapshot` | Capture current coding session |
|
|
92
133
|
| `memoir resume` | Pick up where you left off |
|
|
93
134
|
| `memoir profile` | Manage profiles (personal/work) |
|
|
135
|
+
| `memoir cloud push` | Back up to memoir cloud |
|
|
136
|
+
| `memoir cloud restore` | Restore from memoir cloud |
|
|
137
|
+
| `memoir history` | View cloud backup versions |
|
|
138
|
+
| `memoir login` | Sign in to memoir cloud |
|
|
94
139
|
| `memoir update` | Self-update to latest version |
|
|
95
140
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## Profiles
|
|
141
|
+
## How memoir compares
|
|
99
142
|
|
|
100
|
-
|
|
143
|
+
| Feature | memoir | skillshare | ai-rulez | memories.sh |
|
|
144
|
+
|---------|--------|-----------|----------|-------------|
|
|
145
|
+
| Cross-device sync | **Yes** | Yes (git) | No | Yes |
|
|
146
|
+
| AI-powered translation | **Yes** | No | No | No |
|
|
147
|
+
| Tools supported | **11** | 40+ | 18 | 3 |
|
|
148
|
+
| Cloud backup | **Yes** | No | No | Yes ($15/mo) |
|
|
149
|
+
| Version history | **Yes** | No | No | No |
|
|
150
|
+
| Session handoff | **Yes** | No | No | No |
|
|
151
|
+
| Profiles | **Yes** | No | No | No |
|
|
152
|
+
| Secret scanning | **Yes** | Yes | No | No |
|
|
153
|
+
| Free & open source | **Yes** | Yes | Yes | No |
|
|
101
154
|
|
|
102
|
-
|
|
103
|
-
memoir profile create work # set up work profile with its own repo
|
|
104
|
-
memoir profile create personal # personal side projects
|
|
105
|
-
|
|
106
|
-
memoir push --profile work # sync only work configs
|
|
107
|
-
memoir restore --profile personal
|
|
108
|
-
|
|
109
|
-
memoir profile list # see all profiles
|
|
110
|
-
memoir profile switch work # change default
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Each profile can filter which tools to sync, so your personal side project memory never mixes with work.
|
|
114
|
-
|
|
115
|
-
---
|
|
155
|
+
memoir is free and open source. Cloud sync starts at $0 (3 backups free).
|
|
116
156
|
|
|
117
157
|
## Common Workflows
|
|
118
158
|
|
|
@@ -122,46 +162,36 @@ Each profile can filter which tools to sync, so your personal side project memor
|
|
|
122
162
|
memoir push
|
|
123
163
|
|
|
124
164
|
# New machine
|
|
125
|
-
|
|
126
|
-
memoir
|
|
165
|
+
npm install -g memoir-cli
|
|
166
|
+
memoir init # connect to same repo
|
|
167
|
+
memoir restore # all configs restored in seconds
|
|
127
168
|
```
|
|
128
169
|
|
|
129
|
-
###
|
|
170
|
+
### Switching from ChatGPT to Claude
|
|
130
171
|
```bash
|
|
131
172
|
memoir migrate --from chatgpt --to claude
|
|
132
|
-
# Your
|
|
173
|
+
# Your custom instructions become a proper CLAUDE.md
|
|
133
174
|
```
|
|
134
175
|
|
|
135
|
-
###
|
|
176
|
+
### Daily sync between machines
|
|
136
177
|
```bash
|
|
137
|
-
memoir
|
|
138
|
-
#
|
|
178
|
+
memoir push # end of day on laptop
|
|
179
|
+
memoir restore # next morning on desktop
|
|
139
180
|
```
|
|
140
181
|
|
|
141
|
-
###
|
|
182
|
+
### Cross-platform (Mac ↔ Windows ↔ Linux)
|
|
142
183
|
```bash
|
|
143
|
-
|
|
144
|
-
memoir
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## Security
|
|
150
|
-
|
|
151
|
-
Memoir **only** syncs config files, instructions, and memory markdown. It never touches credentials, API keys, `.env` files, or auth tokens.
|
|
152
|
-
|
|
153
|
-
Run `memoir doctor` to see exactly what would be synced and scan for accidental secrets before pushing.
|
|
154
|
-
|
|
155
|
-
---
|
|
184
|
+
# Push from Mac
|
|
185
|
+
memoir push
|
|
156
186
|
|
|
157
|
-
|
|
187
|
+
# Restore on Windows — paths remap automatically
|
|
188
|
+
memoir restore
|
|
189
|
+
```
|
|
158
190
|
|
|
159
|
-
|
|
160
|
-
- **Cloud sync** — no GitHub needed, encrypted backups
|
|
161
|
-
- **Teams** — shared coding standards across your whole team
|
|
162
|
-
- **Templates** — community-shared AI tool configs
|
|
191
|
+
## Requirements
|
|
163
192
|
|
|
164
|
-
|
|
193
|
+
- Node.js >= 18
|
|
194
|
+
- Works on macOS, Windows, Linux
|
|
165
195
|
|
|
166
196
|
## Contributing
|
|
167
197
|
|
|
@@ -172,6 +202,13 @@ Contributions welcome — especially new tool adapters and migration improvement
|
|
|
172
202
|
3. Commit and push
|
|
173
203
|
4. Open a PR
|
|
174
204
|
|
|
205
|
+
## Links
|
|
206
|
+
|
|
207
|
+
- **Website:** [memoir.sh](https://memoir.sh)
|
|
208
|
+
- **npm:** [memoir-cli](https://npmjs.org/package/memoir-cli)
|
|
209
|
+
- **Blog:** [memoir.sh/blog](https://memoir.sh/blog)
|
|
210
|
+
- **Issues:** [GitHub Issues](https://github.com/camgitt/memoir/issues)
|
|
211
|
+
|
|
175
212
|
## License
|
|
176
213
|
|
|
177
214
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memoir-cli",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "Sync AI memory across devices. Back up and restore Claude, Gemini, Codex, Cursor, Copilot, Windsurf configs. Snapshot coding sessions and resume on another machine. Migrate instructions between AI assistants.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
package/src/adapters/restore.js
CHANGED
|
@@ -70,18 +70,36 @@ function remapProjectPaths(backupDir, adapterSource) {
|
|
|
70
70
|
|
|
71
71
|
// Step 3: Identify foreign home keys in the backup
|
|
72
72
|
// A "home key" is a dir that: has memory/, OR is a prefix of other dirs, AND is not a sub-project
|
|
73
|
+
// Also detect alternate local encodings (e.g. -C-Users-X and C--Users-X are the same machine)
|
|
73
74
|
const foreignHomeKeys = new Set();
|
|
75
|
+
const localAltKeys = new Set(); // alternate encodings of local home dir
|
|
76
|
+
|
|
77
|
+
// Detect alternate local encodings by checking if a dir resolves to the same homedir
|
|
78
|
+
const home = os.homedir();
|
|
79
|
+
const homeNormalized = home.toLowerCase().replace(/[\\/:]/g, '');
|
|
74
80
|
|
|
75
81
|
for (const entry of backupEntries) {
|
|
76
|
-
// Skip dirs that already
|
|
82
|
+
// Skip dirs that already match the primary local key
|
|
77
83
|
if (entry === localHomeKey || entry.startsWith(localHomeKey + '-')) continue;
|
|
78
84
|
|
|
85
|
+
// Check if this entry is an alternate encoding of the local home dir
|
|
86
|
+
const entryNormalized = entry.replace(/^[-]/, '').toLowerCase().replace(/[-]/g, '');
|
|
87
|
+
if (entryNormalized === homeNormalized || homeNormalized.endsWith(entryNormalized) || entryNormalized.endsWith(homeNormalized)) {
|
|
88
|
+
// This is an alternate encoding of the local home — treat as local, not foreign
|
|
89
|
+
localAltKeys.add(entry);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
// Is this a sub-project of another backup dir? Then skip — its parent handles it
|
|
80
94
|
const isSubProject = backupEntries.some(other =>
|
|
81
95
|
other !== entry && entry.startsWith(other + '-')
|
|
82
96
|
);
|
|
83
97
|
if (isSubProject) continue;
|
|
84
98
|
|
|
99
|
+
// Is this a sub-project of an alternate local key? Skip too
|
|
100
|
+
const isAltSubProject = [...localAltKeys].some(alt => entry.startsWith(alt + '-'));
|
|
101
|
+
if (isAltSubProject) continue;
|
|
102
|
+
|
|
85
103
|
// Has memory/ subfolder = definitely a home key
|
|
86
104
|
const hasMemory = fs.existsSync(path.join(projectsDir, entry, 'memory'));
|
|
87
105
|
// Is a prefix of other dirs = likely a home key
|
|
@@ -116,6 +134,33 @@ function remapProjectPaths(backupDir, adapterSource) {
|
|
|
116
134
|
return remaps;
|
|
117
135
|
}
|
|
118
136
|
|
|
137
|
+
// Merge memory dirs from a foreign machine — copies files that don't exist locally,
|
|
138
|
+
// and for files that exist on both, keeps the newer version.
|
|
139
|
+
async function mergeMemoryDirs(src, dest) {
|
|
140
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
141
|
+
for (const entry of entries) {
|
|
142
|
+
const srcPath = path.join(src, entry.name);
|
|
143
|
+
const destPath = path.join(dest, entry.name);
|
|
144
|
+
|
|
145
|
+
if (entry.isDirectory()) {
|
|
146
|
+
await fs.ensureDir(destPath);
|
|
147
|
+
await mergeMemoryDirs(srcPath, destPath);
|
|
148
|
+
} else {
|
|
149
|
+
if (await fs.pathExists(destPath)) {
|
|
150
|
+
// Both machines have this file — keep the newer one
|
|
151
|
+
const srcStat = await fs.stat(srcPath);
|
|
152
|
+
const destStat = await fs.stat(destPath);
|
|
153
|
+
if (srcStat.mtimeMs > destStat.mtimeMs) {
|
|
154
|
+
await fs.copy(srcPath, destPath);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// File only exists on foreign machine — always copy it
|
|
158
|
+
await fs.copy(srcPath, destPath);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
119
164
|
async function syncFiles(src, dest, changes) {
|
|
120
165
|
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
121
166
|
for (const entry of entries) {
|
|
@@ -194,8 +239,8 @@ export async function restoreMemories(sourceDir, spinner, onlyFilter = null, aut
|
|
|
194
239
|
const newDir = path.join(backupDir, 'projects', remap.newName);
|
|
195
240
|
if (await fs.pathExists(oldDir)) {
|
|
196
241
|
if (await fs.pathExists(newDir)) {
|
|
197
|
-
// Merge into existing directory
|
|
198
|
-
await
|
|
242
|
+
// Merge into existing directory — force-copy new files from foreign machine
|
|
243
|
+
await mergeMemoryDirs(oldDir, newDir);
|
|
199
244
|
await fs.remove(oldDir);
|
|
200
245
|
} else {
|
|
201
246
|
await fs.move(oldDir, newDir);
|