Skip to content

fix(core): keep environment overrides out of config.json - #1701

Merged
phernandez merged 2 commits into
mainfrom
fix/1631-env-overrides-not-persisted
Oct 9, 2026
Merged

phernandez merged 2 commits into
mainfrom
fix/1631-env-overrides-not-persisted

Conversation

@phernandez

@phernandez phernandez commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Fixes #1631.

Why

load_config merges BASIC_MEMORY_* environment values over config.json. Every config save then dumped that merged model. A variable set for one command became a permanent file setting. For example, BASIC_MEMORY_LOG_LEVEL=DEBUG bm project add ... left log_level: DEBUG in the file. A stray BASIC_MEMORY_PROJECT_ROOT kept refusing project names with / after the variable was unset (#1598).

Change

  • New env_overridden_fields(file_data) in config.py is the one place that decides which fields come from the environment. load_config uses it to drop file values, and the save path uses it to keep env values out of the file. It also covers the legacy BASIC_MEMORY_SYNC_CHANGES / BASIC_MEMORY_SYNC_DELAY variables, which map onto index_changes / index_delay.
  • save_basic_memory_config writes back, for each env-overridden field, the value the file had on disk. If the file never had the key, it omits it. A file that only had the legacy sync_changes / sync_delay key keeps that value under the new name. This covers every save, including the migration resave and the first-run save. If config.json on disk is corrupt JSON, the save now returns the error instead of overwriting the file.
  • save_config / save_basic_memory_config take a keyword-only persist_env_keys. Every command that explicitly changes one named setting passes it, so that key is persisted even while an env var overrides it:
    • bm config set / bm config unset: the named key (the existing warning is kept)
    • bm cloud api-key save / create: cloud_api_key
    • bm cloud workspace set-default and bm cloud logout: default_workspace
    • bm cloud promo --on/--off: cloud_promo_opt_out
    • ConfigManager.set_default_project (bm project default): default_project
  • Automatic writes stay env-respecting: promo-shown stamps, the auto-update check, doctor's default repair, and project list edits. With BASIC_MEMORY_PROJECTS set, the env owns the project list, so project add does not persist a change to it.

Verification

  • New tests/test_config_env_overrides_not_persisted.py:
    • project add under env overrides keeps the file values and adds no keys the file never had.
    • BASIC_MEMORY_PROJECT_ROOT is not persisted, and project_root is None once the variable is unset.
    • The first-run save does not write env values.
    • An explicit persist_env_keys key is written.
    • A legacy sync_changes file value survives a save.
    • set_default_project writes default_project under an env override.
  • tests/cli/test_config_command.py: config set on a different key leaves the overridden keys untouched, config set on the overridden key persists it, and config unset writes the default.
  • tests/cli/test_cloud_promo.py: bm cloud promo --off against a real config file under env overrides persists cloud_promo_opt_out and keeps log_level at its file value. The logout and promo stub tests assert the persisted key.
  • just fast-check passes.
  • just fast-test over tests/cli, the config tests, the project service, initialization and project router tests: 1376 passed. An earlier run over tests/mcp, tests/services, tests/index and the permalink integration suites: 2524 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea

Every config save dumped the env-merged model, so a one-off
BASIC_MEMORY_* variable became a permanent file setting. Saves now write
the on-disk value (or omit the key) for every env-overridden field.
`bm config set/unset`, `bm cloud api-key save/create`, and
`bm cloud workspace set-default` still persist the key they name.

Fixes #1631.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea
Signed-off-by: phernandez <paul@basicmachines.co>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T02:50:16.100307Z 3573216 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3324bc7a06

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/basic_memory/config.py
Commands that change one named setting now pass it in persist_env_keys,
so the change lands in config.json even while an env var overrides it:

- bm cloud logout: default_workspace
- bm cloud promo --on/--off: cloud_promo_opt_out
- ConfigManager.set_default_project (bm project default): default_project

Automatic writes (promo shown stamps, auto-update check, doctor's
default repair, project list edits) stay env-respecting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea
Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3573216bc4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/basic_memory/config.py
@phernandez
phernandez merged commit 096aa66 into main Oct 9, 2026
39 checks passed
@phernandez
phernandez deleted the fix/1631-env-overrides-not-persisted branch October 9, 2026 03:24
phernandez added a commit that referenced this pull request Oct 9, 2026
Entries for #1697, #1698, #1699, #1700, #1701, #1702, #1704 and #1705,
which landed without changelog edits so the parallel PRs would not
conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea
Signed-off-by: phernandez <paul@basicmachines.co>
phernandez added a commit that referenced this pull request Oct 9, 2026
Entries for #1697, #1698, #1699, #1700, #1701, #1702, #1704 and #1705,
which landed without changelog edits so the parallel PRs would not
conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea
Signed-off-by: phernandez <paul@basicmachines.co>
phernandez added a commit that referenced this pull request Oct 9, 2026
#1696 removed `semantic_search_enabled` from BasicMemoryConfig, but it was
tested against a main that predated several milestone merges that still
read the flag, so main failed static checks and most test jobs:

- `index_project_and_report_readiness` (#1704) passed
  `embeddings=app_config.semantic_search_enabled`, which raised
  AttributeError on every `bm project add`. Semantic search is always on,
  so the add always runs the embedding pass.
- test_db_reindex (#1704) parametrized the add on the flag; it now
  asserts the embedding pass runs.
- test_deferred_embedding_resume (#1700) set the flag on its config.
- test_config_env_overrides_not_persisted (#1701) used the flag as its
  example env-overridden boolean; it now uses `format_on_save`.

Also makes #1704's cloud-prune test compare against str(Path) so it holds
on Windows, where the path prints with backslashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea
Signed-off-by: phernandez <paul@basicmachines.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Environment overrides are persisted into config.json by any config save

1 participant