Skip to content

Commit b94ef01

Browse files
authored
feat(core): add XDG_CONFIG_HOME support (#844)
Signed-off-by: Rafael Madriz <rafa@rafaelmadriz.com>
1 parent 12af793 commit b94ef01

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

src/basic_memory/config.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
DATABASE_NAME = "memory.db"
2323
APP_DATABASE_NAME = "memory.db" # Using the same name but in the app directory
24-
DATA_DIR_NAME = ".basic-memory"
24+
DATA_DIR_NAME = "basic-memory"
2525
CONFIG_FILE_NAME = "config.json"
2626
WATCH_STATUS_JSON = "watch-status.json"
2727
CONFIG_DIR_MODE = 0o700
@@ -69,15 +69,18 @@ def resolve_data_dir() -> Path:
6969
7070
Single source of truth for the per-user state directory. Honors
7171
``BASIC_MEMORY_CONFIG_DIR`` so each process/worktree can isolate config
72-
and database state; otherwise falls back to ``<user home>/.basic-memory``.
72+
and database state; otherwise falls back to ``<user home>/.basic-memory``,
73+
and then to ``XDG_CONFIG_HOME``.
7374
7475
Cross-platform: ``Path.home()`` reads ``$HOME`` on POSIX and
7576
``%USERPROFILE%`` on Windows, so there's no need to check ``$HOME``
7677
explicitly here.
7778
"""
78-
if config_dir := os.getenv("BASIC_MEMORY_CONFIG_DIR"):
79-
return Path(config_dir)
80-
return Path.home() / DATA_DIR_NAME
79+
if basic_memory_dir := os.getenv("BASIC_MEMORY_CONFIG_DIR"):
80+
return Path(basic_memory_dir)
81+
if xdg_config := os.getenv("XDG_CONFIG_HOME"):
82+
return Path(xdg_config) / DATA_DIR_NAME
83+
return Path.home() / ("." + DATA_DIR_NAME)
8184

8285

8386
def default_fastembed_cache_dir() -> str:

tests/test_config.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,9 @@ class TestDataDirHelpers:
308308
"""Module-level helpers that resolve the Basic Memory data directory."""
309309

310310
def test_resolve_data_dir_defaults_to_home_dot_basic_memory(self, config_home, monkeypatch):
311-
"""Without BASIC_MEMORY_CONFIG_DIR, resolver returns ~/.basic-memory."""
311+
"""Without BASIC_MEMORY_CONFIG_DIR and XDG_CONFIG_HOME, resolver returns ~/.basic-memory."""
312312
monkeypatch.delenv("BASIC_MEMORY_CONFIG_DIR", raising=False)
313+
monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
313314

314315
assert resolve_data_dir() == config_home / ".basic-memory"
315316

@@ -320,6 +321,23 @@ def test_resolve_data_dir_honors_config_dir_env(self, tmp_path, monkeypatch):
320321

321322
assert resolve_data_dir() == custom
322323

324+
def test_resolve_data_dir_honors_xdg_config_home(self, tmp_path, monkeypatch):
325+
"""XDG_CONFIG_HOME is honored when BASIC_MEMORY_CONFIG_DIR is not set."""
326+
monkeypatch.delenv("BASIC_MEMORY_CONFIG_DIR", raising=False)
327+
xdg_config = tmp_path / "xdg-config"
328+
monkeypatch.setenv("XDG_CONFIG_HOME", str(xdg_config))
329+
330+
assert resolve_data_dir() == xdg_config / "basic-memory"
331+
332+
def test_basic_memory_config_dir_takes_precedence_over_xdg(self, tmp_path, monkeypatch):
333+
"""BASIC_MEMORY_CONFIG_DIR takes precedence over XDG_CONFIG_HOME."""
334+
xdg_config = tmp_path / "xdg-config"
335+
custom = tmp_path / "custom-config"
336+
monkeypatch.setenv("XDG_CONFIG_HOME", str(xdg_config))
337+
monkeypatch.setenv("BASIC_MEMORY_CONFIG_DIR", str(custom))
338+
339+
assert resolve_data_dir() == custom
340+
323341
def test_default_fastembed_cache_dir_uses_data_dir(self, config_home, monkeypatch):
324342
"""Default cache path is a subdir of the Basic Memory data dir."""
325343
monkeypatch.delenv("BASIC_MEMORY_CONFIG_DIR", raising=False)

0 commit comments

Comments
 (0)