memoir-cli 1.2.0 → 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.
package/bin/memoir.js CHANGED
@@ -8,16 +8,23 @@ import { pushCommand } from '../src/commands/push.js';
8
8
  import { restoreCommand } from '../src/commands/restore.js';
9
9
  import { statusCommand } from '../src/commands/status.js';
10
10
 
11
- const VERSION = '1.1.1';
11
+ const VERSION = '1.2.0';
12
+
13
+ // Custom help banner
14
+ program.addHelpText('beforeAll', '\n' + boxen(
15
+ gradient.pastel.multiline(' memoir ') + '\n' +
16
+ chalk.gray(' Your AI remembers everything.'),
17
+ { padding: { top: 0, bottom: 0, left: 1, right: 1 }, borderStyle: 'round', borderColor: 'cyan', dimBorder: true }
18
+ ) + '\n');
12
19
 
13
20
  program
14
21
  .name('memoir')
15
- .description('Your AI remembers everything. Sync it everywhere.')
22
+ .description(chalk.white('Sync your AI memory across every device.'))
16
23
  .version(VERSION);
17
24
 
18
25
  program
19
26
  .command('init')
20
- .description('Initialize and configure memoir storage preferences')
27
+ .description('Set up memoir with your storage provider')
21
28
  .action(async () => {
22
29
  try {
23
30
  await initCommand();
@@ -30,7 +37,7 @@ program
30
37
  program
31
38
  .command('push')
32
39
  .alias('remember')
33
- .description('Sync your AI memory to your configured storage')
40
+ .description('Back up your AI memory to the cloud')
34
41
  .action(async () => {
35
42
  try {
36
43
  await pushCommand();
@@ -43,7 +50,7 @@ program
43
50
  program
44
51
  .command('restore')
45
52
  .alias('pull')
46
- .description('Restore your AI memory from your configured storage')
53
+ .description('Restore your AI memory on this machine')
47
54
  .action(async () => {
48
55
  try {
49
56
  await restoreCommand();
@@ -55,7 +62,7 @@ program
55
62
 
56
63
  program
57
64
  .command('status')
58
- .description('Show detected AI tools and configuration status')
65
+ .description('See what AI tools are on this machine')
59
66
  .action(async () => {
60
67
  try {
61
68
  await statusCommand();
@@ -67,13 +74,13 @@ program
67
74
 
68
75
  program
69
76
  .command('migrate')
70
- .description('Migrate memory/context from one AI bot to another (e.g. Claude to Gemini)')
77
+ .description('Translate memory between AI providers')
71
78
  .action(() => {
72
79
  console.log('\n' + boxen(
73
- gradient.pastel('memoir migrate (Coming Soon)') + '\n\n' +
74
- chalk.white('We are actively developing the ability to instantly translate') + '\n' +
75
- chalk.white('and swap your context/memories between different AI providers.') + '\n\n' +
76
- chalk.cyan('Stay tuned for updates!'),
80
+ gradient.pastel(' memoir migrate ') + '\n\n' +
81
+ chalk.white('Instantly translate your context between') + '\n' +
82
+ chalk.white('Claude, Gemini, Codex, and more.') + '\n\n' +
83
+ chalk.cyan.bold('Coming soon.'),
77
84
  { padding: 1, borderStyle: 'round', borderColor: 'yellow', align: 'center' }
78
85
  ) + '\n');
79
86
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memoir-cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Your AI remembers everything. Sync it everywhere.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -3,48 +3,82 @@ import fs from 'fs-extra';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import ora from 'ora';
6
+ import boxen from 'boxen';
7
+ import gradient from 'gradient-string';
6
8
  import { getConfig } from '../config.js';
7
- import { extractMemories } from '../adapters/index.js';
9
+ import { extractMemories, adapters } from '../adapters/index.js';
8
10
  import { syncToLocal, syncToGit } from '../providers/index.js';
9
11
 
10
12
  export async function pushCommand() {
11
13
  const config = await getConfig();
12
-
14
+
13
15
  if (!config) {
14
- console.log('\\n' + chalk.red('✖ memoir is not configured.'));
15
- console.log(`Run ${chalk.cyan('memoir init')} to set up your storage provider.\\n`);
16
+ console.log('\n' + boxen(
17
+ chalk.red(' Not configured yet\n\n') +
18
+ chalk.white('Run ') + chalk.cyan.bold('memoir init') + chalk.white(' to get started.'),
19
+ { padding: 1, borderStyle: 'round', borderColor: 'red' }
20
+ ) + '\n');
16
21
  return;
17
22
  }
18
23
 
19
24
  console.log();
20
- const spinner = ora('Initializing AI memory sync...').start();
25
+ const spinner = ora({ text: chalk.gray('Scanning for AI tools...'), spinner: 'dots' }).start();
21
26
 
22
- // Create a temporary staging directory
23
27
  const stagingDir = path.join(os.tmpdir(), `memoir-staging-${Date.now()}`);
24
28
  await fs.ensureDir(stagingDir);
25
29
 
26
30
  try {
27
- spinner.text = 'Scanning system for AI configurations...';
28
-
29
- // Pass spinner so adapter can update it
30
31
  const foundAny = await extractMemories(stagingDir, spinner);
31
-
32
+
32
33
  if (!foundAny) {
33
- spinner.warn(chalk.yellow('No supported AI memory folders found on this system.'));
34
+ spinner.stop();
35
+ console.log('\n' + boxen(
36
+ chalk.yellow('No AI tools detected on this machine.\n\n') +
37
+ chalk.gray('Supported: Claude, Gemini, Codex, Cursor, Copilot, Windsurf, Aider'),
38
+ { padding: 1, borderStyle: 'round', borderColor: 'yellow' }
39
+ ) + '\n');
34
40
  return;
35
41
  }
36
42
 
43
+ // Count what was found
44
+ const found = [];
45
+ for (const adapter of adapters) {
46
+ if (adapter.customExtract) {
47
+ for (const file of adapter.files) {
48
+ if (await fs.pathExists(path.join(adapter.source, file))) {
49
+ found.push(adapter.name);
50
+ break;
51
+ }
52
+ }
53
+ } else if (await fs.pathExists(adapter.source)) {
54
+ found.push(adapter.name);
55
+ }
56
+ }
57
+
58
+ spinner.text = chalk.gray('Uploading to ' + (config.provider === 'git' ? 'GitHub' : 'local storage') + '...');
59
+
37
60
  if (config.provider === 'local' || config.provider.includes('local')) {
38
61
  await syncToLocal(config, stagingDir, spinner);
39
62
  } else if (config.provider === 'git' || config.provider.includes('git')) {
40
63
  await syncToGit(config, stagingDir, spinner);
41
64
  } else {
42
65
  spinner.fail(chalk.red(`Unknown provider: ${config.provider}`));
66
+ return;
43
67
  }
68
+
69
+ spinner.stop();
70
+
71
+ // Success output
72
+ const toolList = found.map(t => chalk.cyan(' ✔ ' + t)).join('\n');
73
+ console.log('\n' + boxen(
74
+ gradient.pastel(' Backed up! ') + '\n\n' +
75
+ toolList + '\n\n' +
76
+ chalk.gray(`${found.length} tool${found.length !== 1 ? 's' : ''} synced to ${config.provider === 'git' ? 'GitHub' : 'local storage'}`),
77
+ { padding: 1, borderStyle: 'round', borderColor: 'green', dimBorder: true }
78
+ ) + '\n');
44
79
  } catch (error) {
45
80
  spinner.fail(chalk.red('Sync failed: ') + error.message);
46
81
  } finally {
47
- // Clean up staging directory
48
82
  await fs.remove(stagingDir);
49
83
  }
50
84
  }
@@ -3,22 +3,26 @@ import fs from 'fs-extra';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import ora from 'ora';
6
+ import boxen from 'boxen';
7
+ import gradient from 'gradient-string';
6
8
  import { getConfig } from '../config.js';
7
9
  import { fetchFromLocal, fetchFromGit } from '../providers/restore.js';
8
10
 
9
11
  export async function restoreCommand() {
10
12
  const config = await getConfig();
11
-
13
+
12
14
  if (!config) {
13
- console.log('\\n' + chalk.red('✖ memoir is not configured.'));
14
- console.log(`Run ${chalk.cyan('memoir init')} to set up your storage provider and fetch your files.\\n`);
15
+ console.log('\n' + boxen(
16
+ chalk.red(' Not configured yet\n\n') +
17
+ chalk.white('Run ') + chalk.cyan.bold('memoir init') + chalk.white(' to get started.'),
18
+ { padding: 1, borderStyle: 'round', borderColor: 'red' }
19
+ ) + '\n');
15
20
  return;
16
21
  }
17
22
 
18
23
  console.log();
19
- const spinner = ora('Initializing AI memory restore...').start();
24
+ const spinner = ora({ text: chalk.gray('Fetching memories from ' + (config.provider === 'git' ? 'GitHub' : 'local storage') + '...'), spinner: 'dots' }).start();
20
25
 
21
- // Create a temporary staging directory to hold the downloaded files
22
26
  const stagingDir = path.join(os.tmpdir(), `memoir-restore-${Date.now()}`);
23
27
  await fs.ensureDir(stagingDir);
24
28
 
@@ -34,16 +38,26 @@ export async function restoreCommand() {
34
38
  return;
35
39
  }
36
40
 
41
+ spinner.stop();
42
+
37
43
  if (restored) {
38
- spinner.succeed(chalk.green('Restore complete! Your AI bots have their memories back.'));
44
+ console.log('\n' + boxen(
45
+ gradient.pastel(' Restored! ') + '\n\n' +
46
+ chalk.white('Your AI tools have their memories back.') + '\n' +
47
+ chalk.gray('They remember everything.'),
48
+ { padding: 1, borderStyle: 'round', borderColor: 'green', dimBorder: true }
49
+ ) + '\n');
39
50
  } else {
40
- spinner.info(chalk.yellow('No memories were restored.'));
51
+ console.log('\n' + boxen(
52
+ chalk.yellow('No memories were restored.\n\n') +
53
+ chalk.gray('Run ') + chalk.cyan('memoir push') + chalk.gray(' on another machine first.'),
54
+ { padding: 1, borderStyle: 'round', borderColor: 'yellow' }
55
+ ) + '\n');
41
56
  }
42
57
 
43
58
  } catch (error) {
44
59
  spinner.fail(chalk.red('Restore failed: ') + error.message);
45
60
  } finally {
46
- // Clean up staging directory
47
61
  await fs.remove(stagingDir);
48
62
  }
49
63
  }
@@ -1,6 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import fs from 'fs-extra';
3
3
  import path from 'path';
4
+ import boxen from 'boxen';
5
+ import gradient from 'gradient-string';
4
6
  import { getConfig } from '../config.js';
5
7
  import { adapters } from '../adapters/index.js';
6
8
 
@@ -10,47 +12,52 @@ export async function statusCommand() {
10
12
  console.log();
11
13
 
12
14
  // Config status
15
+ let configLine;
13
16
  if (config) {
14
- const provider = config.provider === 'git' ? `Git (${config.gitRepo})` : `Local (${config.localPath})`;
15
- console.log(chalk.green('✔ Configured') + chalk.gray(` — ${provider}`));
17
+ const provider = config.provider === 'git'
18
+ ? chalk.cyan(config.gitRepo)
19
+ : chalk.cyan(config.localPath);
20
+ configLine = chalk.green('✔ Connected') + chalk.gray(' → ') + provider;
16
21
  } else {
17
- console.log(chalk.red('✖ Not configured') + chalk.gray(' run memoir init'));
18
- console.log();
19
- return;
22
+ configLine = chalk.red('✖ Not configured') + chalk.gray(' run ') + chalk.cyan('memoir init');
20
23
  }
21
24
 
22
- console.log();
23
-
24
25
  // Detected tools
25
- console.log(chalk.bold('Detected AI tools:\n'));
26
-
26
+ const lines = [];
27
27
  let detected = 0;
28
+
28
29
  for (const adapter of adapters) {
30
+ let found = false;
29
31
  if (adapter.customExtract) {
30
- let hasFiles = false;
31
32
  for (const file of adapter.files) {
32
33
  if (await fs.pathExists(path.join(adapter.source, file))) {
33
- hasFiles = true;
34
+ found = true;
34
35
  break;
35
36
  }
36
37
  }
37
- if (hasFiles) {
38
- console.log(chalk.green(' ✔ ') + adapter.name);
39
- detected++;
40
- } else {
41
- console.log(chalk.gray(' ○ ') + chalk.gray(adapter.name + ' — not found'));
42
- }
43
38
  } else {
44
- if (await fs.pathExists(adapter.source)) {
45
- console.log(chalk.green(' ✔ ') + adapter.name);
46
- detected++;
47
- } else {
48
- console.log(chalk.gray(' ') + chalk.gray(adapter.name + ' — not found'));
49
- }
39
+ found = await fs.pathExists(adapter.source);
40
+ }
41
+
42
+ if (found) {
43
+ lines.push(chalk.green(' ') + chalk.white(adapter.name));
44
+ detected++;
45
+ } else {
46
+ lines.push(chalk.gray(' ○ ' + adapter.name));
50
47
  }
51
48
  }
52
49
 
53
- console.log();
54
- console.log(chalk.white(`${detected} tool${detected !== 1 ? 's' : ''} detected on this machine.`));
55
- console.log();
50
+ const summary = detected > 0
51
+ ? chalk.white(`${detected} tool${detected !== 1 ? 's' : ''} ready to sync`)
52
+ : chalk.yellow('No AI tools detected');
53
+
54
+ console.log(boxen(
55
+ gradient.pastel(' memoir status ') + '\n\n' +
56
+ configLine + '\n\n' +
57
+ chalk.bold.white('AI Tools') + '\n' +
58
+ lines.join('\n') + '\n\n' +
59
+ chalk.gray('─'.repeat(30)) + '\n' +
60
+ summary,
61
+ { padding: 1, borderStyle: 'round', borderColor: 'cyan', dimBorder: true }
62
+ ) + '\n');
56
63
  }