🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

botrun-msync

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

botrun-msync - npm Package Compare versions

Comparing version
0.2.1
to
0.3.0
+8
src/commands/config/set-data-path.mjs
import { loadConfig, saveConfig } from '../../config.mjs';
export async function setDataPath(dataPath, configPath) {
const config = await loadConfig(configPath);
config.data_path = dataPath;
await saveConfig(configPath, config);
return { data_path: dataPath };
}
+1
-1
{
"name": "botrun-msync",
"version": "0.2.1",
"version": "0.3.0",
"description": "Git-backed memory sync CLI for AI agents (forked from botrun-mcli@0.2.2)",

@@ -5,0 +5,0 @@ "type": "module",

+38
-27

@@ -82,32 +82,34 @@ # botrun-msync — Git-backed Memory Sync CLI for Agents

### Base Path
### Config 與 Data 分離
All `bms` data lives under a single base directory:
config.json(scope 定義)和 data(clone 下來的 repo)可以放在不同位置:
- **config.json** — 集中管理,預設 `~/.botrun/bms/config.json`
- **data** — 跟著使用場景走,由 `memory init` 決定位置,預設 `$PWD/data/`
```
~/.botrun/bms/ ← default base path
├── config.json ← scope definitions
└── data/
├── my-notes/ ← git clone of my-notes scope
├── team1/ ← git clone of team1 scope
└── team2/ ← git clone of team2 scope
~/.botrun/bms/config.json ← scope 定義 + data_path 指向
/your/project/data/ ← data 跟著專案走
├── my-notes/ ← git clone of my-notes scope
├── team1/ ← git clone of team1 scope
└── team2/ ← git clone of team2 scope
```
Override with CLI option or environment variable:
### Config File
預設路徑:`~/.botrun/bms/config.json`
覆蓋方式:
```bash
npx botrun-msync --bms-path /tmp/test-bms memory init # CLI option (highest priority)
BMS_PATH=/custom/path npx botrun-msync memory init # environment variable
npx botrun-msync --config-path /path/to/config.json memory init # CLI option
BMS_CONFIG=/path/to/config.json npx botrun-msync memory init # env var
```
Priority: `--bms-path` > `BMS_PATH` > `~/.botrun/bms/`
Priority: `--config-path` > `BMS_CONFIG` > `~/.botrun/bms/config.json`
### Config File
Located at `<BMS_PATH>/config.json` (default: `~/.botrun/bms/config.json`).
Override config path independently with: `BMS_CONFIG=/path/to/config.json`
```json
{
"data_path": "/your/project/data",
"scopes": {

@@ -133,2 +135,9 @@ "my-notes": {

|-------|----------|-------------|
| `data_path` | no | Absolute path to data directory. Written by `memory init` |
| `scopes` | yes | Scope definitions (see below) |
Scope fields:
| Field | Required | Description |
|-------|----------|-------------|
| `repo` | yes | Git repo URL (without `https://`) |

@@ -146,2 +155,3 @@ | `branch` | no | Git branch to use. Omit = repo default branch |

npx botrun-msync config remove-scope <name>
npx botrun-msync config set-data-path <path>
npx botrun-msync config show

@@ -154,4 +164,3 @@ ```

|----------|---------|
| `BMS_PATH` | Base directory for all bms data (default: `~/.botrun/bms`) |
| `BMS_CONFIG` | Config file path (overrides `<BMS_PATH>/config.json`) |
| `BMS_CONFIG` | Config file path (default: `~/.botrun/bms/config.json`) |

@@ -162,11 +171,13 @@ Each scope's token is configured via `--token-env`, which points to an environment variable name. There are no global token variables — every scope must declare its own.

### `npx botrun-msync memory init`
### `npx botrun-msync memory init [--data-path <path>]`
Clones all configured scope repos to `<BMS_PATH>/data/<scope-name>/`. If already cloned, pulls latest.
Clones all configured scope repos. Writes `data_path` to config.json.
Data path priority: `--data-path` > config `data_path` > `$PWD/data/`
```json
{
"scopes": {
"my-notes": { "local": "/root/.botrun/bms/data/my-notes" },
"team1": { "local": "/root/.botrun/bms/data/team1" }
"my-notes": { "local": "/your/project/data/my-notes" },
"team1": { "local": "/your/project/data/team1" }
}

@@ -187,3 +198,3 @@ }

"access": "readwrite",
"local": "/root/.botrun/bms/data/my-notes"
"local": "/your/project/data/my-notes"
},

@@ -194,3 +205,3 @@ "team1": {

"access": "readonly",
"local": "/root/.botrun/bms/data/team1"
"local": "/your/project/data/team1"
}

@@ -226,3 +237,3 @@ }

VM starts
→ npx botrun-msync memory init # clone repos to <BMS_PATH>/data/
→ npx botrun-msync memory init # clone repos to data/
→ agent reads/writes files # using native tools (Read, Write, grep)

@@ -229,0 +240,0 @@ → npx botrun-msync memory sync # push changes

@@ -8,2 +8,3 @@ #!/usr/bin/env node

import { showConfig } from './commands/config/show.mjs';
import { setDataPath } from './commands/config/set-data-path.mjs';
import { initMemory } from './commands/memory/init.mjs';

@@ -31,9 +32,9 @@ import { syncMemory } from './commands/memory/sync.mjs';

.description('Git-backed memory sync for agents')
.version('0.2.0')
.version('0.3.0')
.helpCommand(false)
.option('--bms-path <path>', 'Base directory for all bms data')
.option('--config-path <path>', 'Path to config.json')
.configureHelp({ formatHelp: (cmd) => JSON.stringify(jsonHelp(cmd), null, 2) })
.hook('preAction', (thisCommand) => {
const bmsPath = thisCommand.opts().bmsPath;
if (bmsPath) process.env.BMS_PATH = bmsPath;
const configPath = thisCommand.opts().configPath;
if (configPath) process.env.BMS_CONFIG = configPath;
});

@@ -74,2 +75,10 @@

configCmd
.command('set-data-path <path>')
.description('Update the data directory path in config')
.action(async (path) => {
const result = await setDataPath(path, getConfigPath());
console.log(JSON.stringify(result, null, 2));
});
// --- memory ---

@@ -82,4 +91,8 @@ const memoryCmd = program.command('memory').description('Manage memory repos');

.description('Clone all scope repos')
.action(async () => {
const result = await initMemory({ configPath: getConfigPath() });
.option('--data-path <path>', 'Directory to clone repos into (default: $PWD/data/)')
.action(async (opts) => {
const result = await initMemory({
configPath: getConfigPath(),
dataDir: opts.dataPath,
});
console.log(JSON.stringify(result, null, 2));

@@ -86,0 +99,0 @@ });

import { mkdir, lstat } from 'node:fs/promises';
import { join } from 'node:path';
import { loadConfig, getBasePath } from '../../config.mjs';
import { join, resolve } from 'node:path';
import { loadConfig, saveConfig, getDataPath } from '../../config.mjs';
import { gitExec } from '../../git-cmd.mjs';

@@ -54,6 +54,12 @@ import { detectProvider, getProvider, resolveToken } from '../../git/provider.mjs';

const configPath = options.configPath;
const dataDir = options.dataDir || join(getBasePath(), 'data');
const config = await loadConfig(configPath);
const localMode = options.localMode || false;
const config = await loadConfig(configPath);
// data path priority: options.dataDir > config.data_path > $PWD/data/
const dataDir = options.dataDir || getDataPath(config) || resolve('data');
// Write data_path back to config
config.data_path = dataDir;
await saveConfig(configPath, config);
const result = { scopes: {} };

@@ -60,0 +66,0 @@

import { join } from 'node:path';
import { lstat } from 'node:fs/promises';
import { loadConfig, getBasePath } from '../../config.mjs';
import { loadConfig, getDataPath } from '../../config.mjs';
export async function listScopes(options = {}) {
const config = await loadConfig(options.configPath);
const dataDir = options.dataDir || join(getBasePath(), 'data');
const dataDir = options.dataDir || getDataPath(config);
const result = { scopes: {} };

@@ -15,7 +15,11 @@

const scopeDir = join(dataDir, name);
try {
await lstat(scopeDir);
entry.local = scopeDir;
} catch {
if (dataDir) {
const scopeDir = join(dataDir, name);
try {
await lstat(scopeDir);
entry.local = scopeDir;
} catch {
entry.local = null;
}
} else {
entry.local = null;

@@ -22,0 +26,0 @@ }

import { join } from 'node:path';
import { loadConfig, getBasePath } from '../../config.mjs';
import { loadConfig, getDataPath } from '../../config.mjs';
import { gitExec } from '../../git-cmd.mjs';

@@ -7,4 +7,8 @@

const config = await loadConfig(options.configPath);
const dataDir = options.dataDir || join(getBasePath(), 'data');
const dataDir = options.dataDir || getDataPath(config);
if (!dataDir) {
throw new Error('No data_path in config. Run "bms memory init" first.');
}
const result = { synced: [], pulled: [], skipped: [] };

@@ -17,3 +21,2 @@

// 1. Always pull remote changes first
try {

@@ -25,3 +28,2 @@ const before = await gitExec(['-C', cloneDir, 'rev-parse', 'HEAD']);

} catch {
// pull may fail if no upstream set; try setting it
try {

@@ -39,3 +41,2 @@ const branch = await gitExec(['-C', cloneDir, 'rev-parse', '--abbrev-ref', 'HEAD']);

// 2. Check for local uncommitted changes and push
const status = await gitExec(['-C', cloneDir, 'status', '--porcelain']);

@@ -42,0 +43,0 @@ if (status) {

@@ -5,10 +5,10 @@ import { readFile, writeFile, mkdir } from 'node:fs/promises';

const DEFAULT_BASE_PATH = join(homedir(), '.botrun', 'bms');
const DEFAULT_CONFIG_PATH = join(homedir(), '.botrun', 'bms', 'config.json');
export function getBasePath() {
return process.env.BMS_PATH || DEFAULT_BASE_PATH;
export function getConfigPath() {
return process.env.BMS_CONFIG || DEFAULT_CONFIG_PATH;
}
export function getConfigPath() {
return process.env.BMS_CONFIG || join(getBasePath(), 'config.json');
export function getDataPath(config) {
return config.data_path || null;
}

@@ -15,0 +15,0 @@