basic-memory 0.15.1__tar.gz → 0.15.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of basic-memory might be problematic. Click here for more details.

Files changed (354) hide show
  1. {basic_memory-0.15.1 → basic_memory-0.15.2}/CHANGELOG.md +45 -1
  2. {basic_memory-0.15.1 → basic_memory-0.15.2}/PKG-INFO +1 -1
  3. {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/cloud-cli.md +73 -0
  4. {basic_memory-0.15.1 → basic_memory-0.15.2}/pyproject.toml +1 -1
  5. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/__init__.py +1 -1
  6. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/__init__.py +2 -1
  7. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +4 -57
  8. basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/cloud_utils.py +100 -0
  9. basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/upload.py +128 -0
  10. basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/upload_command.py +93 -0
  11. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/project.py +116 -101
  12. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/cloud.py +7 -3
  13. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_bisync_commands.py +10 -12
  14. basic_memory-0.15.2/tests/cli/test_cloud_utils.py +326 -0
  15. basic_memory-0.15.2/tests/cli/test_upload.py +328 -0
  16. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/agents/python-developer.md +0 -0
  17. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/agents/system-architect.md +0 -0
  18. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/beta.md +0 -0
  19. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/changelog.md +0 -0
  20. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/release-check.md +0 -0
  21. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/release.md +0 -0
  22. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/spec.md +0 -0
  23. {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/test-live.md +0 -0
  24. {basic_memory-0.15.1 → basic_memory-0.15.2}/.dockerignore +0 -0
  25. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  28. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  29. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/dependabot.yml +0 -0
  30. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude-code-review.yml +0 -0
  31. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude-issue-triage.yml +0 -0
  32. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude.yml +0 -0
  33. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/dev-release.yml +0 -0
  34. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/docker.yml +0 -0
  35. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/pr-title.yml +0 -0
  36. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/release.yml +0 -0
  37. {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/test.yml +0 -0
  38. {basic_memory-0.15.1 → basic_memory-0.15.2}/.gitignore +0 -0
  39. {basic_memory-0.15.1 → basic_memory-0.15.2}/.python-version +0 -0
  40. {basic_memory-0.15.1 → basic_memory-0.15.2}/CITATION.cff +0 -0
  41. {basic_memory-0.15.1 → basic_memory-0.15.2}/CLA.md +0 -0
  42. {basic_memory-0.15.1 → basic_memory-0.15.2}/CLAUDE.md +0 -0
  43. {basic_memory-0.15.1 → basic_memory-0.15.2}/CODE_OF_CONDUCT.md +0 -0
  44. {basic_memory-0.15.1 → basic_memory-0.15.2}/CONTRIBUTING.md +0 -0
  45. {basic_memory-0.15.1 → basic_memory-0.15.2}/Dockerfile +0 -0
  46. {basic_memory-0.15.1 → basic_memory-0.15.2}/LICENSE +0 -0
  47. {basic_memory-0.15.1 → basic_memory-0.15.2}/README.md +0 -0
  48. {basic_memory-0.15.1 → basic_memory-0.15.2}/SECURITY.md +0 -0
  49. {basic_memory-0.15.1 → basic_memory-0.15.2}/docker-compose.yml +0 -0
  50. {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/Docker.md +0 -0
  51. {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/ai-assistant-guide-extended.md +0 -0
  52. {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/character-handling.md +0 -0
  53. {basic_memory-0.15.1 → basic_memory-0.15.2}/justfile +0 -0
  54. {basic_memory-0.15.1 → basic_memory-0.15.2}/llms-install.md +0 -0
  55. {basic_memory-0.15.1 → basic_memory-0.15.2}/smithery.yaml +0 -0
  56. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
  57. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
  58. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
  59. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
  60. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
  61. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
  62. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
  63. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
  64. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-2 Slash Commands Reference.md +0 -0
  65. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-3 Agent Definitions.md +0 -0
  66. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
  67. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
  68. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
  69. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-8 TigrisFS Integration.md +0 -0
  70. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
  71. {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
  72. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/alembic.ini +0 -0
  73. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/env.py +0 -0
  74. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/migrations.py +0 -0
  75. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/script.py.mako +0 -0
  76. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  77. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  78. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  79. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  80. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  81. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  82. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  83. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/__init__.py +0 -0
  84. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/app.py +0 -0
  85. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/__init__.py +0 -0
  86. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/directory_router.py +0 -0
  87. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/importer_router.py +0 -0
  88. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  89. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/management_router.py +0 -0
  90. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/memory_router.py +0 -0
  91. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/project_router.py +0 -0
  92. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/prompt_router.py +0 -0
  93. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/resource_router.py +0 -0
  94. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/search_router.py +0 -0
  95. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/utils.py +0 -0
  96. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/template_loader.py +0 -0
  97. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/__init__.py +0 -0
  98. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/app.py +0 -0
  99. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/auth.py +0 -0
  100. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/__init__.py +0 -0
  101. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  102. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  103. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/mount_commands.py +0 -0
  104. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  105. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  106. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
  107. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/db.py +0 -0
  108. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  109. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  110. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  111. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  112. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/mcp.py +0 -0
  113. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/status.py +0 -0
  114. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/sync.py +0 -0
  115. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/tool.py +0 -0
  116. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/main.py +0 -0
  117. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/config.py +0 -0
  118. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/db.py +0 -0
  119. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/deps.py +0 -0
  120. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/file_utils.py +0 -0
  121. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/ignore_utils.py +0 -0
  122. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/__init__.py +0 -0
  123. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/base.py +0 -0
  124. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  125. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  126. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  127. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
  128. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/utils.py +0 -0
  129. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/__init__.py +0 -0
  130. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/entity_parser.py +0 -0
  131. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
  132. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/plugins.py +0 -0
  133. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/schemas.py +0 -0
  134. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/utils.py +0 -0
  135. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/__init__.py +0 -0
  136. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/async_client.py +0 -0
  137. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/project_context.py +0 -0
  138. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  139. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  140. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  141. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  142. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/search.py +0 -0
  143. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
  144. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  145. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
  146. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/server.py +0 -0
  147. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
  148. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
  149. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/canvas.py +0 -0
  150. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  151. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  152. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  153. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  154. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
  155. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
  156. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
  157. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
  158. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  159. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/search.py +0 -0
  160. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/sync_status.py +0 -0
  161. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/utils.py +0 -0
  162. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
  163. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/write_note.py +0 -0
  164. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/__init__.py +0 -0
  165. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/base.py +0 -0
  166. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/knowledge.py +0 -0
  167. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/project.py +0 -0
  168. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/search.py +0 -0
  169. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/__init__.py +0 -0
  170. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/entity_repository.py +0 -0
  171. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/observation_repository.py +0 -0
  172. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/project_info_repository.py +0 -0
  173. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/project_repository.py +0 -0
  174. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/relation_repository.py +0 -0
  175. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/repository.py +0 -0
  176. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/search_repository.py +0 -0
  177. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/__init__.py +0 -0
  178. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/base.py +0 -0
  179. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/delete.py +0 -0
  180. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/directory.py +0 -0
  181. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/importer.py +0 -0
  182. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/memory.py +0 -0
  183. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/project_info.py +0 -0
  184. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/prompt.py +0 -0
  185. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/request.py +0 -0
  186. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/response.py +0 -0
  187. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/search.py +0 -0
  188. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/sync_report.py +0 -0
  189. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/__init__.py +0 -0
  190. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/context_service.py +0 -0
  191. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/directory_service.py +0 -0
  192. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/entity_service.py +0 -0
  193. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/exceptions.py +0 -0
  194. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/file_service.py +0 -0
  195. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/initialization.py +0 -0
  196. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/link_resolver.py +0 -0
  197. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/project_service.py +0 -0
  198. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/search_service.py +0 -0
  199. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/service.py +0 -0
  200. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/sync_status_service.py +0 -0
  201. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/__init__.py +0 -0
  202. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/background_sync.py +0 -0
  203. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/sync_service.py +0 -0
  204. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/watch_service.py +0 -0
  205. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  206. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
  207. {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/utils.py +0 -0
  208. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/BENCHMARKS.md +0 -0
  209. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_project_commands_integration.py +0 -0
  210. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_sync_commands_integration.py +0 -0
  211. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_version_integration.py +0 -0
  212. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/conftest.py +0 -0
  213. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_build_context_underscore.py +0 -0
  214. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_build_context_validation.py +0 -0
  215. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  216. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  217. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_delete_note_integration.py +0 -0
  218. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_edit_note_integration.py +0 -0
  219. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_list_directory_integration.py +0 -0
  220. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_move_note_integration.py +0 -0
  221. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_project_management_integration.py +0 -0
  222. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  223. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_read_content_integration.py +0 -0
  224. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_read_note_integration.py +0 -0
  225. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_search_integration.py +0 -0
  226. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  227. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_write_note_integration.py +0 -0
  228. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_db_wal_mode.py +0 -0
  229. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_disable_permalinks_integration.py +0 -0
  230. {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_sync_performance_benchmark.py +0 -0
  231. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
  232. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/Screenshot.png +0 -0
  233. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/__init__.py +0 -0
  234. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/conftest.py +0 -0
  235. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_async_client.py +0 -0
  236. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_continue_conversation_template.py +0 -0
  237. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_directory_router.py +0 -0
  238. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_importer_router.py +0 -0
  239. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_knowledge_router.py +0 -0
  240. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_management_router.py +0 -0
  241. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_memory_router.py +0 -0
  242. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_project_router.py +0 -0
  243. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_project_router_operations.py +0 -0
  244. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_prompt_router.py +0 -0
  245. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_relation_background_resolution.py +0 -0
  246. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_resource_router.py +0 -0
  247. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_search_router.py +0 -0
  248. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_search_template.py +0 -0
  249. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_template_loader.py +0 -0
  250. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_template_loader_helpers.py +0 -0
  251. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/conftest.py +0 -0
  252. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_cli_tools.py +0 -0
  253. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_cloud_authentication.py +0 -0
  254. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_ignore_utils.py +0 -0
  255. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_chatgpt.py +0 -0
  256. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_claude_conversations.py +0 -0
  257. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_claude_projects.py +0 -0
  258. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_memory_json.py +0 -0
  259. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/conftest.py +0 -0
  260. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  261. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/importers/test_importer_base.py +0 -0
  262. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/importers/test_importer_utils.py +0 -0
  263. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/__init__.py +0 -0
  264. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_entity_parser.py +0 -0
  265. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_markdown_plugins.py +0 -0
  266. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_markdown_processor.py +0 -0
  267. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_observation_edge_cases.py +0 -0
  268. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_parser_edge_cases.py +0 -0
  269. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_relation_edge_cases.py +0 -0
  270. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_task_detection.py +0 -0
  271. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/conftest.py +0 -0
  272. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  273. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  274. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_prompts.py +0 -0
  275. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_resources.py +0 -0
  276. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_build_context.py +0 -0
  277. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_canvas.py +0 -0
  278. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_delete_note.py +0 -0
  279. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_edit_note.py +0 -0
  280. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_list_directory.py +0 -0
  281. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_move_note.py +0 -0
  282. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_read_content.py +0 -0
  283. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_read_note.py +0 -0
  284. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_recent_activity.py +0 -0
  285. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_resource.py +0 -0
  286. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_search.py +0 -0
  287. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_sync_status.py +0 -0
  288. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_utils.py +0 -0
  289. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_view_note.py +0 -0
  290. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_write_note.py +0 -0
  291. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  292. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_entity_repository.py +0 -0
  293. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_entity_repository_upsert.py +0 -0
  294. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_observation_repository.py +0 -0
  295. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_project_info_repository.py +0 -0
  296. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_project_repository.py +0 -0
  297. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_relation_repository.py +0 -0
  298. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_repository.py +0 -0
  299. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_search_repository.py +0 -0
  300. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  301. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  302. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_serialization.py +0 -0
  303. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_url.py +0 -0
  304. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_url_validation.py +0 -0
  305. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_schemas.py +0 -0
  306. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_search.py +0 -0
  307. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_context_service.py +0 -0
  308. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_directory_service.py +0 -0
  309. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_entity_service.py +0 -0
  310. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  311. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_file_service.py +0 -0
  312. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_initialization.py +0 -0
  313. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_link_resolver.py +0 -0
  314. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_removal_bug.py +0 -0
  315. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_service.py +0 -0
  316. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_service_operations.py +0 -0
  317. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_search_service.py +0 -0
  318. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_sync_status_service.py +0 -0
  319. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_character_conflicts.py +0 -0
  320. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_sync_service.py +0 -0
  321. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
  322. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_tmp_files.py +0 -0
  323. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service.py +0 -0
  324. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
  325. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service_reload.py +0 -0
  326. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_config.py +0 -0
  327. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_db_migration_deduplication.py +0 -0
  328. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_deps.py +0 -0
  329. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_production_cascade_delete.py +0 -0
  330. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_file_utils.py +0 -0
  331. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  332. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_parse_tags.py +0 -0
  333. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_permalink_formatting.py +0 -0
  334. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_utf8_handling.py +0 -0
  335. {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_validate_project_path.py +0 -0
  336. {basic_memory-0.15.1 → basic_memory-0.15.2}/uv.lock +0 -0
  337. {basic_memory-0.15.1 → basic_memory-0.15.2}/v0.15.0-RELEASE-DOCS.md +0 -0
  338. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/README.md +0 -0
  339. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/api-performance.md +0 -0
  340. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/background-relations.md +0 -0
  341. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/basic-memory-home.md +0 -0
  342. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/bug-fixes.md +0 -0
  343. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/chatgpt-integration.md +0 -0
  344. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-authentication.md +0 -0
  345. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-bisync.md +0 -0
  346. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-mode-usage.md +0 -0
  347. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-mount.md +0 -0
  348. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/default-project-mode.md +0 -0
  349. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/env-file-removal.md +0 -0
  350. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/env-var-overrides.md +0 -0
  351. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/explicit-project-parameter.md +0 -0
  352. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/gitignore-integration.md +0 -0
  353. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/project-root-env-var.md +0 -0
  354. {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/sqlite-performance.md +0 -0
@@ -1,5 +1,49 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.15.2 (2025-10-14)
4
+
5
+ ### Features
6
+
7
+ - **#356**: Add WebDAV upload command for cloud projects
8
+ ([`5258f45`](https://github.com/basicmachines-co/basic-memory/commit/5258f457))
9
+ - New `bm cloud upload` command for uploading local files/directories to cloud projects
10
+ - WebDAV-based file transfer with automatic directory creation
11
+ - Support for `.gitignore` and `.bmignore` pattern filtering
12
+ - Automatic project creation with `--create-project` flag
13
+ - Optional post-upload sync with `--sync` flag (enabled by default)
14
+ - Human-readable file size reporting (bytes, KB, MB)
15
+ - Comprehensive test coverage (28 unit tests)
16
+
17
+ ### Migration Guide
18
+
19
+ No manual migration required. Upgrade with:
20
+
21
+ ```bash
22
+ # Update via uv
23
+ uv tool upgrade basic-memory
24
+
25
+ # Or install fresh
26
+ uv tool install basic-memory
27
+ ```
28
+
29
+ **What's New:**
30
+ - Upload local files to cloud projects with `bm cloud upload`
31
+ - Streamlined cloud project creation and management
32
+ - Better file filtering with gitignore integration
33
+
34
+ ### Installation
35
+
36
+ ```bash
37
+ # Latest stable release
38
+ uv tool install basic-memory
39
+
40
+ # Update existing installation
41
+ uv tool upgrade basic-memory
42
+
43
+ # Docker
44
+ docker pull ghcr.io/basicmachines-co/basic-memory:v0.15.2
45
+ ```
46
+
3
47
  ## v0.15.1 (2025-10-13)
4
48
 
5
49
  ### Performance Improvements
@@ -1728,4 +1772,4 @@ Co-authored-by: phernandez <phernandez@basicmachines.co>
1728
1772
  ### Chores
1729
1773
 
1730
1774
  - Remove basic-foundation src ref in pyproject.toml
1731
- ([`29fce8b`](https://github.com/basicmachines-co/basic-memory/commit/29fce8b0b922d54d7799bf2534107ee6cfb961b8))
1775
+ ([`29fce8b`](https://github.com/basicmachines-co/basic-memory/commit/29fce8b0b922d54d7799bf2534107ee6cfb961b8))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.15.1
3
+ Version: 0.15.2
4
4
  Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
5
5
  Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
6
6
  Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
@@ -7,6 +7,7 @@ The Basic Memory Cloud CLI provides seamless integration between local and cloud
7
7
  The cloud CLI enables you to:
8
8
  - **Toggle cloud mode** with `bm cloud login` / `bm cloud logout`
9
9
  - **Use regular commands in cloud mode**: `bm project`, `bm sync`, `bm tool` all work with cloud
10
+ - **Upload local files** directly to cloud projects via `bm cloud upload`
10
11
  - **Bidirectional sync** with rclone bisync (recommended for most users)
11
12
  - **Direct file access** via rclone mount (alternative workflow)
12
13
  - **Integrity verification** with `bm cloud check`
@@ -160,6 +161,69 @@ bm project list
160
161
 
161
162
  This Dropbox-like workflow means you don't need to manually coordinate projects between local and cloud.
162
163
 
164
+ ### Uploading Local Files
165
+
166
+ You can directly upload local files or directories to cloud projects using `bm cloud upload`. This is useful for:
167
+ - Migrating existing local projects to the cloud
168
+ - Quickly uploading specific files or directories
169
+ - One-time bulk uploads without setting up sync
170
+
171
+ **Basic Usage:**
172
+
173
+ ```bash
174
+ # Upload a directory to existing project
175
+ bm cloud upload ~/my-notes --project research
176
+
177
+ # Upload a single file
178
+ bm cloud upload important-doc.md --project research
179
+ ```
180
+
181
+ **Create Project On-the-Fly:**
182
+
183
+ If the target project doesn't exist yet, use `--create-project`:
184
+
185
+ ```bash
186
+ # Upload and create project in one step
187
+ bm cloud upload ~/local-project --project new-research --create-project
188
+ ```
189
+
190
+ **Skip Automatic Sync:**
191
+
192
+ By default, the command syncs the project after upload to index the files. To skip this:
193
+
194
+ ```bash
195
+ # Upload without triggering sync
196
+ bm cloud upload ~/bulk-data --project archives --no-sync
197
+ ```
198
+
199
+ **File Filtering:**
200
+
201
+ The upload command respects `.bmignore` and `.gitignore` patterns, automatically excluding:
202
+ - Hidden files (`.git`, `.DS_Store`)
203
+ - Build artifacts (`node_modules`, `__pycache__`)
204
+ - Database files (`*.db`, `*.db-wal`)
205
+ - Environment files (`.env`)
206
+
207
+ To customize what gets uploaded, edit `~/.basic-memory/.bmignore`.
208
+
209
+ **Complete Example:**
210
+
211
+ ```bash
212
+ # 1. Login to cloud
213
+ bm cloud login
214
+
215
+ # 2. Upload local project (creates project if needed)
216
+ bm cloud upload ~/Documents/research-notes --project research --create-project
217
+
218
+ # 3. Verify upload
219
+ bm project list
220
+ ```
221
+
222
+ **Notes:**
223
+ - Files are uploaded directly via WebDAV (no sync setup required)
224
+ - Uploads are immediate and don't require bisync or mount
225
+ - Use this for migration or one-time uploads; use `bm sync` for ongoing synchronization
226
+
163
227
  ## File Synchronization
164
228
 
165
229
  ### The `bm sync` Command (Cloud Mode Aware)
@@ -628,6 +692,15 @@ bm cloud check # Full integrity check
628
692
  bm cloud check --one-way # Faster one-way check
629
693
  ```
630
694
 
695
+ ### File Upload
696
+
697
+ ```bash
698
+ # Upload files/directories to cloud projects
699
+ bm cloud upload <path> --project <name> # Upload to existing project
700
+ bm cloud upload <path> -p <name> --create-project # Upload and create project
701
+ bm cloud upload <path> -p <name> --no-sync # Upload without syncing
702
+ ```
703
+
631
704
  ### Direct File Access (Mount)
632
705
 
633
706
  ```bash
@@ -34,7 +34,7 @@ dependencies = [
34
34
  "pyjwt>=2.10.1",
35
35
  "python-dotenv>=1.1.0",
36
36
  "pytest-aio>=1.9.0",
37
- "aiofiles>=24.1.0", # Async file I/O
37
+ "aiofiles>=24.1.0", # Async file I/O
38
38
  ]
39
39
 
40
40
 
@@ -1,7 +1,7 @@
1
1
  """basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
2
2
 
3
3
  # Package version - updated by release automation
4
- __version__ = "0.15.1"
4
+ __version__ = "0.15.2"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -2,4 +2,5 @@
2
2
 
3
3
  # Import all commands to register them with typer
4
4
  from basic_memory.cli.commands.cloud.core_commands import * # noqa: F401,F403
5
- from basic_memory.cli.commands.cloud.api_client import get_authenticated_headers # noqa: F401
5
+ from basic_memory.cli.commands.cloud.api_client import get_authenticated_headers, get_cloud_config # noqa: F401
6
+ from basic_memory.cli.commands.cloud.upload_command import * # noqa: F401,F403
@@ -12,6 +12,10 @@ from rich.console import Console
12
12
  from rich.table import Table
13
13
 
14
14
  from basic_memory.cli.commands.cloud.api_client import CloudAPIError, make_api_request
15
+ from basic_memory.cli.commands.cloud.cloud_utils import (
16
+ create_cloud_project,
17
+ fetch_cloud_projects,
18
+ )
15
19
  from basic_memory.cli.commands.cloud.rclone_config import (
16
20
  add_tenant_to_rclone_config,
17
21
  )
@@ -21,11 +25,7 @@ from basic_memory.ignore_utils import get_bmignore_path, create_default_bmignore
21
25
  from basic_memory.schemas.cloud import (
22
26
  TenantMountInfo,
23
27
  MountCredentials,
24
- CloudProjectList,
25
- CloudProjectCreateRequest,
26
- CloudProjectCreateResponse,
27
28
  )
28
- from basic_memory.utils import generate_permalink
29
29
 
30
30
  console = Console()
31
31
 
@@ -110,24 +110,6 @@ async def generate_mount_credentials(tenant_id: str) -> MountCredentials:
110
110
  raise BisyncError(f"Failed to generate credentials: {e}") from e
111
111
 
112
112
 
113
- async def fetch_cloud_projects() -> CloudProjectList:
114
- """Fetch list of projects from cloud API.
115
-
116
- Returns:
117
- CloudProjectList with projects from cloud
118
- """
119
- try:
120
- config_manager = ConfigManager()
121
- config = config_manager.config
122
- host_url = config.cloud_host.rstrip("/")
123
-
124
- response = await make_api_request(method="GET", url=f"{host_url}/proxy/projects/projects")
125
-
126
- return CloudProjectList.model_validate(response.json())
127
- except Exception as e:
128
- raise BisyncError(f"Failed to fetch cloud projects: {e}") from e
129
-
130
-
131
113
  def scan_local_directories(sync_dir: Path) -> list[str]:
132
114
  """Scan local sync directory for project folders.
133
115
 
@@ -148,41 +130,6 @@ def scan_local_directories(sync_dir: Path) -> list[str]:
148
130
  return directories
149
131
 
150
132
 
151
- async def create_cloud_project(project_name: str) -> CloudProjectCreateResponse:
152
- """Create a new project on cloud.
153
-
154
- Args:
155
- project_name: Name of project to create
156
-
157
- Returns:
158
- CloudProjectCreateResponse with project details from API
159
- """
160
- try:
161
- config_manager = ConfigManager()
162
- config = config_manager.config
163
- host_url = config.cloud_host.rstrip("/")
164
-
165
- # Use generate_permalink to ensure consistent naming
166
- project_path = generate_permalink(project_name)
167
-
168
- project_data = CloudProjectCreateRequest(
169
- name=project_name,
170
- path=project_path,
171
- set_default=False,
172
- )
173
-
174
- response = await make_api_request(
175
- method="POST",
176
- url=f"{host_url}/proxy/projects/projects",
177
- headers={"Content-Type": "application/json"},
178
- json_data=project_data.model_dump(),
179
- )
180
-
181
- return CloudProjectCreateResponse.model_validate(response.json())
182
- except Exception as e:
183
- raise BisyncError(f"Failed to create cloud project '{project_name}': {e}") from e
184
-
185
-
186
133
  def get_bisync_state_path(tenant_id: str) -> Path:
187
134
  """Get path to bisync state directory."""
188
135
  return Path.home() / ".basic-memory" / "bisync-state" / tenant_id
@@ -0,0 +1,100 @@
1
+ """Shared utilities for cloud operations."""
2
+
3
+ from basic_memory.cli.commands.cloud.api_client import make_api_request
4
+ from basic_memory.config import ConfigManager
5
+ from basic_memory.schemas.cloud import (
6
+ CloudProjectList,
7
+ CloudProjectCreateRequest,
8
+ CloudProjectCreateResponse,
9
+ )
10
+ from basic_memory.utils import generate_permalink
11
+
12
+
13
+ class CloudUtilsError(Exception):
14
+ """Exception raised for cloud utility errors."""
15
+
16
+ pass
17
+
18
+
19
+ async def fetch_cloud_projects() -> CloudProjectList:
20
+ """Fetch list of projects from cloud API.
21
+
22
+ Returns:
23
+ CloudProjectList with projects from cloud
24
+ """
25
+ try:
26
+ config_manager = ConfigManager()
27
+ config = config_manager.config
28
+ host_url = config.cloud_host.rstrip("/")
29
+
30
+ response = await make_api_request(method="GET", url=f"{host_url}/proxy/projects/projects")
31
+
32
+ return CloudProjectList.model_validate(response.json())
33
+ except Exception as e:
34
+ raise CloudUtilsError(f"Failed to fetch cloud projects: {e}") from e
35
+
36
+
37
+ async def create_cloud_project(project_name: str) -> CloudProjectCreateResponse:
38
+ """Create a new project on cloud.
39
+
40
+ Args:
41
+ project_name: Name of project to create
42
+
43
+ Returns:
44
+ CloudProjectCreateResponse with project details from API
45
+ """
46
+ try:
47
+ config_manager = ConfigManager()
48
+ config = config_manager.config
49
+ host_url = config.cloud_host.rstrip("/")
50
+
51
+ # Use generate_permalink to ensure consistent naming
52
+ project_path = generate_permalink(project_name)
53
+
54
+ project_data = CloudProjectCreateRequest(
55
+ name=project_name,
56
+ path=project_path,
57
+ set_default=False,
58
+ )
59
+
60
+ response = await make_api_request(
61
+ method="POST",
62
+ url=f"{host_url}/proxy/projects/projects",
63
+ headers={"Content-Type": "application/json"},
64
+ json_data=project_data.model_dump(),
65
+ )
66
+
67
+ return CloudProjectCreateResponse.model_validate(response.json())
68
+ except Exception as e:
69
+ raise CloudUtilsError(f"Failed to create cloud project '{project_name}': {e}") from e
70
+
71
+
72
+ async def sync_project(project_name: str) -> None:
73
+ """Trigger sync for a specific project on cloud.
74
+
75
+ Args:
76
+ project_name: Name of project to sync
77
+ """
78
+ try:
79
+ from basic_memory.cli.commands.command_utils import run_sync
80
+
81
+ await run_sync(project=project_name)
82
+ except Exception as e:
83
+ raise CloudUtilsError(f"Failed to sync project '{project_name}': {e}") from e
84
+
85
+
86
+ async def project_exists(project_name: str) -> bool:
87
+ """Check if a project exists on cloud.
88
+
89
+ Args:
90
+ project_name: Name of project to check
91
+
92
+ Returns:
93
+ True if project exists, False otherwise
94
+ """
95
+ try:
96
+ projects = await fetch_cloud_projects()
97
+ project_names = {p.name for p in projects.projects}
98
+ return project_name in project_names
99
+ except Exception:
100
+ return False
@@ -0,0 +1,128 @@
1
+ """WebDAV upload functionality for basic-memory projects."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ import aiofiles
7
+ import httpx
8
+
9
+ from basic_memory.ignore_utils import load_gitignore_patterns, should_ignore_path
10
+ from basic_memory.mcp.async_client import get_client
11
+ from basic_memory.mcp.tools.utils import call_put
12
+
13
+
14
+ async def upload_path(local_path: Path, project_name: str) -> bool:
15
+ """
16
+ Upload a file or directory to cloud project via WebDAV.
17
+
18
+ Args:
19
+ local_path: Path to local file or directory
20
+ project_name: Name of cloud project (destination)
21
+
22
+ Returns:
23
+ True if upload succeeded, False otherwise
24
+ """
25
+ try:
26
+ # Resolve path
27
+ local_path = local_path.resolve()
28
+
29
+ # Check if path exists
30
+ if not local_path.exists():
31
+ print(f"Error: Path does not exist: {local_path}")
32
+ return False
33
+
34
+ # Get files to upload
35
+ if local_path.is_file():
36
+ files_to_upload = [(local_path, local_path.name)]
37
+ else:
38
+ files_to_upload = _get_files_to_upload(local_path)
39
+
40
+ if not files_to_upload:
41
+ print("No files found to upload")
42
+ return True
43
+
44
+ print(f"Found {len(files_to_upload)} file(s) to upload")
45
+
46
+ # Upload files using httpx
47
+ total_bytes = 0
48
+
49
+ async with get_client() as client:
50
+ for i, (file_path, relative_path) in enumerate(files_to_upload, 1):
51
+ # Build remote path: /webdav/{project_name}/{relative_path}
52
+ remote_path = f"/webdav/{project_name}/{relative_path}"
53
+ print(f"Uploading {relative_path} ({i}/{len(files_to_upload)})")
54
+
55
+ # Read file content asynchronously
56
+ async with aiofiles.open(file_path, "rb") as f:
57
+ content = await f.read()
58
+
59
+ # Upload via HTTP PUT to WebDAV endpoint
60
+ response = await call_put(client, remote_path, content=content)
61
+ response.raise_for_status()
62
+
63
+ total_bytes += file_path.stat().st_size
64
+
65
+ # Format size based on magnitude
66
+ if total_bytes < 1024:
67
+ size_str = f"{total_bytes} bytes"
68
+ elif total_bytes < 1024 * 1024:
69
+ size_str = f"{total_bytes / 1024:.1f} KB"
70
+ else:
71
+ size_str = f"{total_bytes / (1024 * 1024):.1f} MB"
72
+
73
+ print(f"✓ Upload complete: {len(files_to_upload)} file(s) ({size_str})")
74
+ return True
75
+
76
+ except httpx.HTTPStatusError as e:
77
+ print(f"Upload failed: HTTP {e.response.status_code} - {e.response.text}")
78
+ return False
79
+ except Exception as e:
80
+ print(f"Upload failed: {e}")
81
+ return False
82
+
83
+
84
+ def _get_files_to_upload(directory: Path) -> list[tuple[Path, str]]:
85
+ """
86
+ Get list of files to upload from directory.
87
+
88
+ Uses .bmignore and .gitignore patterns for filtering.
89
+
90
+ Args:
91
+ directory: Directory to scan
92
+
93
+ Returns:
94
+ List of (absolute_path, relative_path) tuples
95
+ """
96
+ files = []
97
+
98
+ # Load ignore patterns from .bmignore and .gitignore
99
+ ignore_patterns = load_gitignore_patterns(directory)
100
+
101
+ # Walk through directory
102
+ for root, dirs, filenames in os.walk(directory):
103
+ root_path = Path(root)
104
+
105
+ # Filter directories based on ignore patterns
106
+ filtered_dirs = []
107
+ for d in dirs:
108
+ dir_path = root_path / d
109
+ if not should_ignore_path(dir_path, directory, ignore_patterns):
110
+ filtered_dirs.append(d)
111
+ dirs[:] = filtered_dirs
112
+
113
+ # Process files
114
+ for filename in filenames:
115
+ file_path = root_path / filename
116
+
117
+ # Check if file should be ignored
118
+ if should_ignore_path(file_path, directory, ignore_patterns):
119
+ continue
120
+
121
+ # Calculate relative path for remote
122
+ rel_path = file_path.relative_to(directory)
123
+ # Use forward slashes for WebDAV paths
124
+ remote_path = str(rel_path).replace("\\", "/")
125
+
126
+ files.append((file_path, remote_path))
127
+
128
+ return files
@@ -0,0 +1,93 @@
1
+ """Upload CLI commands for basic-memory projects."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ import typer
7
+ from rich.console import Console
8
+
9
+ from basic_memory.cli.app import cloud_app
10
+ from basic_memory.cli.commands.cloud.cloud_utils import (
11
+ create_cloud_project,
12
+ project_exists,
13
+ sync_project,
14
+ )
15
+ from basic_memory.cli.commands.cloud.upload import upload_path
16
+
17
+ console = Console()
18
+
19
+
20
+ @cloud_app.command("upload")
21
+ def upload(
22
+ path: Path = typer.Argument(
23
+ ...,
24
+ help="Path to local file or directory to upload",
25
+ exists=True,
26
+ readable=True,
27
+ resolve_path=True,
28
+ ),
29
+ project: str = typer.Option(
30
+ ...,
31
+ "--project",
32
+ "-p",
33
+ help="Cloud project name (destination)",
34
+ ),
35
+ create_project: bool = typer.Option(
36
+ False,
37
+ "--create-project",
38
+ "-c",
39
+ help="Create project if it doesn't exist",
40
+ ),
41
+ sync: bool = typer.Option(
42
+ True,
43
+ "--sync/--no-sync",
44
+ help="Sync project after upload (default: true)",
45
+ ),
46
+ ) -> None:
47
+ """Upload local files or directories to cloud project via WebDAV.
48
+
49
+ Examples:
50
+ bm cloud upload ~/my-notes --project research
51
+ bm cloud upload notes.md --project research --create-project
52
+ bm cloud upload ~/docs --project work --no-sync
53
+ """
54
+
55
+ async def _upload():
56
+ # Check if project exists
57
+ if not await project_exists(project):
58
+ if create_project:
59
+ console.print(f"[blue]Creating cloud project '{project}'...[/blue]")
60
+ try:
61
+ await create_cloud_project(project)
62
+ console.print(f"[green]✓ Created project '{project}'[/green]")
63
+ except Exception as e:
64
+ console.print(f"[red]Failed to create project: {e}[/red]")
65
+ raise typer.Exit(1)
66
+ else:
67
+ console.print(
68
+ f"[red]Project '{project}' does not exist.[/red]\n"
69
+ f"[yellow]Options:[/yellow]\n"
70
+ f" 1. Create it first: bm project add {project}\n"
71
+ f" 2. Use --create-project flag to create automatically"
72
+ )
73
+ raise typer.Exit(1)
74
+
75
+ # Perform upload
76
+ console.print(f"[blue]Uploading {path} to project '{project}'...[/blue]")
77
+ success = await upload_path(path, project)
78
+ if not success:
79
+ console.print("[red]Upload failed[/red]")
80
+ raise typer.Exit(1)
81
+
82
+ console.print(f"[green]✅ Successfully uploaded to '{project}'[/green]")
83
+
84
+ # Sync project if requested
85
+ if sync:
86
+ console.print(f"[blue]Syncing project '{project}'...[/blue]")
87
+ try:
88
+ await sync_project(project)
89
+ except Exception as e:
90
+ console.print(f"[yellow]Warning: Sync failed: {e}[/yellow]")
91
+ console.print("[dim]Files uploaded but may not be indexed yet[/dim]")
92
+
93
+ asyncio.run(_upload())