Summary
bm project list renders an empty table even when a project exists in config.json (and in the local DB). The same project is simultaneously reported as already existing by bm project add, so the two commands disagree about whether the project exists.
Reproduction
$ bm project list
Basic Memory Projects
┏━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━┳━━━━━━┳━━━━━━━━━┓
┃ Name ┃ Local Path ┃ Cloud Path ┃ Workspace ┃ CLI Route ┃ MCP ┃ Sync ┃ Default ┃
┡━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━╇━━━━━━╇━━━━━━━━━┩
└──────┴────────────┴────────────┴───────────┴───────────┴─────┴──────┴─────────┘
$ bm project add main ~/basic-memory
Error adding project: Project 'main' already exists
So add says main exists, but list shows nothing.
Environment
- basic-memory
0.22.0
- macOS (Apple Silicon), Homebrew install
- XDG config:
~/.config/basic-memory/config.json, env: "dev"
- No cloud credentials configured on this machine
What's actually in state
~/.config/basic-memory/config.json:
"projects": {
"main": {
"path": "",
"mode": "cloud",
"workspace_id": null,
"local_sync_path": null,
...
}
},
"default_project": "main"
Local DB (~/.config/basic-memory/memory.db), project table:
3|main|main| <- name=main, permalink=main, path=''
So main is present both in config.projects and in the local DB — it is genuinely not missing. It is mode: cloud with an empty path and no cloud credentials present.
Root cause
In src/basic_memory/cli/commands/project.py, list_projects() builds the table rows (row_names_by_key → sorted_row_keys → project_rows) exclusively from live API query results — the local API list and the per-workspace cloud lists:
# cloud results populate row_names_by_key
for cloud_workspace, cloud_result in cloud_results:
...
row_names_by_key[row_key] = project.name
# local results populate row_names_by_key
for permalink, project in local_projects_by_permalink.items():
if permalink not in cloud_permalinks:
row_names_by_key[(None, permalink)] = project.name
config.projects is consulted only to enrich rows that already exist (configured_names_by_permalink is used for the attached-row lookup), but a configured project never creates a row on its own.
The result: a project that is in config.projects but is not surfaced by either query becomes invisible. That is exactly what happens here — main is mode: cloud, so:
- the cloud branch is skipped because
_has_cloud_credentials(config) is false (no creds on this machine), and
- the local query does not surface a cloud-mode project,
so row_names_by_key ends up empty and the table has zero rows.
Meanwhile bm project add checks the server/DB, finds main, and reports "already exists". The two commands consult different sources of truth.
Expected behavior
bm project list should never show an empty table when config.projects is non-empty. A configured project should appear as a row even when it isn't returned by the live local/cloud queries (e.g. a cloud-mode project on a machine without cloud credentials). At minimum, list should fall back to config.projects for row keys and indicate why a configured project can't be fully resolved (e.g. "cloud, no credentials"), rather than silently hiding it.
Possible fix direction
Seed row_names_by_key from configured_names_by_permalink (config.projects) in addition to the local/cloud query results, so configured-but-unqueried projects still render. Cloud-mode entries with no credentials could show cli_route = cloud and an empty cloud path plus a hint to run bm cloud login.
Related
Summary
bm project listrenders an empty table even when a project exists inconfig.json(and in the local DB). The same project is simultaneously reported as already existing bybm project add, so the two commands disagree about whether the project exists.Reproduction
So
addsaysmainexists, butlistshows nothing.Environment
0.22.0~/.config/basic-memory/config.json,env: "dev"What's actually in state
~/.config/basic-memory/config.json:Local DB (
~/.config/basic-memory/memory.db),projecttable:So
mainis present both inconfig.projectsand in the local DB — it is genuinely not missing. It ismode: cloudwith an emptypathand no cloud credentials present.Root cause
In
src/basic_memory/cli/commands/project.py,list_projects()builds the table rows (row_names_by_key→sorted_row_keys→project_rows) exclusively from live API query results — the local API list and the per-workspace cloud lists:config.projectsis consulted only to enrich rows that already exist (configured_names_by_permalinkis used for the attached-row lookup), but a configured project never creates a row on its own.The result: a project that is in
config.projectsbut is not surfaced by either query becomes invisible. That is exactly what happens here —mainismode: cloud, so:_has_cloud_credentials(config)is false (no creds on this machine), andso
row_names_by_keyends up empty and the table has zero rows.Meanwhile
bm project addchecks the server/DB, findsmain, and reports "already exists". The two commands consult different sources of truth.Expected behavior
bm project listshould never show an empty table whenconfig.projectsis non-empty. A configured project should appear as a row even when it isn't returned by the live local/cloud queries (e.g. a cloud-mode project on a machine without cloud credentials). At minimum, list should fall back toconfig.projectsfor row keys and indicate why a configured project can't be fully resolved (e.g. "cloud, no credentials"), rather than silently hiding it.Possible fix direction
Seed
row_names_by_keyfromconfigured_names_by_permalink(config.projects) in addition to the local/cloud query results, so configured-but-unqueried projects still render. Cloud-mode entries with no credentials could showcli_route = cloudand an empty cloud path plus a hint to runbm cloud login.Related
project add) — related but distinct: there the project is missing from the DB; heremainis present in the DB and still not listed.pathin config) — same empty-path config entry shows up here.