Summary
skip_init_commands in src/basic_memory/cli/app.py contains two entries — "sync" and "watch" — that do not match any registered top-level command. They are unreachable set members. Two commands that are registered top-level (format, orphans) are absent from the set, and I can't tell from the code whether that omission is deliberate.
No user-visible breakage today (see "Why this is behaviour-neutral right now"). Filing as a hygiene/intent question rather than a bug report.
Observed on main @ 8b24eb1ed4aeba45c34e184bd566b6c81603ef24.
The set
src/basic_memory/cli/app.py:133-158 gates ensure_initialization() on ctx.invoked_subcommand not in skip_init_commands.
Evidence
Enumerating every top-level command — @app.command(...) plus app.add_typer(..., name=...):
$ grep -rhoE '[a-z_]+\.add_typer\([a-z_]+, name="[a-z-]+"' src/ | grep -E '^app\.'
app.add_typer(ci_app, name="ci"
app.add_typer(cloud_app, name="cloud"
app.add_typer(config_app, name="config"
app.add_typer(hook_app, name="hook"
app.add_typer(import_app, name="import"
app.add_typer(inspect_app, name="inspect"
app.add_typer(install_app, name="install"
app.add_typer(man_app, name="man"
app.add_typer(project_app, name="project"
app.add_typer(schema_app, name="schema"
app.add_typer(tool_app, name="tool"
app.add_typer(wiki_app, name="wiki"
@app.command functions resolve to: cat, doctor, find, format, grep, head, ls, mcp, orphans, prune, reindex, reset, status, tail, tree, update, workspace.
Set difference against skip_init_commands:
- in the set, not a command:
sync, watch
- a command, not in the set:
format, orphans
Negative control — is sync/watch registered anywhere under src/?
$ grep -rnE '@(app|[a-z_]+_app)\.command\(\s*"(sync|watch)"|def (sync|watch)\(' src/
src/basic_memory/cli/commands/cloud/project_sync.py:274:@cloud_app.command("sync")
The only hit is cloud sync. That is a subcommand of the cloud group, so ctx.invoked_subcommand is "cloud" for bm cloud sync — "cloud" is already in the set on its own line, and the string "sync" cannot be what matches. "watch" has exactly one occurrence in the whole CLI tree, the set member itself:
$ grep -rnE '"watch"' src/basic_memory/cli/
src/basic_memory/cli/app.py:147: "watch",
Why this is behaviour-neutral right now
skip_init_commands only ever suppresses work. An entry matching nothing suppresses nothing, so sync/watch cost one set lookup and no behaviour. I'm not reporting a broken invocation, and I did not find one.
Why it still seems worth a line of cleanup
The set reads as the authoritative list of "commands that manage their own init," and it's commented that way (# Run initialization for commands that don't use the API). Two of its 23 entries name commands that don't exist, which makes it misleading as documentation of the CLI surface — and it means the set has drifted from the command table at least once without anything catching it.
Questions before I send anything
- Are
sync/watch leftovers from removed commands, or placeholders for planned ones? If planned, leaving them is reasonable and this issue should just close.
- Is
format/orphans being outside the set intentional — i.e. do they genuinely need ensure_initialization()? I did not trace their init paths, so I'm asking rather than asserting.
If the answer to (1) is "leftovers" and (2) is "intentional," I'm happy to send a two-line deletion PR. If (2) turns out to be drift too, that's a separate behavioural change and I'd rather you scope it.
One option worth considering either way: assert the set is a subset of the registered command names in a test, so future drift fails CI instead of accumulating. Happy to include that if you want it.
Summary
skip_init_commandsinsrc/basic_memory/cli/app.pycontains two entries —"sync"and"watch"— that do not match any registered top-level command. They are unreachable set members. Two commands that are registered top-level (format,orphans) are absent from the set, and I can't tell from the code whether that omission is deliberate.No user-visible breakage today (see "Why this is behaviour-neutral right now"). Filing as a hygiene/intent question rather than a bug report.
Observed on
main@8b24eb1ed4aeba45c34e184bd566b6c81603ef24.The set
src/basic_memory/cli/app.py:133-158gatesensure_initialization()onctx.invoked_subcommand not in skip_init_commands.Evidence
Enumerating every top-level command —
@app.command(...)plusapp.add_typer(..., name=...):@app.commandfunctions resolve to:cat, doctor, find, format, grep, head, ls, mcp, orphans, prune, reindex, reset, status, tail, tree, update, workspace.Set difference against
skip_init_commands:sync,watchformat,orphansNegative control — is
sync/watchregistered anywhere undersrc/?The only hit is
cloud sync. That is a subcommand of thecloudgroup, soctx.invoked_subcommandis"cloud"forbm cloud sync—"cloud"is already in the set on its own line, and the string"sync"cannot be what matches."watch"has exactly one occurrence in the whole CLI tree, the set member itself:Why this is behaviour-neutral right now
skip_init_commandsonly ever suppresses work. An entry matching nothing suppresses nothing, sosync/watchcost one set lookup and no behaviour. I'm not reporting a broken invocation, and I did not find one.Why it still seems worth a line of cleanup
The set reads as the authoritative list of "commands that manage their own init," and it's commented that way (
# Run initialization for commands that don't use the API). Two of its 23 entries name commands that don't exist, which makes it misleading as documentation of the CLI surface — and it means the set has drifted from the command table at least once without anything catching it.Questions before I send anything
sync/watchleftovers from removed commands, or placeholders for planned ones? If planned, leaving them is reasonable and this issue should just close.format/orphansbeing outside the set intentional — i.e. do they genuinely needensure_initialization()? I did not trace their init paths, so I'm asking rather than asserting.If the answer to (1) is "leftovers" and (2) is "intentional," I'm happy to send a two-line deletion PR. If (2) turns out to be drift too, that's a separate behavioural change and I'd rather you scope it.
One option worth considering either way: assert the set is a subset of the registered command names in a test, so future drift fails CI instead of accumulating. Happy to include that if you want it.