Skip to content

Data dir resolution hardcoded in several places — ignores BASIC_MEMORY_CONFIG_DIR #742

Closed

Description

@groksrc

Summary

Several modules hardcode Path.home() / \".basic-memory\" to locate Basic Memory state instead of using BasicMemoryConfig.data_dir_path / ConfigManager.config_dir. This means they ignore the BASIC_MEMORY_CONFIG_DIR environment variable, which users/tests rely on to redirect Basic Memory state (for isolated worktrees, containerized runs, multi-instance setups, etc.).

Any feature accessed through these call sites will silently read/write the wrong directory when BASIC_MEMORY_CONFIG_DIR is set.

Known offending call sites

  • src/basic_memory/utils.py:284 — log_path = Path.home() / \".basic-memory\" / log_filename (file logging)
  • src/basic_memory/ignore_utils.py:66 — return Path.home() / \".basic-memory\" / \".bmignore\" (global ignore file lookup)
  • src/basic_memory/sync/watch_service.py:92 — self.status_path = Path.home() / \".basic-memory\" / WATCH_STATUS_JSON
  • src/basic_memory/services/project_service.py:1140 — watch_status_path = Path.home() / \".basic-memory\" / WATCH_STATUS_JSON
  • src/basic_memory/cli/commands/cloud/rclone_commands.py:147 — return Path.home() / \".basic-memory\" / \"bisync-state\" / project_name

Example impact

If a user runs with BASIC_MEMORY_CONFIG_DIR=/opt/bm-sandbox:

  • Config and the SQLite DB live under /opt/bm-sandbox/ (correct — honors the env var).
  • But the watch status file, log file, .bmignore, and rclone bisync state all end up under ~/.basic-memory/ (wrong).

This causes split state, stale watchers, log leakage across isolated instances, and broken .bmignore behavior depending on which code path the user hits first.

Proposed fix

Follow-up to #741:

  1. #741 introduces resolve_data_dir() as a module-level helper in config.py (the single source of truth, honoring BASIC_MEMORY_CONFIG_DIR).
  2. This issue: update every call site above to use resolve_data_dir() (or an equivalent already-available config accessor) instead of hardcoding Path.home() / \".basic-memory\".
  3. Add a regression test that exercises each of those code paths under a non-default BASIC_MEMORY_CONFIG_DIR and asserts the file/dir they touch lives under the redirected data dir.

Keeping it out of #741 to avoid scope creep on the FastEmbed cache fix.

Activity

  1. claude commented on Apr 15, 2026

    @claude
    Contributor

    Claude finished @groksrc's task in 1m 37s —— View job


    Issue Triage

    • Analyze issue and classify type/priority
    • Review offending call sites in the codebase
    • Check for duplicate issues
    • Apply appropriate labels (bug applied)
    • Provide triage summary

    Analysis

    Type: Bug (environment variable ignored in multiple code paths)

    Priority: Medium — affects users and tests relying on BASIC_MEMORY_CONFIG_DIR to isolate Basic Memory state (containerized runs, CI, multi-instance setups). No data loss, but causes split state and subtle misbehavior.

    Component: Cross-cutting — sync, services, cli/cloud, plus utils and ignore_utils

    Complexity: Medium — 5 known call sites to update plus regression tests, but each fix is mechanical


    Verified Call Sites

    All 5 hardcoded paths confirmed in the codebase:

    File Line Hardcoded Path Purpose
    src/basic_memory/utils.py 284 Path.home() / ".basic-memory" / log_filename File logging
    src/basic_memory/ignore_utils.py 66 Path.home() / ".basic-memory" / ".bmignore" Global ignore file
    src/basic_memory/sync/watch_service.py 92 Path.home() / ".basic-memory" / WATCH_STATUS_JSON Watch status
    src/basic_memory/services/project_service.py 1140 Path.home() / ".basic-memory" / WATCH_STATUS_JSON System status endpoint
    src/basic_memory/cli/commands/cloud/rclone_commands.py 147 Path.home() / ".basic-memory" / "bisync-state" / project_name rclone bisync state

    Proposed Fix

    The fix is already partially designed: BasicMemoryConfig.data_dir_path (line 710 in config.py) and ConfigManager.config_dir (line 742) both honor BASIC_MEMORY_CONFIG_DIR. The issue mentions that #741 will introduce a module-level resolve_data_dir() helper — but that helper doesn't exist yet.

    Option A: Wait for #741 to land, then use resolve_data_dir() at each call site.

    Option B: Add resolve_data_dir() directly in this PR (it's a one-liner that mirrors BasicMemoryConfig.data_dir_path) and update all 5 call sites.

    For sites that already have access to app_config (e.g., watch_service.py receives BasicMemoryConfig), use app_config.data_dir_path directly. For standalone helpers (utils.py, ignore_utils.py, rclone_commands.py), a module-level resolve_data_dir() is cleaner.

    No Duplicate Found

    Searched open issues — this is a distinct follow-up to #741 as noted by the author.

  2. added 2 commits that reference this issue on Apr 15, 2026
    269b0b9
    e39b8e1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions