basic-memory 0.11.0__tar.gz → 0.12.0__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 (226) hide show
  1. basic_memory-0.12.0/.github/workflows/claude-code-actions.yml +16 -0
  2. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/workflows/test.yml +6 -0
  3. {basic_memory-0.11.0 → basic_memory-0.12.0}/.gitignore +5 -1
  4. {basic_memory-0.11.0 → basic_memory-0.12.0}/CHANGELOG.md +50 -0
  5. {basic_memory-0.11.0 → basic_memory-0.12.0}/PKG-INFO +40 -3
  6. {basic_memory-0.11.0 → basic_memory-0.12.0}/README.md +39 -2
  7. {basic_memory-0.11.0 → basic_memory-0.12.0}/pyproject.toml +1 -1
  8. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/__init__.py +1 -1
  9. basic_memory-0.12.0/src/basic_memory/api/app.py +90 -0
  10. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/app.py +0 -7
  11. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/mcp.py +8 -1
  12. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/sync.py +1 -0
  13. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/tool.py +28 -15
  14. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/main.py +16 -7
  15. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/config.py +28 -4
  16. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/db.py +3 -1
  17. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/file_utils.py +3 -0
  18. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/entity_parser.py +16 -7
  19. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/utils.py +21 -13
  20. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/continue_conversation.py +4 -4
  21. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/search.py +2 -2
  22. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/server.py +2 -2
  23. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/read_note.py +2 -3
  24. basic_memory-0.12.0/src/basic_memory/mcp/tools/search.py +113 -0
  25. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/write_note.py +3 -1
  26. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/search_repository.py +11 -11
  27. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/search.py +2 -2
  28. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/context_service.py +1 -1
  29. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/entity_service.py +10 -10
  30. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/link_resolver.py +8 -1
  31. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/search_service.py +3 -23
  32. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/sync/sync_service.py +60 -23
  33. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/utils.py +10 -2
  34. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/test_knowledge_router.py +3 -3
  35. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/test_search_router.py +8 -8
  36. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/conftest.py +4 -2
  37. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_entity_parser.py +31 -0
  38. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_read_note.py +9 -4
  39. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_resource.py +27 -0
  40. basic_memory-0.12.0/tests/mcp/test_tool_search.py +159 -0
  41. basic_memory-0.11.0/tests/mcp/test_tool_notes.py → basic_memory-0.12.0/tests/mcp/test_tool_write_note.py +63 -6
  42. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/schemas/test_search.py +4 -4
  43. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/services/test_entity_service.py +34 -2
  44. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/services/test_search_service.py +13 -6
  45. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/sync/test_sync_service.py +84 -29
  46. basic_memory-0.12.0/tests/sync/test_sync_wikilink_issue.py +62 -0
  47. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/sync/test_watch_service.py +1 -1
  48. basic_memory-0.12.0/tests/utils/test_parse_tags.py +50 -0
  49. {basic_memory-0.11.0 → basic_memory-0.12.0}/uv.lock +1 -1
  50. basic_memory-0.11.0/src/basic_memory/api/app.py +0 -51
  51. basic_memory-0.11.0/src/basic_memory/mcp/tools/search.py +0 -77
  52. basic_memory-0.11.0/tests/mcp/test_tool_search.py +0 -87
  53. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  54. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  55. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  56. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  57. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/dependabot.yml +0 -0
  58. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/workflows/pr-title.yml +0 -0
  59. {basic_memory-0.11.0 → basic_memory-0.12.0}/.github/workflows/release.yml +0 -0
  60. {basic_memory-0.11.0 → basic_memory-0.12.0}/.python-version +0 -0
  61. {basic_memory-0.11.0 → basic_memory-0.12.0}/CITATION.cff +0 -0
  62. {basic_memory-0.11.0 → basic_memory-0.12.0}/CLA.md +0 -0
  63. {basic_memory-0.11.0 → basic_memory-0.12.0}/CLAUDE.md +0 -0
  64. {basic_memory-0.11.0 → basic_memory-0.12.0}/CODE_OF_CONDUCT.md +0 -0
  65. {basic_memory-0.11.0 → basic_memory-0.12.0}/CONTRIBUTING.md +0 -0
  66. {basic_memory-0.11.0 → basic_memory-0.12.0}/Dockerfile +0 -0
  67. {basic_memory-0.11.0 → basic_memory-0.12.0}/LICENSE +0 -0
  68. {basic_memory-0.11.0 → basic_memory-0.12.0}/Makefile +0 -0
  69. {basic_memory-0.11.0 → basic_memory-0.12.0}/SECURITY.md +0 -0
  70. {basic_memory-0.11.0 → basic_memory-0.12.0}/basic-memory.md +0 -0
  71. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/AI Assistant Guide.md +0 -0
  72. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/CLI Reference.md +0 -0
  73. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Canvas.md +0 -0
  74. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Getting Started with Basic Memory.md +0 -0
  75. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Knowledge Format.md +0 -0
  76. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Obsidian Integration.md +0 -0
  77. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Technical Information.md +0 -0
  78. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/User Guide.md +0 -0
  79. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/Welcome to Basic memory.md +0 -0
  80. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/Canvas.png +0 -0
  81. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/Claude-Obsidian-Demo.mp4 +0 -0
  82. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/Prompt.png +0 -0
  83. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/disk-ai-logo-400x400.png +0 -0
  84. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/disk-ai-logo.png +0 -0
  85. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/prompt 1.png +0 -0
  86. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/prompt2.png +0 -0
  87. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/prompt3.png +0 -0
  88. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/attachments/prompt4.png +0 -0
  89. {basic_memory-0.11.0 → basic_memory-0.12.0}/docs/publish.js +0 -0
  90. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Brewing Equipment.md +0 -0
  91. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Coffee Bean Origins.md +0 -0
  92. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Coffee Brewing Methods.md +0 -0
  93. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Coffee Flavor Map.md +0 -0
  94. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Coffee Knowledge Base.md +0 -0
  95. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Flavor Extraction.md +0 -0
  96. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Perfect Pour Over Coffee Method.canvas +0 -0
  97. {basic_memory-0.11.0 → basic_memory-0.12.0}/examples/Coffee Notes/Tasting Notes.md +0 -0
  98. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/Basic.icns +0 -0
  99. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/README.md +0 -0
  100. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/icon.svg +0 -0
  101. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/installer.py +0 -0
  102. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/make_icons.sh +0 -0
  103. {basic_memory-0.11.0 → basic_memory-0.12.0}/installer/setup.py +0 -0
  104. {basic_memory-0.11.0 → basic_memory-0.12.0}/llms-install.md +0 -0
  105. {basic_memory-0.11.0 → basic_memory-0.12.0}/memory.json +0 -0
  106. {basic_memory-0.11.0 → basic_memory-0.12.0}/scripts/install.sh +0 -0
  107. {basic_memory-0.11.0 → basic_memory-0.12.0}/smithery.yaml +0 -0
  108. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/alembic.ini +0 -0
  109. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/env.py +0 -0
  110. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/migrations.py +0 -0
  111. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/script.py.mako +0 -0
  112. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  113. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  114. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  115. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  116. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/__init__.py +0 -0
  117. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/__init__.py +0 -0
  118. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  119. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/memory_router.py +0 -0
  120. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/project_info_router.py +0 -0
  121. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/resource_router.py +0 -0
  122. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/api/routers/search_router.py +0 -0
  123. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/__init__.py +0 -0
  124. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/__init__.py +0 -0
  125. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/db.py +0 -0
  126. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  127. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  128. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  129. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  130. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/project.py +0 -0
  131. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/cli/commands/status.py +0 -0
  132. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/deps.py +0 -0
  133. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/__init__.py +0 -0
  134. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/markdown_processor.py +0 -0
  135. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/plugins.py +0 -0
  136. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/markdown/schemas.py +0 -0
  137. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/__init__.py +0 -0
  138. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/async_client.py +0 -0
  139. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/main.py +0 -0
  140. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  141. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  142. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  143. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/prompts/utils.py +0 -0
  144. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  145. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/__init__.py +0 -0
  146. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/build_context.py +0 -0
  147. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/canvas.py +0 -0
  148. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  149. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/project_info.py +0 -0
  150. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/read_content.py +0 -0
  151. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  152. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/mcp/tools/utils.py +0 -0
  153. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/models/__init__.py +0 -0
  154. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/models/base.py +0 -0
  155. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/models/knowledge.py +0 -0
  156. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/models/search.py +0 -0
  157. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/__init__.py +0 -0
  158. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/entity_repository.py +0 -0
  159. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/observation_repository.py +0 -0
  160. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/project_info_repository.py +0 -0
  161. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/relation_repository.py +0 -0
  162. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/repository/repository.py +0 -0
  163. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/__init__.py +0 -0
  164. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/base.py +0 -0
  165. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/delete.py +0 -0
  166. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/memory.py +0 -0
  167. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/project_info.py +0 -0
  168. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/request.py +0 -0
  169. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/schemas/response.py +0 -0
  170. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/__init__.py +0 -0
  171. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/exceptions.py +0 -0
  172. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/file_service.py +0 -0
  173. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/services/service.py +0 -0
  174. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/sync/__init__.py +0 -0
  175. {basic_memory-0.11.0 → basic_memory-0.12.0}/src/basic_memory/sync/watch_service.py +0 -0
  176. {basic_memory-0.11.0 → basic_memory-0.12.0}/static/ai_assistant_guide.md +0 -0
  177. {basic_memory-0.11.0 → basic_memory-0.12.0}/static/json_canvas_spec_1_0.md +0 -0
  178. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/Non-MarkdownFileSupport.pdf +0 -0
  179. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/Screenshot.png +0 -0
  180. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/__init__.py +0 -0
  181. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/conftest.py +0 -0
  182. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/test_memory_router.py +0 -0
  183. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/test_project_info_router.py +0 -0
  184. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/api/test_resource_router.py +0 -0
  185. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/conftest.py +0 -0
  186. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_cli_tools.py +0 -0
  187. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_import_chatgpt.py +0 -0
  188. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_import_claude_conversations.py +0 -0
  189. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_import_claude_projects.py +0 -0
  190. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_import_memory_json.py +0 -0
  191. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_project_commands.py +0 -0
  192. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_project_info.py +0 -0
  193. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_status.py +0 -0
  194. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_sync.py +0 -0
  195. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/cli/test_version.py +0 -0
  196. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/edit_file_test.py +0 -0
  197. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/__init__.py +0 -0
  198. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_markdown_plugins.py +0 -0
  199. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_markdown_processor.py +0 -0
  200. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_observation_edge_cases.py +0 -0
  201. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_parser_edge_cases.py +0 -0
  202. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_relation_edge_cases.py +0 -0
  203. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/markdown/test_task_detection.py +0 -0
  204. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/conftest.py +0 -0
  205. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_prompts.py +0 -0
  206. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_resources.py +0 -0
  207. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_canvas.py +0 -0
  208. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_memory.py +0 -0
  209. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_project_info.py +0 -0
  210. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/mcp/test_tool_utils.py +0 -0
  211. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/repository/test_entity_repository.py +0 -0
  212. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/repository/test_observation_repository.py +0 -0
  213. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/repository/test_relation_repository.py +0 -0
  214. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/repository/test_repository.py +0 -0
  215. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/schemas/test_memory_url.py +0 -0
  216. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/schemas/test_schemas.py +0 -0
  217. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/services/test_context_service.py +0 -0
  218. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/services/test_file_service.py +0 -0
  219. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/services/test_link_resolver.py +0 -0
  220. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/sync/test_tmp_files.py +0 -0
  221. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/sync/test_watch_service_edge_cases.py +0 -0
  222. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/test_basic_memory.py +0 -0
  223. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/test_config.py +0 -0
  224. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/utils/test_file_utils.py +0 -0
  225. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/utils/test_permalink_formatting.py +0 -0
  226. {basic_memory-0.11.0 → basic_memory-0.12.0}/tests/utils/test_utf8_handling.py +0 -0
@@ -0,0 +1,16 @@
1
+ name: Claude Code Integration
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [ created ]
6
+ pull_request_review_comment:
7
+ types: [ created ]
8
+
9
+ jobs:
10
+ claude-integration:
11
+ uses: basicmachines-co/claude-code-github-action/.github/workflows/claude-full.yml@v0.11.0
12
+ with:
13
+ issue-label: 'claude-fix' # Optional: customize the trigger label
14
+ secrets:
15
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
16
+ PERSONAL_ACCESS_TOKEN: ${{ secrets.CLAUDE_TOKEN }}
@@ -5,6 +5,12 @@ on:
5
5
  branches: [ "main" ]
6
6
  pull_request:
7
7
  branches: [ "main" ]
8
+ # pull_request_target runs on the BASE of the PR, not the merge result.
9
+ # It has write permissions and access to secrets.
10
+ # It's useful for PRs from forks or automated PRs but requires careful use for security reasons.
11
+ # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
12
+ pull_request_target:
13
+ branches: [ "main" ]
8
14
 
9
15
  jobs:
10
16
  test:
@@ -47,4 +47,8 @@ ENV/
47
47
  # obsidian docs:
48
48
  /docs/.obsidian/
49
49
  /examples/.obsidian/
50
- /examples/.basic-memory/
50
+ /examples/.basic-memory/
51
+
52
+
53
+ # claude action
54
+ claude-output
@@ -1,6 +1,56 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v0.12.0 (2025-04-06)
5
+
6
+ ### Bug Fixes
7
+
8
+ - [bug] `#` character accumulation in markdown frontmatter tags prop
9
+ ([#79](https://github.com/basicmachines-co/basic-memory/pull/79),
10
+ [`6c19c9e`](https://github.com/basicmachines-co/basic-memory/commit/6c19c9edf5131054ba201a109b37f15c83ef150c))
11
+
12
+ - [bug] Cursor has errors calling search tool
13
+ ([#78](https://github.com/basicmachines-co/basic-memory/pull/78),
14
+ [`9d581ce`](https://github.com/basicmachines-co/basic-memory/commit/9d581cee133f9dde4a0a85118868227390c84161))
15
+
16
+ - [bug] Some notes never exit "modified" status
17
+ ([#77](https://github.com/basicmachines-co/basic-memory/pull/77),
18
+ [`7930ddb`](https://github.com/basicmachines-co/basic-memory/commit/7930ddb2919057be30ceac8c4c19da6aaa1d3e92))
19
+
20
+ - [bug] write_note Tool Fails to Update Existing Files in Some Situations.
21
+ ([#80](https://github.com/basicmachines-co/basic-memory/pull/80),
22
+ [`9bff1f7`](https://github.com/basicmachines-co/basic-memory/commit/9bff1f732e71bc60f88b5c2ce3db5a2aa60b8e28))
23
+
24
+ - Set default mcp log level to ERROR
25
+ ([#81](https://github.com/basicmachines-co/basic-memory/pull/81),
26
+ [`248214c`](https://github.com/basicmachines-co/basic-memory/commit/248214cb114a269ca60ff6398e382f9e2495ad8e))
27
+
28
+ - Write_note preserves frontmatter fields in content
29
+ ([#84](https://github.com/basicmachines-co/basic-memory/pull/84),
30
+ [`3f4d9e4`](https://github.com/basicmachines-co/basic-memory/commit/3f4d9e4d872ebc0ed719c61b24d803c14a9db5e6))
31
+
32
+ ### Documentation
33
+
34
+ - Add VS Code instructions to README
35
+ ([#76](https://github.com/basicmachines-co/basic-memory/pull/76),
36
+ [`43cbb7b`](https://github.com/basicmachines-co/basic-memory/commit/43cbb7b38cc0482ac0a41b6759320e3588186e43))
37
+
38
+ - Updated basicmachines.co links to be https
39
+ ([#69](https://github.com/basicmachines-co/basic-memory/pull/69),
40
+ [`40ea28b`](https://github.com/basicmachines-co/basic-memory/commit/40ea28b0bfc60012924a69ecb76511daa4c7d133))
41
+
42
+ ### Features
43
+
44
+ - Add watch to mcp process ([#83](https://github.com/basicmachines-co/basic-memory/pull/83),
45
+ [`00c8633`](https://github.com/basicmachines-co/basic-memory/commit/00c8633cfcee75ff640ff8fe81dafeb956281a94))
46
+
47
+ - Permalink enhancements ([#82](https://github.com/basicmachines-co/basic-memory/pull/82),
48
+ [`617e60b`](https://github.com/basicmachines-co/basic-memory/commit/617e60bda4a590678a5f551f10a73e7b47e3b13e))
49
+
50
+ - Avoiding "useless permalink values" for files without metadata - Enable permalinks to be updated
51
+ on move via config setting
52
+
53
+
4
54
  ## v0.11.0 (2025-03-29)
5
55
 
6
56
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.11.0
3
+ Version: 0.12.0
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
@@ -47,8 +47,8 @@ Basic Memory lets you build persistent knowledge through natural conversations w
47
47
  Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
48
48
  enable any compatible LLM to read and write to your local knowledge base.
49
49
 
50
- - Website: http://basicmachines.co
51
- - Documentation: http://memory.basicmachines.co
50
+ - Website: https://basicmachines.co
51
+ - Documentation: https://memory.basicmachines.co
52
52
 
53
53
  ## Pick up your conversation right where you left off
54
54
 
@@ -296,6 +296,43 @@ Examples of relations:
296
296
  - documented_in [[Coffee Journal]]
297
297
  ```
298
298
 
299
+ ## Using with VS Code
300
+ For one-click installation, click one of the install buttons below...
301
+
302
+ [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-UV-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D&quality=insiders)
303
+
304
+ You can use Basic Memory with VS Code to easily retrieve and store information while coding. Click the installation buttons above for one-click setup, or follow the manual installation instructions below.
305
+
306
+ ### Manual Installation
307
+
308
+ Add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
309
+
310
+ ```json
311
+ {
312
+ "mcp": {
313
+ "servers": {
314
+ "basic-memory": {
315
+ "command": "uvx",
316
+ "args": ["basic-memory", "mcp"]
317
+ }
318
+ }
319
+ }
320
+ }
321
+ ```
322
+
323
+ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace. This will allow you to share the configuration with others.
324
+
325
+ ```json
326
+ {
327
+ "servers": {
328
+ "basic-memory": {
329
+ "command": "uvx",
330
+ "args": ["basic-memory", "mcp"]
331
+ }
332
+ }
333
+ }
334
+ ```
335
+
299
336
  ## Using with Claude Desktop
300
337
 
301
338
  Basic Memory is built using the MCP (Model Context Protocol) and works with the Claude desktop app (https://claude.ai/):
@@ -13,8 +13,8 @@ Basic Memory lets you build persistent knowledge through natural conversations w
13
13
  Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
14
14
  enable any compatible LLM to read and write to your local knowledge base.
15
15
 
16
- - Website: http://basicmachines.co
17
- - Documentation: http://memory.basicmachines.co
16
+ - Website: https://basicmachines.co
17
+ - Documentation: https://memory.basicmachines.co
18
18
 
19
19
  ## Pick up your conversation right where you left off
20
20
 
@@ -262,6 +262,43 @@ Examples of relations:
262
262
  - documented_in [[Coffee Journal]]
263
263
  ```
264
264
 
265
+ ## Using with VS Code
266
+ For one-click installation, click one of the install buttons below...
267
+
268
+ [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-UV-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D&quality=insiders)
269
+
270
+ You can use Basic Memory with VS Code to easily retrieve and store information while coding. Click the installation buttons above for one-click setup, or follow the manual installation instructions below.
271
+
272
+ ### Manual Installation
273
+
274
+ Add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
275
+
276
+ ```json
277
+ {
278
+ "mcp": {
279
+ "servers": {
280
+ "basic-memory": {
281
+ "command": "uvx",
282
+ "args": ["basic-memory", "mcp"]
283
+ }
284
+ }
285
+ }
286
+ }
287
+ ```
288
+
289
+ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace. This will allow you to share the configuration with others.
290
+
291
+ ```json
292
+ {
293
+ "servers": {
294
+ "basic-memory": {
295
+ "command": "uvx",
296
+ "args": ["basic-memory", "mcp"]
297
+ }
298
+ }
299
+ }
300
+ ```
301
+
265
302
  ## Using with Claude Desktop
266
303
 
267
304
  Basic Memory is built using the MCP (Model Context Protocol) and works with the Claude desktop app (https://claude.ai/):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "basic-memory"
3
- version = "0.11.0"
3
+ version = "0.12.0"
4
4
  description = "Local-first knowledge management combining Zettelkasten with knowledge graphs"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12.1"
@@ -1,3 +1,3 @@
1
1
  """basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
2
2
 
3
- __version__ = "0.11.0"
3
+ __version__ = "0.12.0"
@@ -0,0 +1,90 @@
1
+ """FastAPI application for basic-memory knowledge graph API."""
2
+
3
+ import asyncio
4
+ from contextlib import asynccontextmanager
5
+
6
+ from fastapi import FastAPI, HTTPException
7
+ from fastapi.exception_handlers import http_exception_handler
8
+ from loguru import logger
9
+
10
+ from basic_memory import db
11
+ from basic_memory.api.routers import knowledge, memory, project_info, resource, search
12
+ from basic_memory.config import config as project_config
13
+ from basic_memory.config import config_manager
14
+ from basic_memory.sync import SyncService, WatchService
15
+
16
+
17
+ async def run_background_sync(sync_service: SyncService, watch_service: WatchService): # pragma: no cover
18
+ logger.info(f"Starting watch service to sync file changes in dir: {project_config.home}")
19
+ # full sync
20
+ await sync_service.sync(project_config.home, show_progress=False)
21
+
22
+ # watch changes
23
+ await watch_service.run()
24
+
25
+
26
+ @asynccontextmanager
27
+ async def lifespan(app: FastAPI): # pragma: no cover
28
+ """Lifecycle manager for the FastAPI app."""
29
+ await db.run_migrations(project_config)
30
+
31
+ # app config
32
+ basic_memory_config = config_manager.load_config()
33
+ logger.info(f"Sync changes enabled: {basic_memory_config.sync_changes}")
34
+ logger.info(f"Update permalinks on move enabled: {basic_memory_config.update_permalinks_on_move}")
35
+
36
+ watch_task = None
37
+ if basic_memory_config.sync_changes:
38
+ # import after migrations have run
39
+ from basic_memory.cli.commands.sync import get_sync_service
40
+
41
+ sync_service = await get_sync_service()
42
+ watch_service = WatchService(
43
+ sync_service=sync_service,
44
+ file_service=sync_service.entity_service.file_service,
45
+ config=project_config,
46
+ )
47
+ watch_task = asyncio.create_task(run_background_sync(sync_service, watch_service))
48
+ else:
49
+ logger.info("Sync changes disabled. Skipping watch service.")
50
+
51
+
52
+ # proceed with startup
53
+ yield
54
+
55
+ logger.info("Shutting down Basic Memory API")
56
+ if watch_task:
57
+ watch_task.cancel()
58
+
59
+ await db.shutdown_db()
60
+
61
+
62
+ # Initialize FastAPI app
63
+ app = FastAPI(
64
+ title="Basic Memory API",
65
+ description="Knowledge graph API for basic-memory",
66
+ version="0.1.0",
67
+ lifespan=lifespan,
68
+ )
69
+
70
+
71
+ # Include routers
72
+ app.include_router(knowledge.router)
73
+ app.include_router(search.router)
74
+ app.include_router(memory.router)
75
+ app.include_router(resource.router)
76
+ app.include_router(project_info.router)
77
+
78
+
79
+ @app.exception_handler(Exception)
80
+ async def exception_handler(request, exc): # pragma: no cover
81
+ logger.exception(
82
+ "API unhandled exception",
83
+ url=str(request.url),
84
+ method=request.method,
85
+ client=request.client.host if request.client else None,
86
+ path=request.url.path,
87
+ error_type=type(exc).__name__,
88
+ error=str(exc),
89
+ )
90
+ return await http_exception_handler(request, HTTPException(status_code=500, detail=str(exc)))
@@ -1,11 +1,7 @@
1
- import asyncio
2
1
  from typing import Optional
3
2
 
4
3
  import typer
5
4
 
6
- from basic_memory import db
7
- from basic_memory.config import config
8
-
9
5
 
10
6
  def version_callback(value: bool) -> None:
11
7
  """Show version and exit."""
@@ -58,9 +54,6 @@ def app_callback(
58
54
  config = new_config
59
55
 
60
56
 
61
- # Run database migrations
62
- asyncio.run(db.run_migrations(config))
63
-
64
57
  # Register sub-command groups
65
58
  import_app = typer.Typer(help="Import data from various sources")
66
59
  app.add_typer(import_app, name="import")
@@ -4,7 +4,7 @@ from loguru import logger
4
4
 
5
5
  import basic_memory
6
6
  from basic_memory.cli.app import app
7
- from basic_memory.config import config
7
+ from basic_memory.config import config, config_manager
8
8
 
9
9
  # Import mcp instance
10
10
  from basic_memory.mcp.server import mcp as mcp_server # pragma: no cover
@@ -19,8 +19,15 @@ def mcp(): # pragma: no cover
19
19
  home_dir = config.home
20
20
  project_name = config.project
21
21
 
22
+ # app config
23
+ basic_memory_config = config_manager.load_config()
24
+
22
25
  logger.info(f"Starting Basic Memory MCP server {basic_memory.__version__}")
23
26
  logger.info(f"Project: {project_name}")
24
27
  logger.info(f"Project directory: {home_dir}")
28
+ logger.info(f"Sync changes enabled: {basic_memory_config.sync_changes}")
29
+ logger.info(
30
+ f"Update permalinks on move enabled: {basic_memory_config.update_permalinks_on_move}"
31
+ )
25
32
 
26
33
  mcp_server.run()
@@ -70,6 +70,7 @@ async def get_sync_service(): # pragma: no cover
70
70
 
71
71
  # Create sync service
72
72
  sync_service = SyncService(
73
+ config=config,
73
74
  entity_service=entity_service,
74
75
  entity_parser=entity_parser,
75
76
  entity_repository=entity_repository,
@@ -2,31 +2,29 @@
2
2
 
3
3
  import asyncio
4
4
  import sys
5
- from typing import Optional, List, Annotated
5
+ from typing import Annotated, List, Optional
6
6
 
7
7
  import typer
8
8
  from loguru import logger
9
9
  from rich import print as rprint
10
10
 
11
11
  from basic_memory.cli.app import app
12
- from basic_memory.mcp.tools import build_context as mcp_build_context
13
- from basic_memory.mcp.tools import read_note as mcp_read_note
14
- from basic_memory.mcp.tools import recent_activity as mcp_recent_activity
15
- from basic_memory.mcp.tools import search_notes as mcp_search
16
- from basic_memory.mcp.tools import write_note as mcp_write_note
17
12
 
18
13
  # Import prompts
19
14
  from basic_memory.mcp.prompts.continue_conversation import (
20
15
  continue_conversation as mcp_continue_conversation,
21
16
  )
22
-
23
17
  from basic_memory.mcp.prompts.recent_activity import (
24
18
  recent_activity_prompt as recent_activity_prompt,
25
19
  )
26
-
20
+ from basic_memory.mcp.tools import build_context as mcp_build_context
21
+ from basic_memory.mcp.tools import read_note as mcp_read_note
22
+ from basic_memory.mcp.tools import recent_activity as mcp_recent_activity
23
+ from basic_memory.mcp.tools import search_notes as mcp_search
24
+ from basic_memory.mcp.tools import write_note as mcp_write_note
27
25
  from basic_memory.schemas.base import TimeFrame
28
26
  from basic_memory.schemas.memory import MemoryUrl
29
- from basic_memory.schemas.search import SearchQuery, SearchItemType
27
+ from basic_memory.schemas.search import SearchItemType
30
28
 
31
29
  tool_app = typer.Typer()
32
30
  app.add_typer(tool_app, name="tool", help="Access to MCP tools via CLI")
@@ -198,13 +196,28 @@ def search_notes(
198
196
  raise typer.Abort()
199
197
 
200
198
  try:
201
- search_query = SearchQuery(
202
- permalink_match=query if permalink else None,
203
- text=query if not (permalink or title) else None,
204
- title=query if title else None,
205
- after_date=after_date,
199
+ if permalink and title: # pragma: no cover
200
+ typer.echo(
201
+ "Use either --permalink or --title, not both. Exiting.",
202
+ err=True,
203
+ )
204
+ raise typer.Exit(1)
205
+
206
+ # set search type
207
+ search_type = ("permalink" if permalink else None,)
208
+ search_type = ("permalink_match" if permalink and "*" in query else None,)
209
+ search_type = ("title" if title else None,)
210
+ search_type = "text" if search_type is None else search_type
211
+
212
+ results = asyncio.run(
213
+ mcp_search(
214
+ query,
215
+ search_type=search_type,
216
+ page=page,
217
+ after_date=after_date,
218
+ page_size=page_size,
219
+ )
206
220
  )
207
- results = asyncio.run(mcp_search(query=search_query, page=page, page_size=page_size))
208
221
  # Use json module for more controlled serialization
209
222
  import json
210
223
 
@@ -1,21 +1,26 @@
1
1
  """Main CLI entry point for basic-memory.""" # pragma: no cover
2
2
 
3
- from basic_memory.cli.app import app # pragma: no cover
3
+ import asyncio
4
+
4
5
  import typer
5
6
 
7
+ from basic_memory.cli.app import app # pragma: no cover
8
+
6
9
  # Register commands
7
10
  from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
8
- status,
9
- sync,
10
11
  db,
11
- import_memory_json,
12
- mcp,
12
+ import_chatgpt,
13
13
  import_claude_conversations,
14
14
  import_claude_projects,
15
- import_chatgpt,
16
- tool,
15
+ import_memory_json,
16
+ mcp,
17
17
  project,
18
+ status,
19
+ sync,
20
+ tool,
18
21
  )
22
+ from basic_memory.config import config
23
+ from basic_memory.db import run_migrations as db_run_migrations
19
24
 
20
25
 
21
26
  # Version command
@@ -55,4 +60,8 @@ def main(
55
60
 
56
61
 
57
62
  if __name__ == "__main__": # pragma: no cover
63
+ # Run database migrations
64
+ asyncio.run(db_run_migrations(config))
65
+
66
+ # start the app
58
67
  app()
@@ -38,7 +38,11 @@ class ProjectConfig(BaseSettings):
38
38
  default=500, description="Milliseconds to wait after changes before syncing", gt=0
39
39
  )
40
40
 
41
- log_level: str = "DEBUG"
41
+ # update permalinks on move
42
+ update_permalinks_on_move: bool = Field(
43
+ default=False,
44
+ description="Whether to update permalinks when files are moved or renamed. default (False)",
45
+ )
42
46
 
43
47
  model_config = SettingsConfigDict(
44
48
  env_prefix="BASIC_MEMORY_",
@@ -77,6 +81,18 @@ class BasicMemoryConfig(BaseSettings):
77
81
  description="Name of the default project to use",
78
82
  )
79
83
 
84
+ log_level: str = "INFO"
85
+
86
+ update_permalinks_on_move: bool = Field(
87
+ default=False,
88
+ description="Whether to update permalinks when files are moved or renamed. default (False)",
89
+ )
90
+
91
+ sync_changes: bool = Field(
92
+ default=True,
93
+ description="Whether to sync changes in real time. default (True)",
94
+ )
95
+
80
96
  model_config = SettingsConfigDict(
81
97
  env_prefix="BASIC_MEMORY_",
82
98
  extra="ignore",
@@ -194,9 +210,14 @@ def get_project_config(project_name: Optional[str] = None) -> ProjectConfig:
194
210
  "BASIC_MEMORY_PROJECT", project_name or config_manager.default_project
195
211
  )
196
212
 
213
+ update_permalinks_on_move = config_manager.load_config().update_permalinks_on_move
197
214
  try:
198
215
  project_path = config_manager.get_project_path(actual_project_name)
199
- return ProjectConfig(home=project_path, project=actual_project_name)
216
+ return ProjectConfig(
217
+ home=project_path,
218
+ project=actual_project_name,
219
+ update_permalinks_on_move=update_permalinks_on_move,
220
+ )
200
221
  except ValueError: # pragma: no cover
201
222
  logger.warning(f"Project '{actual_project_name}' not found, using default")
202
223
  project_path = config_manager.get_project_path(config_manager.default_project)
@@ -225,8 +246,10 @@ def get_process_name(): # pragma: no cover
225
246
  return "sync"
226
247
  elif "mcp" in sys.argv:
227
248
  return "mcp"
228
- else:
249
+ elif "cli" in sys.argv:
229
250
  return "cli"
251
+ else:
252
+ return "api"
230
253
 
231
254
 
232
255
  process_name = get_process_name()
@@ -234,6 +257,7 @@ process_name = get_process_name()
234
257
  # Global flag to track if logging has been set up
235
258
  _LOGGING_SETUP = False
236
259
 
260
+
237
261
  def setup_basic_memory_logging(): # pragma: no cover
238
262
  """Set up logging for basic-memory, ensuring it only happens once."""
239
263
  global _LOGGING_SETUP
@@ -245,7 +269,7 @@ def setup_basic_memory_logging(): # pragma: no cover
245
269
  setup_logging(
246
270
  env=config.env,
247
271
  home_dir=user_home, # Use user home for logs
248
- log_level=config.log_level,
272
+ log_level=config_manager.load_config().log_level,
249
273
  log_file=f"{DATA_DIR_NAME}/basic-memory-{process_name}.log",
250
274
  console=False,
251
275
  )
@@ -146,7 +146,9 @@ async def engine_session_factory(
146
146
  _session_maker = None
147
147
 
148
148
 
149
- async def run_migrations(app_config: ProjectConfig, database_type=DatabaseType.FILESYSTEM):
149
+ async def run_migrations(
150
+ app_config: ProjectConfig, database_type=DatabaseType.FILESYSTEM
151
+ ): # pragma: no cover
150
152
  """Run any pending alembic migrations."""
151
153
  logger.info("Running database migrations...")
152
154
  try:
@@ -104,6 +104,9 @@ def has_frontmatter(content: str) -> bool:
104
104
  Returns:
105
105
  True if content has valid frontmatter markers (---), False otherwise
106
106
  """
107
+ if not content:
108
+ return False
109
+
107
110
  content = content.strip()
108
111
  if not content.startswith("---"):
109
112
  return False
@@ -92,27 +92,36 @@ class EntityParser:
92
92
  async def parse_file(self, path: Path | str) -> EntityMarkdown:
93
93
  """Parse markdown file into EntityMarkdown."""
94
94
 
95
- absolute_path = self.base_path / path
95
+ # TODO move to api endpoint to check if absolute path was requested
96
+ # Check if the path is already absolute
97
+ if (
98
+ isinstance(path, Path)
99
+ and path.is_absolute()
100
+ or (isinstance(path, str) and Path(path).is_absolute())
101
+ ):
102
+ absolute_path = Path(path)
103
+ else:
104
+ absolute_path = self.base_path / path
105
+
96
106
  # Parse frontmatter and content using python-frontmatter
97
- post = frontmatter.load(str(absolute_path))
107
+ file_content = absolute_path.read_text()
108
+ return await self.parse_file_content(absolute_path, file_content)
98
109
 
110
+ async def parse_file_content(self, absolute_path, file_content):
111
+ post = frontmatter.loads(file_content)
99
112
  # Extract file stat info
100
113
  file_stats = absolute_path.stat()
101
-
102
114
  metadata = post.metadata
103
- metadata["title"] = post.metadata.get("title", absolute_path.name)
115
+ metadata["title"] = post.metadata.get("title", absolute_path.stem)
104
116
  metadata["type"] = post.metadata.get("type", "note")
105
117
  tags = parse_tags(post.metadata.get("tags", [])) # pyright: ignore
106
118
  if tags:
107
119
  metadata["tags"] = tags
108
-
109
120
  # frontmatter
110
121
  entity_frontmatter = EntityFrontmatter(
111
122
  metadata=post.metadata,
112
123
  )
113
-
114
124
  entity_content = parse(post.content)
115
-
116
125
  return EntityMarkdown(
117
126
  frontmatter=entity_frontmatter,
118
127
  content=post.content,