The Basic Memory Cloud CLI provides seamless integration between local and cloud knowledge bases using project-scoped synchronization. Each project can optionally sync with the cloud, giving you fine-grained control over what syncs and where.
The cloud CLI enables you to:
- Toggle cloud mode - All regular
bmcommands work with cloud when enabled - Project-scoped sync - Each project independently manages its sync configuration
- Explicit operations - Sync only what you want, when you want
- Bidirectional sync - Keep local and cloud in sync with rclone bisync
- Offline access - Work locally, sync when ready
Before using Basic Memory Cloud, you need:
- Active Subscription: An active Basic Memory Cloud subscription is required to access cloud features
- Subscribe: Visit https://basicmemory.com/subscribe to sign up
- Optional: Cloud is optional. Local-first open-source usage continues without cloud.
- OSS Discount: Use code
{{OSS_DISCOUNT_CODE}}for 20% off for 3 months.
If you attempt to log in without an active subscription, you'll receive a "Subscription Required" error with a link to subscribe.
Old approach (SPEC-8): All projects lived in a single ~/basic-memory-cloud-sync/ directory. This caused:
- ❌ Directory conflicts between mount and bisync
- ❌ Auto-discovery creating phantom projects
- ❌ Confusion about what syncs and when
- ❌ All-or-nothing sync (couldn't sync just one project)
New approach (SPEC-20): Each project independently configures sync.
Projects can exist in three states:
- Cloud-only - Project exists on cloud, no local copy
- Cloud + Local (synced) - Project has a local working directory that syncs
- Local-only - Project exists locally (when cloud mode is disabled)
Example:
# You have 3 projects on cloud:
# - research: wants local sync at ~/Documents/research
# - work: wants local sync at ~/work-notes
# - temp: cloud-only, no local sync needed
bm project add research --local-path ~/Documents/research
bm project add work --local-path ~/work-notes
bm project add temp # No local sync
# Now you can sync individually (after initial --resync):
bm project bisync --name research
bm project bisync --name work
# temp stays cloud-onlyWhat happens under the covers:
- Config stores
cloud_projectsdict mapping project names to local paths - Each project gets its own bisync state in
~/.basic-memory/bisync-state/{project}/ - Rclone syncs using single remote:
basic-memory-cloud - Projects can live anywhere on your filesystem, not forced into sync directory
Authenticate and enable cloud mode:
bm cloud loginWhat this does:
- Opens browser to Basic Memory Cloud authentication page
- Stores authentication token in
~/.basic-memory/auth/token - Enables cloud mode - all CLI commands now work against cloud
- Validates your subscription status
Result: All bm project, bm tools commands now work with cloud.
Apply OSS discount code {{OSS_DISCOUNT_CODE}} during checkout to receive 20% off for 3 months.
Install rclone and configure credentials:
bm cloud setupWhat this does:
- Installs rclone automatically (if needed)
- Fetches your tenant information from cloud
- Generates scoped S3 credentials for sync
- Configures single rclone remote:
basic-memory-cloud
Result: You're ready to sync projects. No sync directories created yet - those come with project setup.
Create projects with optional local sync paths:
# Create cloud project without local sync
bm project add research
# Create cloud project WITH local sync
bm project add research --local-path ~/Documents/research
# Or configure sync for existing project
bm project sync-setup research ~/Documents/researchWhat happens under the covers:
When you add a project with --local-path:
- Project created on cloud at
/app/data/research - Local path stored in config:
cloud_projects.research.local_path = "~/Documents/research" - Local directory created if it doesn't exist
- Bisync state directory created at
~/.basic-memory/bisync-state/research/
Result: Project is ready to sync, but no files synced yet.
Establish the initial sync baseline. Best practice: Always preview with --dry-run first:
# Step 1: Preview the initial sync (recommended)
bm project bisync --name research --resync --dry-run
# Step 2: If all looks good, run the actual sync
bm project bisync --name research --resyncWhat happens under the covers:
- Rclone reads from
~/Documents/research(local) - Connects to
basic-memory-cloud:bucket-name/app/data/research(remote) - Creates bisync state files in
~/.basic-memory/bisync-state/research/ - Syncs files bidirectionally with settings:
conflict_resolve=newer(most recent wins)max_delete=25(safety limit)- Respects
.bmignorepatterns
Result: Local and cloud are in sync. Baseline established.
Why --resync? This is an rclone requirement for the first bisync run. It establishes the initial state that future syncs will compare against. After the first sync, never use --resync unless you need to force a new baseline.
See: https://rclone.org/bisync/#resync
--resync
This will effectively make both Path1 and Path2 filesystems contain a matching superset of all files. By default, Path2 files that do not exist in Path1 will be copied to Path1, and the process will then copy the Path1 tree to Path2.
After the first sync, just run bisync without --resync:
bm project bisync --name researchWhat happens:
- Rclone compares local and cloud states
- Syncs changes in both directions
- Auto-resolves conflicts (newer file wins)
- Updates
last_synctimestamp in config
Result: Changes flow both ways - edit locally or in cloud, both stay in sync.
Check status:
bm cloud statusYou should see:
Mode: Cloud (enabled)Cloud instance is healthy- Instructions for project sync commands
Key concept: When cloud mode is enabled, use regular bm project commands (not bm cloud project).
# In cloud mode:
bm project list # Lists cloud projects
bm project add research # Creates cloud project
# In local mode:
bm project list # Lists local projects
bm project add research ~/Documents/research # Creates local projectUse case 1: Cloud-only project (no local sync)
bm project add temp-notesWhat this does:
- Creates project on cloud at
/app/data/temp-notes - No local directory created
- No sync configuration
Result: Project exists on cloud, accessible via MCP tools, but no local copy.
Use case 2: Cloud project with local sync
bm project add research --local-path ~/Documents/researchWhat this does:
- Creates project on cloud at
/app/data/research - Creates local directory
~/Documents/research - Stores sync config in
~/.basic-memory/config.json - Prepares for bisync (but doesn't sync yet)
Result: Project ready to sync. Run bm project bisync --name research --resync to establish baseline.
Use case 3: Add sync to existing cloud project
# Project already exists on cloud
bm project sync-setup research ~/Documents/researchWhat this does:
- Updates existing project's sync configuration
- Creates local directory
- Prepares for bisync
Result: Existing cloud project now has local sync path. Run bisync to pull files down.
View all projects:
bm project listWhat you see:
- All projects in cloud (when cloud mode enabled)
- Default project marked
- Project paths shown
Future: Will show sync status (synced/not synced, last sync time).
There are three sync-related commands:
bm project sync- One-way: local → cloud (make cloud match local)bm project bisync- Two-way: local ↔ cloud (recommended)bm project check- Verify files match (no changes)
Use case: You made changes locally and want to push to cloud (overwrite cloud).
bm project sync --name researchWhat happens:
- Reads files from
~/Documents/research(local) - Uses rclone sync to make cloud identical to local
- Respects
.bmignorepatterns - Shows progress bar
Result: Cloud now matches local exactly. Any cloud-only changes are overwritten.
When to use:
- You know local is the source of truth
- You want to force cloud to match local
- You don't care about cloud changes
Use case: You edit files both locally and in cloud UI, want both to stay in sync.
# First time - establish baseline
bm project bisync --name research --resync
# Subsequent syncs
bm project bisync --name researchWhat happens:
- Compares local and cloud states using bisync metadata
- Syncs changes in both directions
- Auto-resolves conflicts (newer file wins)
- Detects excessive deletes and fails safely (max 25 files)
Conflict resolution example:
# Edit locally
echo "Local change" > ~/Documents/research/notes.md
# Edit same file in cloud UI
# Cloud now has: "Cloud change"
# Run bisync
bm project bisync --name research
# Result: Newer file wins (based on modification time)
# If cloud was more recent, cloud version kept
# If local was more recent, local version keptWhen to use:
- Default workflow for most users
- You edit in multiple places
- You want automatic conflict resolution
Use case: Check if local and cloud match without making changes.
bm project check --name researchWhat happens:
- Compares file checksums between local and cloud
- Reports differences
- No files transferred
Result: Shows which files differ. Run bisync to sync them.
# One-way check (faster)
bm project check --name research --one-wayUse case: See what would change without actually syncing.
bm project bisync --name research --dry-runWhat happens:
- Runs bisync logic
- Shows what would be transferred/deleted
- No actual changes made
Result: Safe preview of sync operations.
Use case: See what files exist on cloud without syncing.
# List all files in project
bm project ls --name research
# List files in subdirectory
bm project ls --name research --path subfolderWhat happens:
- Connects to cloud via rclone
- Lists files in remote project path
- No files transferred
Result: See cloud file listing.
Use case: You have several projects with local sync, want to sync all at once.
# Setup multiple projects
bm project add research --local-path ~/Documents/research
bm project add work --local-path ~/work-notes
bm project add personal --local-path ~/personal
# Establish baselines
bm project bisync --name research --resync
bm project bisync --name work --resync
bm project bisync --name personal --resync
# Daily workflow: sync everything
bm project bisync --name research
bm project bisync --name work
bm project bisync --name personalFuture: --all flag will sync all configured projects:
bm project bisync --all # Coming soonUse case: Some projects sync, some stay cloud-only.
# Projects with sync
bm project add research --local-path ~/Documents/research
bm project add work --local-path ~/work
# Cloud-only projects
bm project add archive
bm project add temp-notes
# Sync only the configured ones
bm project bisync --name research
bm project bisync --name work
# Archive and temp-notes stay cloud-onlyResult: Fine-grained control over what syncs.
Instead of toggling global cloud mode, you can route individual projects through the cloud using an API key. This lets you keep some projects local while others route through the cloud.
Option A: Create a key in the web app, then save it locally:
bm cloud set-key bmc_abc123...Option B: Create a key via CLI (requires OAuth login first):
bm cloud login # One-time OAuth login
bm cloud create-key "my-laptop" # Creates key and saves it locallyThe API key is account-level — it grants access to all your cloud projects. It's stored in ~/.basic-memory/config.json as cloud_api_key.
# Route a project through cloud
bm project set-cloud research
# Revert to local mode
bm project set-local research
# View project modes
bm project listWhat happens:
set-cloud: validates the API key exists, then sets the project mode tocloudin configset-local: reverts the project to local mode (removes the mode entry from config)- MCP tools and CLI commands for that project will route to
cloud_host/proxywith the API key as Bearer token
When an MCP tool or CLI command runs for a cloud-mode project:
get_client(project_name="research")checks the project's mode in config- If mode is
cloud, creates an HTTP client pointed atcloud_host/proxywithAuthorization: Bearer bmc_... - If mode is
local(default), uses the in-process ASGI transport as usual
Routing priority (highest to lowest):
- Factory injection (cloud app, tests)
BASIC_MEMORY_FORCE_LOCALenv var- Per-project cloud mode (API key)
- Global cloud mode (OAuth — deprecated fallback)
- Local ASGI transport (default)
{
"projects": {
"personal": "/Users/me/notes",
"research": "/Users/me/research"
},
"project_modes": {
"research": "cloud"
},
"cloud_api_key": "bmc_abc123...",
"cloud_host": "https://cloud.basicmemory.com",
"default_project": "personal"
}In this example, personal stays local and research routes through cloud. Projects not listed in project_modes default to local.
Cloud-mode projects are automatically skipped during local file sync (background sync and file watching). Their files live on the cloud instance, not locally.
Return to local mode (global):
bm cloud logoutWhat this does:
- Disables global cloud mode in config
- All commands now work locally (unless individual projects are set to cloud via
set-cloud) - Auth token remains (can re-enable with login)
Result: All bm commands work with local projects again. Per-project cloud routing via API key continues to work independently of global cloud mode.
The problem: You don't want to sync everything (e.g., .git, node_modules, database files).
The solution: .bmignore file with gitignore-style patterns.
Location: ~/.basic-memory/.bmignore
Default patterns:
# Version control
.git/**
# Python
__pycache__/**
*.pyc
.venv/**
venv/**
# Node.js
node_modules/**
# Basic Memory internals
memory.db/**
memory.db-shm/**
memory.db-wal/**
config.json/**
watch-status.json/**
.bmignore.rclone/**
# OS files
.DS_Store/**
Thumbs.db/**
# Environment files
.env/**
.env.local/**How it works:
- On first sync,
.bmignorecreated with defaults - Patterns converted to rclone filter format (
.bmignore.rclone) - Rclone uses filters during sync
- Same patterns used by all projects
Customizing:
# Edit patterns
code ~/.basic-memory/.bmignore
# Add custom patterns
echo "*.tmp/**" >> ~/.basic-memory/.bmignore
# Next sync uses updated patterns
bm project bisync --name researchProblem: "Authentication failed" or "Invalid token"
Solution: Re-authenticate:
bm cloud logout
bm cloud loginProblem: "Subscription Required" error
Solution:
- Visit subscribe URL shown in error
- Sign up for subscription
- Run
bm cloud loginagain
Note: Access is immediate when subscription becomes active.
Problem: "First bisync requires --resync"
Explanation: Bisync needs a baseline state before it can sync changes.
Solution:
bm project bisync --name research --resyncWhat this does:
- Establishes initial sync state
- Creates baseline in
~/.basic-memory/bisync-state/research/ - Syncs all files bidirectionally
Result: Future syncs work without --resync.
Problem: "Empty prior Path1 listing. Cannot sync to an empty directory"
Explanation: Rclone bisync doesn't work well with completely empty directories. It needs at least one file to establish a baseline.
Solution: Add at least one file before running --resync:
# Create a placeholder file
echo "# Research Notes" > ~/Documents/research/README.md
# Now run bisync
bm project bisync --name research --resyncWhy this happens: Bisync creates listing files that track the state of each side. When both directories are completely empty, these listing files are considered invalid by rclone.
Best practice: Always have at least one file (like a README.md) in your project directory before setting up sync.
Problem: Bisync fails with errors about corrupted state or listing files
Explanation: Sometimes bisync state can become inconsistent (e.g., after mixing dry-run and actual runs, or after manual file operations).
Solution: Clear bisync state and re-establish baseline:
# Clear bisync state
bm project bisync-reset research
# Re-establish baseline
bm project bisync --name research --resyncWhat this does:
- Removes all bisync metadata from
~/.basic-memory/bisync-state/research/ - Forces fresh baseline on next
--resync - Safe operation (doesn't touch your files)
Note: This command also runs automatically when you remove a project to clean up state directories.
Problem: "Error: max delete limit (25) exceeded"
Explanation: Bisync detected you're about to delete more than 25 files. This is a safety check to prevent accidents.
Solution 1: Review what you're deleting, then force resync:
# Check what would be deleted
bm project bisync --name research --dry-run
# If correct, establish new baseline
bm project bisync --name research --resyncSolution 2: Use one-way sync if you know local is correct:
bm project sync --name researchProblem: "Project research has no local_sync_path configured"
Explanation: Project exists on cloud but has no local sync path.
Solution:
bm project sync-setup research ~/Documents/research
bm project bisync --name research --resyncProblem: "Cannot connect to cloud instance"
Solution: Check status:
bm cloud statusIf instance is down, wait a few minutes and retry.
- Authentication: OAuth 2.1 with PKCE flow
- Tokens: Stored securely in
~/.basic-memory/basic-memory-cloud.json - Transport: All data encrypted in transit (HTTPS)
- Credentials: Scoped S3 credentials (read-write to your tenant only)
- Isolation: Your data isolated from other tenants
- Ignore patterns: Sensitive files automatically excluded via
.bmignore
bm cloud login # Authenticate and enable global cloud mode (OAuth)
bm cloud logout # Disable global cloud mode
bm cloud status # Check cloud mode and instance health
bm cloud promo --off # Disable CLI cloud promo noticesbm cloud set-key <key> # Save a cloud API key (bmc_ prefixed)
bm cloud create-key <name> # Create API key via cloud API (requires OAuth login)bm cloud setup # Install rclone and configure credentialsWhen cloud mode is enabled:
bm project list # List projects with mode column
bm project add <name> # Create cloud project (no sync)
bm project add <name> --local-path <path> # Create with local sync
bm project sync-setup <name> <path> # Add sync to existing project
bm project rm <name> # Delete projectbm project set-cloud <name> # Route project through cloud (requires API key)
bm project set-local <name> # Revert project to local mode# One-way sync (local → cloud)
bm project sync --name <project>
bm project sync --name <project> --dry-run
bm project sync --name <project> --verbose
# Two-way sync (local ↔ cloud) - Recommended
bm project bisync --name <project> # After first --resync
bm project bisync --name <project> --resync # First time / force baseline
bm project bisync --name <project> --dry-run
bm project bisync --name <project> --verbose
# Integrity check
bm project check --name <project>
bm project check --name <project> --one-way
# List remote files
bm project ls --name <project>
bm project ls --name <project> --path <subpath>Basic Memory Cloud uses project-scoped sync:
- Enable cloud mode -
bm cloud login - Install rclone -
bm cloud setup - Add projects with sync -
bm project add research --local-path ~/Documents/research - Preview first sync -
bm project bisync --name research --resync --dry-run - Establish baseline -
bm project bisync --name research --resync - Daily workflow -
bm project bisync --name research
Key benefits:
- ✅ Each project independently syncs (or doesn't)
- ✅ Projects can live anywhere on disk
- ✅ Explicit sync operations (no magic)
- ✅ Safe by design (max delete limits, conflict resolution)
- ✅ Full offline access (work locally, sync when ready)
Future enhancements:
--allflag to sync all configured projects- Project list showing sync status
- Watch mode for automatic sync