Skip to content

feat(cli): add bm config command group for get/set/list/unset#1088

Open
phernandez wants to merge 2 commits into
mainfrom
claude/issue-991-20260716-1949
Open

feat(cli): add bm config command group for get/set/list/unset#1088
phernandez wants to merge 2 commits into
mainfrom
claude/issue-991-20260716-1949

Conversation

@phernandez

Copy link
Copy Markdown
Member

Implements #991. Generated by the @claude workflow from the issue instructions; opened for review — not yet verified by a human.

Summary

Adds a bm config command group:

  • bm config list — settings with effective values, env overrides marked
  • bm config get <key>
  • bm config set <key> <value> — round-trips through BasicMemoryConfig so invalid values fail with the Pydantic error
  • bm config unset <key> — revert to default

Redaction rules (never print cloud_api_key, mask database_url creds) were factored out of basic_memory_diagnostics into a shared basic_memory/redaction.py so both surfaces stay in sync.

Review checklist

Closes #991

🤖 Generated with Claude Code

Every user-facing setting previously required hand-editing config.json or
knowing the BASIC_MEMORY_* env-var convention. `bm config list|get|set|unset`
covers the scalar subset of BasicMemoryConfig (derived from the model, not a
hand-maintained list), validates `set` through the model so invalid values
fail with the Pydantic error, and marks BASIC_MEMORY_* env overrides.

Secret-redaction rules (cloud_api_key never printed, database_url credentials
masked) are factored out of the existing basic_memory_diagnostics MCP tool
into a shared basic_memory/redaction.py module so both surfaces stay in sync.

Closes #991

Co-authored-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
assert result.exit_code == 0, result.output
assert "dbpass" not in result.output
assert "dbuser" not in result.output
assert "host.example.com" in result.output
@phernandez

Copy link
Copy Markdown
Member Author

Local validation

CI didn't auto-run on this branch (it was pushed by the bot's GITHUB_TOKEN, and test.yml is push-only — GitHub doesn't fire push workflows for bot-token pushes). Ran the added tests locally instead:

uv run pytest tests/cli/test_config_command.py
→ 24 passed in 3.01s

No failures. ✅

phernandez added a commit that referenced this pull request Jul 16, 2026
Anthropic's OIDC exchange is broken for the pull_request_target event
(401 'Invalid OIDC token'; anthropics/claude-code-action#713). The workflow
invoked that path whenever a PR body contained '@claude' — and bot-authored PR
descriptions carry attribution text ('Generated by the @claude workflow'), so
opening #1088/#1089/#1090/#1091 self-triggered the broken path and each failed
its 'claude' check with a 401. A normal issue_comment run succeeded with the
same secret in between, so the OAuth token is valid and needs no rotation.

Remove the pull_request_target trigger and its PR-body '@claude' clause, so
attribution text can never be read as a command and no event routes into the
broken OIDC path. Explicit '@claude' mentions in issues, issue comments, PR
reviews, and PR review comments remain the trigger. Also drop the now-dead
pull_request.author_association gate clauses (reviewer identity is covered by
sender.author_association) and the pull_request_target-only checkout ref.

If automatic PR-open review is wanted later, it should be a dedicated workflow
with a fixed prompt, not a PR-body mention.

Signed-off-by: phernandez <paul@basicmachines.co>
Self-review follow-up on the generated code. config.py worked (24 tests
green) but did not read like the rest of the codebase:

- Introduce a frozen/slots ConfigSetting dataclass for the list rows instead of
  anonymous dict literals threaded through list/get output (docs/ENGINEERING_STYLE
  asks for dataclasses over ad-hoc dict[str, Any] shapes). JSON output is
  unchanged (asdict -> key/value/source).
- Fully type the helpers and collections (list[ConfigSetting], frozenset[str]);
  redaction.py signatures are dict[str, Any] rather than bare dict.
- Drop the silent 'except (OSError, json.JSONDecodeError)' fallback when reading
  config.json for source labelling. ConfigManager already parsed the file to load
  the config, so a read failure is a real inconsistency that should surface, not
  be swallowed into mislabelling every setting as a default (fail-fast rule).
- De-duplicate secret masking: _render_value delegates to _redact_for_display
  instead of re-checking SECRET_FIELDS; name the display sentinels
  (SECRET_MASK / NOT_SET).
- Collapse the two-step _unknown_key_error/_require_known_key into one, add
  section headers.

Behavior and the 24 existing tests are unchanged; the model-derived allowlist is
kept (it is the correct way to track BasicMemoryConfig).

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.

Add 'bm config' command group (get/set/list) for managing config.json from the CLI

2 participants