bm — Git-backed Memory CLI for Agents
bm manages persistent memory for AI agents across ephemeral VMs. Memories are stored as files in Git repos (GitHub / GitLab), and bm handles the git plumbing — clone, sync, and scope management. Agents read/write memory files directly using their own tools.
Install
npx bm --help
Quick Start
npx bm config add-scope my-notes \
--repo github.com/your-org/agent-memory \
--token-env MY_GITHUB_TOKEN \
--description "My personal notes" \
--access readwrite
export MY_GITHUB_TOKEN=ghp_xxxxx
npx bm memory init
npx bm memory sync
Concepts
Scope
A scope is a logical name that maps to a git repo. Each agent can have multiple scopes pointing to different repos.
npx bm config add-scope my-notes \
--repo github.com/org/my-memory \
--token-env BM_TOKEN_NOTES \
--description "Personal research notes" \
--access readwrite
Multi-Repo Architecture
Different scopes can point to different repos. Permissions are controlled by Git provider tokens — not by bm. Each scope binds to its own token via --token-env, enabling per-repo permission control.
npx bm config add-scope director \
--repo github.com/org/director-memory \
--token-env BM_TOKEN_DIRECTOR \
--description "Director personal research" \
--access readwrite
npx bm config add-scope team1 \
--repo github.com/org/team1-memory \
--token-env BM_TOKEN_TEAMS \
--description "Team 1 memory" \
--access readonly
npx bm config add-scope team2 \
--repo github.com/org/team2-memory \
--token-env BM_TOKEN_TEAMS \
--description "Team 2 memory" \
--access readonly
Create separate GitHub Fine-grained PATs with different permissions:
BM_TOKEN_DIRECTOR → Contents: Read and write (only director-memory repo)
BM_TOKEN_TEAMS → Contents: Read-only (only team1-memory + team2-memory repos)
This way, even if a user modifies the config, they can't write to repos their token doesn't allow.
Config
Base Path
All bm data lives under a single base directory:
~/.botrun/bm/ ← 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
Override with CLI option or environment variable:
npx bm --bm-path /tmp/test-bm memory init
BM_PATH=/custom/path npx bm memory init
Priority: --bm-path > BM_PATH > ~/.botrun/bm/
Config File
Located at <BM_PATH>/config.json (default: ~/.botrun/bm/config.json).
Override config path independently with: BM_CONFIG=/path/to/config.json
{
"scopes": {
"my-notes": {
"repo": "github.com/org/member1-memory",
"token_env": "BM_TOKEN_NOTES",
"description": "Personal research notes",
"access": "readwrite"
},
"team1": {
"repo": "github.com/org/team1-memory",
"branch": "dev",
"token_env": "BM_TOKEN_TEAMS",
"description": "Team 1 memory",
"access": "readonly"
}
}
}
repo | yes | Git repo URL (without https://) |
branch | no | Git branch to use. Omit = repo default branch |
token_env | no | Env var name for this scope's token (for per-repo permission control) |
description | no | Description for agent context |
access | no | Access hint for agent: readwrite or readonly (default: readwrite) |
provider | no | github or gitlab. Auto-detected from URL |
Config Commands
npx bm config add-scope <name> --repo <url> [--branch <branch>] [--token-env <envVar>] [--description <text>] [--access <mode>]
npx bm config remove-scope <name>
npx bm config show
Environment Variables
BM_PATH | Base directory for all bm data (default: ~/.botrun/bm) |
BM_CONFIG | Config file path (overrides <BM_PATH>/config.json) |
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.
Memory Commands
npx bm memory init
Clones all configured scope repos to <BM_PATH>/data/<scope-name>/. If already cloned, pulls latest.
{
"scopes": {
"my-notes": { "local": "/root/.botrun/bm/data/my-notes" },
"team1": { "local": "/root/.botrun/bm/data/team1" }
}
}
npx bm memory scopes
Lists all scopes with their repo, description, access, and local filesystem path.
{
"scopes": {
"my-notes": {
"repo": "github.com/org/member1-memory",
"description": "Personal research notes",
"access": "readwrite",
"local": "/root/.botrun/bm/data/my-notes"
},
"team1": {
"repo": "github.com/org/team1-memory",
"description": "Team 1 memory",
"access": "readonly",
"local": "/root/.botrun/bm/data/team1"
}
}
}
npx bm memory sync
Commits and pushes all changed memory files back to remote repos.
{
"synced": ["my-notes"],
"skipped": ["team1"]
}
JSON Output
All commands output structured JSON, including --help:
npx bm --help
npx bm config --help
npx bm memory --help
Agent Lifecycle
VM starts
→ npx bm memory init # clone repos to <BM_PATH>/data/
→ agent reads/writes files # using native tools (Read, Write, grep)
→ npx bm memory sync # push changes
VM destroyed
Development
npm install
npm test
License
MIT