- Simplify `bm cloud status` output: remove verbose health check details
(status/version/timestamp), show simple "Cloud connected" / "Cloud not
connected" message instead
- Improve `bm reindex --project` error for cloud projects: distinguish
between "project not found" and "project is cloud-only" with a helpful
message explaining reindexing is a local operation
- Improve `bm project list` cloud error message: show the actual error
and soften the credentials suggestion
- Add tests for cloud status command (5 tests)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Make `query` optional in `search_notes` so it becomes the single search tool.
Remove `search_by_metadata` entirely — it was unreleased and redundant since
`search_notes` already supports `metadata_filters`, `tags`, and `status`.
- 🔧 `query` param is now `Optional[str] = None`
- 🛡️ Added None guards for project detection and URL resolution
- ✅ Added `no_criteria()` validation with helpful error message
- 🗑️ Deleted `search_by_metadata` tool, imports, tests, and contract entry
- 📝 Updated docs, README, and v0.19.0 release notes
Closes#605
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Replace Layout-based display (expanded to terminal width) with a compact
Panel using Table.grid(expand=False). Add horizontal bar charts for note
types (top 5), embedding coverage bar with Unicode blocks, and colored
status dots. Removes verbose sections (most connected, recent activity,
available projects) in favor of a dense, visually engaging dashboard. 📊
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
- Prompts (search, continue_conversation) now call MCP tools directly
instead of going through API endpoints, matching the recent_activity
pattern and fixing #526 where prompts returned empty results
- sync_file catches SemanticDependenciesMissingError separately so
entities are still returned successfully when vector embedding fails,
with a clear warning instead of silent failure (#578)
- `bm status` and `bm doctor` default to local routing since they scan
the local filesystem — cloud routing returned Docker-internal paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Cloud projects with bisync had a split-brain problem: `path` held a cloud
slug while the actual local directory lived in `local_sync_path`. This caused
`bm status` and file sync to fail for bisync'd cloud projects.
Changes:
- Config migration promotes `local_sync_path` → `path` for entries where
`path` is a non-absolute cloud slug
- `ensure_project_paths_exists` skips cloud-only projects with slug paths
- `initialize_file_sync` and watch service now keep cloud projects that have
an absolute local path (bisync copy) instead of skipping all cloud projects
- `sync-setup` and `project add --cloud --local-path` set both `path` and
`local_sync_path` to the local directory
- `sync-setup` creates the project in the local DB for immediate MCP use
- `_get_sync_project` falls back from `local_sync_path` to `path`
- Config load errors now show user-friendly messages instead of stack traces
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Use config.default_project as single source of truth for the Default
column in `bm project list`, removing checks against local DB and cloud
API is_default fields that could independently mark multiple projects.
Also updates tests that were out of date after get_project_mode changed
to default unknown projects to CLOUD:
- test_get_client_local_project_uses_asgi_transport: register "main" as LOCAL
- test_run_filters_cloud_projects_each_cycle: register local project in config
- test_new_project_addition_scenario: register projects as LOCAL in config
- test_get_project_mode_defaults_to_cloud: assert new CLOUD default
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Refactor CLI commands to use typed ProjectClient instead of raw HTTP calls,
and add workspace metadata to cloud project listings so users can distinguish
personal vs organization projects.
Key changes:
- 🔧 CLI commands now use ProjectClient typed API clients instead of
call_get/call_post with manual URL construction
- 🏢 Cloud project listings include workspace_name, workspace_type, and
workspace_tenant_id for each cloud-sourced project
- Pass config.default_workspace when fetching cloud projects via
_fetch_cloud_projects() and CLI list_projects
- Add --workspace flag to `bm project list` for explicit workspace override
- Add "Workspace" column to CLI project list table
- Add `bm tool list-projects` and `bm tool list-workspaces` JSON commands
- Comprehensive tests for workspace passthrough, merge behavior, and CLI routing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Refactor importers to use FileService for all file operations instead of
direct filesystem calls. This enables cloud environments to override file
operations via dependency injection (e.g., S3FileService).
Changes:
- Add `to_markdown_string()` method to MarkdownProcessor for content
serialization without file I/O
- Update Importer base class to accept FileService and use it for:
- `write_entity()` - now uses FileService.write_file()
- `ensure_folder_exists()` - now async, uses FileService.ensure_directory()
- Fix direct `mkdir()` calls in:
- claude_projects_importer.py
- memory_json_importer.py
- Update deps.py to inject FileService into all importers (v1 and v2)
- Update CLI commands to create and pass FileService to importers
- Update tests to work with new FileService dependency
This follows the pattern used by /knowledge API and SyncService, enabling
cloud to override file operations by providing S3FileService via DI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
MCP server crashes in cloud mode with:
ValueError: DATABASE_URL must be set when using Postgres backend
Root cause: initialize_app() did not check cloud_mode_enabled before
trying to initialize the database. Only ensure_initialization() had
the check. In cloud mode, tenant DBs are per-request via headers,
not via DATABASE_URL environment variable.
Also includes minor formatting fix in telemetry.py.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>