---
title: "CLI Reference"
description: "Command-line reference for Basic Memory local and cloud workflows."
canonical_url: "https://docs.basicmemory.com/reference/cli-reference"
---
# CLI Reference

> Command-line reference for Basic Memory local and cloud workflows.

Use `bm` (short) or `basic-memory` (full). Examples below use `bm`.

<note>

**New in v0.24:** shell-style read commands (`bm cat`, `bm head`, `bm grep`, `bm ls`, `bm find`, `bm tail`, `bm tree`), a bundled manual (`bm man`), `bm wiki`, `bm okf`, `bm prune`, `bm import document`, and `bm install`. See [What's new in v0.24](https://docs.basicmemory.com/whats-new/v0-24) and the [v0.24 upgrade guide](https://docs.basicmemory.com/whats-new/v0-24-upgrade) for behavior changes.

</note>

Every command also has a manual page: `bm man list` lists them and `bm man <page>` prints one (see [Manual commands](#manual-commands)).

---

## Core commands

### `bm status`

Show the current project-index observation and readiness: how many project files were seen, with file details under `--verbose`. Use `--json` for automation.

```bash
bm status
bm status --verbose
bm status --json
bm status --project research
bm status --wait --timeout 60
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --verbose
      </code>
      
      , <code>
        -v
      </code>
    </td>
    
    <td>
      Show detailed file information
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --wait
      </code>
    </td>
    
    <td>
      Poll until every readiness stage settles (or <code>
        --timeout
      </code>
      
       elapses)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --timeout
      </code>
    </td>
    
    <td>
      Seconds to wait when <code>
        --wait
      </code>
      
       is set (default <code>
        30
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

In v0.24, `--json` reports readiness per stage. `readiness.stages` covers file indexing, relation resolution, and embeddings separately, and `readiness.phase` tells a project that was never indexed apart from one that is indexed and idle. `--wait` now blocks until every stage settles, embeddings included, not just until file changes are processed.

### `bm doctor`

Run local consistency checks to verify file/database sync. Defaults to local routing since it scans the local filesystem.

```bash
bm doctor
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm mcp`

Run the MCP server with configurable transport options. The server handles initialization, file sync, and cleanup automatically.

```bash
# Default: stdio transport (for Claude Desktop, Claude Code, etc.)
bm mcp

# Lock to a single project
bm mcp --project main

# HTTP transport (binds 127.0.0.1 by default)
bm mcp --transport streamable-http --port 8000

# SSE transport for compatibility with existing clients
bm mcp --transport sse

# Accept connections from other machines (no authentication; trusted networks only)
bm mcp --transport streamable-http --host 0.0.0.0
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --transport
      </code>
    </td>
    
    <td>
      Transport type: <code>
        stdio
      </code>
      
       (default), <code>
        streamable-http
      </code>
      
      , <code>
        sse
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --host
      </code>
    </td>
    
    <td>
      Host for HTTP transports (default <code>
        127.0.0.1
      </code>
      
      ; use <code>
        0.0.0.0
      </code>
      
       to allow external connections)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --port
      </code>
    </td>
    
    <td>
      Port for HTTP transports (default <code>
        8000
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --path
      </code>
    </td>
    
    <td>
      Path prefix for streamable-http transport (default <code>
        /mcp
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Restrict MCP server to a single project
    </td>
  </tr>
</tbody>
</table>

<warning>

**Changed in v0.24:** the HTTP transports (`streamable-http` and `sse`) bind to `127.0.0.1` by default instead of `0.0.0.0`. The HTTP server has no authentication, so it is no longer reachable from the network unless you pass a non-loopback `--host`. When you do, the command prints a warning on startup.

On a loopback bind, both HTTP transports also reject requests whose `Host` or `Origin` header is foreign. This blocks DNS-rebinding attacks from a browser tab. To allow extra hosts or origins, set FastMCP's `FASTMCP_HTTP_ALLOWED_HOSTS` and `FASTMCP_HTTP_ALLOWED_ORIGINS`. A non-loopback bind gets the Host/Origin check only when those allowlists are set. The official Docker image already passes `--host 0.0.0.0` and works as before.

</warning>

<note>

This command works regardless of cloud mode setting. Users with cloud mode enabled can still run a local MCP server for Claude Code and Claude Desktop.

</note>

### `bm reindex`

Rebuild search indexes and/or vector embeddings without dropping the database.

```bash
# Rebuild everything (search + embeddings)
bm reindex

# Rebuild only full-text search index
bm reindex --search
bm reindex -s

# Rebuild only vector embeddings
bm reindex --embeddings
bm reindex -e

# Reindex a specific project
bm reindex -p main
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --search
      </code>
      
      , <code>
        -s
      </code>
    </td>
    
    <td>
      Rebuild only the full-text search index
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --embeddings
      </code>
      
      , <code>
        -e
      </code>
    </td>
    
    <td>
      Rebuild only vector embeddings
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --full
      </code>
    </td>
    
    <td>
      Force a complete rebuild and re-embed (the default run is incremental and skips unchanged content)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
      
      , <code>
        -p
      </code>
    </td>
    
    <td>
      Target a specific project (default: all projects)
    </td>
  </tr>
</tbody>
</table>

When neither `--search` nor `--embeddings` is specified, both are rebuilt. To index a single project by name, `bm project index NAME` does the same as `bm reindex --project NAME`.

`bm reindex --embeddings` exits nonzero if any embedding fails and reports the configured vector index. Changing `semantic_vector_index` requires this command; until it succeeds, vector search returns no results and hybrid search serves full-text results only.

In v0.24, semantic search is always on, so `--embeddings` never refuses. It also finishes oversized notes before reporting success. Vector sync embeds at most 256 chunks of one note per pass, and the reindex now repeats passes until no deferred chunks remain. With `--full`, vectors are cleared only once. If a pass stops making progress, the command reports how many notes still have pending chunks and exits nonzero.

### `bm prune`

Remove index entries for files that your current `.bmignore` or `.gitignore` patterns now exclude. Indexing skips ignored files, but entries indexed before a pattern was added stay in the index because the files are still on disk. Like `git rm --cached`, `prune` removes the index entries (entity, relations, search rows, vectors) and leaves the files untouched.

```bash
bm prune --dry-run
bm prune
bm prune --project research --yes
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
      
      , <code>
        -p
      </code>
    </td>
    
    <td>
      Project to prune (defaults to the default project)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --dry-run
      </code>
    </td>
    
    <td>
      List what would be removed without deleting anything
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --yes
      </code>
      
      , <code>
        -y
      </code>
    </td>
    
    <td>
      Delete without a confirmation prompt
    </td>
  </tr>
</tbody>
</table>

`prune` lists the entries before removing them. For cloud projects, use [`bm cloud prune`](#sync) instead.

### `bm reset`

Reset database — drops all tables and recreates them. Files are never deleted.

```bash
bm reset
bm reset --reindex
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --reindex
      </code>
    </td>
    
    <td>
      Rebuild the database index from filesystem after reset
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --force
      </code>
    </td>
    
    <td>
      Skip the pre-flight check that refuses to reset while a <code>
        basic-memory mcp
      </code>
      
       process is running. Use only in automation where you've ensured no MCP clients are attached.
    </td>
  </tr>
</tbody>
</table>

<warning>

This rebuilds the entire database from your files. Safe (files are untouched) but may take time for large knowledge bases. `bm reset` refuses to run while an MCP server is attached to the database — stop it first, or pass `--force` in automated workflows.

</warning>

### `bm orphans`

List entities that have no relations — no incoming or outgoing connections in the knowledge graph. Useful for finding notes that aren't yet linked to anything, or notes that had their relations removed.

```bash
bm orphans
bm orphans --json
bm orphans --project research
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm update`

Check for a newer Basic Memory release and install it when supported. Basic Memory also checks for updates automatically in the background for Homebrew and `uv tool` installs (uvx environments are skipped — uvx resolves its own cache); MCP server processes check silently and never block.

```bash
# Check for updates and install if available
bm update

# Check only — report without installing
bm update --check
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --check
      </code>
    </td>
    
    <td>
      Check for updates only; do not install
    </td>
  </tr>
</tbody>
</table>

<note>

Auto-update behavior is configurable — see [Configuration](https://docs.basicmemory.com/reference/configuration) for the `auto_update` and `update_check_interval` settings.

</note>

### `bm format`

Format files using configured formatters. Uses the `formatter_command` or `formatters` settings from your config. By default, formats all `.md`, `.json`, and `.canvas` files in the current project.

```bash
bm format                         # Format all files in current project
bm format --project research      # Format files in specific project
bm format notes/meeting.md        # Format a specific file
bm format notes/                  # Format all files in a directory
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
      
      , <code>
        -p
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
</tbody>
</table>

---

## Shell-style read commands

New in v0.24. These read-only verbs mirror the familiar Unix tools and share one translation layer with the MCP `cat`, `grep`, `ls`, `find`, and `tail` tools. All of them accept `--project`, `--project-id`, `--local`, and `--cloud`, plus `--json` and `--plain` for output. They follow the same output rules as [`bm tool`](#tool-commands-cli-wrapper-for-mcp-tools): Rich on a TTY, JSON when piped.

Projects act as mount points. `bm ls /` lists your projects as top-level directories, and a path whose first segment names a project routes to that project (`bm ls /research/specs`). The paths these commands return can be passed straight back in.

### `bm cat`

Print a note, resolved exactly by title, permalink, or `memory://` URL. Notes are indexed by heading, so you can read one section, a line range, or a token budget instead of the whole note.

```bash
bm cat specs/search
bm cat specs/search --lines 20-40
bm cat specs/search --section Decisions
bm cat specs/search --section "Auth/Decisions"
bm cat specs/search --max-tokens 500 --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --lines
      </code>
    </td>
    
    <td>
      Line range: <code>
        N-M
      </code>
      
      , <code>
        N-
      </code>
      
       (to end), or <code>
        N
      </code>
      
       (one line); 1-indexed and inclusive
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --section
      </code>
    </td>
    
    <td>
      Heading slice: <code>
        Decisions
      </code>
      
      , a path such as <code>
        Auth/Decisions
      </code>
      
      , or <code>
        Heading[1]
      </code>
      
       for a duplicate heading
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --max-tokens
      </code>
    </td>
    
    <td>
      Approximate token budget; truncates at a section or paragraph boundary
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --frontmatter
      </code>
      
      , <code>
        --no-frontmatter
      </code>
    </td>
    
    <td>
      Include the YAML frontmatter block (default on; ignored for section and token slices)
    </td>
  </tr>
</tbody>
</table>

`--lines` and `--section` cannot be combined. A section response includes `start_line` and `end_line` for follow-up `--lines` reads. With `--plain`, the raw content goes to stdout and slice details go to stderr.

### `bm head`

Print the first lines of a note (`head(1)` over `bm cat`).

```bash
bm head specs/search
bm head specs/search -n 3 --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --lines
      </code>
      
      , <code>
        -n
      </code>
    </td>
    
    <td>
      Number of lines to print from line 1 (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --frontmatter
      </code>
      
      , <code>
        --no-frontmatter
      </code>
    </td>
    
    <td>
      Include the YAML frontmatter block (default on)
    </td>
  </tr>
</tbody>
</table>

### `bm grep`

Search note content by keyword. A pattern found in no note returns no results. The pattern is tokenized like a full-text query, not treated as a regex. Pass `--semantic` to rank by meaning instead; semantic results are nearest neighbours, so they can include notes that do not contain the pattern.

```bash
bm grep "BASIC_MEMORY_FORCE_LOCAL"
bm grep "retry" -C 3 --plain
bm grep --semantic "auth token rotation"
bm grep "deploy checklist" --page-size 20 --json
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --semantic
      </code>
      
      , <code>
        -s
      </code>
    </td>
    
    <td>
      Rank by meaning instead of matching keywords
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --context-lines
      </code>
      
      , <code>
        -C
      </code>
    </td>
    
    <td>
      Return compact line-match windows with <code>
        N
      </code>
      
       lines of context (0–10; not with <code>
        --semantic
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --max-matches
      </code>
    </td>
    
    <td>
      Matching lines per candidate note in context mode (1–100, default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Results per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

With `-C N`, the full-text index selects candidate notes, and their current content is checked for case-insensitive literal matches. Overlapping windows merge. Line numbers include frontmatter, so you can pass them straight to `bm cat NOTE --lines N-M` or `bm tool read-note NOTE --start-line N --end-line M`. Pagination and totals count candidate notes, not matching lines.

### `bm ls`

List the immediate contents of one directory. Directories print with a trailing slash. With no path, `bm ls` lists `/`, where each project appears as a directory.

```bash
bm ls
bm ls /research
bm ls /research/specs
bm ls /main/notes --page 2 --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Entries per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

`--plain` prints one path per line, `ls -1` style. When more pages exist, `--plain` reports that on stderr so stdout stays clean for pipes.

### `bm find`

Recursively list files by name glob, or query notes by frontmatter metadata.

```bash
# List files
bm find --name "*.md"
bm find /specs --depth 3
bm find /notes --name "auth*" --plain

# Query notes by frontmatter
bm find /specs --meta "status=active" --meta "confidence>0.6"
bm find --meta "priority in high,critical" --fields title,priority,owner
bm find --meta "tags has security" --meta "owner=null"
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --name
      </code>
    </td>
    
    <td>
      File-name glob, e.g. <code>
        "*.md"
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --depth
      </code>
    </td>
    
    <td>
      Recursion depth, 1–10 (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --meta
      </code>
    </td>
    
    <td>
      Metadata predicate (repeatable; all must hold)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --fields
      </code>
    </td>
    
    <td>
      Comma-separated frontmatter fields to return per hit (requires <code>
        --meta
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Entries per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

Predicates use one key per `--meta` flag:

<table>
<thead>
  <tr>
    <th>
      Predicate
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        status=active
      </code>
    </td>
    
    <td>
      Equality
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        confidence>0.6
      </code>
    </td>
    
    <td>
      Comparison (<code>
        >
      </code>
      
      , <code>
        >=
      </code>
      
      , <code>
        <
      </code>
      
      , <code>
        <=
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        priority in high,critical
      </code>
    </td>
    
    <td>
      Any of the listed values
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tags has security,oauth
      </code>
    </td>
    
    <td>
      Array contains all listed values
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        score between 0.3,0.8
      </code>
    </td>
    
    <td>
      Inclusive range
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        owner=null
      </code>
    </td>
    
    <td>
      Key missing or explicitly null
    </td>
  </tr>
</tbody>
</table>

Values are inferred as JSON scalars, so `true`, `false`, `null`, and numbers are typed. Quote a value to force a literal string, for example `status="true"`. Keys accept dot-paths into nested frontmatter (`review.approved`). `PATH` still scopes a `--meta` query, by file path. `--name` and `--depth` are refused alongside `--meta`.

`--fields` works like a SELECT clause. Each hit returns the note's identity (title, permalink, file path, external ID, last updated) plus a `fields` object with the named values, instead of the note body. `--plain` reports further pages on stderr.

### `bm tail`

Show the most recently changed notes in a project, newest first. This is the tail of the change log, not of one file.

```bash
bm tail
bm tail -n 20 --timeframe 1d
bm tail --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --timeframe
      </code>
    </td>
    
    <td>
      Time window, e.g. <code>
        7d
      </code>
      
      , <code>
        yesterday
      </code>
      
       (default <code>
        7d
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --lines
      </code>
      
      , <code>
        -n
      </code>
    </td>
    
    <td>
      Rows to show, 1–100 (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

Each row shows the last-change time (`updated_at`), type, title, permalink, and file path.

### `bm tree`

Show a directory hierarchy (`tree(1)` over `bm find`).

```bash
bm tree
bm tree /specs --depth 2
bm tree --name "*.md" --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --name
      </code>
    </td>
    
    <td>
      File-name glob
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --depth
      </code>
    </td>
    
    <td>
      Recursion depth, 1–10 (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Entries per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

---

## Manual commands

New in v0.24. The manual ships inside the package. Section 1 covers the shell commands (`cat(1)`, `grep(1)`, `okf-export(1)`, ...), and section 3 has one page per MCP tool (`search-notes(3)`, `write-note(3)`, ...). The MCP server serves the same pages as `memory://man` resources.

```bash
bm man list                       # every page with its one-line summary
bm man search-notes               # print a page as Markdown
bm man "grep(1)"
bm man apropos "conflict resolution"
bm man install                    # install man pages, then try `man bm`
```

<table>
<thead>
  <tr>
    <th>
      Command
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        bm man <page>
      </code>
      
       / <code>
        bm man show <page>
      </code>
    </td>
    
    <td>
      Print a manual page as Markdown. Accepts <code>
        search-notes
      </code>
      
      , <code>
        search-notes(3)
      </code>
      
      , and similar spellings
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bm man list
      </code>
    </td>
    
    <td>
      List every bundled page with its summary
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bm man apropos QUERY
      </code>
    </td>
    
    <td>
      Search a <code>
        manual
      </code>
      
       project's pages (<code>
        --project
      </code>
      
      , <code>
        --json
      </code>
      
      , <code>
        --plain
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bm man install
      </code>
    </td>
    
    <td>
      Install the <code>
        bm
      </code>
      
       man pages (<code>
        --dir
      </code>
      
      , default <code>
        ~/.local/share/man
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

---

## Wiki navigation commands

New in v0.24. `bm wiki` generates deterministic navigation pages for a local project: a root and per-folder `index.md`, plus `log.md` with the 25 most recent changes. Local and cloud produce the same bytes. A hand-written `index.md` or `log.md` is never overwritten; it is reported as a conflict instead.

```bash
bm wiki status
bm wiki validate --project research
bm wiki rebuild --dry-run
bm wiki rebuild --all
```

<table>
<thead>
  <tr>
    <th>
      Command
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      Show whether the generated navigation is current
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        validate
      </code>
    </td>
    
    <td>
      Validate the generated documents; exits nonzero when repair is needed
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rebuild
      </code>
    </td>
    
    <td>
      Build every generated <code>
        index.md
      </code>
      
       and <code>
        log.md
      </code>
      
       (idempotent). <code>
        init
      </code>
      
       and <code>
        update
      </code>
      
       are aliases
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
      
      , <code>
        -p
      </code>
    </td>
    
    <td>
      Project to act on (defaults to the default project)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --all
      </code>
    </td>
    
    <td>
      Act on every local project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --dry-run
      </code>
    </td>
    
    <td>
      Preview generated writes (<code>
        rebuild
      </code>
      
       only)
    </td>
  </tr>
</tbody>
</table>

---

## OKF export commands

New in v0.24. Export a local project as a static OKF v0.2-compatible bundle, or check an existing bundle.

```bash
bm okf export ~/exports/research-okf --project research
bm okf export ~/exports/research-okf --project research --replace
bm okf check ~/exports/research-okf
bm okf check ~/exports/research-okf --json
```

`bm okf export DESTINATION --project NAME` keeps concept frontmatter, categorized observations, and relative asset paths. It rewrites wikilinks to standard Markdown links, resolved the way the graph resolves them, and records the original relation types in a `bm.okf_export` extension. It also generates per-folder `index.md` files and a dated root `log.md` from the accepted-write journal. The export is staged beside the destination and validated before publishing. It refuses to overwrite an existing destination without `--replace`, and it restores the previous bundle if publication fails. The destination must be outside the source project, and cloud projects must be pulled locally first.

`bm okf check BUNDLE_PATH` reports per-file, per-rule diagnostics and exits nonzero on any violation. Both commands accept `--json`. See `bm man okf-export` for the full rules.

---

## Agent host install commands

New in v0.24. `bm install` installs the Basic Memory plugin or package into an agent host. None of these commands touch the Basic Memory database.

```bash
bm install codex
bm install claude-code --scope project
bm install tau --dry-run
bm install pi --local
```

<table>
<thead>
  <tr>
    <th>
      Command
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        codex
      </code>
    </td>
    
    <td>
      Install the plugin through Codex's user-level marketplace
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        claude-code
      </code>
    </td>
    
    <td>
      Install the plugin through Claude Code's marketplace. <code>
        --scope user|project|local
      </code>
      
       (default <code>
        user
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tau
      </code>
    </td>
    
    <td>
      Copy the packaged extension, skills, and prompt templates; existing config is never changed. <code>
        --replace
      </code>
      
      , <code>
        --sync
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pi
      </code>
    </td>
    
    <td>
      Install the packaged Pi extension and skills, then register them with Pi. <code>
        --local
      </code>
      
       registers in <code>
        .pi/settings.json
      </code>
    </td>
  </tr>
</tbody>
</table>

All four accept `--dry-run` to preview the plan and `--yes` to approve it without a prompt. Codex and Claude Code installs delegate to the host's own plugin CLI and accept `--source` to use a different marketplace Git source or local repo.

---

## Retrieval inspection commands

Read-only diagnostics for search, new in v0.23. When a note doesn't come back for a query you expected it to, `bm inspect chunks` answers "is this note indexed, embedded, and current?" and `bm inspect query` answers "what did retrieval actually do with my query?".

### `bm inspect chunks`

Show how the retrieval index decomposes one note into search rows and vector chunks. Accepts the same identifiers as `read_note`: a title, permalink, or `memory://` URL.

```bash
bm inspect chunks "coffee-brewing-methods"
bm inspect chunks "Coffee Brewing Methods" --project research
bm inspect chunks coffee-brewing-methods --json
```

The output shows the note's entity, observation, and relation search rows with the vector chunks each row produced, plus a readiness summary and a per-chunk status:

<table>
<thead>
  <tr>
    <th>
      Status
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        ready
      </code>
    </td>
    
    <td>
      Embedded under the configured model and vector index — visible to vector search
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pending
      </code>
    </td>
    
    <td>
      Awaiting embedding — not yet visible to vector search
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stale
      </code>
    </td>
    
    <td>
      The stored chunk no longer matches the note's current search rows
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        orphaned
      </code>
    </td>
    
    <td>
      Embedded under a different model or vector index than the one configured — retrieval cannot see it; rebuild with <code>
        bm reindex --embeddings
      </code>
    </td>
  </tr>
</tbody>
</table>

A freshness state (`fresh`, `not_indexed`, `index_behind_rows`, `rows_behind_file`, or `unknown`) distinguishes a chunking problem from an indexing-lag problem, with the checksum or fingerprint evidence for any non-fresh state.

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Output raw JSON — the stable machine-readable schema (automatic when piped)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --plain
      </code>
    </td>
    
    <td>
      Undecorated plain-text output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project-id
      </code>
    </td>
    
    <td>
      Project external ID (UUID); takes precedence over <code>
        --project
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm inspect query`

Run a search and trace its execution: every retrieval stage — matching, hydration, filtering, fusion, reranking, and the final page window — that produced the result page. The trace is captured by the same call that returns the results, so it reflects the actual execution rather than a reconstruction, and ordinary searches are unaffected.

```bash
bm inspect query "how do we handle auth"
bm inspect query "auth" --mode vector --show-misses
bm inspect query "auth" --mode hybrid --page 1 --page-size 10 --json
```

The output shows the engine identity (vector index, embedding model, fusion formula, minimum similarity, reranker status), a stage table with in/out/dropped counts and timings, and the ranked results with final scores and rerank movement (Δ).

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --mode
      </code>
    </td>
    
    <td>
      Retrieval mode: <code>
        text
      </code>
      
       (default), <code>
        vector
      </code>
      
      , or <code>
        hybrid
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --show-misses
      </code>
    </td>
    
    <td>
      Also render bounded rejected candidates and why each was dropped (vector and hybrid modes)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --show-ids
      </code>
    </td>
    
    <td>
      Include stable entity IDs in human output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Result page to inspect (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Results per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Output raw JSON — every captured candidate, stable schema (automatic when piped)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --plain
      </code>
    </td>
    
    <td>
      Undecorated plain-text output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project-id
      </code>
    </td>
    
    <td>
      Project external ID (UUID); takes precedence over <code>
        --project
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

---

## Configuration commands

### `bm config list`

List every scalar setting with its effective value and source. Environment overrides are marked with the exact `BASIC_MEMORY_*` variable.

```bash
bm config list
bm config list --json
```

### `bm config get`

Show one effective value and report any environment override:

```bash
bm config get reranker_enabled
bm config get milvus_uri
```

### `bm config set`

Validate a value through the same config model used at startup, then write it to `config.json`:

```bash
bm config set reranker_enabled true
bm config set cli_output_style plain
```

Invalid keys or values exit nonzero without changing the config file. If an environment variable overrides the file value, the command writes the value but warns that the environment still wins. `bm config set default_project` rejects an unknown project and accepts a project's display name.

### `bm config unset`

Remove a setting from `config.json`:

```bash
bm config unset reranker_enabled
```

The effective value then falls back to an environment override when one exists, otherwise to the built-in default.

`list`, `get`, `set`, and `unset` mask secret values and redact credentials embedded in URLs. Structured fields such as projects are managed by their dedicated command groups and do not appear as writable scalar settings.

---

## Harness hook commands

`bm hook` is the lifecycle front door used by the Basic Memory Claude Code and Codex plugins. See [Harness Capture](https://docs.basicmemory.com/integrations/harness-capture) for event behavior, settings, and retention.

```bash
# Inspect shared inbox and harness settings health
bm hook status --harness codex --project-dir /path/to/repository
bm hook status --harness claude --project-dir /path/to/repository

# Archive local lifecycle envelopes
bm hook flush
bm hook flush --older-than-days 30

# Wire or remove user-level hooks without a plugin
bm hook install --harness codex
bm hook remove --harness codex
bm hook install --harness claude
bm hook remove --harness claude
```

<table>
<thead>
  <tr>
    <th>
      Command
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        session-start
      </code>
    </td>
    
    <td>
      Print the configured context brief and capture a session-start envelope when enabled
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pre-compact
      </code>
    </td>
    
    <td>
      Capture the compaction event and coordinate a durable checkpoint
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stop
      </code>
    </td>
    
    <td>
      Compatibility no-op for stale pre-upgrade Stop hooks; not registered by new installs
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      Show inbox depth, last flush, settings, capture/checkpoint state, and tool versions
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flush
      </code>
    </td>
    
    <td>
      Archive pending envelopes locally; never writes graph notes
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        install
      </code>
    </td>
    
    <td>
      Add ownership-tagged user-level harness hooks idempotently
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        remove
      </code>
    </td>
    
    <td>
      Remove only the entries written by <code>
        bm hook install
      </code>
    </td>
  </tr>
</tbody>
</table>

---

## Project management

### `bm project list`

List projects from local config and (when available) cloud.

```bash
bm project list
bm project list --json
bm project list --workspace my-workspace
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --workspace
      </code>
    </td>
    
    <td>
      Cloud workspace name, slug, type, or tenant ID
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm project info`

Display detailed information and statistics about a project. Shows an htop-inspired compact dashboard with horizontal bar charts for note types, embedding coverage bars, and colored status dots.

```bash
bm project info main
bm project info main --json
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing (ignore cloud mode)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm project add`

Add a new project. A local project is indexed before the command returns, so its notes are searchable immediately and the command shows embedding progress. Pass `--no-wait` to register a large directory now and index it later with `bm project index`.

```bash
# Local project (indexed before returning)
bm project add research ~/Documents/research

# Register now, index later
bm project add archive ~/Documents/archive --no-wait
bm project index archive

# Cloud project (no local sync)
bm project add research --cloud

# Cloud project with local sync path
bm project add research --cloud --local-path ~/docs

# Cloud project in a specific team workspace, visible to all members
bm project add team-wiki --cloud --workspace acme --visibility workspace

# Cloud project restricted to specific people you grant access to
bm project add hiring --cloud --workspace acme --visibility shared

# Add and set as default
bm project add research ~/Documents/research --default
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --local-path
      </code>
    </td>
    
    <td>
      Local sync path for cloud mode
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --workspace
      </code>
    </td>
    
    <td>
      Cloud workspace name, slug, type, or tenant ID (cloud mode only)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --visibility
      </code>
    </td>
    
    <td>
      Cloud project visibility: <code>
        workspace
      </code>
      
       (default, visible to everyone in the workspace) or <code>
        shared
      </code>
      
       (invite-only)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --default
      </code>
    </td>
    
    <td>
      Set as default project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --no-wait
      </code>
    </td>
    
    <td>
      Register the project without indexing it; reads stay empty until you index
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

<note>

The cloud has only `workspace` and `shared` visibility. As of v0.24, `--cloud --visibility private` is refused. Earlier versions accepted it but created a workspace-visible project while reporting success.

</note>

Under `BASIC_MEMORY_PROJECT_ROOT`, a project name whose permalink contains `/` (such as `Research/2026`) is refused, so every project stays a single top-level directory under the shared root.

### `bm project index`

Index a project's files so its notes become searchable. Builds the search index and the embeddings. Same as `bm reindex --project NAME`.

```bash
bm project index research
```

Use it after `bm project add --no-wait`, or after fixing permissions on a directory the file watcher could not read.

### `bm project remove`

Remove a project. What happens to files depends on where the project lives.

```bash
# Stop tracking a local project; files stay on disk
bm project remove research

# Remove a local project and delete its files
bm project remove research --delete-notes

# Remove a cloud project (always deletes its cloud files; asks to confirm)
bm project remove research --cloud

# Also delete the local sync directory, without a prompt
bm project remove research --cloud --delete-local-files --yes
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --delete-notes
      </code>
    </td>
    
    <td>
      Delete a local project's files from disk. Cloud projects always delete their cloud files
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --delete-local-files
      </code>
    </td>
    
    <td>
      Cloud projects only: also delete the local sync directory on this machine
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --yes
      </code>
      
      , <code>
        -y
      </code>
    </td>
    
    <td>
      Delete a cloud project without a confirmation prompt
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

**Local projects:** removing one stops tracking it. Its files stay on disk unless you pass `--delete-notes`.

**Cloud projects:** removing one always deletes its files from cloud storage. There is no longer a way to keep them. The command warns that the files can be recovered only from a cloud snapshot (`bm cloud snapshot list`) and asks for confirmation. Cloud deletion is accepted asynchronously: a background job purges the objects under the project's storage prefix, then completes the hard delete. Existing snapshots follow their own retention lifecycle. The local routing entry is removed too, so you can add the name again. A cloud-only project removed without `--cloud` is still treated as cloud-routed.

<warning>

**Changed in v0.24:** `--delete-notes` no longer deletes a cloud project's local sync directory. Use `--delete-local-files` for that. Take a snapshot (`bm cloud snapshot create`) before removing a cloud project you might need again.

</warning>

### `bm project default`

Set the default project used as fallback when no project is specified.

```bash
bm project default main
```

### `bm project move`

Update a local project's configured filesystem path. This changes configuration only — move the files to the new path yourself (Basic Memory does not move them).

```bash
bm project move research /new/path/to/research
```

### `bm project ls`

List files in a project directory.

```bash
bm project ls --name research
bm project ls --name research subfolder
bm project ls --name research --local
bm project ls --name research --cloud
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --name
      </code>
    </td>
    
    <td>
      Project name (required)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      List files from local instance
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      List files from cloud instance
    </td>
  </tr>
</tbody>
</table>

### Routing modes (per project)

Route specific projects through cloud while keeping others local:

```bash
bm project set-cloud research
bm project set-local research
```

---

## Cloud commands

### Authentication and status

```bash
bm cloud login
bm cloud status
bm cloud logout
```

### API keys

```bash
bm cloud api-key save bmc_...
bm cloud api-key create "my-laptop"
```

<note>

`bm cloud api-key create` requires an active OAuth session. Run `bm cloud login` first.

</note>

### Setup and upload

```bash
bm cloud setup   # provision the rclone remote (Personal workspaces; Team push/pull needs no setup)
bm cloud upload ~/my-notes --project research --create-project
```

### Sync

```bash
# Fetch cloud changes additively (Personal + Team workspaces)
bm cloud pull --name research

# Upload local changes additively (Personal + Team workspaces)
bm cloud push --name research

# Choose conflict resolution: fail (default) | keep-local | keep-cloud | keep-both
bm cloud pull --name research --on-conflict keep-cloud

# Preview and delete cloud files matching ~/.basic-memory/.bmignore (Personal only)
bm cloud prune --name research --dry-run
bm cloud prune --name research

# Verify file integrity between local and cloud (Personal only)
bm cloud check --name research

# Configure local sync for an existing cloud project
bm cloud sync-setup research ~/Documents/research
```

`push`/`pull` are additive (never delete on the destination) and abort on conflicts by default, git-style. They are the supported sync workflow on both Personal and Team workspaces. On Team workspaces they run over the cloud's permissioned WebDAV API, with no `bm cloud setup` required and access checked per project. `prune` performs only ignore-based remote cleanup and asks for confirmation unless you pass `--yes`. For local index cleanup, use [`bm prune`](#bm-prune). See the [Cloud Sync guide](https://docs.basicmemory.com/cloud/cloud-sync) for details.

<warning>

**Deprecated in v0.24:** `bm cloud sync`, `bm cloud bisync`, and `bm cloud bisync-reset` will be removed in a future release. They are marked deprecated in `--help` and print a notice with the equivalent `push`/`pull` command on every run. They still work on Personal workspaces; on Team workspaces they exit with that notice. Switch scripts to `bm cloud push` and `bm cloud pull`.

</warning>

### Public shares

```bash
bm cloud share create research notes/my-idea
bm cloud share create research notes/my-idea --expires-at 2099-12-31
bm cloud share list
bm cloud share list --project research
bm cloud share update SHARE_TOKEN --disable
bm cloud share update SHARE_TOKEN --enable
bm cloud share update SHARE_TOKEN --expires-at none
bm cloud share revoke SHARE_TOKEN
bm cloud share revoke SHARE_TOKEN --force
```

All share commands accept `--workspace` to route by workspace slug, display name, or tenant ID. `revoke` confirms before deletion unless `--force` is set.

### Snapshots

```bash
bm cloud snapshot create "Before migration"
bm cloud snapshot list
bm cloud snapshot show <snapshot-id>
bm cloud snapshot browse <snapshot-id>
bm cloud snapshot delete <snapshot-id>
```

### Restore

```bash
bm cloud restore <path> --snapshot <snapshot-id>
```

### Workspaces

```bash
# List cloud workspaces available to the current session
bm cloud workspace list

# Set the default workspace for CLI and MCP routing
bm cloud workspace set-default acme
```

See [Teams](https://docs.basicmemory.com/teams/about) for working with shared team workspaces.

### Promo controls

```bash
bm cloud promo --off
bm cloud promo --on
```

---

## Schema commands

Tools for defining, validating, and evolving note structure. See [Schema System](https://docs.basicmemory.com/concepts/schema-system) for concepts and workflow.

### `bm schema validate`

Validate notes against their schema definition. Pass a note type to validate all notes of that type, a specific file path to validate one note, or omit to validate all notes that have schemas.

```bash
# Validate all notes with schemas
bm schema validate

# Validate all notes of a type
bm schema validate person

# Validate one specific note
bm schema validate people/ada-lovelace.md

# Strict mode — exit 1 if any validation errors are found
bm schema validate person --strict

# Machine-readable output
bm schema validate person --json

# Target a specific project
bm schema validate person --project research
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --strict
      </code>
    </td>
    
    <td>
      Exit with code 1 if any validation errors are found (warnings never affect the exit code)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm schema infer`

Analyze existing notes of a type and suggest a schema based on common observation categories, relation types, and frontmatter fields. Fields present in 95%+ of notes become required; fields above the threshold become optional.

```bash
# Infer schema for a note type
bm schema infer person

# Lower the threshold to include less common fields
bm schema infer person --threshold 0.1

# Machine-readable output
bm schema infer person --json

# Target a specific project
bm schema infer person --project research
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --threshold
      </code>
    </td>
    
    <td>
      Minimum field frequency for inclusion (default <code>
        0.25
      </code>
      
       — fields in 25%+ of notes)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --save
      </code>
    </td>
    
    <td>
      Save the inferred schema as a schema note in the <code>
        schemas/
      </code>
      
       directory
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm schema diff`

Compare a schema definition against actual note usage to detect drift. Shows new fields appearing, old fields disappearing, and cardinality changes.

```bash
# Check drift for a note type
bm schema diff person

# Machine-readable output
bm schema diff person --json

# Target a specific project
bm schema diff person --project research
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target a specific project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

---

## Tool commands (CLI wrapper for MCP tools)

Command group: `bm tool` (singular). This provides CLI access to the same MCP tools that AI assistants use, useful for scripting, debugging, and quick operations from the terminal.

Search, read, context, and activity commands use Rich tables, panels, trees, or Markdown when stdout is a TTY. Output precedence is:

1. `--json` for raw machine-readable JSON.
2. `--plain` for undecorated human-readable text.
3. Non-TTY output defaults to JSON, preserving piped and redirected scripts.
4. TTY output follows `cli_output_style` (`rich` by default, or `plain`).

`--json` and `--plain` are mutually exclusive. Set the interactive default with `bm config set cli_output_style plain`.

Exit status follows the tool result. Reading a note that does not exist exits with status `1` in every output mode, and JSON output carries `error: "NOTE_NOT_FOUND"`. A refused `write-note` or a failed or refused `edit-note` prints the error and exits `1`; for `write-note`, the JSON payload still goes to stdout. Before v0.24, a missing note exited `0` with null fields, so scripts should check the exit status.

### `bm tool write-note`

```bash
# Create a note with inline content
bm tool write-note --title "API Notes" --folder specs --content "# API Notes"

# Pipe content from stdin
echo "# My Note" | bm tool write-note --title "My Note" --folder notes

# Set the note type at creation time
bm tool write-note --title "Standup" --folder meetings --type meeting

# Replace an existing note (past the overwrite guard)
bm tool write-note --title "API Notes" --folder specs --content "..." --overwrite

# Replace it only if it is still the revision you read
bm tool write-note --title "API Notes" --folder specs --content "..." --overwrite --expected-checksum <checksum>
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --title
      </code>
    </td>
    
    <td>
      Note title (required)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --folder
      </code>
    </td>
    
    <td>
      Destination folder (required)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --content
      </code>
    </td>
    
    <td>
      Note content (reads from stdin if omitted)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --tags
      </code>
    </td>
    
    <td>
      Tags to apply
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --type
      </code>
    </td>
    
    <td>
      Frontmatter note type (e.g. <code>
        meeting
      </code>
      
      , <code>
        task
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --overwrite
      </code>
    </td>
    
    <td>
      Replace an existing note at the same path (past the overwrite guard)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --expected-checksum
      </code>
    </td>
    
    <td>
      With <code>
        --overwrite
      </code>
      
      , replace the note only if it is still this revision. Use the <code>
        checksum
      </code>
      
       from a previous JSON <code>
        read-note
      </code>
      
      , <code>
        write-note
      </code>
      
      , or <code>
        edit-note
      </code>
      
       result
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm tool read-note`

```bash
bm tool read-note "specs/api-notes"
bm tool read-note my-note --frontmatter
bm tool read-note my-note --json
bm tool read-note my-note --start-line 120 --end-line 180 --plain
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --frontmatter
      </code>
    </td>
    
    <td>
      Include YAML frontmatter in output (<code>
        --include-frontmatter
      </code>
      
       is a deprecated alias)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --start-line
      </code>
    </td>
    
    <td>
      First document line to read, 1-based, counting frontmatter lines
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --end-line
      </code>
    </td>
    
    <td>
      Last line to read, inclusive; omit to read to the end
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Raw JSON output, including the note's full <code>
        checksum
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --plain
      </code>
    </td>
    
    <td>
      Undecorated plain text
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

A line-range read returns numbered lines plus the next range to read. A start line past the end of the note is an error. Line numbers from `bm grep -C` can be passed straight in.

### `bm tool edit-note`

```bash
bm tool edit-note my-note --operation append --content "new content"
bm tool edit-note my-note --operation find_replace --find-text "old" --content "new"
bm tool edit-note my-note --operation replace_section --section "## Notes" --content "updated"
bm tool edit-note my-note --operation replace_section --section "## Notes" --content "updated" --no-replace-subsections
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --operation
      </code>
    </td>
    
    <td>
      Edit operation: <code>
        append
      </code>
      
      , <code>
        prepend
      </code>
      
      , <code>
        find_replace
      </code>
      
      , <code>
        replace_section
      </code>
      
      , <code>
        insert_before_section
      </code>
      
      , <code>
        insert_after_section
      </code>
      
       (required; the insert operations also require <code>
        --section
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --content
      </code>
    </td>
    
    <td>
      Content for the edit (required)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --find-text
      </code>
    </td>
    
    <td>
      Text to find (required for <code>
        find_replace
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --section
      </code>
    </td>
    
    <td>
      Section heading (required for <code>
        replace_section
      </code>
      
      , <code>
        insert_before_section
      </code>
      
      , and <code>
        insert_after_section
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --expected-replacements
      </code>
    </td>
    
    <td>
      Expected replacement count for <code>
        find_replace
      </code>
      
       (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --replace-subsections
      </code>
      
      , <code>
        --no-replace-subsections
      </code>
    </td>
    
    <td>
      For <code>
        replace_section
      </code>
      
      , replace nested subsections by default or preserve them with <code>
        --no-replace-subsections
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

As of v0.24, `replace_section` fails when the exact heading is not in the note, instead of appending a duplicate section. Give a heading such as `## Open items #urgent` in full, or use `append` to create a new section on purpose.

### `bm tool delete-note`

```bash
bm tool delete-note notes/old-draft
bm tool delete-note docs/archive --is-directory
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --is-directory
      </code>
    </td>
    
    <td>
      Delete a directory instead of a single note
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project-id
      </code>
    </td>
    
    <td>
      Project external ID (UUID); takes precedence over <code>
        --project
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm tool search-notes`

```bash
# Text search (query is a positional argument)
bm tool search-notes "authentication"

# Tag and metadata filters (query is optional)
bm tool search-notes --tag python --tag async
bm tool search-notes --meta status=draft
bm tool search-notes --type person --type meeting

# Search observations by category
bm tool search-notes "auth" --entity-type observation --category decision

# Search modes
bm tool search-notes "how to speed up the app" --hybrid
bm tool search-notes "how to speed up the app" --vector
bm tool search-notes --permalink "specs/*"
bm tool search-notes --title "API Design"

# Advanced metadata filter (JSON)
bm tool search-notes --filter '{"priority": {"$in": ["high", "critical"]}}'

# Pagination
bm tool search-notes "api" --page 2 --page-size 20

# Identifiers and metadata only, without note bodies
bm tool search-notes "api" --compact
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --compact
      </code>
    </td>
    
    <td>
      Omit note bodies and matched excerpts; return identifiers, metadata, and pagination for discovery
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --hybrid
      </code>
    </td>
    
    <td>
      Use hybrid search (keyword + semantic)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --vector
      </code>
    </td>
    
    <td>
      Use vector (semantic-only) search
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --permalink
      </code>
    </td>
    
    <td>
      Search permalink values
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --title
      </code>
    </td>
    
    <td>
      Search title values
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --tag
      </code>
    </td>
    
    <td>
      Filter by frontmatter tag (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --status
      </code>
    </td>
    
    <td>
      Filter by frontmatter status
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --type
      </code>
    </td>
    
    <td>
      Filter by frontmatter type (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --entity-type
      </code>
    </td>
    
    <td>
      Filter by result type: <code>
        entity
      </code>
      
      , <code>
        observation
      </code>
      
      , <code>
        relation
      </code>
      
       (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --category
      </code>
    </td>
    
    <td>
      Filter observation results to exact categories (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --meta
      </code>
    </td>
    
    <td>
      Filter by frontmatter <code>
        key=value
      </code>
      
       (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --filter
      </code>
    </td>
    
    <td>
      JSON metadata filter (advanced)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --after_date
      </code>
    </td>
    
    <td>
      Date filter (e.g., <code>
        2d
      </code>
      
      , <code>
        1 week
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Results per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm tool build-context`

```bash
bm tool build-context memory://specs/search
bm tool build-context specs/search --depth 2 --timeframe 30d
bm tool build-context memory://specs/search --compact
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --compact
      </code>
    </td>
    
    <td>
      Omit note and observation bodies; return identifiers, metadata, relation targets, and pagination
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --depth
      </code>
    </td>
    
    <td>
      Traversal depth, 1–5 (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --timeframe
      </code>
    </td>
    
    <td>
      Time window filter (default <code>
        7d
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Results per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --max-related
      </code>
    </td>
    
    <td>
      Maximum related items (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### `bm tool recent-activity`

```bash
bm tool recent-activity
bm tool recent-activity --timeframe 30d --page-size 20
bm tool recent-activity --type entity --type observation
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --type
      </code>
    </td>
    
    <td>
      Filter by item type (repeatable)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --depth
      </code>
    </td>
    
    <td>
      Context depth, 1–5 (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --timeframe
      </code>
    </td>
    
    <td>
      Time window (default <code>
        7d
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page
      </code>
    </td>
    
    <td>
      Page number (default <code>
        1
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --page-size
      </code>
    </td>
    
    <td>
      Results per page (default <code>
        10
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --project
      </code>
    </td>
    
    <td>
      Target project
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --local
      </code>
    </td>
    
    <td>
      Force local routing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cloud
      </code>
    </td>
    
    <td>
      Force cloud routing
    </td>
  </tr>
</tbody>
</table>

### Schema tool commands

These are CLI wrappers around the schema MCP tools with JSON output:

```bash
bm tool schema-validate person
bm tool schema-infer person
bm tool schema-diff person
bm tool list-projects
bm tool list-workspaces
```

---

## Import commands

```bash
bm import claude conversations
bm import claude projects
bm import chatgpt
bm import memory-json /path/to/export.json
```

### `bm import document`

Extract a PDF, Word (`.docx`), PowerPoint (`.pptx`), or CSV file that is already stored inside a project into a sidecar Markdown note. New in v0.24.

```bash
# Install the extractors: [documents] for Word/PowerPoint, [pdf] for PDF
uv tool install "basic-memory[documents,pdf]"

# Paths are relative to the project root, not your current directory
bm import document reports/q3-review.pdf
bm import document decks/roadmap.pptx --project research
```

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --project
      </code>
      
      , <code>
        -p
      </code>
    </td>
    
    <td>
      Project containing the source file (defaults to the default project)
    </td>
  </tr>
</tbody>
</table>

The command indexes the project, extracts the file, and writes `<file>.<ext>.md` next to it, plus a run note under `document-ingestion-runs/`. CSV needs no extra and renders a bounded preview. Re-running is a no-op while the source is unchanged, and the command refuses to overwrite a hand-written or enriched note at the sidecar path.

<note>

A relative `PATH` resolves against the project root, matching `bm ls` and `bm cat`. An absolute path must point inside the project, so copy external files into the project first. A command that relied on the pre-v0.24 behavior (paths relative to the current directory) now fails with "File not found" and the resolved path.

</note>

---

## Notes on defaults

- If `--project` is omitted, Basic Memory falls back to `default_project` when configured.
- Most `bm tool` subcommands accept `--project-id` (the project's external UUID from `bm project list --json`) to disambiguate same-named projects across cloud workspaces.
- `--local` and `--cloud` flags are available on most commands for routing overrides.
- `BASIC_MEMORY_*` environment variables override `config.json` for the current process only. As of v0.24 they are no longer written into `config.json` when a command saves config.

---

## Related pages

- [What's new in v0.24](https://docs.basicmemory.com/whats-new/v0-24)
- [Upgrade to v0.24](https://docs.basicmemory.com/whats-new/v0-24-upgrade)
- [Configuration](https://docs.basicmemory.com/reference/configuration)
- [MCP Tools Reference](https://docs.basicmemory.com/reference/mcp-tools-reference)
- [Cloud Guide](https://docs.basicmemory.com/cloud/cloud-guide)
- [Schema System](https://docs.basicmemory.com/concepts/schema-system)
- [Semantic Search](https://docs.basicmemory.com/concepts/semantic-search)


## Sitemap

See the full [sitemap](https://docs.basicmemory.com/sitemap.md) for all pages.
