Compare commits
687 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 513fef79c5 | |||
| afa694ba8d | |||
| 8668118f78 | |||
| e81cdc2980 | |||
| d8c9156ffd | |||
| 291a8085ef | |||
| 49041a5168 | |||
| 8cbe1634b6 | |||
| c4b651f5b0 | |||
| 33fdd3d44e | |||
| ef6c47e674 | |||
| f9c3baf5b9 | |||
| 24abf11dab | |||
| ca9a4d9c12 | |||
| aa9594d82a | |||
| 93494b8c13 | |||
| 93ed34001b | |||
| ec94feb6a4 | |||
| 831b9141a5 | |||
| 2de19713f6 | |||
| 79fcfbce6a | |||
| 3d22ba3004 | |||
| 62229d9d0a | |||
| 03ba268cb1 | |||
| de53e0ecc5 | |||
| 4128cac9ab | |||
| 9b53d7863f | |||
| a8d034b940 | |||
| 7c0937f658 | |||
| 8570d96bad | |||
| 480a2d9468 | |||
| df7452e3ba | |||
| 85a8e59d0f | |||
| 07cb7a606b | |||
| 0ef03edde6 | |||
| efe43a10ea | |||
| 4fe6fe09c8 | |||
| 8acdb49a41 | |||
| f7304bf553 | |||
| 5b034f081d | |||
| 271c883ea8 | |||
| 816ee85fb9 | |||
| 3ba3a9504d | |||
| 1667cdc000 | |||
| f916662ff3 | |||
| 0c9800cd3b | |||
| 476239d878 | |||
| 20bb19f4cd | |||
| f6565b9d23 | |||
| b6e8c636ce | |||
| 442fd1523c | |||
| ce4b5d47a0 | |||
| 59e865c079 | |||
| 96b6b21a88 | |||
| 5973f9b787 | |||
| 8887267256 | |||
| a6cfed96f1 | |||
| 2de8183e85 | |||
| 0adbc12f09 | |||
| 80ca5a07fd | |||
| 4502bd3c3b | |||
| b386502020 | |||
| 16ba55d7b4 | |||
| 5458c35b35 | |||
| fc2ee07076 | |||
| 61891f2e33 | |||
| 5f59ca49a2 | |||
| 2ba1ca8722 | |||
| 4b6de80faa | |||
| 1eb4cd154f | |||
| bfee8958ad | |||
| 63f5c62dfd | |||
| 451f27cfd9 | |||
| df5f0f4c04 | |||
| 731e7baac1 | |||
| 877e52fd73 | |||
| fc8ac86fa1 | |||
| df3eb3208c | |||
| 2886ab64e1 | |||
| 36c245f0d2 | |||
| 2bd52676d9 | |||
| 215a2d9f99 | |||
| f485c1ef3f | |||
| 3ff40d51fc | |||
| 82f6d15946 | |||
| 4e7a217fa7 | |||
| 354e1642b2 | |||
| b1bd6d57e8 | |||
| 5365f971ef | |||
| 4ea03d2bf1 | |||
| f652a09664 | |||
| d8901efb46 | |||
| c717d9997e | |||
| f865d39d3d | |||
| 6a667dd3f8 | |||
| 8d21a38588 | |||
| 597b12fcd1 | |||
| c86f4402f6 | |||
| f07643d3a8 | |||
| 8bf7bdbc0d | |||
| d0ae373f45 | |||
| 1acec0a69d | |||
| a2276a8a04 | |||
| ff5d872a8c | |||
| 96ee4eafd2 | |||
| b109b7337f | |||
| 36b51b676e | |||
| 9af320187c | |||
| 5a34a420c9 | |||
| a7e2368f9e | |||
| c755127317 | |||
| 94c04ee456 | |||
| d4ed02ba74 | |||
| 40ed7129c8 | |||
| c4ef7abff5 | |||
| c75f45f3cf | |||
| 5ae8a733ea | |||
| b94ef01f82 | |||
| 12af7930de | |||
| 60ec6728de | |||
| a84e77f4af | |||
| 6910620968 | |||
| 214a54d740 | |||
| 5a90c7cedf | |||
| 9e3fe26a83 | |||
| 47ee982041 | |||
| 4d22c398c6 | |||
| 8ac2d975f9 | |||
| 34830bfad7 | |||
| f5e0c42047 | |||
| 3f98da8c67 | |||
| 14ff77d1c2 | |||
| 4e4da6128d | |||
| 3bed6d8890 | |||
| 4cba7ba01c | |||
| 8eeec64e28 | |||
| c6fa185bf3 | |||
| 415c2b3d6e | |||
| 4aa0cbdd62 | |||
| 55f314237d | |||
| 9862ef5411 | |||
| df5e8d805f | |||
| 831dc1ecdc | |||
| 26381aeed1 | |||
| 7918e5c6bf | |||
| f312341020 | |||
| e871298e95 | |||
| 177ae21ba7 | |||
| 3415fd1014 | |||
| b08659e228 | |||
| 09a4b09436 | |||
| a661e924df | |||
| 05adda1502 | |||
| 0a72d81bb3 | |||
| 5ccf433cad | |||
| b4bf14ebf7 | |||
| 0b335476d6 | |||
| 2fccc74a20 | |||
| c4956cac16 | |||
| 128c2da40c | |||
| 2bfb9c76df | |||
| 3d927b848f | |||
| 953fe20aef | |||
| a4282d9f2f | |||
| 799dd6c629 | |||
| 26e74ea118 | |||
| ee1558ea68 | |||
| 4d62b623db | |||
| 2fe4488eda | |||
| f3e46d7984 | |||
| 56d6f1b4a5 | |||
| 1b39062ecd | |||
| c4cf0aff1e | |||
| 1c343bed66 | |||
| c50d97e548 | |||
| e2e65575d6 | |||
| bf9a6b4a75 | |||
| 474100efef | |||
| b3d5448355 | |||
| 4e53bb83fd | |||
| 8f2b25f0e0 | |||
| 052545b661 | |||
| abd4a5a6da | |||
| a872947e03 | |||
| 093c94fea5 | |||
| cc104f761f | |||
| 7945c1e2f7 | |||
| d7f3f6a96f | |||
| 540da418b3 | |||
| 3e40cb9657 | |||
| 8c81d3ce17 | |||
| b35d594ef0 | |||
| e982900084 | |||
| b3403e96b3 | |||
| fe04a0b2a2 | |||
| 86ad639890 | |||
| 88c8f18200 | |||
| 41a16b93cb | |||
| 367fcaac50 | |||
| 69808b23ca | |||
| 6f207c20c0 | |||
| cff31c5797 | |||
| 2d1ccfa36c | |||
| a2e0f935d6 | |||
| e6b98a15c7 | |||
| 733c4f7514 | |||
| cfa70004be | |||
| 7696fca826 | |||
| 98a2a3cbaf | |||
| 01cbad1dbe | |||
| a4e0422926 | |||
| 552a835669 | |||
| 888e3c2909 | |||
| d1320f671e | |||
| 94bdfe77e4 | |||
| 4791e19685 | |||
| 36848410a1 | |||
| a77b51a28e | |||
| 1a6a65571e | |||
| c8b00449d2 | |||
| 013864ebf0 | |||
| dd91b49054 | |||
| 7c96a0777d | |||
| 148e07c580 | |||
| 21334cc29b | |||
| db60942267 | |||
| 7bfac158df | |||
| 87616924ff | |||
| 5cb0502ed2 | |||
| a94a717b1b | |||
| 6e4bb72f10 | |||
| 11b0e31e24 | |||
| a5c9e77f16 | |||
| 30a89357cb | |||
| 222ec5d3b6 | |||
| d42aec7ea9 | |||
| 9809b469c6 | |||
| 76ac880f2d | |||
| ad3f2650d9 | |||
| d6508d985c | |||
| 7b95b9f37b | |||
| 0bce4be1a6 | |||
| a316424edf | |||
| af71cf4896 | |||
| e846ae85d8 | |||
| 63e4bcdf1d | |||
| f23dd0474b | |||
| fced804438 | |||
| 1fdc9fdc69 | |||
| 2feecdfaf7 | |||
| 195229f78e | |||
| d15f6a8427 | |||
| b8a3a14ad2 | |||
| 9b199c6dcb | |||
| fe4a7b1622 | |||
| 7d2012a82c | |||
| 7f2d4d2a6f | |||
| 8b7f39ee9b | |||
| a368d06fd2 | |||
| 3a2b80b7e9 | |||
| bd5099120f | |||
| 8e64caf784 | |||
| ccb5740920 | |||
| 373893a7ee | |||
| 1987581ee3 | |||
| 59134affa4 | |||
| c7d97decd6 | |||
| 5d5efa02a5 | |||
| 4f12182e28 | |||
| 2c5b63c4a2 | |||
| c4c9f842ea | |||
| dc0ca71c18 | |||
| 236ae268aa | |||
| bd5923a370 | |||
| 4ea5396ddd | |||
| e97eafa55a | |||
| 254e30423d | |||
| 496af07ced | |||
| b5667f9b55 | |||
| 54b968b93c | |||
| e59b5cb6d9 | |||
| f0335b998e | |||
| 66effb04a7 | |||
| 9331126ba1 | |||
| 3bbb44af0b | |||
| f9b2a075a9 | |||
| 0a3f3f07f8 | |||
| 184ea6d9fa | |||
| f5a0e942b0 | |||
| e46555bf2c | |||
| 74e6afdc0f | |||
| aa635b8a8b | |||
| 1856d4b462 | |||
| 73413486bc | |||
| b09eca1698 | |||
| 3004d0d1fe | |||
| b6369d3d14 | |||
| db6d0dcd9e | |||
| 5a5eb443ea | |||
| e1df23d793 | |||
| 0462a7d4ba | |||
| 79db876bd6 | |||
| 0130573342 | |||
| c372dfb09f | |||
| d763d86798 | |||
| 538af97cba | |||
| 054178d155 | |||
| 18f00f861d | |||
| da4d369c32 | |||
| 0f3889fdd0 | |||
| c44291830c | |||
| e1cccba72d | |||
| 6ff39076a0 | |||
| 56cefbaafd | |||
| 3337c7d1ff | |||
| e248763a73 | |||
| 2e5813d31e | |||
| 2cde8d2659 | |||
| 9515130b2a | |||
| b86dd6fb53 | |||
| 8451f2b1d7 | |||
| ee0397513d | |||
| 9c9ff2931d | |||
| bbe6c1e8f3 | |||
| edb7991ccf | |||
| d7faeb754e | |||
| deef89a724 | |||
| 30499a9f61 | |||
| 1ac65b944c | |||
| 306e562281 | |||
| ed82b0c417 | |||
| 0cb3f95d67 | |||
| 0a36256f8a | |||
| 36e67e6eec | |||
| f2683291e4 | |||
| 8c05a9ec80 | |||
| a6d8d4c0f6 | |||
| 0239f4abb4 | |||
| 9259a7eb59 | |||
| 55d675e278 | |||
| 6afe4fd0cc | |||
| 113d1b6f1b | |||
| 545804f194 | |||
| 8bc03d1357 | |||
| f6e0a5b5bb | |||
| 7624a20d8d | |||
| d84708ca7f | |||
| 1428d18de1 | |||
| 312662f382 | |||
| ed9487708e | |||
| 8df88e4d02 | |||
| 07778790d3 | |||
| b609c4e531 | |||
| f1a065bce3 | |||
| 2b94d9a278 | |||
| 344e651693 | |||
| c97733d785 | |||
| 00537272c6 | |||
| b057912452 | |||
| 8489a3d37e | |||
| a47c9c021f | |||
| c46d7a6833 | |||
| 343a6e118b | |||
| a0e754b7ae | |||
| 24ca5f6804 | |||
| f1d50c2ba7 | |||
| 8072449a78 | |||
| 45d3f58e4d | |||
| d9c8923148 | |||
| 15bd6b95ef | |||
| 0715dcff3d | |||
| 009e84926d | |||
| 8838571509 | |||
| 530cbac73f | |||
| e3ced49d9d | |||
| 8f962fdd87 | |||
| fbb497f6dc | |||
| 0023e736ab | |||
| 0b2080114b | |||
| 8730067f3a | |||
| e14ba92631 | |||
| 9d98892570 | |||
| 3be4495723 | |||
| 17c0e0a29b | |||
| 7ebf16a95d | |||
| c05075f8d4 | |||
| 4cef9281ca | |||
| 6888effef2 | |||
| 38616c345d | |||
| f3c1aa895c | |||
| d978aba09b | |||
| 2aaee734c9 | |||
| 369ad37b3d | |||
| 4e5f701d22 | |||
| 9d9ea4d61c | |||
| 7a502e6474 | |||
| c7835a9d5c | |||
| 85835ae533 | |||
| 671e3d4db9 | |||
| e11aeff8d9 | |||
| 803f3efe53 | |||
| d6dab8552c | |||
| d1d433df15 | |||
| 1799c94953 | |||
| 07996181b3 | |||
| a1c37c1dba | |||
| aff53cca93 | |||
| 863e0a4e24 | |||
| eeeade4f07 | |||
| 03793eaf7c | |||
| 26f7e98932 | |||
| 5947f04bd3 | |||
| ba1439fefc | |||
| ef411ceb12 | |||
| c6baf58aa7 | |||
| 3c1748cc89 | |||
| 9206e7960a | |||
| 53c4c20d22 | |||
| b4486d20bd | |||
| a4000f64ce | |||
| 88a1778798 | |||
| 4ce21984a4 | |||
| eb7fbaf0bf | |||
| 8adf1f4ed4 | |||
| 45ce1813e4 | |||
| 2744c4b6a5 | |||
| fd732aa6fe | |||
| 537e58ad7d | |||
| 48e6e84beb | |||
| 02c14acddb | |||
| 0b5425f163 | |||
| 0bcda4a14a | |||
| 7a49f57dee | |||
| 58db2817d2 | |||
| 98fbd60527 | |||
| 6281a81256 | |||
| be1d0b169f | |||
| 148bf6f75a | |||
| 272a983709 | |||
| ef7adb7b99 | |||
| 3cd9178415 | |||
| 856737fe3c | |||
| 1fd680c3f1 | |||
| 38919d11cb | |||
| 85684f848f | |||
| 14ce5a3bd0 | |||
| 45d6caf723 | |||
| 1652f862dd | |||
| c23927d124 | |||
| 1a74d85973 | |||
| d71c6e8568 | |||
| 63b98491be | |||
| 622d37e4a8 | |||
| 916baf8971 | |||
| 95937c6d0a | |||
| 24dc9a2931 | |||
| 85c63e5a7a | |||
| f227ef6a86 | |||
| 897b1edaa4 | |||
| 0c12a39a98 | |||
| efbc758325 | |||
| a0f20eb102 | |||
| 78673d8e51 | |||
| 126c0495c0 | |||
| 4a43d7df4a | |||
| c462faf046 | |||
| 70bb10be1d | |||
| fbf9045d78 | |||
| 1094210c52 | |||
| 391feb639f | |||
| a920a9ff29 | |||
| 05efe8701c | |||
| 0eaf30bb06 | |||
| 0818bda565 | |||
| 6f99d2e551 | |||
| 73d940e064 | |||
| c3678a11d2 | |||
| 203d684c24 | |||
| a872220924 | |||
| 7d763a66ff | |||
| b5d4fb559c | |||
| 830775276d | |||
| ed894fc3ed | |||
| 704338edcf | |||
| 0ca02a7ebe | |||
| 28cc5225a7 | |||
| 9b7bbc7116 | |||
| 138c283d6c | |||
| 7a8954c37e | |||
| 10c7c19c03 | |||
| fb5e9e1d77 | |||
| 66b91b2847 | |||
| b004565df9 | |||
| a258b73e1d | |||
| 9a845f2906 | |||
| 6517e9845f | |||
| 1af05392ee | |||
| cad7019c89 | |||
| 099c334e3d | |||
| 7685586178 | |||
| e9d0a944a9 | |||
| caf3c14bb1 | |||
| c5d9067754 | |||
| e0fc59ea97 | |||
| 49b2adc35c | |||
| 1646572f69 | |||
| f0d7398815 | |||
| 581b7b17c6 | |||
| d775f7bab9 | |||
| fc01f6abaf | |||
| 4614fd09d5 | |||
| 0d4ad7bbf0 | |||
| 7ccec7eba2 | |||
| 021af74545 | |||
| 2ad0ee9d5d | |||
| c9946ecf1e | |||
| 0ba6f219f1 | |||
| 0b3272ae6e | |||
| a7d7cc5ee6 | |||
| a7e696b039 | |||
| 8aaddb6d45 | |||
| d7565312fc | |||
| c7e6eab02f | |||
| bb8da31472 | |||
| e78345ff25 | |||
| 32236cd247 | |||
| 4fd6d0c648 | |||
| e6c8e3662c | |||
| 449b62d947 | |||
| b7497d7484 | |||
| d1431bdb1b | |||
| 171bef717f | |||
| 729a5a3b8d | |||
| 434cdf24dd | |||
| 7f9c1a97a4 | |||
| 53fb13b054 | |||
| bd6c8348b8 | |||
| 994c8b8e7e | |||
| a78e8c3ac5 | |||
| 53900c5baa | |||
| 02c6de3387 | |||
| 9ccf4b6b56 | |||
| ba74ca7e18 | |||
| 5258f45730 | |||
| e773c002ce | |||
| e70ba944e7 | |||
| e41579f971 | |||
| 2b7008d997 | |||
| 56e5cc072b | |||
| c0538ad2dd | |||
| 962d88ea43 | |||
| cd5efd4a44 | |||
| 00b73b0d08 | |||
| a09066e0f0 | |||
| be352ab474 | |||
| 8d2e70cfc8 | |||
| 53438d1eab | |||
| 032de7e3f2 | |||
| fd2b188645 | |||
| 453cba94e4 | |||
| 48cb4be4cd | |||
| 3e876a7549 | |||
| 1fa93ecbd2 | |||
| 73202d1aab | |||
| 795e339333 | |||
| 07e304ce8e | |||
| 2a1c06d9ad | |||
| c6f93a0294 | |||
| ccc4386627 | |||
| 7616b2bb08 | |||
| 14c1fe4e89 | |||
| 367dc6962a | |||
| ee18eb2fea | |||
| 2a050edee4 | |||
| f3b1945e4c | |||
| 16d7eddbf7 | |||
| f5a11f3911 | |||
| ee83b0e5a8 | |||
| a7bf42ef49 | |||
| 903591384d | |||
| 33ee1e0831 | |||
| c83d567917 | |||
| ace6a0f50d | |||
| fc38877008 | |||
| 99a35a7fb4 | |||
| ea2e93d926 | |||
| 324844a670 | |||
| f818702ab7 | |||
| 2efd8f44e2 | |||
| 5da97e4820 | |||
| 17a6733c9d | |||
| 3e168b98f3 | |||
| 1091e11322 | |||
| f40ab31685 | |||
| bcf7f40979 | |||
| 8c7e29e325 | |||
| 84c0b36dee | |||
| 2c5c606a39 | |||
| a1d7792bdb | |||
| 7979b4192e | |||
| 52d9b3c752 | |||
| e0d8aeb149 | |||
| 17b929446a | |||
| b00e4ff5a1 | |||
| 0499319ded | |||
| 3a6baf80fc | |||
| ec2fa07350 | |||
| 73cade27ab | |||
| 7e024a8674 | |||
| 22f7bfa398 | |||
| cd7cee650f | |||
| 105bcaa025 | |||
| 74e12eb782 | |||
| 7a8b08d11e | |||
| 9aa40246a8 | |||
| 7aff836c57 | |||
| 285e96baea | |||
| 2cd2a62f30 | |||
| f3d8d8d617 | |||
| 9743fcd13e | |||
| 65d1984a53 | |||
| b814d40ab1 | |||
| 2438094914 | |||
| 5d74d7407c | |||
| b6aeb3217c | |||
| 08ee7e1201 | |||
| 63ae9ee0e4 | |||
| 0e78751d34 | |||
| 59eae34dee | |||
| b1e55e169e | |||
| 173bff35c1 | |||
| 629c8e47c9 | |||
| 9e4b8bca8f | |||
| b0cc559426 | |||
| 7460a938df | |||
| 43fa5762a8 | |||
| fb1350b294 | |||
| 7585a29c96 | |||
| 752c78c379 | |||
| a4a3b1b689 | |||
| 6361574a20 | |||
| 24a1d6195d | |||
| a0cf62375d | |||
| 473f70c949 | |||
| 2c29dcc2b2 | |||
| 448210e552 | |||
| 3621bb7b4d | |||
| f80ac0ee72 | |||
| 23ddf1918c | |||
| 2aca19aa05 | |||
| 827f7cf3e3 | |||
| bd4f55158b | |||
| 5360005122 | |||
| 39f811f8b5 | |||
| 8e69c8b533 | |||
| 627a5c3c22 | |||
| cd88945b22 | |||
| cd8e372f0a | |||
| a589f8b894 | |||
| c2f4b632cf | |||
| 46d102cef1 | |||
| 8e4dc026ce | |||
| 7af8e198c2 | |||
| 12b51522bc | |||
| ac9e148bcc | |||
| 546e3cd8db | |||
| de4737cc22 | |||
| 77eefeb252 | |||
| e5923a0378 | |||
| 1bf348259b | |||
| 224e4bf9e4 | |||
| 9f1db23c78 | |||
| db5ef7d35c | |||
| f50650763d | |||
| 8a065c32f4 | |||
| 2a3adc109a | |||
| a52ce1c860 | |||
| 616c1f0710 | |||
| 74847cc380 | |||
| d3b6c85184 | |||
| af44941d5a | |||
| 35e4f73ae8 | |||
| 7be001ca68 | |||
| 3269a2f33a | |||
| b8191d090f | |||
| 2ce8a8e4b0 | |||
| f8099cd004 |
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "basic-memory-local",
|
||||
"interface": {
|
||||
"displayName": "Basic Memory Local"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "codex",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/codex"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Developer Tools"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
---
|
||||
name: adversarial-review
|
||||
description: Cross-vendor adversarial code review of the current branch. Two different model families (Claude + Codex/GPT) review the diff independently, then try to refute each other's findings; survivors are reported by confidence. Runs from either Claude Code or Codex. Use when the user asks for an adversarial review, a cross-model / second-opinion review, or wants high-confidence findings before merging. Report-only — never auto-applies fixes.
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Adversarial code review
|
||||
|
||||
Two reviewers from **different model families** — **Claude** and **Codex/GPT** — review the
|
||||
same diff independently, then each tries to **refute** the other's findings. A finding's
|
||||
confidence comes from whether it survives that cross-examination. This kills the two failure
|
||||
modes of solo LLM review: self-ratification (a model won't critique its own work) and
|
||||
confident false positives.
|
||||
|
||||
## You are the orchestrator — and one of the two reviewers
|
||||
|
||||
This skill runs from **either** Claude Code **or** Codex. First, **identify which model
|
||||
family you are** (Claude or Codex/GPT). Then:
|
||||
|
||||
- **You** are reviewer #1. You review **natively**, in this session, using your own tools.
|
||||
- **The other family** is reviewer #2. You invoke it as a **subprocess CLI** for an
|
||||
independent pass: a fresh process, no shared context — that independence is the point.
|
||||
|
||||
The CLI for "the other model":
|
||||
|
||||
| If you are… | Invoke the other via… |
|
||||
|-------------|------------------------|
|
||||
| **Claude** | `codex exec` (GPT) |
|
||||
| **Codex** | `claude -p` (Claude) |
|
||||
|
||||
Everything else in the flow is symmetric. Resolve the `prompts/` and `schemas/` paths
|
||||
below relative to **this skill's own directory** (where this SKILL.md lives).
|
||||
|
||||
## Inputs
|
||||
|
||||
Two independent, optional inputs:
|
||||
|
||||
- `BASE` — the ref to diff against. Default `main`.
|
||||
- `SCOPE` — a pathspec to narrow the review (e.g. `src/basic_memory`). Default: none (whole diff).
|
||||
|
||||
These are separate: a ref and a pathspec are not interchangeable. Build the **canonical diff
|
||||
command** once in preflight and reuse it everywhere below — never re-spell the diff inline
|
||||
(the scattered, inconsistent spelling is what broke earlier). Build it as an **argv array**,
|
||||
not a string, so a `$SCOPE` containing spaces or glob characters survives intact:
|
||||
|
||||
```bash
|
||||
BASE="${BASE:-main}"
|
||||
DIFF=(git diff "$BASE...HEAD") # argv array — never a scalar string
|
||||
[ -n "$SCOPE" ] && DIFF+=(-- "$SCOPE") # pathspec stays one argument even with spaces
|
||||
DIFF_STR=$(printf '%q ' "${DIFF[@]}") # shell-quoted rendering, for embedding in a prompt
|
||||
```
|
||||
|
||||
To **run** it, use `"${DIFF[@]}"` (quoted, no word-splitting). To **embed** it as text inside
|
||||
a subprocess prompt, use `$DIFF_STR`.
|
||||
|
||||
## Preflight
|
||||
|
||||
0. Set `SKILL_DIR` to the directory this SKILL.md lives in. Canonical location is
|
||||
`.agents/skills/adversarial-review` (the shared agent-skills store); Claude Code reaches it
|
||||
via the `.claude/skills/adversarial-review` symlink, Codex via its own skills path. The
|
||||
`prompts/` and `schemas/` subdirs are siblings of this file in every case.
|
||||
1. Confirm the *other* model's CLI is on PATH (`codex` if you're Claude, `claude` if you're
|
||||
Codex). If it's missing, tell the user the panel falls back to single-model (which loses
|
||||
the cross-vendor benefit) and ask whether to proceed or stop.
|
||||
2. Run `"${DIFF[@]}"`. If it prints nothing, report "nothing to review against $BASE"
|
||||
(mention `$SCOPE` if set) and stop.
|
||||
3. `RUN=$(mktemp -d)` — scratch dir for the other model's output. Transient, never committed.
|
||||
No persisted artifacts, no state file.
|
||||
|
||||
## Phase 0 — Deterministic gates (before the models)
|
||||
|
||||
Models are statistically blind to negation ("never do X"). Enforce mechanical house rules
|
||||
with tools, not prompts, and treat hits as high-confidence facts (reported separately from
|
||||
model findings):
|
||||
|
||||
- `just lint` and `just typecheck` if the diff touches `src/`.
|
||||
- Grep the diff for catchable house-rule violations: `getattr(.*,.*,` defaults, bare
|
||||
`except:` / `except Exception: pass`, function-scope imports.
|
||||
|
||||
## Phase 1 — Independent review (you + the other model, concurrently)
|
||||
|
||||
Both reviewers get the same brief: `prompts/review.md` + the repo's `CLAUDE.md` house rules,
|
||||
reviewing the diff from `"${DIFF[@]}"`. Both emit findings matching `schemas/findings.schema.json`.
|
||||
|
||||
**Your native pass:** review as yourself, following `prompts/review.md`. Hold your findings
|
||||
as that JSON shape.
|
||||
|
||||
**The other model's pass** — run, from the repo root, the row that matches you:
|
||||
|
||||
Always redirect `codex` stdin from `/dev/null` — if stdin is a pipe (e.g. the call gets
|
||||
backgrounded), `codex exec` blocks "Reading additional input from stdin..." and fails.
|
||||
|
||||
```bash
|
||||
# You are Claude → run Codex:
|
||||
codex exec -s read-only \
|
||||
--output-schema "$SKILL_DIR/schemas/findings.schema.json" \
|
||||
-o "$RUN/other_findings.json" \
|
||||
"$(cat "$SKILL_DIR/prompts/review.md")
|
||||
|
||||
Review the diff: $DIFF_STR" </dev/null
|
||||
|
||||
# You are Codex → run Claude (read-only via plan mode; parse the JSON block it returns):
|
||||
claude -p --permission-mode plan --output-format json \
|
||||
"$(cat "$SKILL_DIR/prompts/review.md")
|
||||
|
||||
Review the diff: $DIFF_STR
|
||||
Return ONLY a JSON object matching this schema:
|
||||
$(cat "$SKILL_DIR/schemas/findings.schema.json")" </dev/null > "$RUN/other_raw.json"
|
||||
# claude --output-format json output shape varies by CLI version: it may be a JSON ARRAY
|
||||
# of event objects, OR a single result object. Normalize before reading: if it's an array,
|
||||
# take the element with type=='result'; otherwise use the object as-is. Then read its
|
||||
# .result string, strip the ```json fence if present, and parse that.
|
||||
# (Verified empirically: the CLI in this environment emits the array form.)
|
||||
```
|
||||
|
||||
> Runtime note for Codex orchestrating: `claude -p` needs network access, which Codex's
|
||||
> default sandbox blocks. Run it from a Codex session whose project is trusted with network
|
||||
> allowed (or approve the `claude` call when prompted). Keep Codex's own sandbox on — do not
|
||||
> bypass it just to reach the network.
|
||||
|
||||
Tag each finding with its origin (`claude` / `codex`).
|
||||
|
||||
## Phase 2 — Cross-refute
|
||||
|
||||
Each model tries to refute the *other's* findings, per `prompts/refute.md`
|
||||
(verdicts match `schemas/verdicts.schema.json`).
|
||||
|
||||
- **You** refute the other model's findings natively.
|
||||
- **The other model** refutes *your* findings — invoke it again the same way (swap
|
||||
`prompts/review.md` for `prompts/refute.md`, append your findings JSON **and `$DIFF_STR`**
|
||||
so it judges against the right base and scope, and for Codex use
|
||||
`--output-schema "$SKILL_DIR/schemas/verdicts.schema.json"`).
|
||||
|
||||
Match verdicts to findings by `id`.
|
||||
|
||||
## Phase 3 — Synthesize and report (no auto-fix)
|
||||
|
||||
Merge, dedupe (same file + overlapping lines + same root cause = one finding), assign
|
||||
confidence from provenance:
|
||||
|
||||
- **High** — both models raised it independently, OR one raised it and the other upheld it.
|
||||
- **Medium** — one raised it; the other could not refute it but did not independently find it.
|
||||
- **Low / contested** — one raised it and the other **refuted** it. Keep it, show both sides,
|
||||
let the human judge. Never silently drop a contested finding.
|
||||
- Deterministic-gate hits are reported as facts, separate from the model panel.
|
||||
|
||||
Rank by `severity × confidence`. Present a compact table: `severity | confidence | file:line
|
||||
| claim | found-by / upheld-or-refuted-by`. Expand the high-confidence ones with `why` and
|
||||
any suggested fix.
|
||||
|
||||
End by asking which findings, if any, to fix. **Do not edit code until the user picks.**
|
||||
Convergence between the models is not correctness — your job is to surface a ranked,
|
||||
cross-examined list, not to declare the branch clean.
|
||||
|
||||
## Deliberately NOT done
|
||||
|
||||
- No loop-until-both-agree (models converge by going silent, not by being right).
|
||||
- No persisted artifacts / state machine — the scratch dir is thrown away.
|
||||
- No auto-applying fixes.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Refute the other reviewer
|
||||
|
||||
A different reviewer (a different model family) produced the findings below against the
|
||||
same diff under review (the exact `git diff` command is provided with the findings). Your
|
||||
job is to try to **refute** each one.
|
||||
|
||||
Default to skepticism: assume a finding is wrong until the code proves it right. A finding
|
||||
that survives a genuine attempt to disprove it is worth far more than one nobody checked.
|
||||
|
||||
For each finding, read the actual code it points at and return a verdict:
|
||||
|
||||
- **refuted** — the claim is wrong, the code does not do what the finding says, the case
|
||||
cannot occur, or it is pure style with no correctness impact. Cite the specific code or
|
||||
fact that disproves it.
|
||||
- **upheld** — you tried to refute it and could not; the finding is real.
|
||||
- **partial** — the underlying issue is real but the finding mis-states the severity or
|
||||
scope. Explain, and set `corrected_severity` if the severity should change.
|
||||
|
||||
Do not be agreeable for its own sake, and do not refute for its own sake. Follow the code.
|
||||
|
||||
Return ONLY the structured verdicts object conforming to the provided schema. Every
|
||||
verdict's `id` must match the `id` of the finding it judges.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Adversarial reviewer
|
||||
|
||||
You are an independent, skeptical code reviewer. Another agent wrote this code; your
|
||||
job is to find what is actually wrong with it — not to praise it, not to rubber-stamp it.
|
||||
|
||||
You are reviewing a specific diff — the exact `git diff` command to run is provided at the
|
||||
end of this prompt by the orchestrator. Run it, then read the changed files in full for
|
||||
context, not just the hunks.
|
||||
|
||||
## What to look for, in priority order
|
||||
|
||||
1. **Correctness** — logic errors, wrong conditions, off-by-one, unhandled `None`,
|
||||
broken async/await, races, resource leaks, incorrect error handling.
|
||||
2. **Security** — injection, path traversal, secret leakage, missing authz, unsafe
|
||||
deserialization.
|
||||
3. **House rules** (this repo's `CLAUDE.md`/`AGENTS.md` — these are hard rules):
|
||||
- No swallowed exceptions / no silent fallback logic. Code must fail fast.
|
||||
- Imports at the top of the file unless deferral is justified in a comment.
|
||||
- No speculative `getattr(obj, "attr", default)` to paper over unknown attributes.
|
||||
- Repository pattern for data access; MCP tools talk to API routers via the httpx
|
||||
ASGI client, not directly to services.
|
||||
- 100-char lines; full type annotations; async SQLAlchemy 2.0; Pydantic v2.
|
||||
- New code needs tests (coverage stays at 100%).
|
||||
4. **Performance** — N+1 queries, work inside hot loops, sync I/O on the async path.
|
||||
5. **Maintainability** — only when it materially risks a bug. Do not report pure style.
|
||||
|
||||
## Rules of engagement
|
||||
|
||||
- Every finding MUST be falsifiable: cite the specific file, line, and the code that
|
||||
triggers it. "This could be cleaner" is not a finding.
|
||||
- Do not invent issues to seem thorough. An empty findings list is a valid, good result.
|
||||
- Watch your own negation blindness: when a rule says "never do X," check the diff for X
|
||||
explicitly rather than trusting a gestalt impression.
|
||||
- Prefer few high-confidence findings over many speculative ones.
|
||||
- Assign severity honestly: `critical` = data loss/security/crash in normal use;
|
||||
`high` = wrong behavior on a common path; `medium` = wrong on an edge case or a real
|
||||
house-rule violation; `low` = minor.
|
||||
|
||||
Return ONLY the structured findings object conforming to the provided schema.
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "AdversarialReviewFindings",
|
||||
"description": "Structured output for one reviewer's pass over a diff.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["findings"],
|
||||
"properties": {
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "file", "line", "severity", "category", "claim", "why", "suggested_fix"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Short stable slug for this finding, e.g. 'swallowed-exc-sync-service'."
|
||||
},
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Path relative to repo root."
|
||||
},
|
||||
"line": {
|
||||
"type": "integer",
|
||||
"description": "Best line number in the new file, or 0 if not line-specific."
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low"]
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["correctness", "security", "house-rule", "performance", "maintainability"]
|
||||
},
|
||||
"claim": {
|
||||
"type": "string",
|
||||
"description": "One sentence: what is wrong."
|
||||
},
|
||||
"why": {
|
||||
"type": "string",
|
||||
"description": "Concrete reasoning + the specific code that triggers it. Must be falsifiable, not vibes."
|
||||
},
|
||||
"suggested_fix": {
|
||||
"type": ["string", "null"],
|
||||
"description": "The smallest change that resolves it, or null if none is obvious."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "AdversarialReviewVerdicts",
|
||||
"description": "One reviewer's attempt to refute another reviewer's findings.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["verdicts"],
|
||||
"properties": {
|
||||
"verdicts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "verdict", "reasoning", "corrected_severity"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "The id of the finding being judged (must match the input finding's id)."
|
||||
},
|
||||
"verdict": {
|
||||
"type": "string",
|
||||
"enum": ["upheld", "refuted", "partial"],
|
||||
"description": "upheld = the finding is real; refuted = it is wrong or a non-issue; partial = real but mis-scoped/wrong-severity."
|
||||
},
|
||||
"reasoning": {
|
||||
"type": "string",
|
||||
"description": "Why. For refuted, cite the specific code or fact that disproves the claim."
|
||||
},
|
||||
"corrected_severity": {
|
||||
"type": ["string", "null"],
|
||||
"enum": ["critical", "high", "medium", "low", null],
|
||||
"description": "Set only when verdict is 'partial' and severity should change; otherwise null."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: code-review
|
||||
description: Use when reviewing Basic Machines code for house style, architecture risk, pre-merge hardening, or whether a change fits basic-memory/basic-memory-cloud conventions.
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Basic Machines Review
|
||||
|
||||
Use this skill for repo-local review passes where ordinary code review needs Basic Machines
|
||||
house style and architecture judgment. Report findings only; do not edit code unless the user
|
||||
asks you to fix specific findings.
|
||||
|
||||
## Scope
|
||||
|
||||
Review the current diff or named files against:
|
||||
|
||||
- The repo's `AGENTS.md` / `CLAUDE.md`
|
||||
- `docs/ENGINEERING_STYLE.md`
|
||||
- The touched code paths and tests
|
||||
|
||||
Apply only the guidance for the active repo. In `basic-memory`, prioritize local-first
|
||||
file/database/MCP boundaries. In `basic-memory-cloud`, prioritize tenant/workspace isolation,
|
||||
cloud worker behavior, and web-v2 state/runtime boundaries.
|
||||
|
||||
## Review Rubric
|
||||
|
||||
Report only concrete, falsifiable risks:
|
||||
|
||||
- **Cognitive load:** Is the change harder to understand than the problem requires?
|
||||
- **Change propagation:** Will one product change force edits across unrelated layers?
|
||||
- **Knowledge duplication:** Is the same rule encoded in multiple places that can drift?
|
||||
- **Accidental complexity:** Did the change add abstractions, fallbacks, or state without need?
|
||||
- **Dependency direction:** Are API/MCP/CLI, services, repositories, and UI stores respecting
|
||||
their intended boundaries?
|
||||
- **Domain model distortion:** Do names and types still match the product concept, or did a
|
||||
transport/storage detail leak into the domain?
|
||||
- **Test oracle quality:** Would the tests fail for the bug or regression the change claims to
|
||||
protect against?
|
||||
|
||||
## House Rules To Check Explicitly
|
||||
|
||||
- No speculative `getattr(obj, "attr", default)` for unknown model shapes.
|
||||
- No broad exception swallowing, warning-only failure paths, or hidden fallback behavior.
|
||||
- No casts or `Any` that hide an unclear type relationship.
|
||||
- Dataclasses for internal value/result objects; Pydantic at validation/serialization
|
||||
boundaries.
|
||||
- Narrow `Protocol`s when only a capability is needed.
|
||||
- Explicit async/resource ownership, cancellation, and cleanup.
|
||||
- Meaningful regression tests or verification for risky changes.
|
||||
- Comments explain why, not what.
|
||||
|
||||
## Reporting Format
|
||||
|
||||
Lead with findings ordered by severity. Each finding should include:
|
||||
|
||||
| Severity | Use for |
|
||||
| -------- | ------- |
|
||||
| `high` | A likely correctness, security, data-loss, or tenant/workspace isolation failure |
|
||||
| `medium` | A concrete maintainability or boundary risk that can cause future defects |
|
||||
| `low` | A minor consistency issue, ambiguous guidance, or review-only cleanup |
|
||||
|
||||
```text
|
||||
severity | file:line | risk category | claim
|
||||
Why: concrete behavior or code path that proves the risk.
|
||||
Fix: smallest practical change, or "none obvious" if the risk needs product input.
|
||||
```
|
||||
|
||||
If there are no findings, say so and note any verification gaps that remain.
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: fix-pr-issues
|
||||
description: Use when addressing Basic Memory pull request feedback, failed checks, or BM Bossbot blockers from Codex.
|
||||
---
|
||||
|
||||
# Fix Basic Memory PR Issues
|
||||
|
||||
Resolve PR feedback and failed checks, then wait for BM Bossbot to approve the
|
||||
new head SHA. This skill never merges a PR.
|
||||
|
||||
## Gather
|
||||
|
||||
1. Identify the PR:
|
||||
- `gh pr view --json number,url,headRefOid,mergeStateStatus,statusCheckRollup`
|
||||
|
||||
2. Collect feedback:
|
||||
- PR comments and review summaries
|
||||
- inline review comments and unresolved review threads
|
||||
- failed GitHub Actions jobs and relevant logs
|
||||
- the managed `BM_BOSSBOT_SUMMARY` block in the PR body
|
||||
|
||||
3. Build a short issue ledger:
|
||||
- source
|
||||
- concrete problem
|
||||
- expected fix
|
||||
- verification needed
|
||||
|
||||
## Fix
|
||||
|
||||
1. Address one ledger item at a time.
|
||||
2. Read each file in full before editing it.
|
||||
3. Keep diffs narrow and preserve unrelated user changes.
|
||||
4. Run the smallest meaningful verification first, then widen as needed.
|
||||
5. Commit with `git commit -s` when code or docs changed.
|
||||
|
||||
## Push And Recheck
|
||||
|
||||
1. Push the branch.
|
||||
2. Watch checks for the new `headRefOid`.
|
||||
3. Wait for the required `BM Bossbot Approval` status to pass on that exact SHA.
|
||||
4. If BM Bossbot reviews an older SHA, treat the approval as stale and keep
|
||||
waiting for the current one.
|
||||
|
||||
## Reply
|
||||
|
||||
For each addressed comment or blocker, reply with the fix commit, verification
|
||||
run, and current BM Bossbot status. Do not resolve or dismiss substantive
|
||||
feedback without evidence.
|
||||
@@ -0,0 +1,7 @@
|
||||
interface:
|
||||
display_name: "Fix PR Issues"
|
||||
short_description: "Address PR feedback and BM Bossbot blockers"
|
||||
icon_small: "./assets/icon.svg"
|
||||
icon_large: "./assets/icon.svg"
|
||||
brand_color: "#2563EB"
|
||||
default_prompt: "Use $fix-pr-issues to address PR feedback and wait for BM Bossbot Approval on the latest head SHA."
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24" fill="none" stroke="#111827" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12h4l2-6 4 12 2-6h6"/>
|
||||
<path d="M4 20h16"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1,247 @@
|
||||
---
|
||||
name: infographics
|
||||
description: Use when generating Basic Memory PR, changelog, release, or weekly images from Codex.
|
||||
---
|
||||
|
||||
# Basic Memory Images
|
||||
|
||||
Generate repository visuals with evidence-grounded content and canonical output
|
||||
paths. The file and marker names still say "infographic" for compatibility, but
|
||||
PR generation is image-first: scene, poster, painting, photograph, cover,
|
||||
tableau, staged artifact, or another editorial visual moment that describes the
|
||||
intent of the PR. PR images are non-gating BM Bossbot artifacts; changelog and
|
||||
release-summary images are manual evidence-pack workflows.
|
||||
|
||||
## Output Contract
|
||||
|
||||
- Base output directory: `docs/assets/infographics/`
|
||||
- PR image: `docs/assets/infographics/pr-<number>.webp`
|
||||
- Changelog image: `docs/assets/infographics/changelog.webp`
|
||||
- Weekly image:
|
||||
- This is always a 2-Week Retro window: previous ISO week through current ISO
|
||||
week (`start-week = current-week - 1`, `end-week = current-week`).
|
||||
- Same year window: `docs/assets/infographics/<year>-w<start-week>-w<end-week>.webp`
|
||||
- Cross-year window:
|
||||
`docs/assets/infographics/<start-year>-w<start-week>-<end-year>-w<end-week>.webp`
|
||||
|
||||
## PR Mode
|
||||
|
||||
PR mode uses the BM Bossbot summary block as source material. Do not hand-write
|
||||
claims that are not present in the PR body.
|
||||
|
||||
1. Fetch the PR body:
|
||||
|
||||
```bash
|
||||
gh pr view <number> --json body --jq '.body // ""' > /tmp/bm-pr-body.md
|
||||
```
|
||||
|
||||
2. Generate the canonical asset:
|
||||
|
||||
```bash
|
||||
uv run --script scripts/generate_pr_infographic.py \
|
||||
--pr-number <number> \
|
||||
--pr-body-file /tmp/bm-pr-body.md \
|
||||
--theme "<optional visual theme>" \
|
||||
--provenance-output /tmp/bm-infographic-provenance.md \
|
||||
--output docs/assets/infographics/pr-<number>.webp
|
||||
```
|
||||
|
||||
If the PR body contains a managed image theme block, the script reads it
|
||||
automatically:
|
||||
|
||||
```markdown
|
||||
<!-- BM_INFOGRAPHIC_THEME:start -->
|
||||
<theme>
|
||||
<!-- BM_INFOGRAPHIC_THEME:end -->
|
||||
```
|
||||
|
||||
Before spending an image call, test the prompt path locally:
|
||||
|
||||
```bash
|
||||
uv run --script scripts/generate_pr_infographic.py \
|
||||
--pr-number <number> \
|
||||
--pr-body-file /tmp/bm-pr-body.md \
|
||||
--theme "<optional visual theme>" \
|
||||
--output docs/assets/infographics/pr-<number>.webp \
|
||||
--print-prompt
|
||||
```
|
||||
|
||||
`--dry-run` is an alias for `--print-prompt`; both print the final prompt and
|
||||
exit without calling OpenAI.
|
||||
|
||||
When no theme is supplied, the script selects a deterministic BM visual
|
||||
direction from the style pool below based on the PR number and Bossbot summary.
|
||||
This keeps repeated PR images from collapsing into the same generic visual.
|
||||
|
||||
When the image is generated, also write provenance with
|
||||
`--provenance-output <path>`. BM Bossbot publishes that managed block into the
|
||||
PR body with these markers:
|
||||
|
||||
```markdown
|
||||
<!-- BM_INFOGRAPHIC_PROVENANCE:start -->
|
||||
...
|
||||
<!-- BM_INFOGRAPHIC_PROVENANCE:end -->
|
||||
```
|
||||
|
||||
The provenance block records the generated asset path, image model, size,
|
||||
quality, image mode, theme source, and selected visual direction. It
|
||||
intentionally does not dump the full generated prompt into the PR body. Treat
|
||||
this block as debugging and creative provenance only; it is not a merge gate.
|
||||
|
||||
The PR image is visual support only. The authoritative merge gate is the
|
||||
GitHub commit status named `BM Bossbot Approval`.
|
||||
|
||||
## Changelog Mode
|
||||
|
||||
Build an evidence pack before writing a prompt:
|
||||
|
||||
- diff truth source: merged PR diffs, merge commits, or local reconstructed diffs
|
||||
- changed-file orientation: `git diff --stat` plus key file reads
|
||||
- impact ledger: before/after outcomes tied to actual changes
|
||||
- discard list: misleading titles, reverted work, rename-only churn, speculative TODOs
|
||||
- chosen image form: poster, scene, tableau, cover, painting, photograph,
|
||||
staged artifact, or another editorial visual moment
|
||||
- chosen BM style category: exactly one category from the selection pool below
|
||||
|
||||
Read these references before drafting the prompt:
|
||||
|
||||
- `references/prompt-blueprint.md`
|
||||
- `references/style-balance.md`
|
||||
|
||||
Read the current `CHANGELOG.md` entries and include the latest meaningful
|
||||
changes.
|
||||
|
||||
## Style And Category Selection
|
||||
|
||||
Select exactly one BM style category per image based on semantic fit. The
|
||||
visual language should be recognizable and tasteful, while staying
|
||||
business-readable.
|
||||
|
||||
Create an image-first visual form that communicates the change: poster, scene,
|
||||
tableau, cover image, painting, photograph, staged artifact, or another
|
||||
editorial visual moment. Maps, diagrams, dossiers, charts, and labels can appear
|
||||
as props inside the scene, but do not make a text-heavy infographic.
|
||||
|
||||
BM category pool:
|
||||
|
||||
- computer science college textbooks: SICP-style diagrams, algorithms lectures,
|
||||
compiler pipelines, automata, database systems, type theory, operating systems
|
||||
- classic literature subjects: sea voyages, gothic manors, Dickensian city maps,
|
||||
Austen social graphs, library marginalia, travel journals
|
||||
- fantasy/D&D-inspired: quest maps, dungeon keys, guild ledgers, spellbooks,
|
||||
bestiaries, tavern notice boards; no copyrighted settings
|
||||
- Music: Metal, Hard Rock, Punk, techno, soul, reggae bands; no pop music, no
|
||||
direct band logos, album covers, or musician likenesses
|
||||
- sci-fi: Star Wars inspired knockoff, Spaceballs-adjacent space opera, fleet
|
||||
routes, mission consoles, contraband manifests; avoid copyrighted characters,
|
||||
logos, or named fictional universes
|
||||
- Conan the barbarian-inspired sword-and-sorcery: ruined temples, desert routes,
|
||||
battle standards, ancient maps; no named character likenesses
|
||||
- Comic books: issue covers, splash pages, action-panel maps, caption boxes,
|
||||
halftone energy, clean sound-effect typography
|
||||
- French new wave movies: poster style, stark typography, city route maps,
|
||||
jump-cut sequencing, high-contrast editorial photography cues
|
||||
- WWII propaganda posters: home-front public-information poster language,
|
||||
logistics arrows, ration charts, mobilization maps, bold simplified figures;
|
||||
no real-world party symbols, hate imagery, dehumanizing slogans, or false
|
||||
historical claims
|
||||
- Italian movie posters: hand-painted drama, bold credits, expressive color,
|
||||
route-map collage, 1960s or 1970s cinema energy; no direct film titles or
|
||||
actor likenesses
|
||||
- Shakespeare: stage maps, acts and scenes, dramatis personae, royal courts,
|
||||
backstage cue sheets
|
||||
- Greek mythology: temple diagrams, constellation routes, hero's journey maps,
|
||||
oracle tablets, labyrinths, ship routes
|
||||
- noir detective boards: case files, red-string maps, typed evidence labels,
|
||||
precinct wall charts
|
||||
- NASA mission-control dashboards: launch timelines, telemetry maps, orbital
|
||||
routes, status boards
|
||||
- space exploration and astronomy: celestial atlases, observatory charts,
|
||||
star-field maps, orbital mechanics diagrams, planetary survey routes,
|
||||
telescope annotations, mission trajectories, deep-space timelines
|
||||
- paintings: abstract painting, classical landscape, Remington-inspired western
|
||||
action painting, Rembrandt-inspired chiaroscuro, historical mural, stormy
|
||||
seascape, allegorical editorial painting
|
||||
- classic black-and-white photography: documentary field report, newsroom
|
||||
archive print, editorial photo essay, street photography, high-contrast
|
||||
darkroom print, contact sheet, civic infrastructure photograph
|
||||
- 80's action movies: practical explosions, smoky backlit warehouses, neon city
|
||||
streets, helicopter searchlights, mission dossiers, heroic silhouettes,
|
||||
high-stakes countdowns, painted ensemble posters; no direct actor likenesses,
|
||||
real film titles, franchise marks, or catchphrases
|
||||
- alchemy manuscripts: transformation diagrams, annotated symbols, recipe-like
|
||||
process maps, illuminated margins
|
||||
- brutalist civic planning: transit maps, concrete signage, zoning blocks,
|
||||
infrastructure diagrams
|
||||
|
||||
Selection rules:
|
||||
|
||||
- Pick one category only; do not create mixed mashups.
|
||||
- Pick the most appropriate image form. Prefer an actual scene, poster,
|
||||
painting, photograph, tableau, or cover over a text-heavy infographic.
|
||||
- Match metaphor to content, but do not overthink it. The category is a creative
|
||||
catalyst, not a semantic constraint.
|
||||
- Use a polished editorial rendering direction: smooth anti-aliased
|
||||
text, high contrast, clean edges, readable labels.
|
||||
- Make the category drive the composition through a readable staged moment,
|
||||
editorial composition, symbolic environment, route, artifact, or visual
|
||||
metaphor.
|
||||
- Keep the structure literal enough to aid understanding, but not so heavy that
|
||||
it obscures engineering meaning.
|
||||
- Give the image generator creative latitude on layout, structure, color palette,
|
||||
and visual metaphors. Be precise about what content to show, loose about how
|
||||
to show it.
|
||||
- Do not use copyrighted characters, logos, or named fictional universes. Use
|
||||
genre cues, knockoffs, and original compositions instead.
|
||||
|
||||
## Content-First Aesthetic Contract
|
||||
|
||||
The meaning must be readable and clearly hierarchical. Everything else is
|
||||
creative territory: image form, layout, visual metaphors, decorative elements,
|
||||
color choices, and category-specific visual language.
|
||||
|
||||
Hierarchy:
|
||||
|
||||
1. Meaning: what shipped, what changed, and why it matters must be clear.
|
||||
2. If the image uses text, labels, sections, or evidence bullets, they must be
|
||||
legible.
|
||||
3. The selected category's visual DNA should drive the composition as a poster,
|
||||
scene, painting, photograph, tableau, cover, or symbolic object arrangement.
|
||||
4. Do not play it safe. A visually striking image that someone wants to look at
|
||||
beats a correct but boring one.
|
||||
|
||||
Hard rules:
|
||||
|
||||
- Content sections and labels must be readable when present. Text cannot be
|
||||
obscured by decorations.
|
||||
- Do not use lore-heavy copy that competes with engineering or business meaning.
|
||||
- Every prompt must include a clear image-first composition cue: a staged scene,
|
||||
poster composition, painting, photograph, symbolic tableau, hero object,
|
||||
mission room, dossier, artifact, route, or visual metaphor.
|
||||
- Do not over-prescribe exact coordinates or panel geometry; give a composition
|
||||
backbone and let the model compose around it.
|
||||
|
||||
## Generation
|
||||
|
||||
1. Write the final prompt to a temporary markdown file.
|
||||
2. Generate with the shared image helper:
|
||||
|
||||
```bash
|
||||
uv run --script scripts/generate_infographic.py \
|
||||
--prompt-file /tmp/bm-infographic-prompt.md \
|
||||
--output docs/assets/infographics/<name>.webp
|
||||
```
|
||||
|
||||
3. Verify the image exists and is readable before reporting success.
|
||||
|
||||
## Quality Bar
|
||||
|
||||
- Tell a concrete before/after value story, not vague improvement claims.
|
||||
- Stay understandable for both engineers and non-technical stakeholders.
|
||||
- Use plain-language section titles and labels when text is present.
|
||||
- Include clear visual hierarchy: title, staged focal point, symbolic scene,
|
||||
evidence props, or hero object.
|
||||
- Avoid invented facts; only use provided source material.
|
||||
- Favor shipped outcomes over intermediate or reverted work.
|
||||
- Preserve readability with high contrast, non-tiny labels, and uncluttered
|
||||
layout.
|
||||
@@ -0,0 +1,7 @@
|
||||
interface:
|
||||
display_name: "Infographics"
|
||||
short_description: "Generate Basic Memory repo infographics"
|
||||
icon_small: "./assets/icon.svg"
|
||||
icon_large: "./assets/icon.svg"
|
||||
brand_color: "#2563EB"
|
||||
default_prompt: "Use $infographics to generate a Basic Memory PR or changelog infographic with canonical output paths."
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24" fill="none" stroke="#111827" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12h4l2-6 4 12 2-6h6"/>
|
||||
<path d="M4 20h16"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1,72 @@
|
||||
# Prompt Blueprint
|
||||
|
||||
Convert an evidence pack into a final visual prompt. Be precise about the
|
||||
content and loose about visual execution.
|
||||
|
||||
## Required Inputs
|
||||
|
||||
- Diff truth source summary
|
||||
- Changed-file orientation summary
|
||||
- Impact ledger with before/after outcomes
|
||||
- Discard list for excluded noise
|
||||
- Chosen image form
|
||||
- Chosen BM style category
|
||||
|
||||
## Prompt Shape
|
||||
|
||||
```text
|
||||
Create a polished Basic Memory editorial image inspired by
|
||||
<BM_STYLE_CATEGORY>. Use a poster, scene, tableau, painting, photograph, cover
|
||||
image, staged artifact, or another image-first form that best communicates the
|
||||
intent. Use HD editorial rendering with smooth anti-aliased text when text is
|
||||
present. Go bold and let the selected category drive the visual language through
|
||||
original, non-infringing cues.
|
||||
|
||||
TITLE:
|
||||
- "<clear title>"
|
||||
- "<scope subtitle>"
|
||||
|
||||
COMPOSITION:
|
||||
- Recreate a clear staged moment or symbolic image that describes the PR
|
||||
intent.
|
||||
- Maps, diagrams, dossiers, route lines, labels, and artifacts can appear as
|
||||
props inside the scene, but the output should read as an image rather than a
|
||||
dense infographic.
|
||||
- Take creative liberty with layout and styling.
|
||||
- The hard rule: the meaning must be readable and clearly hierarchical.
|
||||
- Keep labels plain-language and technical when labels are used.
|
||||
|
||||
CONTENT:
|
||||
1. "<section>"
|
||||
- <evidence-grounded outcome>
|
||||
- <evidence-grounded outcome>
|
||||
|
||||
2. "<section>"
|
||||
- <evidence-grounded outcome>
|
||||
- <evidence-grounded outcome>
|
||||
|
||||
METRICS:
|
||||
- <metric>
|
||||
- <metric>
|
||||
|
||||
STYLE DIRECTION:
|
||||
- Upscaled editorial, high contrast, anti-aliased text, smooth edges.
|
||||
- Let the category's visual DNA drive the composition.
|
||||
- Use genre/category cues only; do not use copyrighted characters, logos, named
|
||||
fictional universes, direct band logos, album art, or celebrity likenesses.
|
||||
|
||||
DO NOT:
|
||||
- Make text unreadable or let decoration obscure content.
|
||||
- Render a text-heavy infographic, dashboard, flowchart, timeline strip,
|
||||
checklist, bullet-list panel, or dense explanatory diagram.
|
||||
- Use crunchy low-resolution pixel art.
|
||||
- Invent facts not present in the evidence pack.
|
||||
```
|
||||
|
||||
## Writing Rules
|
||||
|
||||
- Keep each bullet specific and evidence-grounded.
|
||||
- Prefer outcome language over implementation trivia.
|
||||
- Default to three or four sections; never exceed five.
|
||||
- Give proportionally more space to dominant changes.
|
||||
- Keep the final prompt short, energetic, and readable.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Style Balance Rubric
|
||||
|
||||
## Core Principle
|
||||
|
||||
Be bold, not confusing. The selected BM style category should structure the
|
||||
visual through a readable image-first composition, not decorate a generic grid.
|
||||
Use an editorial scene, poster, painting, photograph, cover, staged artifact, or
|
||||
tableau that turns the PR intent into a visual moment.
|
||||
|
||||
## Required Traits
|
||||
|
||||
- Anti-aliased typography
|
||||
- Smooth edges
|
||||
- High contrast between text and background
|
||||
- Plain-language section labels
|
||||
- Clear composition backbone: staged scene, editorial poster, painting,
|
||||
photograph, symbolic tableau, hero artifact, dossier, mission room, or route
|
||||
embodied as part of the scene
|
||||
- A single coherent BM style category, expressed through original visual cues
|
||||
|
||||
## Reject Or Rewrite If
|
||||
|
||||
- Content text is unreadable.
|
||||
- The prompt lacks a composition backbone.
|
||||
- The prompt over-prescribes exact panel positions or a rigid grid.
|
||||
- The style leans into crunchy low-resolution pixelation.
|
||||
- Copy uses lore-heavy references instead of engineering meaning.
|
||||
- The prompt uses copyrighted characters, logos, named fictional universes,
|
||||
direct band logos, album art, or celebrity likenesses.
|
||||
|
||||
## Creative Integration Patterns
|
||||
|
||||
- Use category-native map details to organize content: textbook diagrams,
|
||||
literary journeys, quest maps, tour posters, mission-control routes, stage
|
||||
blocking, mythic constellations, star charts, mission trajectories, case
|
||||
boards, or civic plans as props inside the image.
|
||||
- Recreate a scene, editorial poster, painting, photograph, cover, artifact, or
|
||||
tableau instead of sectioned bullets.
|
||||
- Map engineering metrics to visual counters, route progress, or status boards
|
||||
only when they naturally belong in the scene.
|
||||
- Let headers and accents borrow from the selected style.
|
||||
- Keep atmospheric details behind or around content, never over it.
|
||||
@@ -0,0 +1,244 @@
|
||||
---
|
||||
name: instrumentation
|
||||
description: Add Pydantic Logfire observability to applications. Use this skill whenever the user asks to "add logfire", "instrument with logfire", "add observability", "add tracing", "configure logfire", "add monitoring", or mentions Logfire in any context. Supports Python, JavaScript/TypeScript, and Rust. Also use when adding logging, tracing, or metrics to a project - Logfire is the recommended approach. Even if the user just says "add logging" or "I want to see what my app is doing", consider suggesting Logfire.
|
||||
---
|
||||
|
||||
# Instrument with Logfire
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Invoke this skill when:
|
||||
- User asks to "add logfire", "add observability", "add tracing", or "add monitoring"
|
||||
- User wants to instrument an app with structured logging or tracing (Python, JS/TS, or Rust)
|
||||
- User mentions Logfire in any context
|
||||
- User asks to "add logging" or "see what my app is doing"
|
||||
- User wants to monitor AI/LLM calls (PydanticAI, OpenAI, Anthropic)
|
||||
- User asks to add observability to an AI agent or LLM pipeline
|
||||
|
||||
## How Logfire Works
|
||||
|
||||
Logfire is an observability platform built on OpenTelemetry. It captures traces, logs, and metrics from applications. Logfire has native SDKs for Python, JavaScript/TypeScript, and Rust, plus support for any language via OpenTelemetry.
|
||||
|
||||
The reason this skill exists is that Claude tends to get a few things subtly wrong with Logfire - especially the ordering of `configure()` vs `instrument_*()` calls, the structured logging syntax, and which extras to install. These matter because a misconfigured setup silently drops traces.
|
||||
|
||||
## Step 1: Detect Language and Frameworks
|
||||
|
||||
Identify the project language and instrumentable libraries:
|
||||
|
||||
- **Python**: Read `pyproject.toml` or `requirements.txt`. Common instrumentable libraries: FastAPI, httpx, asyncpg, SQLAlchemy, psycopg, Redis, Celery, Django, Flask, requests, PydanticAI.
|
||||
- **JavaScript/TypeScript**: Read `package.json`. Common frameworks: Express, Next.js, Fastify. Also check for Cloudflare Workers or Deno.
|
||||
- **Rust**: Read `Cargo.toml`.
|
||||
|
||||
Then follow the language-specific steps below.
|
||||
|
||||
---
|
||||
|
||||
## Python
|
||||
|
||||
### Install with Extras
|
||||
|
||||
Install `logfire` with extras matching the detected frameworks. Each instrumented library needs its corresponding extra - without it, the `instrument_*()` call will fail at runtime with a missing dependency error.
|
||||
|
||||
```bash
|
||||
uv add 'logfire[fastapi,httpx,asyncpg]'
|
||||
```
|
||||
|
||||
The full list of available extras: `fastapi`, `starlette`, `django`, `flask`, `httpx`, `requests`, `asyncpg`, `psycopg`, `psycopg2`, `sqlalchemy`, `redis`, `pymongo`, `mysql`, `sqlite3`, `celery`, `aiohttp`, `aws-lambda`, `system-metrics`, `litellm`, `dspy`, `google-genai`.
|
||||
|
||||
### Configure and Instrument
|
||||
|
||||
This is where ordering matters. `logfire.configure()` initializes the SDK and must come before everything else. The `instrument_*()` calls register hooks into each library. If you call `instrument_*()` before `configure()`, the hooks register but traces go nowhere.
|
||||
|
||||
```python
|
||||
import logfire
|
||||
|
||||
# 1. Configure first - always
|
||||
logfire.configure()
|
||||
|
||||
# 2. Instrument libraries - after configure, before app starts
|
||||
logfire.instrument_fastapi(app)
|
||||
logfire.instrument_httpx()
|
||||
logfire.instrument_asyncpg()
|
||||
```
|
||||
|
||||
Placement rules:
|
||||
- `logfire.configure()` goes in the application entry point (`main.py`, or the module that creates the app)
|
||||
- Call it **once per process** - not inside request handlers, not in library code
|
||||
- `instrument_*()` calls go right after `configure()`
|
||||
- Web framework instrumentors (`instrument_fastapi`, `instrument_flask`, `instrument_django`) need the app instance as an argument. HTTP client and database instrumentors (`instrument_httpx`, `instrument_asyncpg`) are global and take no arguments.
|
||||
- In **Gunicorn** deployments, call `logfire.configure()` inside the `post_fork` hook, not at module level - each worker is a separate process
|
||||
|
||||
### Structured Logging
|
||||
|
||||
Replace `print()` and `logging.*()` calls with Logfire's structured logging. The key pattern: use `{key}` placeholders with keyword arguments, never f-strings.
|
||||
|
||||
```python
|
||||
# Correct - each {key} becomes a searchable attribute in the Logfire UI
|
||||
logfire.info("Created user {user_id}", user_id=uid)
|
||||
logfire.error("Payment failed {amount} {currency}", amount=100, currency="USD")
|
||||
|
||||
# Wrong - creates a flat string, nothing is searchable
|
||||
logfire.info(f"Created user {uid}")
|
||||
```
|
||||
|
||||
For grouping related operations and measuring duration, use spans:
|
||||
|
||||
```python
|
||||
with logfire.span("Processing order {order_id}", order_id=order_id):
|
||||
items = await fetch_items(order_id)
|
||||
total = calculate_total(items)
|
||||
logfire.info("Calculated total {total}", total=total)
|
||||
```
|
||||
|
||||
For exceptions, use `logfire.exception()` which automatically captures the traceback:
|
||||
|
||||
```python
|
||||
try:
|
||||
await process_order(order_id)
|
||||
except Exception:
|
||||
logfire.exception("Failed to process order {order_id}", order_id=order_id)
|
||||
raise
|
||||
```
|
||||
|
||||
### AI/LLM Instrumentation (Python)
|
||||
|
||||
Logfire auto-instruments AI libraries to capture LLM calls, token usage, tool invocations, and agent runs.
|
||||
|
||||
```bash
|
||||
uv add 'logfire[pydantic-ai]'
|
||||
# or: uv add 'logfire[openai]' / uv add 'logfire[anthropic]'
|
||||
```
|
||||
|
||||
Available AI extras: `pydantic-ai`, `openai`, `anthropic`, `litellm`, `dspy`, `google-genai`.
|
||||
|
||||
```python
|
||||
logfire.configure()
|
||||
logfire.instrument_pydantic_ai() # captures agent runs, tool calls, LLM request/response
|
||||
# or:
|
||||
logfire.instrument_openai() # captures chat completions, embeddings, token counts
|
||||
logfire.instrument_anthropic() # captures messages, token usage
|
||||
```
|
||||
|
||||
For PydanticAI, each agent run becomes a parent span containing child spans for every tool call and LLM request.
|
||||
|
||||
---
|
||||
|
||||
## JavaScript / TypeScript
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
# Node.js
|
||||
npm install @pydantic/logfire-node
|
||||
|
||||
# Cloudflare Workers
|
||||
npm install @pydantic/logfire-cf-workers logfire
|
||||
|
||||
# Next.js / generic
|
||||
npm install logfire
|
||||
```
|
||||
|
||||
### Configure
|
||||
|
||||
**Node.js (Express, Fastify, etc.)** - create an `instrumentation.ts` loaded before your app:
|
||||
|
||||
```typescript
|
||||
import * as logfire from '@pydantic/logfire-node'
|
||||
logfire.configure()
|
||||
```
|
||||
|
||||
Launch with: `node --require ./instrumentation.js app.js`
|
||||
|
||||
The SDK auto-instruments common libraries when loaded before the app. Set `LOGFIRE_TOKEN` in your environment or pass `token` to `configure()`.
|
||||
|
||||
**Cloudflare Workers** - wrap your handler with `instrument()`:
|
||||
|
||||
```typescript
|
||||
import { instrument } from '@pydantic/logfire-cf-workers'
|
||||
|
||||
export default instrument(handler, {
|
||||
service: { name: 'my-worker', version: '1.0.0' }
|
||||
})
|
||||
```
|
||||
|
||||
**Next.js** - set environment variables for OpenTelemetry export:
|
||||
|
||||
```
|
||||
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://logfire-api.pydantic.dev/v1/traces
|
||||
OTEL_EXPORTER_OTLP_HEADERS=Authorization=<your-write-token>
|
||||
```
|
||||
|
||||
### Structured Logging (JS/TS)
|
||||
|
||||
```typescript
|
||||
// Structured attributes as second argument
|
||||
logfire.info('Created user', { user_id: uid })
|
||||
logfire.error('Payment failed', { amount: 100, currency: 'USD' })
|
||||
|
||||
// Spans
|
||||
logfire.span('Processing order', { order_id }, {}, async () => {
|
||||
logfire.info('Processing step completed')
|
||||
})
|
||||
|
||||
// Error reporting
|
||||
logfire.reportError('order processing', error)
|
||||
```
|
||||
|
||||
Log levels: `trace`, `debug`, `info`, `notice`, `warn`, `error`, `fatal`.
|
||||
|
||||
---
|
||||
|
||||
## Rust
|
||||
|
||||
### Install
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
logfire = "0.6"
|
||||
```
|
||||
|
||||
### Configure
|
||||
|
||||
```rust
|
||||
let shutdown_handler = logfire::configure()
|
||||
.install_panic_handler()
|
||||
.finish()?;
|
||||
```
|
||||
|
||||
Set `LOGFIRE_TOKEN` in your environment or use the Logfire CLI to select a project.
|
||||
|
||||
### Structured Logging (Rust)
|
||||
|
||||
The Rust SDK is built on `tracing` and `opentelemetry` - existing `tracing` macros work automatically.
|
||||
|
||||
```rust
|
||||
// Spans
|
||||
logfire::span!("processing order", order_id = order_id).in_scope(|| {
|
||||
// traced code
|
||||
});
|
||||
|
||||
// Events
|
||||
logfire::info!("Created user {user_id}", user_id = uid);
|
||||
```
|
||||
|
||||
Always call `shutdown_handler.shutdown()` before program exit to flush data.
|
||||
|
||||
---
|
||||
|
||||
## Verify
|
||||
|
||||
After instrumentation, verify the setup works:
|
||||
|
||||
1. Run `logfire auth` to check authentication (or set `LOGFIRE_TOKEN`)
|
||||
2. Start the app and trigger a request
|
||||
3. Check https://logfire.pydantic.dev/ for traces
|
||||
|
||||
If traces aren't appearing: check that `configure()` is called before `instrument_*()` (Python), check that `LOGFIRE_TOKEN` is set, and check that the correct packages/extras are installed.
|
||||
|
||||
## References
|
||||
|
||||
Detailed patterns and integration tables, organized by language:
|
||||
|
||||
- **Python**: `${CLAUDE_PLUGIN_ROOT}/skills/instrumentation/references/python/logging-patterns.md` (log levels, spans, stdlib integration, metrics, capfire testing) and `${CLAUDE_PLUGIN_ROOT}/skills/instrumentation/references/python/integrations.md` (full instrumentor table with extras)
|
||||
- **JavaScript/TypeScript**: `${CLAUDE_PLUGIN_ROOT}/skills/instrumentation/references/javascript/patterns.md` (log levels, spans, error handling, config) and `${CLAUDE_PLUGIN_ROOT}/skills/instrumentation/references/javascript/frameworks.md` (Node.js, Cloudflare Workers, Next.js, Deno setup)
|
||||
- **Rust**: `${CLAUDE_PLUGIN_ROOT}/skills/instrumentation/references/rust/patterns.md` (macros, spans, tracing/log crate integration, async, shutdown)
|
||||
@@ -0,0 +1,78 @@
|
||||
# JavaScript Framework Setup
|
||||
|
||||
## Node.js (Express, Fastify, etc.)
|
||||
|
||||
Create `instrumentation.ts` and load it before your app:
|
||||
|
||||
```typescript
|
||||
// instrumentation.ts
|
||||
import * as logfire from '@pydantic/logfire-node'
|
||||
import 'dotenv/config'
|
||||
|
||||
logfire.configure()
|
||||
```
|
||||
|
||||
Launch:
|
||||
|
||||
```bash
|
||||
node --require ./instrumentation.js app.js
|
||||
# or with ts-node:
|
||||
npx ts-node --require ./instrumentation.ts app.ts
|
||||
```
|
||||
|
||||
The SDK auto-instruments common libraries (http, fetch, express, etc.) when loaded before the app via `--require`.
|
||||
|
||||
## Cloudflare Workers
|
||||
|
||||
```typescript
|
||||
import { instrument } from '@pydantic/logfire-cf-workers'
|
||||
|
||||
const handler = {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
||||
return new Response('Hello')
|
||||
},
|
||||
}
|
||||
|
||||
export default instrument(handler, {
|
||||
service: { name: 'my-worker', version: '1.0.0' },
|
||||
})
|
||||
```
|
||||
|
||||
Add `LOGFIRE_TOKEN` to `.dev.vars` and enable `nodejs_compat` in `wrangler.toml`:
|
||||
|
||||
```toml
|
||||
compatibility_flags = ["nodejs_compat"]
|
||||
```
|
||||
|
||||
## Next.js / Vercel
|
||||
|
||||
Set environment variables in `.env.local` or Vercel dashboard:
|
||||
|
||||
```bash
|
||||
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://logfire-api.pydantic.dev/v1/traces
|
||||
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://logfire-api.pydantic.dev/v1/metrics
|
||||
OTEL_EXPORTER_OTLP_HEADERS=Authorization=<your-write-token>
|
||||
```
|
||||
|
||||
Optionally use the `logfire` package for manual spans in server components and API routes:
|
||||
|
||||
```typescript
|
||||
import * as logfire from 'logfire'
|
||||
|
||||
logfire.info('Server action executed', { action: 'createUser' })
|
||||
```
|
||||
|
||||
## Deno
|
||||
|
||||
Deno has built-in OpenTelemetry support. Set environment variables:
|
||||
|
||||
```bash
|
||||
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://logfire-api.pydantic.dev/v1/traces
|
||||
OTEL_EXPORTER_OTLP_HEADERS=Authorization=<your-write-token>
|
||||
```
|
||||
|
||||
Run with telemetry enabled:
|
||||
|
||||
```bash
|
||||
deno run --allow-env --unstable-otel app.ts
|
||||
```
|
||||
@@ -0,0 +1,75 @@
|
||||
# JavaScript / TypeScript Patterns
|
||||
|
||||
## Log Levels
|
||||
|
||||
From lowest to highest severity:
|
||||
|
||||
```typescript
|
||||
logfire.trace('Detailed trace', { detail: x })
|
||||
logfire.debug('Debug info', { state: s })
|
||||
logfire.info('Normal operation', { event: e })
|
||||
logfire.notice('Notable event', { event: e })
|
||||
logfire.warn('Warning', { issue: i })
|
||||
logfire.error('Error occurred', { error: err })
|
||||
logfire.fatal('Fatal error', { error: err })
|
||||
```
|
||||
|
||||
All methods accept `(message, attributes?, options?)`. Options can include `{ tags: ['tag1'] }`.
|
||||
|
||||
## Spans
|
||||
|
||||
### Callback-based (auto-closes)
|
||||
|
||||
```typescript
|
||||
await logfire.span('Processing order', { order_id }, {}, async () => {
|
||||
const items = await fetchItems(order_id)
|
||||
logfire.info('Fetched items', { count: items.length })
|
||||
return processItems(items)
|
||||
})
|
||||
```
|
||||
|
||||
### Manual control
|
||||
|
||||
```typescript
|
||||
const span = logfire.startSpan('Long operation', { job_id })
|
||||
try {
|
||||
await doWork()
|
||||
} finally {
|
||||
span.end()
|
||||
}
|
||||
```
|
||||
|
||||
Child spans reference their parent via the `parentSpan` option.
|
||||
|
||||
## Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await processOrder(orderId)
|
||||
} catch (error) {
|
||||
logfire.reportError('order processing', error)
|
||||
throw error
|
||||
}
|
||||
```
|
||||
|
||||
`reportError` automatically extracts stack traces and error details into structured span attributes.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment variables
|
||||
|
||||
```bash
|
||||
LOGFIRE_TOKEN=your-write-token
|
||||
LOGFIRE_SERVICE_NAME=my-service
|
||||
LOGFIRE_SERVICE_VERSION=1.0.0
|
||||
```
|
||||
|
||||
### Programmatic
|
||||
|
||||
```typescript
|
||||
logfire.configure({
|
||||
token: process.env.LOGFIRE_TOKEN,
|
||||
serviceName: 'my-service',
|
||||
serviceVersion: '1.0.0',
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
# Python Integration Reference
|
||||
|
||||
## Web Frameworks
|
||||
|
||||
| Framework | Instrumentor | Needs app instance | Extra |
|
||||
|-----------|-------------|-------------------|-------|
|
||||
| FastAPI | `logfire.instrument_fastapi(app)` | Yes | `fastapi` |
|
||||
| Django | `logfire.instrument_django(app)` | Yes | `django` |
|
||||
| Flask | `logfire.instrument_flask(app)` | Yes | `flask` |
|
||||
| Starlette | `logfire.instrument_starlette(app)` | Yes | `starlette` |
|
||||
| AIOHTTP | `logfire.instrument_aiohttp_client()` | No | `aiohttp` |
|
||||
|
||||
## HTTP Clients
|
||||
|
||||
| Library | Instrumentor | Extra |
|
||||
|---------|-------------|-------|
|
||||
| httpx | `logfire.instrument_httpx()` | `httpx` |
|
||||
| requests | `logfire.instrument_requests()` | `requests` |
|
||||
|
||||
## Databases
|
||||
|
||||
| Library | Instrumentor | Extra |
|
||||
|---------|-------------|-------|
|
||||
| asyncpg | `logfire.instrument_asyncpg()` | `asyncpg` |
|
||||
| psycopg | `logfire.instrument_psycopg()` | `psycopg` |
|
||||
| psycopg2 | `logfire.instrument_psycopg2()` | `psycopg2` |
|
||||
| SQLAlchemy | `logfire.instrument_sqlalchemy()` | `sqlalchemy` |
|
||||
| PyMongo | `logfire.instrument_pymongo()` | `pymongo` |
|
||||
| MySQL | `logfire.instrument_mysql()` | `mysql` |
|
||||
| SQLite3 | `logfire.instrument_sqlite3()` | `sqlite3` |
|
||||
| Redis | `logfire.instrument_redis()` | `redis` |
|
||||
|
||||
## AI/LLM Frameworks
|
||||
|
||||
| Framework | Instrumentor | Extra |
|
||||
|-----------|-------------|-------|
|
||||
| PydanticAI | `logfire.instrument_pydantic_ai()` | `pydantic-ai` |
|
||||
| OpenAI | `logfire.instrument_openai()` | `openai` |
|
||||
| Anthropic | `logfire.instrument_anthropic()` | `anthropic` |
|
||||
| LiteLLM | `logfire.instrument_litellm()` | `litellm` |
|
||||
| DSPy | `logfire.instrument_dspy()` | `dspy` |
|
||||
| Google GenAI | `logfire.instrument_google_genai()` | `google-genai` |
|
||||
|
||||
## Task Queues
|
||||
|
||||
| Framework | Instrumentor | Extra |
|
||||
|-----------|-------------|-------|
|
||||
| Celery | `logfire.instrument_celery()` | `celery` |
|
||||
|
||||
## Other
|
||||
|
||||
| Feature | Instrumentor | Extra |
|
||||
|---------|-------------|-------|
|
||||
| System Metrics | `logfire.instrument_system_metrics()` | `system-metrics` |
|
||||
| Pydantic Models | `logfire.instrument_pydantic()` | - (built-in) |
|
||||
| AWS Lambda | handler wrapper | `aws-lambda` |
|
||||
|
||||
## Gunicorn Configuration
|
||||
|
||||
```python
|
||||
# gunicorn.conf.py
|
||||
import logfire
|
||||
|
||||
def post_fork(server, worker):
|
||||
logfire.configure()
|
||||
logfire.instrument_fastapi(app)
|
||||
```
|
||||
@@ -0,0 +1,101 @@
|
||||
# Python Logging Patterns
|
||||
|
||||
## Log Levels
|
||||
|
||||
From lowest to highest severity:
|
||||
|
||||
```python
|
||||
logfire.trace("Detailed trace {detail}", detail=x)
|
||||
logfire.debug("Debug info {state}", state=s)
|
||||
logfire.info("Normal operation {event}", event=e)
|
||||
logfire.notice("Notable event {event}", event=e)
|
||||
logfire.warn("Warning {issue}", issue=i)
|
||||
logfire.error("Error occurred {error}", error=err)
|
||||
logfire.fatal("Fatal error {error}", error=err)
|
||||
```
|
||||
|
||||
## Nested Spans
|
||||
|
||||
Spans nest to create a tree visible in the Logfire UI. Use them to show the structure of an operation, not just that it happened:
|
||||
|
||||
```python
|
||||
with logfire.span("HTTP request {method} {url}", method="POST", url=url):
|
||||
with logfire.span("Serialize payload"):
|
||||
payload = model.model_dump_json()
|
||||
with logfire.span("Send request"):
|
||||
response = await client.post(url, content=payload)
|
||||
logfire.info("Response {status}", status=response.status_code)
|
||||
```
|
||||
|
||||
## Standard Library Logging Integration
|
||||
|
||||
For projects that already use Python's `logging` module, route existing log calls through Logfire rather than rewriting them all:
|
||||
|
||||
```python
|
||||
from logging import basicConfig
|
||||
import logfire
|
||||
|
||||
logfire.configure()
|
||||
basicConfig(handlers=[logfire.LogfireLoggingHandler()])
|
||||
```
|
||||
|
||||
Or with `dictConfig`:
|
||||
|
||||
```python
|
||||
from logging.config import dictConfig
|
||||
import logfire
|
||||
|
||||
logfire.configure()
|
||||
dictConfig({
|
||||
'version': 1,
|
||||
'handlers': {
|
||||
'logfire': {'class': 'logfire.LogfireLoggingHandler'},
|
||||
},
|
||||
'root': {'handlers': ['logfire']},
|
||||
})
|
||||
```
|
||||
|
||||
## Suppressing Noisy Libraries
|
||||
|
||||
Some libraries emit excessive debug logs. Silence them at the `logging` level:
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
logging.getLogger('httpcore').setLevel(logging.WARNING)
|
||||
logging.getLogger('httpx').setLevel(logging.WARNING)
|
||||
```
|
||||
|
||||
## Custom Metrics
|
||||
|
||||
For dashboards and alerting, create metrics:
|
||||
|
||||
```python
|
||||
counter = logfire.metric_counter("orders_processed", unit="1")
|
||||
counter.add(1, {"status": "success"})
|
||||
|
||||
histogram = logfire.metric_histogram("request_duration", unit="s")
|
||||
histogram.record(0.123, {"endpoint": "/api/users"})
|
||||
|
||||
gauge = logfire.metric_gauge("active_connections")
|
||||
gauge.set(42)
|
||||
```
|
||||
|
||||
## Testing with capfire
|
||||
|
||||
Use the `capfire` pytest fixture to assert on emitted spans without sending data to production:
|
||||
|
||||
```python
|
||||
from logfire.testing import CaptureLogfire
|
||||
|
||||
def test_order_processing(capfire: CaptureLogfire) -> None:
|
||||
process_order(order_id=123)
|
||||
|
||||
spans = capfire.exporter.exported_spans_as_dict()
|
||||
assert any(
|
||||
span['attributes'].get('order_id') == 123
|
||||
for span in spans
|
||||
)
|
||||
```
|
||||
|
||||
Configure logfire with `send_to_logfire=False` in test fixtures to prevent production data leakage.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Rust Patterns
|
||||
|
||||
## Core Macros
|
||||
|
||||
The Rust SDK is built on `tracing` and `opentelemetry`. All `tracing` macros work automatically with Logfire.
|
||||
|
||||
### Events (log points)
|
||||
|
||||
```rust
|
||||
logfire::trace!("Detailed trace {detail}", detail = x);
|
||||
logfire::debug!("Debug info {state}", state = s);
|
||||
logfire::info!("Normal operation {event}", event = e);
|
||||
logfire::warn!("Warning {issue}", issue = i);
|
||||
logfire::error!("Error occurred {err}", err = e);
|
||||
```
|
||||
|
||||
### Spans
|
||||
|
||||
```rust
|
||||
// Scoped - span closes when closure completes
|
||||
logfire::span!("Processing order {order_id}", order_id = id).in_scope(|| {
|
||||
let items = fetch_items(id);
|
||||
logfire::info!("Fetched {count} items", count = items.len());
|
||||
process_items(items)
|
||||
});
|
||||
|
||||
// Guard-based - span closes when guard is dropped
|
||||
let _guard = logfire::span!("Long operation {job_id}", job_id = id).entered();
|
||||
do_work();
|
||||
// span ends when _guard goes out of scope
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```rust
|
||||
use logfire;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let shutdown_handler = logfire::configure()
|
||||
.install_panic_handler() // captures panics as error spans
|
||||
.finish()?;
|
||||
|
||||
// application code...
|
||||
|
||||
shutdown_handler.shutdown()?; // flush all pending spans
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
Set `LOGFIRE_TOKEN` in your environment or use the Logfire CLI (`logfire auth`).
|
||||
|
||||
## Tracing Crate Compatibility
|
||||
|
||||
Any library using `tracing` macros automatically sends data through Logfire:
|
||||
|
||||
```rust
|
||||
use tracing;
|
||||
|
||||
tracing::info!("This also appears in Logfire");
|
||||
|
||||
#[tracing::instrument]
|
||||
fn my_function(param: &str) {
|
||||
// automatically creates a span with param as an attribute
|
||||
}
|
||||
```
|
||||
|
||||
## Log Crate Integration
|
||||
|
||||
The `log` crate is automatically captured and forwarded to Logfire. Libraries using `log::info!()`, `log::error!()`, etc. will appear in your Logfire dashboard without any additional configuration.
|
||||
|
||||
## Async Spans
|
||||
|
||||
```rust
|
||||
use tracing::Instrument;
|
||||
|
||||
async fn process_order(order_id: u64) {
|
||||
let span = logfire::span!("process order {order_id}", order_id = order_id);
|
||||
async {
|
||||
fetch_items(order_id).await;
|
||||
logfire::info!("Order processed");
|
||||
}
|
||||
.instrument(span)
|
||||
.await;
|
||||
}
|
||||
```
|
||||
|
||||
## Shutdown
|
||||
|
||||
Always call `shutdown()` before program exit to flush pending data:
|
||||
|
||||
```rust
|
||||
// In main()
|
||||
let shutdown_handler = logfire::configure().finish()?;
|
||||
|
||||
// ... app runs ...
|
||||
|
||||
// Before exit
|
||||
shutdown_handler.shutdown()?;
|
||||
```
|
||||
|
||||
For web servers using `tokio`, handle shutdown via signal:
|
||||
|
||||
```rust
|
||||
tokio::signal::ctrl_c().await?;
|
||||
shutdown_handler.shutdown()?;
|
||||
```
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: pr-create
|
||||
description: Use when creating or updating a Basic Memory pull request from Codex with BM Bossbot merge-gate monitoring.
|
||||
---
|
||||
|
||||
# Create A Basic Memory PR
|
||||
|
||||
Create or update a pull request for the current branch, then wait for BM
|
||||
Bossbot to approve the latest head SHA. This skill never merges a PR.
|
||||
|
||||
## Inputs
|
||||
|
||||
- Optional `<theme>`: free-form visual direction for the non-gating PR
|
||||
image. Example: `$pr-create "Italian movie poster"`.
|
||||
- Treat `<theme>` as style guidance only. It must not affect PR readiness,
|
||||
BM Bossbot review, status checks, or merge behavior.
|
||||
|
||||
## How To Use
|
||||
|
||||
Ask Codex to use the skill from a feature branch:
|
||||
|
||||
```text
|
||||
$pr-create
|
||||
$pr-create "Italian movie poster"
|
||||
$pr-create "80's action movies"
|
||||
```
|
||||
|
||||
Use the plain form when you only want the PR workflow. Pass a theme when you
|
||||
want the non-gating image to lean toward a particular visual direction. The
|
||||
theme can be specific ("Rembrandt-inspired approval scene") or broad ("let the
|
||||
model choose from BM categories").
|
||||
|
||||
## What Happens
|
||||
|
||||
1. Codex checks the branch, local verification, GitHub auth, commit sign-offs,
|
||||
and semantic PR title shape.
|
||||
2. Codex pushes the branch, creates or reuses the PR, and adds the optional
|
||||
`BM_INFOGRAPHIC_THEME` block when a theme was supplied.
|
||||
3. BM Bossbot runs from trusted base code, reviews sanitized PR metadata and
|
||||
diff context, and sets the required `BM Bossbot Approval` status for the
|
||||
exact head SHA.
|
||||
4. If approval succeeds, BM Bossbot may publish a non-gating image block and a
|
||||
provenance block:
|
||||
|
||||
```markdown
|
||||
<!-- BM_INFOGRAPHIC_PROVENANCE:start -->
|
||||
...
|
||||
<!-- BM_INFOGRAPHIC_PROVENANCE:end -->
|
||||
```
|
||||
|
||||
The provenance records the image mode, theme source, selected visual
|
||||
direction, and image settings. It is for review/debugging context only.
|
||||
5. Codex reports the PR URL, head SHA, checks watched, verification run, and BM
|
||||
Bossbot verdict.
|
||||
|
||||
The skill never merges, never enables auto-merge, and never treats the image or
|
||||
provenance block as a gate. The only required merge signal is the
|
||||
`BM Bossbot Approval` status on the current PR head SHA.
|
||||
|
||||
## Preflight
|
||||
|
||||
1. Confirm the repo and branch:
|
||||
- `git status --short --branch`
|
||||
- stop if detached or on `main`
|
||||
- keep unrelated user changes intact
|
||||
|
||||
2. Confirm GitHub access:
|
||||
- `gh auth status`
|
||||
- `gh repo view --json nameWithOwner,defaultBranchRef,url`
|
||||
|
||||
3. Check PR readiness:
|
||||
- commits are signed off with `git commit -s`
|
||||
- title uses the repo semantic format
|
||||
- local verification appropriate to the change has run
|
||||
|
||||
## Create Or Reuse
|
||||
|
||||
1. Push the branch:
|
||||
- `git push -u origin HEAD`
|
||||
|
||||
2. Check for an existing PR:
|
||||
- `gh pr view --json number,url,headRefOid,mergeStateStatus,statusCheckRollup`
|
||||
|
||||
3. If no PR exists, create one:
|
||||
- `gh pr create --fill`
|
||||
- adjust the title if it does not satisfy the semantic PR title workflow
|
||||
|
||||
4. If `<theme>` is provided, add or update this managed block in the PR body:
|
||||
|
||||
```markdown
|
||||
<!-- BM_INFOGRAPHIC_THEME:start -->
|
||||
<theme>
|
||||
<!-- BM_INFOGRAPHIC_THEME:end -->
|
||||
```
|
||||
|
||||
Keep the rest of the PR body intact. The theme is non-gating image guidance
|
||||
only.
|
||||
|
||||
5. Do not merge. Do not enable auto-merge.
|
||||
|
||||
## Watch The Gate
|
||||
|
||||
1. Trigger or wait for `.github/workflows/bm-bossbot.yml`.
|
||||
2. Watch the required commit status named `BM Bossbot Approval`.
|
||||
3. Treat approval as valid only when it is green for the current `headRefOid`.
|
||||
4. If the branch changes after approval, wait for BM Bossbot to review the new
|
||||
head SHA.
|
||||
5. If BM Bossbot fails or requests changes, use `$fix-pr-issues`.
|
||||
|
||||
## Report
|
||||
|
||||
Return the PR URL, current head SHA, checks watched, verification run, and the
|
||||
BM Bossbot verdict. Include the image `<theme>` if one was supplied. Be
|
||||
explicit when any check is still pending.
|
||||
@@ -0,0 +1,7 @@
|
||||
interface:
|
||||
display_name: "PR Create"
|
||||
short_description: "Create PRs and wait for BM Bossbot"
|
||||
icon_small: "./assets/icon.svg"
|
||||
icon_large: "./assets/icon.svg"
|
||||
brand_color: "#2563EB"
|
||||
default_prompt: "Use $pr-create to create or update this Basic Memory PR and wait for BM Bossbot Approval."
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24" fill="none" stroke="#111827" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12h4l2-6 4 12 2-6h6"/>
|
||||
<path d="M4 20h16"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "basicmachines-co",
|
||||
"owner": {
|
||||
"name": "Basic Machines",
|
||||
"email": "hello@basicmachines.co"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Official Basic Memory plugins from the canonical basic-memory repository",
|
||||
"version": "0.21.6"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "basic-memory",
|
||||
"source": "./plugins/claude-code",
|
||||
"description": "The bridge between Claude's working memory and Basic Memory's durable knowledge graph \u2014 session briefings, pre-compaction checkpoints, and capture reflexes",
|
||||
"version": "0.21.6",
|
||||
"author": {
|
||||
"name": "Basic Machines"
|
||||
},
|
||||
"keywords": [
|
||||
"memory",
|
||||
"knowledge",
|
||||
"mcp",
|
||||
"specs",
|
||||
"context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
# /project:check-health - Project Health Assessment
|
||||
|
||||
Comprehensive health check of the Basic Memory project including code quality, test coverage, dependencies, and documentation.
|
||||
|
||||
## Usage
|
||||
```
|
||||
/project:check-health
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
You are an expert DevOps engineer for the Basic Memory project. When the user runs `/project:check-health`, execute the following comprehensive assessment:
|
||||
|
||||
### Step 1: Git Repository Health
|
||||
1. **Repository Status**
|
||||
```bash
|
||||
git status
|
||||
git log --oneline -5
|
||||
git branch -vv
|
||||
```
|
||||
- Check working directory status
|
||||
- Verify branch alignment with remote
|
||||
- Check recent commit activity
|
||||
|
||||
2. **Branch Analysis**
|
||||
- Verify on main branch
|
||||
- Check if ahead/behind remote
|
||||
- Identify any untracked files
|
||||
|
||||
### Step 2: Code Quality Assessment
|
||||
1. **Linting and Formatting**
|
||||
```bash
|
||||
uv run ruff check .
|
||||
uv run pyright
|
||||
```
|
||||
- Count linting issues by severity
|
||||
- Check type annotation coverage
|
||||
- Verify code formatting compliance
|
||||
|
||||
2. **Test Suite Health**
|
||||
```bash
|
||||
uv run pytest --collect-only -q
|
||||
uv run pytest --co -q | wc -l
|
||||
```
|
||||
- Count total tests
|
||||
- Check for test discovery issues
|
||||
- Verify test structure integrity
|
||||
|
||||
### Step 3: Dependency Analysis
|
||||
1. **Dependency Health**
|
||||
```bash
|
||||
uv tree
|
||||
uv lock --dry-run
|
||||
```
|
||||
- Check for dependency conflicts
|
||||
- Identify outdated dependencies
|
||||
- Verify lock file consistency
|
||||
|
||||
2. **Security Scan**
|
||||
```bash
|
||||
uv run pip-audit --desc
|
||||
```
|
||||
- Scan for known vulnerabilities
|
||||
- Check dependency licenses
|
||||
- Identify security advisories
|
||||
|
||||
### Step 4: Performance Metrics
|
||||
1. **Test Performance**
|
||||
```bash
|
||||
uv run pytest --durations=10
|
||||
```
|
||||
- Identify slowest tests
|
||||
- Check overall test execution time
|
||||
- Monitor test suite growth
|
||||
|
||||
2. **Build Performance**
|
||||
```bash
|
||||
time uv run python -c "import basic_memory"
|
||||
```
|
||||
- Check import time
|
||||
- Validate package installation
|
||||
- Monitor startup performance
|
||||
|
||||
### Step 5: Documentation Health
|
||||
1. **Documentation Coverage**
|
||||
- Check README.md currency
|
||||
- Verify CLI documentation
|
||||
- Validate MCP tool documentation
|
||||
- Check changelog completeness
|
||||
|
||||
2. **API Documentation**
|
||||
- Verify docstring coverage
|
||||
- Check type annotation completeness
|
||||
- Validate example code
|
||||
|
||||
### Step 6: Project Metrics
|
||||
1. **Code Statistics**
|
||||
```bash
|
||||
find src -name "*.py" | xargs wc -l
|
||||
find tests -name "*.py" | xargs wc -l
|
||||
```
|
||||
- Lines of code trends
|
||||
- Test-to-code ratio
|
||||
- File organization metrics
|
||||
|
||||
## Health Report Format
|
||||
|
||||
Generate comprehensive health dashboard:
|
||||
|
||||
```
|
||||
🏥 Basic Memory Project Health Report
|
||||
|
||||
📊 OVERALL HEALTH: 🟢 EXCELLENT (92/100)
|
||||
|
||||
🗂️ GIT REPOSITORY
|
||||
✅ Clean working directory
|
||||
✅ Up to date with origin/main
|
||||
✅ Recent commit activity (5 commits this week)
|
||||
|
||||
🔍 CODE QUALITY
|
||||
✅ Linting: 0 errors, 2 warnings
|
||||
✅ Type checking: 100% coverage
|
||||
✅ Formatting: Compliant
|
||||
⚠️ Complex functions: 3 need refactoring
|
||||
|
||||
🧪 TEST SUITE
|
||||
✅ Total tests: 744
|
||||
✅ Test discovery: All tests found
|
||||
✅ Coverage: 98.2%
|
||||
⚡ Performance: 45.2s (good)
|
||||
|
||||
📦 DEPENDENCIES
|
||||
✅ Dependencies: Up to date
|
||||
✅ Security: No vulnerabilities
|
||||
✅ Conflicts: None detected
|
||||
⚠️ Outdated: 2 minor updates available
|
||||
|
||||
📖 DOCUMENTATION
|
||||
✅ README: Current
|
||||
✅ API docs: 95% coverage
|
||||
⚠️ CLI reference: Needs update
|
||||
✅ Changelog: Complete
|
||||
|
||||
📈 METRICS
|
||||
├── Source code: 15,432 lines
|
||||
├── Test code: 8,967 lines
|
||||
├── Test ratio: 58% (excellent)
|
||||
└── Complexity: Low (maintainable)
|
||||
|
||||
🎯 RECOMMENDATIONS:
|
||||
1. Update CLI documentation
|
||||
2. Refactor 3 complex functions
|
||||
3. Update minor dependencies
|
||||
4. Consider splitting large test files
|
||||
|
||||
🏆 PROJECT STATUS: Ready for v0.13.0 release!
|
||||
```
|
||||
|
||||
## Health Scoring
|
||||
|
||||
### Excellent (90-100)
|
||||
- All quality gates pass
|
||||
- High test coverage (>95%)
|
||||
- No security issues
|
||||
- Documentation current
|
||||
|
||||
### Good (75-89)
|
||||
- Minor issues present
|
||||
- Good test coverage (>90%)
|
||||
- No critical security issues
|
||||
- Most documentation current
|
||||
|
||||
### Needs Attention (60-74)
|
||||
- Several quality issues
|
||||
- Adequate test coverage (>80%)
|
||||
- Minor security concerns
|
||||
- Documentation gaps
|
||||
|
||||
### Critical (<60)
|
||||
- Major quality problems
|
||||
- Low test coverage (<80%)
|
||||
- Security vulnerabilities
|
||||
- Significant documentation issues
|
||||
|
||||
## Context
|
||||
- Provides comprehensive project overview
|
||||
- Identifies potential issues before they become problems
|
||||
- Tracks project health trends over time
|
||||
- Helps prioritize maintenance tasks
|
||||
- Supports release readiness decisions
|
||||
@@ -1,62 +0,0 @@
|
||||
# Basic Memory Custom Commands
|
||||
|
||||
This directory contains custom Claude Code slash commands for the Basic Memory project.
|
||||
|
||||
## Available Commands
|
||||
|
||||
### Release Management (`/project:release:*`)
|
||||
- `/project:release:beta` - Create beta releases with automated quality checks
|
||||
- `/project:release:release` - Create stable releases with comprehensive validation
|
||||
- `/project:release:release-check` - Pre-flight validation without making changes
|
||||
- `/project:release:changelog` - Generate changelog entries from commits
|
||||
|
||||
### Development (`/project:*`)
|
||||
- `/project:test-coverage` - Run tests with detailed coverage analysis
|
||||
- `/project:test-live` - Live testing suite using real Basic Memory installation
|
||||
- `/project:lint-fix` - Run comprehensive linting with auto-fix
|
||||
- `/project:check-health` - Comprehensive project health assessment
|
||||
|
||||
## Command Structure
|
||||
|
||||
Commands are organized by functionality:
|
||||
```
|
||||
.claude/commands/
|
||||
├── release/ # Release management commands
|
||||
│ ├── beta.md # /project:release:beta
|
||||
│ ├── release.md # /project:release:release
|
||||
│ ├── release-check.md # /project:release:release-check
|
||||
│ └── changelog.md # /project:release:changelog
|
||||
├── test-coverage.md # /project:test-coverage
|
||||
├── test-live.md # /project:test-live
|
||||
├── lint-fix.md # /project:lint-fix
|
||||
├── check-health.md # /project:check-health
|
||||
└── commands.md # This overview file
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Commands are invoked using the `/project:` prefix:
|
||||
- `/project:release:beta v0.13.0b4`
|
||||
- `/project:test-coverage mcp`
|
||||
- `/project:test-live core`
|
||||
- `/project:release:release-check`
|
||||
- `/project:check-health`
|
||||
|
||||
## Implementation
|
||||
|
||||
Each command is implemented as a Markdown file containing structured prompts that:
|
||||
1. Validate preconditions
|
||||
2. Execute steps in the correct order
|
||||
3. Handle errors gracefully
|
||||
4. Provide clear status updates
|
||||
5. Return actionable results
|
||||
|
||||
## Tooling Integration
|
||||
|
||||
Commands leverage existing project tooling:
|
||||
- `just check` - Quality checks
|
||||
- `just test` - Test suite
|
||||
- `just update-deps` - Dependency updates
|
||||
- `uv` - Package management
|
||||
- `git` - Version control
|
||||
- GitHub Actions - CI/CD pipeline
|
||||
@@ -1,145 +0,0 @@
|
||||
# /project:lint-fix - Comprehensive Code Quality Fix
|
||||
|
||||
Run comprehensive linting and auto-fix code quality issues across the codebase.
|
||||
|
||||
## Usage
|
||||
```
|
||||
/project:lint-fix
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
You are an expert code quality engineer for the Basic Memory project. When the user runs `/project:lint-fix`, execute the following steps:
|
||||
|
||||
### Step 1: Pre-flight Check
|
||||
1. **Verify Clean Working Directory**
|
||||
```bash
|
||||
git status --porcelain
|
||||
```
|
||||
- Check for uncommitted changes
|
||||
- Warn if working directory is not clean
|
||||
- Suggest stashing changes if needed
|
||||
|
||||
### Step 2: Import Organization
|
||||
1. **Fix Import Order and Cleanup**
|
||||
```bash
|
||||
uv run ruff check --select I --fix .
|
||||
```
|
||||
- Sort imports by category (standard, third-party, local)
|
||||
- Remove unused imports
|
||||
- Fix import spacing and organization
|
||||
|
||||
### Step 3: Code Formatting
|
||||
1. **Apply Consistent Formatting**
|
||||
```bash
|
||||
uv run ruff format .
|
||||
```
|
||||
- Format code according to project style
|
||||
- Fix line length issues (100 chars max)
|
||||
- Standardize quotes and spacing
|
||||
|
||||
### Step 4: Linting with Auto-fix
|
||||
1. **Fix Linting Issues**
|
||||
```bash
|
||||
uv run ruff check --fix .
|
||||
```
|
||||
- Auto-fix safe linting issues
|
||||
- Report any remaining manual fixes needed
|
||||
- Focus on code quality and best practices
|
||||
|
||||
### Step 5: Type Checking
|
||||
1. **Validate Type Annotations**
|
||||
```bash
|
||||
uv run pyright
|
||||
```
|
||||
- Check for type errors
|
||||
- Report any missing type annotations
|
||||
- Validate type compatibility
|
||||
|
||||
### Step 6: Report Generation
|
||||
Generate comprehensive quality report:
|
||||
|
||||
```
|
||||
🔧 Code Quality Fix Report
|
||||
|
||||
✅ FIXES APPLIED:
|
||||
├── Import organization: 12 files updated
|
||||
├── Code formatting: 8 files reformatted
|
||||
├── Auto-fixable lint issues: 23 issues resolved
|
||||
└── Total files processed: 156
|
||||
|
||||
⚠️ MANUAL ATTENTION NEEDED:
|
||||
├── Type annotations missing in entity_service.py:45
|
||||
├── Complex function needs refactoring in sync_service.py:123
|
||||
└── Unused variable in test_utils.py:67
|
||||
|
||||
🎯 QUALITY SCORE: 96.2% (excellent)
|
||||
|
||||
📁 Run `git diff` to review all changes
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Issues
|
||||
- **Merge Conflicts**: Provide resolution guidance
|
||||
- **Syntax Errors**: Point to specific files and lines
|
||||
- **Type Errors**: Suggest specific fixes
|
||||
- **Import Errors**: Check for missing dependencies
|
||||
|
||||
### Recovery Steps
|
||||
- If auto-fixes introduce issues, provide rollback instructions
|
||||
- If type checking fails, suggest incremental fixes
|
||||
- If tests break, provide debugging guidance
|
||||
|
||||
## Quality Gates
|
||||
|
||||
### Must Pass
|
||||
- [ ] All auto-fixable lint issues resolved
|
||||
- [ ] Code formatting consistent
|
||||
- [ ] No syntax errors
|
||||
- [ ] Import organization clean
|
||||
|
||||
### Should Pass (Warnings)
|
||||
- [ ] No type checking errors
|
||||
- [ ] No complex function warnings
|
||||
- [ ] No unused variables/imports
|
||||
- [ ] Consistent naming conventions
|
||||
|
||||
## Output Examples
|
||||
|
||||
### Successful Fix
|
||||
```
|
||||
🎉 CODE QUALITY IMPROVED!
|
||||
|
||||
✅ All auto-fixes applied successfully
|
||||
📏 Code formatting: 100% compliant
|
||||
🔍 Linting: No issues found
|
||||
🏷️ Type checking: All passed
|
||||
|
||||
Ready for commit! Use:
|
||||
git add -A && git commit -m "style: fix code quality issues"
|
||||
```
|
||||
|
||||
### Issues Requiring Attention
|
||||
```
|
||||
⚠️ PARTIAL SUCCESS - MANUAL FIXES NEEDED
|
||||
|
||||
✅ Auto-fixes applied: 45 issues
|
||||
❌ Manual fixes needed: 3 issues
|
||||
|
||||
Priority fixes:
|
||||
1. Fix type annotation in services/entity_service.py:142
|
||||
2. Simplify complex function in sync/sync_service.py:67
|
||||
3. Remove unused import in tests/conftest.py:12
|
||||
|
||||
Run these commands:
|
||||
# Fix specific file
|
||||
uv run pyright src/basic_memory/services/entity_service.py
|
||||
```
|
||||
|
||||
## Context
|
||||
- Uses ruff for fast Python linting and formatting
|
||||
- Uses pyright for type checking
|
||||
- Follows project code style guidelines (100 char line length)
|
||||
- Maintains backward compatibility
|
||||
- Integrates with existing pre-commit hooks
|
||||
@@ -30,7 +30,8 @@ The justfile target handles:
|
||||
- ✅ Beta version format validation (supports b1, b2, rc1, etc.)
|
||||
- ✅ Git status and branch checks
|
||||
- ✅ Quality checks (`just check` - lint, format, type-check, tests)
|
||||
- ✅ Version update in `src/basic_memory/__init__.py`
|
||||
- ✅ Version update across all consolidated manifests via `just set-version` (Python
|
||||
package + Claude Code plugin/marketplaces + Codex plugin + Hermes + OpenClaw)
|
||||
- ✅ Automatic commit with proper message
|
||||
- ✅ Tag creation and pushing to GitHub
|
||||
- ✅ Beta release workflow trigger
|
||||
@@ -90,6 +91,6 @@ Monitor release: https://github.com/basicmachines-co/basic-memory/actions
|
||||
- Beta releases are pre-releases for testing new features
|
||||
- Automatically published to PyPI with pre-release flag
|
||||
- Uses the automated justfile target for consistency
|
||||
- Version is automatically updated in `__init__.py`
|
||||
- Version is automatically updated across all consolidated manifests via `just set-version`
|
||||
- Ideal for validating changes before stable release
|
||||
- Supports both beta (b1, b2) and release candidate (rc1, rc2) versions
|
||||
- Supports both beta (b1, b2) and release candidate (rc1, rc2) versions
|
||||
|
||||
@@ -8,7 +8,7 @@ Analyze commits and generate formatted changelog entry for a version.
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `version` (required): Version like `v0.13.0` or `v0.13.0b4`
|
||||
- `version` (required): Version like `v0.14.0` or `v0.14.0b1`
|
||||
- `type` (optional): `beta`, `rc`, or `stable` (default: `stable`)
|
||||
|
||||
## Implementation
|
||||
@@ -59,8 +59,9 @@ You are an expert technical writer for the Basic Memory project. When the user r
|
||||
### Step 3: Generate Changelog Entry
|
||||
Create formatted entry following existing CHANGELOG.md style:
|
||||
|
||||
Example:
|
||||
```markdown
|
||||
## v0.13.0 (2025-06-03)
|
||||
## <version> (<date>)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -128,6 +129,8 @@ Create formatted entry following existing CHANGELOG.md style:
|
||||
## Output Format
|
||||
|
||||
### For Beta Releases
|
||||
|
||||
Example:
|
||||
```markdown
|
||||
## v0.13.0b4 (2025-06-03)
|
||||
|
||||
|
||||
@@ -15,10 +15,16 @@ Create a stable release using the automated justfile target with comprehensive v
|
||||
You are an expert release manager for the Basic Memory project. When the user runs `/release`, execute the following steps:
|
||||
|
||||
### Step 1: Pre-flight Validation
|
||||
1. Verify version format matches `v\d+\.\d+\.\d+` pattern
|
||||
2. Check current git status for uncommitted changes
|
||||
3. Verify we're on the `main` branch
|
||||
4. Confirm no existing tag with this version
|
||||
|
||||
#### Version Check
|
||||
1. Check current version in `src/basic_memory/__init__.py`
|
||||
2. Verify new version format matches `v\d+\.\d+\.\d+` pattern
|
||||
3. Confirm version is higher than current version
|
||||
|
||||
#### Git Status
|
||||
1. Check current git status for uncommitted changes
|
||||
2. Verify we're on the `main` branch
|
||||
3. Confirm no existing tag with this version
|
||||
|
||||
#### Documentation Validation
|
||||
1. **Changelog Check**
|
||||
@@ -36,22 +42,115 @@ The justfile target handles:
|
||||
- ✅ Version format validation
|
||||
- ✅ Git status and branch checks
|
||||
- ✅ Quality checks (`just check` - lint, format, type-check, tests)
|
||||
- ✅ Version update in `src/basic_memory/__init__.py`
|
||||
- ✅ Version update across all consolidated manifests via `just set-version` (Python
|
||||
package + Claude Code plugin/marketplaces + Codex plugin + Hermes + OpenClaw)
|
||||
- ✅ Automatic commit with proper message
|
||||
- ✅ Tag creation and pushing to GitHub
|
||||
- ✅ Release workflow trigger
|
||||
- ✅ Release workflow trigger (automatic on tag push)
|
||||
|
||||
The GitHub Actions workflow (`.github/workflows/release.yml`) then:
|
||||
- ✅ Builds the package using `uv build`
|
||||
- ✅ Creates GitHub release with auto-generated notes
|
||||
- ✅ Publishes to PyPI
|
||||
- ✅ Updates Homebrew formula (stable releases only)
|
||||
|
||||
### Step 3: Monitor Release Process
|
||||
1. Check that GitHub Actions workflow starts successfully
|
||||
2. Monitor workflow completion at: https://github.com/basicmachines-co/basic-memory/actions
|
||||
3. Verify PyPI publication
|
||||
4. Test installation: `uv tool install basic-memory`
|
||||
1. Verify tag push triggered the workflow (should start automatically within seconds)
|
||||
2. Monitor workflow progress at: https://github.com/basicmachines-co/basic-memory/actions
|
||||
3. Watch for successful completion of both jobs:
|
||||
- `release` - Builds package and publishes to PyPI
|
||||
- `homebrew` - Updates Homebrew formula (stable releases only)
|
||||
4. Check for any workflow failures and investigate logs if needed
|
||||
|
||||
### Step 4: Post-Release Validation
|
||||
1. Verify GitHub release is created automatically
|
||||
2. Check PyPI publication
|
||||
3. Validate release assets
|
||||
4. Update any post-release documentation
|
||||
|
||||
#### GitHub Release
|
||||
1. Verify GitHub release is created at: https://github.com/basicmachines-co/basic-memory/releases/tag/<version>
|
||||
2. Check that release notes are auto-generated from commits
|
||||
3. Validate release assets (`.whl` and `.tar.gz` files are attached)
|
||||
|
||||
#### PyPI Publication
|
||||
1. Verify package published at: https://pypi.org/project/basic-memory/<version>/
|
||||
2. Test installation: `uv tool install basic-memory`
|
||||
3. Verify installed version: `basic-memory --version`
|
||||
|
||||
#### Homebrew Formula (Stable Releases Only)
|
||||
1. Check formula update at: https://github.com/basicmachines-co/homebrew-basic-memory
|
||||
2. Verify formula version matches release
|
||||
3. Test Homebrew installation: `brew install basicmachines-co/basic-memory/basic-memory`
|
||||
|
||||
#### MCP Registry Publication
|
||||
|
||||
After PyPI release is published, update the MCP registry:
|
||||
|
||||
1. **Verify PyPI Release**
|
||||
- Confirm package is live: https://pypi.org/project/basic-memory/<version>/
|
||||
- The `server.json` version was auto-updated by `just release`
|
||||
|
||||
2. **Publish to MCP Registry**
|
||||
```bash
|
||||
cd /Users/drew/code/basic-memory
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
If not authenticated:
|
||||
```bash
|
||||
mcp-publisher login github
|
||||
# Follow device authentication flow
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
3. **Verify Publication**
|
||||
```bash
|
||||
curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=basic-memory"
|
||||
```
|
||||
|
||||
**Note:** The `mcp-publisher` CLI can be installed via Homebrew (`brew install mcp-publisher`) or from GitHub releases.
|
||||
|
||||
#### Website Updates
|
||||
|
||||
**1. basicmachines.co** (`/Users/drew/code/basicmachines.co`)
|
||||
- **Goal**: Update version number displayed on the homepage
|
||||
- **Location**: Search for "Basic Memory v0." in the codebase to find version displays
|
||||
- **What to update**:
|
||||
- Hero section heading that shows "Basic Memory v{VERSION}"
|
||||
- "What's New in v{VERSION}" section heading
|
||||
- Feature highlights array (look for array of features with title/description)
|
||||
- **Process**:
|
||||
1. Pull latest from GitHub: `git pull origin main`
|
||||
2. Create release branch: `git checkout -b release/v{VERSION}`
|
||||
3. Search codebase for current version number (e.g., "v0.16.1")
|
||||
4. Update version numbers to new release version
|
||||
5. Update feature highlights with 3-5 key features from this release (extract from CHANGELOG.md)
|
||||
6. Commit changes: `git commit -m "chore: update to v{VERSION}"`
|
||||
7. Push branch: `git push origin release/v{VERSION}`
|
||||
- **Deploy**: Follow deployment process for basicmachines.co
|
||||
|
||||
**2. docs.basicmemory.com** (`/Users/drew/code/docs.basicmemory.com`)
|
||||
- **Goal**: Add new release notes section to the latest-releases page
|
||||
- **File**: `src/pages/latest-releases.mdx`
|
||||
- **What to do**:
|
||||
1. Pull latest from GitHub: `git pull origin main`
|
||||
2. Create release branch: `git checkout -b release/v{VERSION}`
|
||||
3. Read the existing file to understand the format and structure
|
||||
4. Read `/Users/drew/code/basic-memory/CHANGELOG.md` to get release content
|
||||
5. Add new release section **at the top** (after MDX imports, before other releases)
|
||||
6. Follow the existing pattern:
|
||||
- Heading: `## [v{VERSION}](github-link) — YYYY-MM-DD`
|
||||
- Focus statement if applicable
|
||||
- `<Info>` block with highlights (3-5 key items)
|
||||
- Sections for Features, Bug Fixes, Breaking Changes, etc.
|
||||
- Link to full changelog at the end
|
||||
- Separator `---` between releases
|
||||
7. Commit changes: `git commit -m "docs: add v{VERSION} release notes"`
|
||||
8. Push branch: `git push origin release/v{VERSION}`
|
||||
- **Source content**: Extract and format sections from CHANGELOG.md for this version
|
||||
- **Deploy**: Follow deployment process for docs.basicmemory.com
|
||||
|
||||
**4. Announce Release**
|
||||
- Post to Discord community if significant changes
|
||||
- Update social media if major release
|
||||
- Notify users via appropriate channels
|
||||
|
||||
## Pre-conditions Check
|
||||
Before starting, verify:
|
||||
@@ -74,19 +173,35 @@ Before starting, verify:
|
||||
🏷️ Tag: v0.13.2
|
||||
📋 GitHub Release: https://github.com/basicmachines-co/basic-memory/releases/tag/v0.13.2
|
||||
📦 PyPI: https://pypi.org/project/basic-memory/0.13.2/
|
||||
🍺 Homebrew: https://github.com/basicmachines-co/homebrew-basic-memory
|
||||
🔌 MCP Registry: https://registry.modelcontextprotocol.io
|
||||
🚀 GitHub Actions: Completed
|
||||
|
||||
Install with:
|
||||
uv tool install basic-memory
|
||||
Install with pip/uv:
|
||||
uv tool install basic-memory
|
||||
|
||||
Install with Homebrew:
|
||||
brew install basicmachines-co/basic-memory/basic-memory
|
||||
|
||||
Users can now upgrade:
|
||||
uv tool upgrade basic-memory
|
||||
uv tool upgrade basic-memory
|
||||
brew upgrade basic-memory
|
||||
```
|
||||
|
||||
## Context
|
||||
- This creates production releases used by end users
|
||||
- Must pass all quality gates before proceeding
|
||||
- Uses the automated justfile target for consistency
|
||||
- Version is automatically updated in `__init__.py`
|
||||
- Version is automatically updated across **all** consolidated manifests via
|
||||
`just set-version <version>` (which calls `scripts/update_versions.py`): the
|
||||
Python package (`__init__.py`, `server.json`) **and** the plugin/agent artifacts
|
||||
(Claude Code `plugin.json` + root/local marketplaces, Codex `plugin.json`,
|
||||
Hermes `plugin.yaml` + `__init__.py`, OpenClaw `package.json`). To bump only
|
||||
the plugin/agent artifacts
|
||||
out of band, use `just set-packages-version <version>` (preview with
|
||||
`just set-packages-version-dry-run <version>`).
|
||||
- Triggers automated GitHub release with changelog
|
||||
- Leverages uv-dynamic-versioning for package version management
|
||||
- Package is published to PyPI for `pip` and `uv` users
|
||||
- Homebrew formula is automatically updated for stable releases
|
||||
- MCP Registry is updated manually via `mcp-publisher publish`
|
||||
- Supports multiple installation methods (uv, pip, Homebrew)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
allowed-tools: mcp__basic-memory__write_note, mcp__basic-memory__read_note, mcp__basic-memory__search_notes, mcp__basic-memory__edit_note
|
||||
argument-hint: [create|status|show|review] [spec-name]
|
||||
description: Manage specifications in our development process
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Specifications are managed in the Basic Memory "specs" project. All specs live in a centralized location accessible across all repositories via MCP tools.
|
||||
|
||||
See SPEC-1 and SPEC-2 in the "specs" project for the full specification-driven development process.
|
||||
|
||||
Available commands:
|
||||
- `create [name]` - Create new specification
|
||||
- `status` - Show all spec statuses
|
||||
- `show [spec-name]` - Read a specific spec
|
||||
- `review [spec-name]` - Review implementation against spec
|
||||
|
||||
## Your task
|
||||
|
||||
Execute the spec command: `/spec $ARGUMENTS`
|
||||
|
||||
### If command is "create":
|
||||
1. Get next SPEC number by searching existing specs in "specs" project
|
||||
2. Create new spec using template from SPEC-2
|
||||
3. Use mcp__basic-memory__write_note with project="specs"
|
||||
4. Include standard sections: Why, What, How, How to Evaluate
|
||||
|
||||
### If command is "status":
|
||||
1. Use mcp__basic-memory__search_notes with project="specs"
|
||||
2. Display table with spec number, title, and progress
|
||||
3. Show completion status from checkboxes in content
|
||||
|
||||
### If command is "show":
|
||||
1. Use mcp__basic-memory__read_note with project="specs"
|
||||
2. Display the full spec content
|
||||
|
||||
### If command is "review":
|
||||
1. Read the specified spec and its "How to Evaluate" section
|
||||
2. Review current implementation against success criteria with careful evaluation of:
|
||||
- **Functional completeness** - All specified features working
|
||||
- **Test coverage analysis** - Actual test files and coverage percentage
|
||||
- Count existing test files vs required components/APIs/composables
|
||||
- Verify unit tests, integration tests, and end-to-end tests
|
||||
- Check for missing test categories (component, API, workflow)
|
||||
- **Code quality metrics** - TypeScript compilation, linting, performance
|
||||
- **Architecture compliance** - Component isolation, state management patterns
|
||||
- **Documentation completeness** - Implementation matches specification
|
||||
3. Provide honest, accurate assessment - do not overstate completeness
|
||||
4. Document findings and update spec with review results using mcp__basic-memory__edit_note
|
||||
5. If gaps found, clearly identify what still needs to be implemented/tested
|
||||
@@ -1,131 +0,0 @@
|
||||
# /test-coverage - Run Tests with Coverage Analysis
|
||||
|
||||
Execute test suite with comprehensive coverage reporting and analysis.
|
||||
|
||||
## Usage
|
||||
```
|
||||
/test-coverage [pattern]
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `pattern` (optional): Test pattern to run specific tests (e.g., `test_mcp`, `*integration*`)
|
||||
|
||||
## Implementation
|
||||
|
||||
You are an expert QA engineer for the Basic Memory project. When the user runs `/test-coverage`, execute the following steps:
|
||||
|
||||
### Step 1: Test Execution
|
||||
1. **Run Tests with Coverage**
|
||||
```bash
|
||||
# Full test suite
|
||||
uv run pytest --cov=basic_memory --cov-report=html --cov-report=term -v
|
||||
|
||||
# Or with pattern if provided
|
||||
uv run pytest tests/*{pattern}* --cov=basic_memory --cov-report=html --cov-report=term -v
|
||||
```
|
||||
|
||||
2. **Generate Coverage Reports**
|
||||
- Terminal summary with percentages
|
||||
- HTML report for detailed analysis
|
||||
- Identify files below coverage threshold
|
||||
|
||||
### Step 2: Coverage Analysis
|
||||
1. **Summary Statistics**
|
||||
- Overall coverage percentage
|
||||
- Number of files with 100% coverage
|
||||
- Files below 95% threshold
|
||||
- Total lines covered/missed
|
||||
|
||||
2. **Detailed Breakdown**
|
||||
- Coverage by module/package
|
||||
- Identify untested code paths
|
||||
- Find missing edge case tests
|
||||
|
||||
### Step 3: Report Generation
|
||||
Generate comprehensive coverage report:
|
||||
|
||||
```
|
||||
🧪 Test Coverage Report
|
||||
|
||||
📊 OVERALL COVERAGE: 98.2% (target: 95%+)
|
||||
|
||||
✅ EXCELLENT COVERAGE (>95%):
|
||||
├── basic_memory/mcp/: 99.1%
|
||||
├── basic_memory/services/: 98.8%
|
||||
├── basic_memory/repository/: 97.9%
|
||||
└── basic_memory/api/: 96.2%
|
||||
|
||||
⚠️ NEEDS ATTENTION (<95%):
|
||||
├── basic_memory/sync/: 94.1% (missing 12 lines)
|
||||
└── basic_memory/importers/: 91.8% (missing 23 lines)
|
||||
|
||||
🎯 SPECIFIC GAPS:
|
||||
├── sync_service.py:142-145 (error handling)
|
||||
├── importer_base.py:67-70 (edge case)
|
||||
└── file_utils.py:89 (exception path)
|
||||
|
||||
📁 HTML Report: htmlcov/index.html
|
||||
🚀 Run `open htmlcov/index.html` to view detailed report
|
||||
```
|
||||
|
||||
### Step 4: Actionable Recommendations
|
||||
1. **Coverage Improvements**
|
||||
- Suggest specific tests to add
|
||||
- Identify edge cases to cover
|
||||
- Recommend integration tests
|
||||
|
||||
2. **Quality Insights**
|
||||
- Highlight well-tested modules
|
||||
- Point out testing patterns to follow
|
||||
- Suggest refactoring for testability
|
||||
|
||||
## Advanced Analysis
|
||||
|
||||
### Performance Metrics
|
||||
- Test execution time by module
|
||||
- Slowest tests identification
|
||||
- Coverage collection overhead
|
||||
|
||||
### Integration Coverage
|
||||
- MCP tool integration tests
|
||||
- API endpoint coverage
|
||||
- Database operation coverage
|
||||
- File system operation coverage
|
||||
|
||||
## Output Examples
|
||||
|
||||
### Full Coverage Success
|
||||
```
|
||||
🎉 EXCELLENT COVERAGE!
|
||||
|
||||
📊 Coverage: 98.7% (744 tests passed)
|
||||
✅ All modules above 95% threshold
|
||||
🏆 23 files with 100% coverage
|
||||
⚡ Tests completed in 45.2s
|
||||
|
||||
Ready for release! 🚀
|
||||
```
|
||||
|
||||
### Coverage Issues Found
|
||||
```
|
||||
⚠️ COVERAGE GAPS DETECTED
|
||||
|
||||
📊 Coverage: 92.1% (below 95% target)
|
||||
❌ 3 modules need attention
|
||||
🔍 43 uncovered lines found
|
||||
|
||||
Priority fixes:
|
||||
1. Add tests for error handling in sync_service.py
|
||||
2. Cover edge cases in importer_base.py
|
||||
3. Test exception paths in file_utils.py
|
||||
|
||||
Run specific tests:
|
||||
uv run pytest tests/sync/ -v
|
||||
```
|
||||
|
||||
## Context
|
||||
- Uses pytest with coverage plugin
|
||||
- Generates both terminal and HTML reports
|
||||
- Focuses on actionable improvement suggestions
|
||||
- Integrates with existing test infrastructure
|
||||
- Helps maintain high code quality standards
|
||||
@@ -1,6 +1,7 @@
|
||||
# /project:test-live - Live Basic Memory Testing Suite
|
||||
|
||||
Execute comprehensive real-world testing of Basic Memory using the installed version, following the methodology in TESTING.md. All test results are recorded as notes in a dedicated test project.
|
||||
Execute comprehensive real-world testing of Basic Memory using the installed version.
|
||||
All test results are recorded as notes in a dedicated test project.
|
||||
|
||||
## Usage
|
||||
```
|
||||
@@ -8,12 +9,81 @@ Execute comprehensive real-world testing of Basic Memory using the installed ver
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `phase` (optional): Specific test phase to run (`core`, `features`, `edge`, `workflows`, `stress`, or `all`)
|
||||
- `phase` (optional): Specific test phase to run (`recent`, `core`, `features`, `edge`, `workflows`, `stress`, or `all`)
|
||||
- `recent` - Focus on recent changes and new features (recommended for regular testing)
|
||||
- `core` - Essential tools only (Tier 1: write_note, read_note, search_notes, edit_note, list_memory_projects, recent_activity)
|
||||
- `features` - Core + important workflows (Tier 1 + Tier 2)
|
||||
- `all` - Comprehensive testing of all tools and scenarios
|
||||
|
||||
## Implementation
|
||||
|
||||
You are an expert QA engineer conducting live testing of Basic Memory.
|
||||
When the user runs `/project:test-live`, execute comprehensive testing following the TESTING.md methodology:
|
||||
When the user runs `/project:test-live`, execute comprehensive test plan:
|
||||
|
||||
## Tool Testing Priority
|
||||
|
||||
### **Tier 1: Critical Core (Always Test)**
|
||||
1. **write_note** - Foundation of all knowledge creation
|
||||
2. **read_note** - Primary knowledge retrieval mechanism
|
||||
3. **search_notes** - Essential for finding information
|
||||
4. **edit_note** - Core content modification capability
|
||||
5. **list_memory_projects** - Project discovery and session guidance
|
||||
6. **recent_activity** - Project discovery mode and activity analysis
|
||||
|
||||
### **Tier 2: Important Workflows (Usually Test)**
|
||||
7. **build_context** - Conversation continuity via memory:// URLs
|
||||
8. **create_memory_project** - Essential for project setup
|
||||
9. **move_note** - Knowledge organization
|
||||
10. **sync_status** - Understanding system state
|
||||
11. **delete_project** - Project lifecycle management
|
||||
|
||||
### **Tier 3: Enhanced Functionality (Sometimes Test)**
|
||||
12. **view_note** - Claude Desktop artifact display
|
||||
13. **read_content** - Raw content access
|
||||
14. **delete_note** - Content removal
|
||||
15. **list_directory** - File system exploration
|
||||
16. **edit_note** (advanced modes) - Complex find/replace operations
|
||||
|
||||
### **Tier 4: Specialized (Rarely Test)**
|
||||
17. **canvas** - Obsidian visualization (specialized use case)
|
||||
18. **MCP Prompts** - Enhanced UX tools (ai_assistant_guide, continue_conversation)
|
||||
|
||||
## Stateless Architecture Testing
|
||||
|
||||
### **Project Discovery Workflow (CRITICAL)**
|
||||
Test the new stateless project selection flow:
|
||||
|
||||
1. **Initial Discovery**
|
||||
- Call `list_memory_projects()` without knowing which project to use
|
||||
- Verify clear session guidance appears: "Next: Ask which project to use"
|
||||
- Confirm removal of CLI-specific references
|
||||
|
||||
2. **Activity-Based Discovery**
|
||||
- Call `recent_activity()` without project parameter (discovery mode)
|
||||
- Verify intelligent project suggestions based on activity
|
||||
- Test guidance: "Should I use [most-active-project] for this task?"
|
||||
|
||||
3. **Session Tracking Validation**
|
||||
- Verify all tool responses include `[Session: Using project 'name']`
|
||||
- Confirm guidance reminds about session-wide project tracking
|
||||
|
||||
4. **Single Project Constraint Mode**
|
||||
- Test MCP server with `--project` parameter
|
||||
- Verify all operations constrained to specified project
|
||||
- Test project override behavior in constrained mode
|
||||
|
||||
### **Explicit Project Parameters (CRITICAL)**
|
||||
All tools must require explicit project parameters:
|
||||
|
||||
1. **Parameter Validation**
|
||||
- Test all Tier 1 tools require `project` parameter
|
||||
- Verify clear error messages for missing project
|
||||
- Test invalid project name handling
|
||||
|
||||
2. **No Session State Dependencies**
|
||||
- Confirm no tool relies on "current project" concept
|
||||
- Test rapid project switching within conversation
|
||||
- Verify each call is truly independent
|
||||
|
||||
### Pre-Test Setup
|
||||
|
||||
@@ -22,7 +92,13 @@ When the user runs `/project:test-live`, execute comprehensive testing following
|
||||
- Check version and confirm it's the expected release
|
||||
- Test MCP connection and tool availability
|
||||
|
||||
2. **Test Project Creation**
|
||||
2. **Recent Changes Analysis** (if phase includes 'recent' or 'all')
|
||||
- Run `git log --oneline -20` to examine recent commits
|
||||
- Identify new features, bug fixes, and enhancements
|
||||
- Generate targeted test scenarios for recent changes
|
||||
- Prioritize regression testing for recently fixed issues
|
||||
|
||||
3. **Test Project Creation**
|
||||
|
||||
Run the bash `date` command to get the current date/time.
|
||||
|
||||
@@ -32,85 +108,151 @@ Run the bash `date` command to get the current date/time.
|
||||
Purpose: Record all test observations and results
|
||||
```
|
||||
|
||||
Make sure to switch to the newly created project with the `switch_project()` tool.
|
||||
Make sure to use the newly created project for all subsequent test operations by specifying it in the `project` parameter of each tool call.
|
||||
|
||||
3. **Baseline Documentation**
|
||||
4. **Baseline Documentation**
|
||||
Create initial test session note with:
|
||||
- Test environment details
|
||||
- Version being tested
|
||||
- Recent changes identified (if applicable)
|
||||
- Test objectives and scope
|
||||
- Start timestamp
|
||||
|
||||
### Phase 1: Core Functionality Validation
|
||||
### Phase 0: Recent Changes Validation (if 'recent' or 'all' phase)
|
||||
|
||||
Test all fundamental MCP tools systematically:
|
||||
Based on recent commit analysis, create targeted test scenarios:
|
||||
|
||||
**write_note Tests:**
|
||||
- Basic note creation with various content types
|
||||
- Frontmatter handling (tags, custom fields)
|
||||
- Special characters in titles and content
|
||||
- Unicode and emoji support
|
||||
- Empty notes and minimal content
|
||||
**Recent Changes Test Protocol:**
|
||||
1. **Feature Addition Tests** - For each new feature identified:
|
||||
- Test basic functionality
|
||||
- Test integration with existing tools
|
||||
- Verify documentation accuracy
|
||||
- Test edge cases and error handling
|
||||
|
||||
**read_note Tests:**
|
||||
- Read by title, permalink, memory:// URLs
|
||||
- Non-existent notes (error handling)
|
||||
- Notes with complex formatting
|
||||
- Performance with large notes
|
||||
2. **Bug Fix Regression Tests** - For each recent fix:
|
||||
- Recreate the original problem scenario
|
||||
- Verify the fix works as expected
|
||||
- Test related functionality isn't broken
|
||||
- Document the verification in test notes
|
||||
|
||||
**view_note Tests:**
|
||||
- View notes as formatted artifacts (Claude Desktop)
|
||||
- Title extraction from frontmatter and headings
|
||||
- Unicode and emoji content in artifacts
|
||||
- Error handling for non-existent notes
|
||||
- Artifact display quality and readability
|
||||
3. **Performance/Enhancement Validation** - For optimizations:
|
||||
- Establish baseline timing
|
||||
- Compare with expected improvements
|
||||
- Test under various load conditions
|
||||
- Document performance observations
|
||||
|
||||
**search_notes Tests:**
|
||||
- Simple text queries
|
||||
- Tag-based searches
|
||||
- Boolean operators and complex queries
|
||||
- Empty/no results scenarios
|
||||
- Performance with growing knowledge base
|
||||
**Example Recent Changes (Update based on actual git log):**
|
||||
- Watch Service Restart (#156): Test project creation → file modification → automatic restart
|
||||
- Cross-Project Moves (#161): Test move_note with cross-project detection
|
||||
- Docker Environment Support (#174): Test BASIC_MEMORY_HOME behavior
|
||||
- MCP Server Logging (#164): Verify log level configurations
|
||||
|
||||
**Recent Activity Tests:**
|
||||
- Various timeframes ("today", "1 week", "1d")
|
||||
- Type filtering (if available)
|
||||
- Empty project scenarios
|
||||
- Performance with many recent changes
|
||||
### Phase 1: Core Functionality Validation (Tier 1 Tools)
|
||||
|
||||
**Context Building Tests:**
|
||||
- Different depth levels (1, 2, 3+)
|
||||
- Various timeframes
|
||||
- Relation traversal accuracy
|
||||
- Performance with complex graphs
|
||||
Test essential MCP tools that form the foundation of Basic Memory:
|
||||
|
||||
### Phase 2: v0.13.0 Feature Deep Dive
|
||||
**1. write_note Tests (Critical):**
|
||||
- ✅ Basic note creation with frontmatter
|
||||
- ✅ Special characters and Unicode in titles
|
||||
- ✅ Various content types (lists, headings, code blocks)
|
||||
- ✅ Empty notes and minimal content edge cases
|
||||
- ⚠️ Error handling for invalid parameters
|
||||
|
||||
**Project Management:**
|
||||
- Create multiple projects dynamically
|
||||
- Switch between projects mid-conversation
|
||||
- Cross-project operations
|
||||
- Project discovery and status
|
||||
- Default project behavior
|
||||
- Invalid project handling
|
||||
**2. read_note Tests (Critical):**
|
||||
- ✅ Read by title, permalink, memory:// URLs
|
||||
- ✅ Non-existent notes (error handling)
|
||||
- ✅ Notes with complex markdown formatting
|
||||
- ⚠️ Performance with large notes (>10MB)
|
||||
|
||||
**Advanced Note Editing:**
|
||||
- `edit_note` with append operations
|
||||
- Prepend operations
|
||||
- Find/replace with validation
|
||||
- Section replacement under headers
|
||||
- Error scenarios (invalid operations)
|
||||
- Frontmatter preservation
|
||||
**3. search_notes Tests (Critical):**
|
||||
- ✅ Simple text queries across content
|
||||
- ✅ Tag-based searches with multiple tags
|
||||
- ✅ Boolean operators (AND, OR, NOT)
|
||||
- ✅ Empty/no results scenarios
|
||||
- ⚠️ Performance with 100+ notes
|
||||
|
||||
**File Management:**
|
||||
- `move_note` within same project
|
||||
- Move between projects
|
||||
- Automatic folder creation
|
||||
- Special characters in paths
|
||||
- Database consistency validation
|
||||
- Search index updates after moves
|
||||
**4. edit_note Tests (Critical):**
|
||||
- ✅ Append operations preserving frontmatter
|
||||
- ✅ Prepend operations
|
||||
- ✅ Find/replace with validation
|
||||
- ✅ Section replacement under headers
|
||||
- ⚠️ Error scenarios (invalid operations)
|
||||
|
||||
### Phase 3: Edge Case Exploration
|
||||
**5. list_memory_projects Tests (Critical):**
|
||||
- ✅ Display all projects with clear session guidance
|
||||
- ✅ Project discovery workflow prompts
|
||||
- ✅ Removal of CLI-specific references
|
||||
- ✅ Empty project list handling
|
||||
- ✅ Single project constraint mode display
|
||||
|
||||
**6. recent_activity Tests (Critical - Discovery Mode):**
|
||||
- ✅ Discovery mode without project parameter
|
||||
- ✅ Intelligent project suggestions based on activity
|
||||
- ✅ Guidance prompts for project selection
|
||||
- ✅ Session tracking reminders in responses
|
||||
- ⚠️ Performance with multiple projects
|
||||
|
||||
### Phase 2: Important Workflows (Tier 2 Tools)
|
||||
|
||||
**7. build_context Tests (Important):**
|
||||
- ✅ Different depth levels (1, 2, 3+)
|
||||
- ✅ Various timeframes for context
|
||||
- ✅ memory:// URL navigation
|
||||
- ⚠️ Performance with complex relation graphs
|
||||
|
||||
**8. create_memory_project Tests (Important):**
|
||||
- ✅ Create projects dynamically
|
||||
- ✅ Set default during creation
|
||||
- ✅ Path validation and creation
|
||||
- ⚠️ Invalid paths and names
|
||||
- ✅ Integration with existing projects
|
||||
|
||||
**9. move_note Tests (Important):**
|
||||
- ✅ Move within same project
|
||||
- ✅ Cross-project moves with detection (#161)
|
||||
- ✅ Automatic folder creation
|
||||
- ✅ Database consistency validation
|
||||
- ⚠️ Special characters in paths
|
||||
|
||||
**10. sync_status Tests (Important):**
|
||||
- ✅ Background operation monitoring
|
||||
- ✅ File synchronization status
|
||||
- ✅ Project sync state reporting
|
||||
- ⚠️ Error state handling
|
||||
|
||||
### Phase 3: Enhanced Functionality (Tier 3 Tools)
|
||||
|
||||
**11. view_note Tests (Enhanced):**
|
||||
- ✅ Claude Desktop artifact display
|
||||
- ✅ Title extraction from frontmatter
|
||||
- ✅ Unicode and emoji content rendering
|
||||
- ⚠️ Error handling for non-existent notes
|
||||
|
||||
**12. read_content Tests (Enhanced):**
|
||||
- ✅ Raw file content access
|
||||
- ✅ Binary file handling
|
||||
- ✅ Image file reading
|
||||
- ⚠️ Large file performance
|
||||
|
||||
**13. delete_note Tests (Enhanced):**
|
||||
- ✅ Single note deletion
|
||||
- ✅ Database consistency after deletion
|
||||
- ⚠️ Non-existent note handling
|
||||
- ✅ Confirmation of successful deletion
|
||||
|
||||
**14. list_directory Tests (Enhanced):**
|
||||
- ✅ Directory content listing
|
||||
- ✅ Depth control and filtering
|
||||
- ✅ File name globbing
|
||||
- ⚠️ Empty directory handling
|
||||
|
||||
**15. delete_project Tests (Enhanced):**
|
||||
- ✅ Project removal from config
|
||||
- ✅ Database cleanup
|
||||
- ⚠️ Default project protection
|
||||
- ⚠️ Non-existent project handling
|
||||
|
||||
### Phase 4: Edge Case Exploration
|
||||
|
||||
**Boundary Testing:**
|
||||
- Very long titles and content (stress limits)
|
||||
@@ -134,7 +276,7 @@ Test all fundamental MCP tools systematically:
|
||||
- Rapid successive operations
|
||||
- Memory usage monitoring
|
||||
|
||||
### Phase 4: Real-World Workflow Scenarios
|
||||
### Phase 5: Real-World Workflow Scenarios
|
||||
|
||||
**Meeting Notes Pipeline:**
|
||||
1. Create meeting notes with action items
|
||||
@@ -154,7 +296,7 @@ Test all fundamental MCP tools systematically:
|
||||
1. Technical documentation project
|
||||
2. Personal recipe collection project
|
||||
3. Learning/course notes project
|
||||
4. Switch contexts during conversation
|
||||
4. Specify different projects for different operations
|
||||
5. Cross-reference related concepts
|
||||
|
||||
**Content Evolution:**
|
||||
@@ -164,7 +306,35 @@ Test all fundamental MCP tools systematically:
|
||||
4. Update content with edit operations
|
||||
5. Validate knowledge graph integrity
|
||||
|
||||
### Phase 5: Creative Stress Testing
|
||||
### Phase 6: Specialized Tools Testing (Tier 4)
|
||||
|
||||
**16. canvas Tests (Specialized):**
|
||||
- ✅ JSON Canvas generation
|
||||
- ✅ Node and edge creation
|
||||
- ✅ Obsidian compatibility
|
||||
- ⚠️ Complex graph handling
|
||||
|
||||
**17. MCP Prompts Tests (Specialized):**
|
||||
- ✅ ai_assistant_guide output
|
||||
- ✅ continue_conversation functionality
|
||||
- ✅ Formatted search results
|
||||
- ✅ Enhanced activity reports
|
||||
|
||||
### Phase 7: Integration & File Watching Tests
|
||||
|
||||
**File System Integration:**
|
||||
- ✅ Watch service behavior with file changes
|
||||
- ✅ Project creation → watch restart (#156)
|
||||
- ✅ Multi-project synchronization
|
||||
- ⚠️ MCP→API→DB→File stack validation
|
||||
|
||||
**Real Integration Testing:**
|
||||
- ✅ End-to-end file watching vs manual operations
|
||||
- ✅ Cross-session persistence
|
||||
- ✅ Database consistency across operations
|
||||
- ⚠️ Performance under real file system changes
|
||||
|
||||
### Phase 8: Creative Stress Testing
|
||||
|
||||
**Creative Exploration:**
|
||||
- Rapid project creation/switching patterns
|
||||
@@ -180,6 +350,26 @@ Test all fundamental MCP tools systematically:
|
||||
- Complex boolean search expressions
|
||||
- Resource constraint testing
|
||||
|
||||
## Test Execution Guidelines
|
||||
|
||||
### Quick Testing (core/features phases)
|
||||
- Focus on Tier 1 tools (core) or Tier 1+2 (features)
|
||||
- Test essential functionality and common edge cases
|
||||
- Record critical issues immediately
|
||||
- Complete in 15-20 minutes
|
||||
|
||||
### Comprehensive Testing (all phase)
|
||||
- Cover all tiers systematically
|
||||
- Include specialized tools and stress testing
|
||||
- Document performance baselines
|
||||
- Complete in 45-60 minutes
|
||||
|
||||
### Recent Changes Focus (recent phase)
|
||||
- Analyze git log for recent commits
|
||||
- Generate targeted test scenarios
|
||||
- Focus on regression testing for fixes
|
||||
- Validate new features thoroughly
|
||||
|
||||
## Test Observation Format
|
||||
|
||||
Record ALL observations immediately as Basic Memory notes:
|
||||
@@ -202,14 +392,14 @@ permalink: test-session-[phase]-[timestamp]
|
||||
## Test Results
|
||||
|
||||
### ✅ Successful Operations
|
||||
- [timestamp] write_note: Created note with emoji title 📝 #functionality
|
||||
- [timestamp] search_notes: Boolean query returned 23 results in 0.4s #performance
|
||||
- [timestamp] edit_note: Append operation preserved frontmatter #reliability
|
||||
- [timestamp] ✅ write_note: Created note with emoji title 📝 #tier1 #functionality
|
||||
- [timestamp] ✅ search_notes: Boolean query returned 23 results in 0.4s #tier1 #performance
|
||||
- [timestamp] ✅ edit_note: Append operation preserved frontmatter #tier1 #reliability
|
||||
|
||||
### ⚠️ Issues Discovered
|
||||
- [timestamp] move_note: Slow with deep folder paths (2.1s) #performance
|
||||
- [timestamp] search_notes: Unicode query returned unexpected results #bug
|
||||
- [timestamp] project switch: Context lost for memory:// URLs #issue
|
||||
- [timestamp] ⚠️ move_note: Slow with deep folder paths (2.1s) #tier2 #performance
|
||||
- [timestamp] 🚨 search_notes: Unicode query returned unexpected results #tier1 #bug #critical
|
||||
- [timestamp] ⚠️ build_context: Context lost for memory:// URLs #tier2 #issue
|
||||
|
||||
### 🚀 Enhancements Identified
|
||||
- edit_note could benefit from preview mode #ux-improvement
|
||||
@@ -219,7 +409,7 @@ permalink: test-session-[phase]-[timestamp]
|
||||
### 📊 Performance Metrics
|
||||
- Average write_note time: 0.3s
|
||||
- Search with 100+ notes: 0.6s
|
||||
- Project switch overhead: 0.1s
|
||||
- Project parameter overhead: <0.1s
|
||||
- Memory usage: [observed levels]
|
||||
|
||||
## Relations
|
||||
@@ -239,7 +429,7 @@ permalink: test-session-[phase]-[timestamp]
|
||||
- Learning curve and intuitiveness
|
||||
|
||||
**System Behavior:**
|
||||
- Context preservation across operations
|
||||
- Stateless operation independence
|
||||
- memory:// URL navigation reliability
|
||||
- Multi-step workflow cohesion
|
||||
- Edge case graceful handling
|
||||
@@ -353,24 +543,44 @@ For each error discovered:
|
||||
- Create comprehensive summary report
|
||||
- Generate development recommendations
|
||||
|
||||
## Testing Success Criteria
|
||||
|
||||
### Core Testing (Tier 1) - Must Pass
|
||||
- All 6 critical tools function correctly
|
||||
- No critical bugs in essential workflows
|
||||
- Acceptable performance for basic operations
|
||||
- Error handling works as expected
|
||||
|
||||
### Feature Testing (Tier 1+2) - Should Pass
|
||||
- All 11 core + important tools function
|
||||
- Workflow scenarios complete successfully
|
||||
- Performance meets baseline expectations
|
||||
- Integration points work correctly
|
||||
|
||||
### Comprehensive Testing (All Tiers) - Complete Coverage
|
||||
- All tools tested across all scenarios
|
||||
- Edge cases and stress testing completed
|
||||
- Performance baselines established
|
||||
- Full documentation of issues and enhancements
|
||||
|
||||
## Expected Outcomes
|
||||
|
||||
**System Validation:**
|
||||
- v0.13.0 feature verification in real usage
|
||||
- Edge case discovery beyond unit tests
|
||||
- Feature verification prioritized by tier importance
|
||||
- Recent changes validated for regression
|
||||
- Performance baseline establishment
|
||||
- Bug identification with reproduction cases
|
||||
- Bug identification with severity assessment
|
||||
|
||||
**Knowledge Base Creation:**
|
||||
- Comprehensive testing documentation
|
||||
- Prioritized testing documentation
|
||||
- Real usage examples for user guides
|
||||
- Edge case scenarios for future testing
|
||||
- Recent changes validation records
|
||||
- Performance insights for optimization
|
||||
|
||||
**Development Insights:**
|
||||
- Prioritized bug fix list
|
||||
- Tier-based bug priority list
|
||||
- Recent changes impact assessment
|
||||
- Enhancement ideas from real usage
|
||||
- Architecture validation results
|
||||
- User experience improvement areas
|
||||
|
||||
## Post-Test Deliverables
|
||||
@@ -402,9 +612,11 @@ For each error discovered:
|
||||
- Add performance benchmarks and targets
|
||||
|
||||
## Context
|
||||
- Uses installed basic-memory version (not development)
|
||||
- Uses real installed basic-memory version
|
||||
- Tests complete MCP→API→DB→File stack
|
||||
- Creates living documentation in Basic Memory itself
|
||||
- Follows integration over isolation philosophy
|
||||
- Prioritizes testing by tool importance and usage frequency
|
||||
- Adapts to recent development changes dynamically
|
||||
- Focuses on real usage patterns over checklist validation
|
||||
- Generates actionable insights for development team
|
||||
- Generates actionable insights prioritized by impact
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||
"env": {
|
||||
"CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
|
||||
"CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY": "1",
|
||||
"CLAUDE_CODE_NO_FLICKER": "1",
|
||||
"CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING": "1"
|
||||
},
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(just fast-check)",
|
||||
"Bash(just check)",
|
||||
"Bash(just fix)",
|
||||
"Bash(just typecheck)",
|
||||
"Bash(just lint)",
|
||||
"Bash(just test)"
|
||||
],
|
||||
"deny": []
|
||||
},
|
||||
"enableAllProjectMcpServers": true
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/adversarial-review
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/basic-machines-review
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/instrumentation
|
||||
@@ -0,0 +1,60 @@
|
||||
# Git files
|
||||
.git/
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# Development files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Testing files
|
||||
tests/
|
||||
test-int/
|
||||
.pytest_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# Build artifacts
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
|
||||
# Virtual environments (uv creates these during build)
|
||||
.venv/
|
||||
venv/
|
||||
.env
|
||||
|
||||
# CI/CD files
|
||||
.github/
|
||||
|
||||
# Documentation (keep README.md and pyproject.toml)
|
||||
docs/
|
||||
CHANGELOG.md
|
||||
CLAUDE.md
|
||||
CONTRIBUTING.md
|
||||
|
||||
# Example files not needed for runtime
|
||||
examples/
|
||||
|
||||
# Local development files
|
||||
.basic-memory/
|
||||
*.db
|
||||
*.sqlite3
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
*.log
|
||||
@@ -0,0 +1,28 @@
|
||||
# Basic Memory Environment Variables Example
|
||||
# Copy this file to .env and customize as needed
|
||||
# Note: .env files are gitignored and should never be committed
|
||||
|
||||
# ============================================================================
|
||||
# PostgreSQL Test Database Configuration
|
||||
# ============================================================================
|
||||
# These variables allow you to override the default test database credentials
|
||||
# Default values match docker-compose-postgres.yml for local development
|
||||
#
|
||||
# Only needed if you want to use different credentials or a remote test database
|
||||
# By default, tests use: postgresql://basic_memory_user:dev_password@localhost:5433/basic_memory_test
|
||||
|
||||
# Full PostgreSQL test database URL (used by tests and migrations)
|
||||
# POSTGRES_TEST_URL=postgresql+asyncpg://basic_memory_user:dev_password@localhost:5433/basic_memory_test
|
||||
|
||||
# Individual components (used by justfile postgres-reset command)
|
||||
# POSTGRES_USER=basic_memory_user
|
||||
# POSTGRES_TEST_DB=basic_memory_test
|
||||
|
||||
# ============================================================================
|
||||
# Production Database Configuration
|
||||
# ============================================================================
|
||||
# For production use, set these in your deployment environment
|
||||
# DO NOT use the test credentials above in production!
|
||||
|
||||
# BASIC_MEMORY_DATABASE_BACKEND=postgres # or "sqlite"
|
||||
# BASIC_MEMORY_DATABASE_URL=postgresql+asyncpg://user:password@host:port/database
|
||||
@@ -1,55 +0,0 @@
|
||||
# OAuth Configuration for Basic Memory MCP Server
|
||||
# Copy this file to .env and update the values
|
||||
|
||||
# Enable OAuth authentication
|
||||
FASTMCP_AUTH_ENABLED=true
|
||||
|
||||
# OAuth provider type: basic, github, google, or supabase
|
||||
# - basic: Built-in OAuth provider with in-memory storage
|
||||
# - github: Integrate with GitHub OAuth
|
||||
# - google: Integrate with Google OAuth
|
||||
# - supabase: Integrate with Supabase Auth (recommended for production)
|
||||
FASTMCP_AUTH_PROVIDER=basic
|
||||
|
||||
# OAuth issuer URL (your MCP server URL)
|
||||
FASTMCP_AUTH_ISSUER_URL=http://localhost:8000
|
||||
|
||||
# Documentation URL for OAuth endpoints
|
||||
FASTMCP_AUTH_DOCS_URL=http://localhost:8000/docs/oauth
|
||||
|
||||
# Required scopes (comma-separated)
|
||||
# Examples: read,write,admin
|
||||
FASTMCP_AUTH_REQUIRED_SCOPES=read,write
|
||||
|
||||
# Secret key for JWT tokens (auto-generated if not set)
|
||||
# FASTMCP_AUTH_SECRET_KEY=your-secret-key-here
|
||||
|
||||
# Enable client registration endpoint
|
||||
FASTMCP_AUTH_CLIENT_REGISTRATION_ENABLED=true
|
||||
|
||||
# Enable token revocation endpoint
|
||||
FASTMCP_AUTH_REVOCATION_ENABLED=true
|
||||
|
||||
# Default scopes for new clients
|
||||
FASTMCP_AUTH_DEFAULT_SCOPES=read
|
||||
|
||||
# Valid scopes that can be requested
|
||||
FASTMCP_AUTH_VALID_SCOPES=read,write,admin
|
||||
|
||||
# Client secret expiry in seconds (optional)
|
||||
# FASTMCP_AUTH_CLIENT_SECRET_EXPIRY=86400
|
||||
|
||||
# GitHub OAuth settings (if using github provider)
|
||||
# GITHUB_CLIENT_ID=your-github-client-id
|
||||
# GITHUB_CLIENT_SECRET=your-github-client-secret
|
||||
|
||||
# Google OAuth settings (if using google provider)
|
||||
# GOOGLE_CLIENT_ID=your-google-client-id
|
||||
# GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
|
||||
# Supabase settings (if using supabase provider)
|
||||
# SUPABASE_URL=https://your-project.supabase.co
|
||||
# SUPABASE_ANON_KEY=your-anon-key
|
||||
# SUPABASE_SERVICE_KEY=your-service-key # Optional, for admin operations
|
||||
# SUPABASE_JWT_SECRET=your-jwt-secret # Optional, for token validation
|
||||
# SUPABASE_ALLOWED_CLIENTS=client1,client2 # Comma-separated list of allowed client IDs
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto BM Soul
|
||||
|
||||
Write project updates for humans who will return later trying to understand what happened.
|
||||
|
||||
## Voice
|
||||
|
||||
- Clear, direct, warm, and technically honest.
|
||||
- Prefer concrete observations over generic praise.
|
||||
- It is okay to say when code is messy, risky, clever, boring, or satisfying.
|
||||
- Keep personality in service of memory, not performance.
|
||||
|
||||
## Do
|
||||
|
||||
- Tell the story.
|
||||
- Name the tradeoffs.
|
||||
- Call out sharp edges.
|
||||
- Notice good simplifications.
|
||||
- Let the note have taste and a little life when the evidence supports it.
|
||||
|
||||
## Do Not
|
||||
|
||||
- Do not invent intent, impact, tests, or drama.
|
||||
- Dunk on people.
|
||||
- Turn the note into marketing copy.
|
||||
- Hide uncertainty behind confident prose.
|
||||
@@ -0,0 +1,7 @@
|
||||
project: dev
|
||||
workspace: basic-memory-7020de4e925843c68c9056c60d101d9e
|
||||
deploy_workflows:
|
||||
- Deploy Production
|
||||
production_environments:
|
||||
- production
|
||||
note_folder: project-updates/github/{owner}/{repo}
|
||||
@@ -0,0 +1,64 @@
|
||||
# Memory CI Capture
|
||||
|
||||
You turn GitHub delivery context into a durable project update for Basic Memory.
|
||||
GitHub records the mechanics. Basic Memory remembers what changed and why.
|
||||
|
||||
## Inputs
|
||||
|
||||
- Read `.github/basic-memory/project-update-context.json`.
|
||||
- Read `.github/basic-memory/SOUL.md` if it exists. It is the repo-local voice and style guide
|
||||
for project updates.
|
||||
- Read the PR diff before writing when a SHA is available. Useful commands:
|
||||
`git show --stat --name-only <sha>` and `git show --format=fuller --no-patch <sha>`.
|
||||
- Use linked issue details, changed files, commit messages, PR body, labels, and
|
||||
source links as evidence.
|
||||
- Treat GitHub payload fields as immutable facts.
|
||||
- Do not invent tests, deployment status, issues, or user impact.
|
||||
|
||||
## Writing Standard
|
||||
|
||||
Do not write a fill-in-the-blanks note. Tell the story from the PR:
|
||||
problem -> solution -> impact.
|
||||
|
||||
Explain what problem was being addressed. If linked issue details are present,
|
||||
use them. If they are absent, ground the problem in the PR body, title, commits,
|
||||
and diff, and say when the original problem statement is unavailable.
|
||||
|
||||
Explain why the fix solves the problem, what complexity it introduced, what it
|
||||
refactored or removed, which components changed, and how the system is different
|
||||
after the merge. Prefer specific component names, file paths, modules, commands,
|
||||
and behavior over generic phrases.
|
||||
|
||||
## Voice And Candor
|
||||
|
||||
You may have a point of view. Be clear, specific, and human.
|
||||
It is okay to say when the code is messy, risky, clever, boring, or satisfying,
|
||||
but explain why. If the work is elegant or genuinely useful, say that too.
|
||||
Ground all judgments in the PR, linked issues, diff, tests, and source facts.
|
||||
|
||||
The soul file can shape tone, taste, and personality. It cannot override source
|
||||
facts, schema requirements, or the evidence standard above. Do not be mean,
|
||||
vague, theatrical, or invent criticism.
|
||||
|
||||
## Output
|
||||
|
||||
Return only JSON that matches the provided AgentSynthesis schema:
|
||||
|
||||
- `summary`: one concise sentence; do not merely repeat the PR title.
|
||||
- `story`: 2-4 sentences that connect problem -> solution -> impact.
|
||||
- `problem_addressed`: the concrete problem, bug, missing capability, or delivery need.
|
||||
- `solution`: why this change solves the problem.
|
||||
- `system_impact`: how the system, workflow, or architecture changed after the merge.
|
||||
- `why_it_matters`: durable project-memory context for future humans and agents.
|
||||
- `components_changed`: modules, workflows, commands, schemas, docs, or services touched.
|
||||
- `complexity_introduced`: tradeoffs, new moving parts, operational costs, or edge cases.
|
||||
- `refactors_or_removals`: cleanup, simplification, deleted paths, or "none found".
|
||||
- `user_facing_changes`: visible behavior or product changes.
|
||||
- `internal_changes`: implementation, infrastructure, or operational changes.
|
||||
- `verification`: checks, tests, deploy evidence, or explicit unknowns.
|
||||
- `follow_ups`: concrete remaining work only.
|
||||
- `decision_candidates`: explicit product or architecture decisions only.
|
||||
- `task_candidates`: concrete future tasks only.
|
||||
|
||||
Use empty arrays only when a list truly has no grounded entries. This is project
|
||||
memory, not marketing copy and not a commit-by-commit changelog.
|
||||
@@ -0,0 +1,75 @@
|
||||
name: Basic Memory Project Updates
|
||||
|
||||
"on":
|
||||
pull_request:
|
||||
types: [closed]
|
||||
workflow_run:
|
||||
workflows: ["Deploy Production"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
project-update:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Basic Memory from checkout
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
|
||||
- name: Collect project update context
|
||||
id: collect
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
bm ci collect \
|
||||
--config .github/basic-memory/config.yml \
|
||||
--output .github/basic-memory/project-update-context.json
|
||||
|
||||
- name: Stop when event is not eligible
|
||||
if: steps.collect.outputs.eligible != 'true'
|
||||
run: |
|
||||
echo "Auto BM skipped: ${{ steps.collect.outputs.skip_reason }}"
|
||||
|
||||
- name: Write Codex output schema
|
||||
if: steps.collect.outputs.eligible == 'true'
|
||||
run: |
|
||||
bm ci agent-schema --output "${{ runner.temp }}/agent-synthesis.schema.json"
|
||||
|
||||
- name: Synthesize project update with Codex
|
||||
if: steps.collect.outputs.eligible == 'true'
|
||||
uses: openai/codex-action@v1
|
||||
with:
|
||||
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
|
||||
prompt-file: .github/basic-memory/memory-ci-capture.md
|
||||
output-file: ${{ runner.temp }}/agent-synthesis.json
|
||||
output-schema-file: ${{ runner.temp }}/agent-synthesis.schema.json
|
||||
sandbox: read-only
|
||||
safety-strategy: drop-sudo
|
||||
|
||||
- name: Publish project update
|
||||
if: steps.collect.outputs.eligible == 'true'
|
||||
env:
|
||||
BASIC_MEMORY_CLOUD_API_KEY: ${{ secrets.BASIC_MEMORY_API_KEY }}
|
||||
BASIC_MEMORY_CI_CLOUD_HOST: ${{ vars.BASIC_MEMORY_CLOUD_HOST }}
|
||||
run: |
|
||||
if [ -n "$BASIC_MEMORY_CI_CLOUD_HOST" ]; then
|
||||
export BASIC_MEMORY_CLOUD_HOST="$BASIC_MEMORY_CI_CLOUD_HOST"
|
||||
fi
|
||||
bm ci publish \
|
||||
--cloud \
|
||||
--config .github/basic-memory/config.yml \
|
||||
--context .github/basic-memory/project-update-context.json \
|
||||
--synthesis "${{ runner.temp }}/agent-synthesis.json"
|
||||
@@ -0,0 +1,193 @@
|
||||
name: BM Bossbot
|
||||
|
||||
"on":
|
||||
workflow_run:
|
||||
workflows:
|
||||
- Tests
|
||||
types:
|
||||
- completed
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: Pull request number to review
|
||||
required: true
|
||||
# Review-thread activity re-evaluates the approval status without re-running
|
||||
# the full LLM review: new feedback flips the gate to failure, resolving the
|
||||
# last thread restores a previously earned approval for the same head SHA.
|
||||
pull_request_review:
|
||||
types:
|
||||
- submitted
|
||||
pull_request_review_comment:
|
||||
types:
|
||||
- created
|
||||
pull_request_review_thread:
|
||||
types:
|
||||
- resolved
|
||||
- unresolved
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
issues: read
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
BM_BOSSBOT_STATUS_CONTEXT: "BM Bossbot Approval"
|
||||
|
||||
jobs:
|
||||
review:
|
||||
name: BM Bossbot Review
|
||||
# Job-level concurrency (not workflow-level): thread-recheck events for the
|
||||
# same PR must never cancel an in-flight review run, and vice versa.
|
||||
concurrency:
|
||||
group: bm-bossbot-review-${{ github.event.workflow_run.pull_requests[0].number || inputs.pr_number }}
|
||||
cancel-in-progress: true
|
||||
if: |
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(
|
||||
github.event_name == 'workflow_run' &&
|
||||
github.event.workflow_run.conclusion == 'success' &&
|
||||
github.event.workflow_run.pull_requests[0].number != ''
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
pr_number: ${{ steps.pr.outputs.pr_number }}
|
||||
should_review: ${{ steps.pr.outputs.should_review }}
|
||||
|
||||
steps:
|
||||
- name: Checkout trusted base ref
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Normalize PR event
|
||||
id: pr
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
event_file="${RUNNER_TEMP}/bm-bossbot-event.json"
|
||||
should_review=true
|
||||
|
||||
if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then
|
||||
pr_number="${{ inputs.pr_number }}"
|
||||
tested_sha=""
|
||||
else
|
||||
pr_number="$(jq -r '.workflow_run.pull_requests[0].number // ""' "${GITHUB_EVENT_PATH}")"
|
||||
tested_sha="$(jq -r '.workflow_run.head_sha // ""' "${GITHUB_EVENT_PATH}")"
|
||||
fi
|
||||
|
||||
gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" > "${RUNNER_TEMP}/pull.json"
|
||||
current_head_sha="$(jq -r '.head.sha' "${RUNNER_TEMP}/pull.json")"
|
||||
draft="$(jq -r '.draft' "${RUNNER_TEMP}/pull.json")"
|
||||
|
||||
if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then
|
||||
tests_run_id="$(
|
||||
gh api -X GET "repos/${GITHUB_REPOSITORY}/actions/workflows/test.yml/runs" \
|
||||
-f event=push \
|
||||
-f head_sha="${current_head_sha}" \
|
||||
-f status=completed \
|
||||
--jq '[.workflow_runs[] | select(.conclusion == "success")][0].id // ""'
|
||||
)"
|
||||
if [ -z "${tests_run_id}" ]; then
|
||||
should_review=false
|
||||
echo "BM Bossbot skipped PR ${pr_number}: no successful Tests workflow for ${current_head_sha}."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${draft}" = "true" ]; then
|
||||
should_review=false
|
||||
echo "BM Bossbot skipped PR ${pr_number}: draft pull request."
|
||||
fi
|
||||
|
||||
if [ -n "${tested_sha}" ] && [ "${tested_sha}" != "${current_head_sha}" ]; then
|
||||
should_review=false
|
||||
echo "BM Bossbot skipped PR ${pr_number}: Tests passed for ${tested_sha}, but current head is ${current_head_sha}."
|
||||
fi
|
||||
|
||||
jq --arg repo "${GITHUB_REPOSITORY}" \
|
||||
'{repository:{full_name:$repo}, pull_request:{number:.number,title:.title,body:(.body // ""),html_url:.html_url,head:{sha:.head.sha,ref:.head.ref},base:{ref:.base.ref,sha:.base.sha},author_association:.author_association,draft:.draft}}' \
|
||||
"${RUNNER_TEMP}/pull.json" > "${event_file}"
|
||||
|
||||
echo "event_file=${event_file}" >> "${GITHUB_OUTPUT}"
|
||||
echo "pr_number=$(jq -r '.pull_request.number' "${event_file}")" >> "${GITHUB_OUTPUT}"
|
||||
echo "head_sha=$(jq -r '.pull_request.head.sha' "${event_file}")" >> "${GITHUB_OUTPUT}"
|
||||
echo "head_ref=$(jq -r '.pull_request.head.ref' "${event_file}")" >> "${GITHUB_OUTPUT}"
|
||||
echo "author_association=$(jq -r '.pull_request.author_association // ""' "${event_file}")" >> "${GITHUB_OUTPUT}"
|
||||
echo "tested_sha=${tested_sha}" >> "${GITHUB_OUTPUT}"
|
||||
echo "should_review=${should_review}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Classify PR author
|
||||
id: trust
|
||||
if: steps.pr.outputs.should_review == 'true'
|
||||
env:
|
||||
AUTHOR_ASSOCIATION: ${{ steps.pr.outputs.author_association }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
case "${AUTHOR_ASSOCIATION}" in
|
||||
OWNER|MEMBER|COLLABORATOR)
|
||||
trusted_author=true
|
||||
;;
|
||||
*)
|
||||
trusted_author=false
|
||||
;;
|
||||
esac
|
||||
echo "trusted_author=${trusted_author}" >> "${GITHUB_OUTPUT}"
|
||||
echo "author_association=${AUTHOR_ASSOCIATION}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Mark BM Bossbot approval pending
|
||||
if: steps.pr.outputs.should_review == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
uv run --script scripts/bm_bossbot_status.py pending \
|
||||
--event "${{ steps.pr.outputs.event_file }}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
||||
|
||||
- name: Finalize BM Bossbot approval
|
||||
if: always() && steps.pr.outputs.should_review == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
uv run --script scripts/bm_bossbot_status.py finalize \
|
||||
--event "${{ steps.pr.outputs.event_file }}" \
|
||||
--trusted "${{ steps.trust.outputs.trusted_author }}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
||||
|
||||
recheck:
|
||||
name: BM Bossbot Thread Recheck
|
||||
if: |
|
||||
github.event_name == 'pull_request_review' ||
|
||||
github.event_name == 'pull_request_review_comment' ||
|
||||
github.event_name == 'pull_request_review_thread'
|
||||
runs-on: ubuntu-latest
|
||||
# Job-level concurrency: collapse bursts of thread events for one PR while
|
||||
# staying isolated from the review job's group so neither cancels the other.
|
||||
concurrency:
|
||||
group: bm-bossbot-recheck-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: Checkout trusted base ref
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Re-evaluate approval from review-thread state
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
uv run --script scripts/bm_bossbot_status.py recheck \
|
||||
--pr-number "${{ github.event.pull_request.number }}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
||||
@@ -0,0 +1,85 @@
|
||||
name: Claude Code Review
|
||||
|
||||
"on":
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: Pull request number to review manually
|
||||
required: true
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
if: inputs.pr_number != ''
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code Review
|
||||
id: claude-review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
track_progress: true # Enable visual progress tracking
|
||||
allowed_bots: '*'
|
||||
prompt: |
|
||||
Review Basic Memory PR #${{ inputs.pr_number }} as an advisory manual review.
|
||||
|
||||
Use `gh pr view ${{ inputs.pr_number }}` and related `gh pr`/`gh api`
|
||||
commands to inspect the pull request. Do not merge the PR and do not
|
||||
treat this advisory review as the required merge gate. BM Bossbot owns
|
||||
the required `BM Bossbot Approval` status.
|
||||
|
||||
Review the PR against our team checklist:
|
||||
|
||||
## Code Quality & Standards
|
||||
- [ ] Follows Basic Memory's coding conventions in CLAUDE.md
|
||||
- [ ] Python 3.12+ type annotations and async patterns
|
||||
- [ ] SQLAlchemy 2.0 best practices
|
||||
- [ ] FastAPI and Typer conventions followed
|
||||
- [ ] 100-character line length limit maintained
|
||||
- [ ] No commented-out code blocks
|
||||
|
||||
## Testing & Documentation
|
||||
- [ ] Unit tests for new functions/methods
|
||||
- [ ] Integration tests for new MCP tools
|
||||
- [ ] Test coverage for edge cases
|
||||
- [ ] **100% test coverage maintained** (use `# pragma: no cover` only for truly hard-to-test code)
|
||||
- [ ] Documentation updated (README, docstrings)
|
||||
- [ ] CLAUDE.md updated if conventions change
|
||||
|
||||
## Basic Memory Architecture
|
||||
- [ ] MCP tools follow atomic, composable design
|
||||
- [ ] Database changes include Alembic migrations
|
||||
- [ ] Preserves local-first architecture principles
|
||||
- [ ] Knowledge graph operations maintain consistency
|
||||
- [ ] Markdown file handling preserves integrity
|
||||
- [ ] AI-human collaboration patterns followed
|
||||
|
||||
## Security & Performance
|
||||
- [ ] No hardcoded secrets or credentials
|
||||
- [ ] Input validation for MCP tools
|
||||
- [ ] Proper error handling and logging
|
||||
- [ ] Performance considerations addressed
|
||||
- [ ] No sensitive data in logs or commits
|
||||
|
||||
## Compatability
|
||||
- [ ] File path comparisons must be windows compatible
|
||||
- [ ] Avoid using emojis and unicode characters in console and log output
|
||||
|
||||
Read the CLAUDE.md file for detailed project context. For each checklist item, verify if it's satisfied and comment on any that need attention. Use inline comments for specific code issues and post a summary with checklist results.
|
||||
|
||||
# Allow broader tool access for thorough code review
|
||||
claude_args: '--allowed-tools "Bash(gh pr:*),Bash(gh issue:*),Bash(gh api:*),Bash(git log:*),Bash(git show:*),Read,Grep,Glob"'
|
||||
@@ -0,0 +1,74 @@
|
||||
name: Claude Issue Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Issue Triage
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
track_progress: true # Show triage progress
|
||||
prompt: |
|
||||
Analyze this new Basic Memory issue and perform triage:
|
||||
|
||||
**Issue Analysis:**
|
||||
1. **Type Classification:**
|
||||
- Bug report (code defect)
|
||||
- Feature request (new functionality)
|
||||
- Enhancement (improvement to existing feature)
|
||||
- Documentation (docs improvement)
|
||||
- Question/Support (user help)
|
||||
- MCP tool issue (specific to MCP functionality)
|
||||
|
||||
2. **Priority Assessment:**
|
||||
- Critical: Security issues, data loss, complete breakage
|
||||
- High: Major functionality broken, affects many users
|
||||
- Medium: Minor bugs, usability issues
|
||||
- Low: Nice-to-have improvements, cosmetic issues
|
||||
|
||||
3. **Component Classification:**
|
||||
- CLI commands
|
||||
- MCP tools
|
||||
- Database/sync
|
||||
- Cloud functionality
|
||||
- Documentation
|
||||
- Testing
|
||||
|
||||
4. **Complexity Estimate:**
|
||||
- Simple: Quick fix, documentation update
|
||||
- Medium: Requires some investigation/testing
|
||||
- Complex: Major feature work, architectural changes
|
||||
|
||||
**Actions to Take:**
|
||||
1. Add appropriate labels using: `gh issue edit ${{ github.event.issue.number }} --add-label "label1,label2"`
|
||||
2. Check for duplicates using: `gh search issues`
|
||||
3. If duplicate found, comment mentioning the original issue
|
||||
4. For feature requests, ask clarifying questions if needed
|
||||
5. For bugs, request reproduction steps if missing
|
||||
|
||||
**Available Labels:**
|
||||
- Type: bug, enhancement, feature, documentation, question, mcp-tool
|
||||
- Priority: critical, high, medium, low
|
||||
- Component: cli, mcp, database, cloud, docs, testing
|
||||
- Complexity: simple, medium, complex
|
||||
- Status: needs-reproduction, needs-clarification, duplicate
|
||||
|
||||
Read the issue carefully and provide helpful triage with appropriate labels.
|
||||
|
||||
claude_args: '--allowed-tools "Bash(gh issue:*),Bash(gh search:*),Read"'
|
||||
@@ -9,106 +9,62 @@ on:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
pull_request_target:
|
||||
types: [opened, synchronize]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
|
||||
(
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ||
|
||||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.body, '@claude'))
|
||||
) && (
|
||||
github.event.comment.author_association == 'OWNER' ||
|
||||
github.event.comment.author_association == 'MEMBER' ||
|
||||
github.event.comment.author_association == 'COLLABORATOR' ||
|
||||
github.event.sender.author_association == 'OWNER' ||
|
||||
github.event.sender.author_association == 'MEMBER' ||
|
||||
github.event.sender.author_association == 'COLLABORATOR' ||
|
||||
github.event.pull_request.author_association == 'OWNER' ||
|
||||
github.event.pull_request.author_association == 'MEMBER' ||
|
||||
github.event.pull_request.author_association == 'COLLABORATOR'
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
actions: read # Required for Claude to read CI results on PRs
|
||||
steps:
|
||||
- name: Check user permissions
|
||||
id: check_membership
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let actor;
|
||||
if (context.eventName === 'issue_comment') {
|
||||
actor = context.payload.comment.user.login;
|
||||
} else if (context.eventName === 'pull_request_review_comment') {
|
||||
actor = context.payload.comment.user.login;
|
||||
} else if (context.eventName === 'pull_request_review') {
|
||||
actor = context.payload.review.user.login;
|
||||
} else if (context.eventName === 'issues') {
|
||||
actor = context.payload.issue.user.login;
|
||||
}
|
||||
|
||||
console.log(`Checking permissions for user: ${actor}`);
|
||||
|
||||
// List of explicitly allowed users (organization members)
|
||||
const allowedUsers = [
|
||||
'phernandez',
|
||||
'groksrc',
|
||||
'nellins',
|
||||
'bm-claudeai'
|
||||
];
|
||||
|
||||
if (allowedUsers.includes(actor)) {
|
||||
console.log(`User ${actor} is in the allowed list`);
|
||||
core.setOutput('is_member', true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: Check if user has repository permissions
|
||||
try {
|
||||
const collaboration = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username: actor
|
||||
});
|
||||
|
||||
const permission = collaboration.data.permission;
|
||||
console.log(`User ${actor} has permission level: ${permission}`);
|
||||
|
||||
// Allow if user has push access or higher (write, maintain, admin)
|
||||
const allowed = ['write', 'maintain', 'admin'].includes(permission);
|
||||
|
||||
core.setOutput('is_member', allowed);
|
||||
|
||||
if (!allowed) {
|
||||
core.notice(`User ${actor} does not have sufficient repository permissions (has: ${permission})`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Error checking permissions: ${error.message}`);
|
||||
|
||||
// Final fallback: Check if user is a public member of the organization
|
||||
try {
|
||||
const membership = await github.rest.orgs.getMembershipForUser({
|
||||
org: 'basicmachines-co',
|
||||
username: actor
|
||||
});
|
||||
|
||||
const allowed = membership.data.state === 'active';
|
||||
core.setOutput('is_member', allowed);
|
||||
|
||||
if (!allowed) {
|
||||
core.notice(`User ${actor} is not a public member of basicmachines-co organization`);
|
||||
}
|
||||
} catch (membershipError) {
|
||||
console.log(`Error checking organization membership: ${membershipError.message}`);
|
||||
core.setOutput('is_member', false);
|
||||
core.notice(`User ${actor} does not have access to this repository`);
|
||||
}
|
||||
}
|
||||
|
||||
- name: Checkout repository
|
||||
if: steps.check_membership.outputs.is_member == 'true'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# For pull_request_target, checkout the PR head to review the actual changes
|
||||
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
if: steps.check_membership.outputs.is_member == 'true'
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@beta
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
allowed_tools: Bash(uv run pytest),Bash(uv run ruff check . --fix),Bash(uv run ruff format .),Bash(uv run pyright),Bash(just test),Bash(just lint),Bash(just format),Bash(just type-check),Bash(just check),Read,Write,Edit,MultiEdit,Glob,Grep,LS
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
track_progress: true # Enable visual progress tracking
|
||||
|
||||
# This is an optional setting that allows Claude to read CI results on PRs
|
||||
additional_permissions: |
|
||||
actions: read
|
||||
|
||||
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
||||
# prompt: 'Update the pull request description to include a summary of changes.'
|
||||
|
||||
# Optional: Add claude_args to customize behavior and configuration
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
|
||||
# claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
name: Consolidated Packages
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".claude-plugin/**"
|
||||
- "plugins/**"
|
||||
- "skills/**"
|
||||
- "integrations/**"
|
||||
- "scripts/update_versions.py"
|
||||
- "scripts/validate_*.py"
|
||||
- "justfile"
|
||||
- ".github/workflows/consolidated-packages.yml"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".claude-plugin/**"
|
||||
- "plugins/**"
|
||||
- "skills/**"
|
||||
- "integrations/**"
|
||||
- "scripts/update_versions.py"
|
||||
- "scripts/validate_*.py"
|
||||
- "justfile"
|
||||
- ".github/workflows/consolidated-packages.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
claude-code:
|
||||
name: Claude Code marketplace
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Validate manifests, agent, and bundled skills
|
||||
run: just --justfile plugins/claude-code/justfile --working-directory plugins/claude-code ci-check
|
||||
|
||||
- name: Verify shared version dry run
|
||||
run: just release-dry-run v0.99.0
|
||||
|
||||
skills:
|
||||
name: Shared skills
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Validate SKILL.md source
|
||||
run: just --justfile skills/justfile --working-directory skills check
|
||||
|
||||
hermes:
|
||||
name: Hermes unit tests
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: integrations/hermes
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install 3.12
|
||||
|
||||
- name: Validate manifest and run unit tests
|
||||
run: just check
|
||||
|
||||
openclaw:
|
||||
name: OpenClaw package
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: integrations/openclaw
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: "1.3.8"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Release readiness
|
||||
run: just release-check
|
||||
@@ -5,6 +5,9 @@ on:
|
||||
branches: [main]
|
||||
workflow_dispatch: # Allow manual triggering
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
dev-release:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -13,12 +16,12 @@ jobs:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -50,4 +53,4 @@ jobs:
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
skip-existing: true # Don't fail if version already exists
|
||||
skip-existing: true # Don't fail if version already exists
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Docker Image CI
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # Trigger on version tags like v1.0.0, v0.13.0, etc.
|
||||
workflow_dispatch: # Allow manual triggering for testing
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: basicmachines-co/basic-memory
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: depot-ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Depot
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: depot/build-push-action@v1
|
||||
with:
|
||||
project: ${{ vars.DEPOT_BASIC_MEMORY_PROJECT_ID || vars.DEPOT_PROJECT_ID }}
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -7,11 +7,14 @@ on:
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
- uses: amannn/action-semantic-pull-request@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
@@ -35,7 +38,11 @@ jobs:
|
||||
mcp
|
||||
sync
|
||||
ui
|
||||
ci
|
||||
deps
|
||||
installer
|
||||
plugins
|
||||
skills
|
||||
integrations
|
||||
# Allow breaking changes (needs "!" after type/scope)
|
||||
requireScopeForBreakingChange: true
|
||||
requireScopeForBreakingChange: true
|
||||
|
||||
@@ -5,6 +5,9 @@ on:
|
||||
tags:
|
||||
- 'v*' # Trigger on version tags like v1.0.0, v0.13.0, etc.
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -13,12 +16,12 @@ jobs:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -39,7 +42,7 @@ jobs:
|
||||
echo "Build completed successfully"
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: |
|
||||
dist/*.whl
|
||||
@@ -51,4 +54,112 @@ jobs:
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
|
||||
openclaw:
|
||||
name: Publish OpenClaw npm Package
|
||||
needs: release
|
||||
# npm publishes only for stable product tags. Pre-release Python tags use
|
||||
# versions like 0.21.3b1, which are not valid npm pre-release semver.
|
||||
if: ${{ !contains(github.ref_name, 'dev') && !contains(github.ref_name, 'b') && !contains(github.ref_name, 'rc') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: integrations/openclaw
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: "1.3.8"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Release readiness
|
||||
run: just release-check
|
||||
|
||||
- name: Publish to npm
|
||||
run: npm publish --access public --provenance
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
homebrew:
|
||||
name: Update Homebrew Formula
|
||||
needs: release
|
||||
runs-on: ubuntu-latest
|
||||
# Only run for stable releases (not dev, beta, or rc versions)
|
||||
if: ${{ !contains(github.ref_name, 'dev') && !contains(github.ref_name, 'b') && !contains(github.ref_name, 'rc') }}
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
# Inline bump replaces mislav/bump-homebrew-formula-action@v4.x.
|
||||
# The action does a HEAD request to api.github.com /repos/.../tarball/<ref>
|
||||
# with the bearer token and expects a 302 redirect. GitHub now returns
|
||||
# 303 on that endpoint when authenticated, which the action treats as a
|
||||
# fatal error. Re-implementing the bump as plain git+sed keeps the same
|
||||
# contract (update url + sha256, commit, push) with no third-party action.
|
||||
- name: Update Homebrew formula
|
||||
env:
|
||||
HOMEBREW_TOKEN: ${{ secrets.HOMEBREW_TOKEN }}
|
||||
REF: ${{ github.ref_name }}
|
||||
REPO: ${{ github.repository }}
|
||||
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${REF#v}"
|
||||
ARCHIVE_URL="https://github.com/${REPO}/archive/refs/tags/${REF}.tar.gz"
|
||||
|
||||
echo "::group::Compute tarball sha256"
|
||||
SHA256="$(curl --fail --silent --location "$ARCHIVE_URL" | sha256sum | awk '{print $1}')"
|
||||
test -n "$SHA256"
|
||||
echo "sha256: $SHA256"
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Clone tap"
|
||||
git clone \
|
||||
--depth 1 \
|
||||
"https://x-access-token:${HOMEBREW_TOKEN}@github.com/basicmachines-co/homebrew-basic-memory.git" \
|
||||
tap
|
||||
cd tap
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Patch Formula/basic-memory.rb"
|
||||
# Pipe-delimited sed because the URL contains slashes. The Formula
|
||||
# only has one `url` and one `sha256` directive, so a first-match
|
||||
# replacement is unambiguous. POSIX character classes ([[:space:]])
|
||||
# keep this portable across BSD and GNU sed.
|
||||
sed -i -E \
|
||||
-e "s|^([[:space:]]*url[[:space:]]+)\"[^\"]+\"|\1\"${ARCHIVE_URL}\"|" \
|
||||
-e "s|^([[:space:]]*sha256[[:space:]]+)\"[^\"]+\"|\1\"${SHA256}\"|" \
|
||||
Formula/basic-memory.rb
|
||||
git --no-pager diff Formula/basic-memory.rb
|
||||
echo "::endgroup::"
|
||||
|
||||
if git diff --quiet Formula/basic-memory.rb; then
|
||||
echo "Formula already at ${REF}; nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::group::Commit & push"
|
||||
git add Formula/basic-memory.rb
|
||||
git commit -m "basic-memory ${VERSION}
|
||||
|
||||
Created by ${RUN_URL}"
|
||||
git push origin HEAD:main
|
||||
echo "::endgroup::"
|
||||
|
||||
@@ -1,32 +1,87 @@
|
||||
name: Tests
|
||||
|
||||
concurrency:
|
||||
group: bm-ci-${{ github.workflow }}-${{ github.repository }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
# Trigger: PR branch pushes already publish commit statuses that show up on the PR.
|
||||
# Why: running the full matrix on both push and pull_request doubles CI time for the
|
||||
# exact same branch head commit.
|
||||
# Outcome: each branch push runs the test suite once, including PR updates.
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
# pull_request_target runs on the BASE of the PR, not the merge result.
|
||||
# It has write permissions and access to secrets.
|
||||
# It's useful for PRs from forks or automated PRs but requires careful use for security reasons.
|
||||
# See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||
pull_request_target:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
# Required CI records pytest-testmon data but still runs the full selected suite.
|
||||
# The selective mode stays on explicit developer flows such as `just testmon`.
|
||||
BASIC_MEMORY_TESTMON_FLAGS: "--testmon-noselect"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
static-checks:
|
||||
name: Static Checks (Python 3.12)
|
||||
timeout-minutes: 20
|
||||
runs-on: depot-ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
uv venv
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run type checks
|
||||
run: |
|
||||
just typecheck
|
||||
|
||||
- name: Run linting
|
||||
run: |
|
||||
just lint
|
||||
|
||||
test-sqlite-unit:
|
||||
name: Test SQLite Unit (${{ matrix.os }}, Python ${{ matrix.python-version }})
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: [ "3.12" ]
|
||||
include:
|
||||
- os: depot-ubuntu-24.04
|
||||
python-version: "3.12"
|
||||
- os: depot-ubuntu-24.04
|
||||
python-version: "3.13"
|
||||
# Python 3.14 unit tests are the longest full-suite slice; keep this
|
||||
# one on GitHub-hosted runners after Depot terminated it mid-suite.
|
||||
- os: ubuntu-latest
|
||||
python-version: "3.14"
|
||||
- os: windows-latest
|
||||
python-version: "3.12"
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
@@ -35,9 +90,20 @@ jobs:
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- name: Install just
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Cache pytest-testmon results
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.testmondata
|
||||
.testmondata-shm
|
||||
.testmondata-wal
|
||||
key: ${{ runner.os }}-testmon-sqlite-unit-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-testmon-sqlite-unit-py${{ matrix.python-version }}-${{ github.ref_name }}-
|
||||
${{ runner.os }}-testmon-sqlite-unit-py${{ matrix.python-version }}-main-
|
||||
${{ runner.os }}-testmon-sqlite-unit-py${{ matrix.python-version }}-
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
@@ -45,13 +111,259 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e .[dev]
|
||||
|
||||
- name: Run type checks
|
||||
run: |
|
||||
just type-check
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
uv pip install pytest pytest-cov
|
||||
just test
|
||||
just test-unit-sqlite
|
||||
|
||||
test-sqlite-integration:
|
||||
name: Test SQLite Integration (${{ matrix.os }}, Python ${{ matrix.python-version }})
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: depot-ubuntu-24.04
|
||||
python-version: "3.12"
|
||||
- os: depot-ubuntu-24.04
|
||||
python-version: "3.13"
|
||||
- os: depot-ubuntu-24.04
|
||||
python-version: "3.14"
|
||||
- os: windows-latest
|
||||
python-version: "3.12"
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Cache pytest-testmon results
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.testmondata
|
||||
.testmondata-shm
|
||||
.testmondata-wal
|
||||
key: ${{ runner.os }}-testmon-sqlite-integration-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-testmon-sqlite-integration-py${{ matrix.python-version }}-${{ github.ref_name }}-
|
||||
${{ runner.os }}-testmon-sqlite-integration-py${{ matrix.python-version }}-main-
|
||||
${{ runner.os }}-testmon-sqlite-integration-py${{ matrix.python-version }}-
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
uv venv
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
just test-int-sqlite
|
||||
|
||||
test-postgres-unit:
|
||||
name: Test Postgres Unit (Python ${{ matrix.python-version }})
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- python-version: "3.12"
|
||||
os: depot-ubuntu-24.04
|
||||
- python-version: "3.13"
|
||||
os: depot-ubuntu-24.04
|
||||
# Match the SQLite unit slice: this full Python 3.14 path outlived
|
||||
# the Depot runner and was terminated mid-suite.
|
||||
- python-version: "3.14"
|
||||
os: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
env:
|
||||
POSTGRES_USER: basic_memory_user
|
||||
POSTGRES_PASSWORD: dev_password
|
||||
POSTGRES_DB: basic_memory_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U basic_memory_user -d basic_memory_test"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
BASIC_MEMORY_TEST_POSTGRES_URL: postgresql://basic_memory_user:dev_password@127.0.0.1:5432/basic_memory_test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Cache pytest-testmon results
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.testmondata
|
||||
.testmondata-shm
|
||||
.testmondata-wal
|
||||
key: ${{ runner.os }}-testmon-postgres-unit-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-testmon-postgres-unit-py${{ matrix.python-version }}-${{ github.ref_name }}-
|
||||
${{ runner.os }}-testmon-postgres-unit-py${{ matrix.python-version }}-main-
|
||||
${{ runner.os }}-testmon-postgres-unit-py${{ matrix.python-version }}-
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
uv venv
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
just test-unit-postgres
|
||||
|
||||
test-postgres-integration:
|
||||
name: Test Postgres Integration (Python ${{ matrix.python-version }})
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- python-version: "3.12"
|
||||
- python-version: "3.13"
|
||||
- python-version: "3.14"
|
||||
runs-on: depot-ubuntu-24.04
|
||||
services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
env:
|
||||
POSTGRES_USER: basic_memory_user
|
||||
POSTGRES_PASSWORD: dev_password
|
||||
POSTGRES_DB: basic_memory_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U basic_memory_user -d basic_memory_test"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
BASIC_MEMORY_TEST_POSTGRES_URL: postgresql://basic_memory_user:dev_password@127.0.0.1:5432/basic_memory_test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Cache pytest-testmon results
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.testmondata
|
||||
.testmondata-shm
|
||||
.testmondata-wal
|
||||
key: ${{ runner.os }}-testmon-postgres-integration-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-testmon-postgres-integration-py${{ matrix.python-version }}-${{ github.ref_name }}-
|
||||
${{ runner.os }}-testmon-postgres-integration-py${{ matrix.python-version }}-main-
|
||||
${{ runner.os }}-testmon-postgres-integration-py${{ matrix.python-version }}-
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
uv venv
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
just test-int-postgres
|
||||
|
||||
test-semantic:
|
||||
name: Test Semantic (Python 3.12)
|
||||
timeout-minutes: 45
|
||||
runs-on: depot-ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
|
||||
- uses: extractions/setup-just@v4
|
||||
|
||||
- name: Cache pytest-testmon results
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.testmondata
|
||||
.testmondata-shm
|
||||
.testmondata-wal
|
||||
key: ${{ runner.os }}-testmon-semantic-py3.12-${{ github.ref_name }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-testmon-semantic-py3.12-${{ github.ref_name }}-
|
||||
${{ runner.os }}-testmon-semantic-py3.12-main-
|
||||
${{ runner.os }}-testmon-semantic-py3.12-
|
||||
|
||||
- name: Create virtual env
|
||||
run: |
|
||||
uv venv
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
just test-semantic
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
*.py[cod]
|
||||
__pycache__/
|
||||
.pytest_cache/
|
||||
.testmondata*
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
@@ -48,8 +49,19 @@ ENV/
|
||||
/docs/.obsidian/
|
||||
/examples/.obsidian/
|
||||
/examples/.basic-memory/
|
||||
|
||||
/docs/assets
|
||||
|
||||
# claude action
|
||||
claude-output
|
||||
**/.claude/settings.local.json
|
||||
**/.claude/settings.local.json
|
||||
.mcp.json
|
||||
!/plugins/codex/.mcp.json
|
||||
.mcpregistry_*
|
||||
/.testmondata
|
||||
.benchmarks/
|
||||
|
||||
# Consolidated package build artifacts
|
||||
/integrations/openclaw/node_modules/
|
||||
/integrations/openclaw/dist/
|
||||
/integrations/openclaw/skills/
|
||||
/integrations/openclaw/*.tgz
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"--directory",
|
||||
"/Users/phernandez/dev/basicmachines/basic-memory",
|
||||
"run",
|
||||
"src/basic_memory/cli/main.py",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
3.12
|
||||
3.14
|
||||
|
||||
@@ -0,0 +1,540 @@
|
||||
# AGENTS.md - Basic Memory Project Guide
|
||||
|
||||
## Project Overview
|
||||
|
||||
Basic Memory is a local-first knowledge management system built on the Model Context Protocol (MCP). It enables
|
||||
bidirectional communication between LLMs (like Claude) and markdown files, creating a personal knowledge graph that can
|
||||
be traversed using links between documents.
|
||||
|
||||
## CODEBASE DEVELOPMENT
|
||||
|
||||
### Project information
|
||||
|
||||
See the [README.md](README.md) file for a project overview.
|
||||
|
||||
### Build and Test Commands
|
||||
|
||||
- Install: `just install` or `pip install -e ".[dev]"`
|
||||
- Run all tests (SQLite + Postgres): `just test`
|
||||
- Run all tests against SQLite: `just test-sqlite`
|
||||
- Run all tests against Postgres: `just test-postgres` (uses testcontainers)
|
||||
- Run unit tests (SQLite): `just test-unit-sqlite`
|
||||
- Run unit tests (Postgres): `just test-unit-postgres`
|
||||
- Run integration tests (SQLite): `just test-int-sqlite`
|
||||
- Run integration tests (Postgres): `just test-int-postgres`
|
||||
- Run impacted tests: `just testmon` (pytest-testmon; only tests affected by changed code)
|
||||
- Run MCP smoke test: `just test-smoke`
|
||||
- Fast local loop: `just fast-check` (default iteration flow)
|
||||
- Local consistency check: `just doctor`
|
||||
- Run all consolidated agent package checks: `just package-check`
|
||||
- Run Claude Code plugin checks: `just package-check-claude-code`
|
||||
- Run shared skills checks: `just package-check-skills`
|
||||
- Run Hermes plugin checks: `just package-check-hermes`
|
||||
- Run OpenClaw plugin checks: `just package-check-openclaw`
|
||||
- Run host-native agent harness checks: `just agent-harness-check`
|
||||
- Generate HTML coverage: `just coverage`
|
||||
- Single test: `pytest tests/path/to/test_file.py::test_function_name`
|
||||
- Run benchmarks: `pytest test-int/test_sync_performance_benchmark.py -v -m "benchmark and not slow"`
|
||||
- Lint: `just lint` or `ruff check . --fix`
|
||||
- Type check: `just typecheck` or `uv run ty check src tests test-int`
|
||||
- Type check (pyright): `just typecheck-pyright` or `uv run pyright`
|
||||
- Format: `just format` or `uv run ruff format .`
|
||||
- Run all code checks: `just check` (runs lint, format, typecheck, test)
|
||||
- Create db migration: `just migration "Your migration message"`
|
||||
- Run development MCP Inspector: `just run-inspector`
|
||||
|
||||
**Note:** Project requires Python 3.12+ (uses type parameter syntax and `type` aliases introduced in 3.12)
|
||||
|
||||
**Postgres Testing:** Uses [testcontainers](https://testcontainers-python.readthedocs.io/) which automatically spins up a Postgres instance in Docker. No manual database setup required - just have Docker running.
|
||||
|
||||
**Doctor Note:** `just doctor` runs with a temporary HOME/config so it won't touch your local Basic Memory settings. It leaves temp dirs in `/tmp` (safe to ignore or remove).
|
||||
|
||||
**Testmon Note:** When no files have changed, `just testmon` may collect 0 tests. That's expected and means no impacted tests were detected.
|
||||
|
||||
### Code/Test/Verify Loop (fast path)
|
||||
|
||||
1) **Code:** make changes.
|
||||
2) **Test:** `just fast-check` (lint/format/typecheck + pytest-testmon impacted tests for changed code).
|
||||
3) **Verify:** `just doctor` (end-to-end file ↔ DB loop in a temp project).
|
||||
4) **Package verify:** `just package-check` when changes touch `plugins/`, `skills/`, `integrations/`, package metadata, or release wiring.
|
||||
5) **Full gate (when needed):** `just test` or `just check` for SQLite + Postgres.
|
||||
|
||||
Run `just test-smoke` when you specifically need the MCP smoke flow.
|
||||
|
||||
If testmon is “cold,” the first run may be long. Subsequent runs get much faster.
|
||||
|
||||
### Consolidated Agent Package Checks
|
||||
|
||||
The monorepo ships several host-native packages alongside the Python core. Use the root justfile as the canonical entry point:
|
||||
|
||||
- `just package-check` — validates every copied package and generated bundle path.
|
||||
- `just package-check-claude-code` — validates the root and plugin-local Claude marketplace manifests, the SessionStart/PreCompact hooks, the bundled output style, and the seed schemas, then runs `claude plugin validate . --strict`.
|
||||
- `just package-check-skills` — validates every top-level `skills/memory-*/SKILL.md` frontmatter block.
|
||||
- `just package-check-hermes` — validates `integrations/hermes/plugin.yaml`, the Hermes provider entrypoint, bundled skill, and runs the hermetic unit suite.
|
||||
- `just package-check-openclaw` — runs the OpenClaw package install, copies top-level skills into the generated bundle, typechecks, lints, builds `dist/`, runs Bun tests, and performs `npm pack --dry-run`.
|
||||
- `just agent-harness-check` — checks the host-specific harnesses without the shared markdown-only skills target.
|
||||
|
||||
Package-local justfiles live in `plugins/claude-code/`, `skills/`, `integrations/hermes/`, and `integrations/openclaw/`. Prefer the root targets for PR verification so command names stay stable as package internals evolve.
|
||||
|
||||
### PR CI Gate
|
||||
|
||||
Before opening or updating a PR, run the checks that mirror the common required CI failures:
|
||||
|
||||
- Run `just typecheck` in addition to targeted `ruff` and `pytest` commands when tests were added or changed.
|
||||
- Sign commits with `git commit -s` so DCO passes. If a PR branch already has unsigned commits, rewrite the branch with signed-off commits before asking for review.
|
||||
- Use a semantic PR title accepted by `.github/workflows/pr-title.yml`: `type(scope): summary`.
|
||||
- Use one of the allowed scopes: `core`, `cli`, `api`, `mcp`, `sync`, `ui`, `ci`, `deps`, `installer`, `plugins`, `skills`, `integrations`.
|
||||
|
||||
### Test Structure
|
||||
|
||||
- `tests/` - Unit tests for individual components (mocked, fast)
|
||||
- `test-int/` - Integration tests for real-world scenarios (no mocks, realistic)
|
||||
- Both directories are covered by unified coverage reporting
|
||||
- Benchmark tests in `test-int/` are marked with `@pytest.mark.benchmark`
|
||||
- Slow tests are marked with `@pytest.mark.slow`
|
||||
- Smoke tests are marked with `@pytest.mark.smoke`
|
||||
|
||||
### Code Style Guidelines
|
||||
|
||||
- Line length: 100 characters max
|
||||
- Python 3.12+ with full type annotations (uses type parameters and type aliases)
|
||||
- Format with ruff (consistent styling)
|
||||
- Import order: standard lib, third-party, local imports
|
||||
- Naming: snake_case for functions/variables, PascalCase for classes
|
||||
- Prefer async patterns with SQLAlchemy 2.0
|
||||
- Use Pydantic v2 for data validation and schemas
|
||||
- CLI uses Typer for command structure
|
||||
- API uses FastAPI for endpoints
|
||||
- Follow the repository pattern for data access
|
||||
- Tools communicate to api routers via the httpx ASGI client (in process)
|
||||
|
||||
### Programming Style
|
||||
|
||||
See [docs/ENGINEERING_STYLE.md](docs/ENGINEERING_STYLE.md) for the fuller house style. The
|
||||
short version for agents:
|
||||
|
||||
- Prefer type-safe, explicit designs over object-heavy indirection. Use Python 3.12 `type`
|
||||
aliases, full annotations, and narrow `Protocol`s when a caller only needs a capability.
|
||||
- Use dataclasses for internal value objects and operation results; use Pydantic v2 at API,
|
||||
CLI, MCP, and persistence boundaries where validation and serialization matter.
|
||||
- Keep async boundaries obvious. Resource-owning code should use context managers, propagate
|
||||
cancellation, and avoid hidden background work unless the lifecycle is explicit.
|
||||
- Fail fast. Do not add silent fallback logic, broad exception swallowing, speculative
|
||||
`getattr`, or casts that hide an unclear model shape.
|
||||
- Keep control flow simple and local. Push branching decisions up, keep leaf helpers focused,
|
||||
and name values after the domain concept they carry.
|
||||
- Use evidence-first testing. Add or update meaningful regression tests for bugs and risky
|
||||
behavior, prefer real code paths over mocks, and run the narrowest command that proves the
|
||||
change before widening verification.
|
||||
- Comments should explain why a branch, invariant, or constraint exists. Avoid comments that
|
||||
merely narrate obvious code.
|
||||
|
||||
### Code Change Guidelines
|
||||
|
||||
- **Full file read before edits**: Before editing any file, read it in full first to ensure complete context; partial reads lead to corrupted edits
|
||||
- **Minimize diffs**: Prefer the smallest change that satisfies the request. Avoid unrelated refactors or style rewrites unless necessary for correctness
|
||||
- **House style is canonical**: Follow the Programming Style section above for type-safe,
|
||||
fail-fast code; do not hide unclear models with speculative attributes, broad exception
|
||||
handling, casts, or unapproved fallback logic
|
||||
- **No guessing**: Do not say "The issue is..." before you actually know what the issue is. Investigate first.
|
||||
|
||||
### Literate Programming Style
|
||||
|
||||
Code should tell a story. Comments must explain the "why" and narrative flow, not just the "what".
|
||||
|
||||
**Section Headers:**
|
||||
For files with multiple phases of logic, add section headers so the control flow reads like chapters:
|
||||
```python
|
||||
# --- Authentication ---
|
||||
# ... auth logic ...
|
||||
|
||||
# --- Data Validation ---
|
||||
# ... validation logic ...
|
||||
|
||||
# --- Business Logic ---
|
||||
# ... core logic ...
|
||||
```
|
||||
|
||||
**Decision Point Comments:**
|
||||
For conditionals that materially change behavior (gates, fallbacks, retries, feature flags), add comments with:
|
||||
- **Trigger**: what condition causes this branch
|
||||
- **Why**: the rationale (cost, correctness, UX, determinism)
|
||||
- **Outcome**: what changes downstream
|
||||
|
||||
```python
|
||||
# Trigger: project has no active sync watcher
|
||||
# Why: avoid duplicate file system watchers consuming resources
|
||||
# Outcome: starts new watcher, registers in active_watchers dict
|
||||
if project_id not in active_watchers:
|
||||
start_watcher(project_id)
|
||||
```
|
||||
|
||||
**Constraint Comments:**
|
||||
If code exists because of a constraint (async requirements, rate limits, schema compatibility), explain the constraint near the code:
|
||||
```python
|
||||
# SQLite requires WAL mode for concurrent read/write access
|
||||
connection.execute("PRAGMA journal_mode=WAL")
|
||||
```
|
||||
|
||||
**What NOT to Comment:**
|
||||
Avoid comments that restate obvious code:
|
||||
```python
|
||||
# Bad - restates code
|
||||
counter += 1 # increment counter
|
||||
|
||||
# Good - explains why
|
||||
counter += 1 # track retries for backoff calculation
|
||||
```
|
||||
|
||||
### Codebase Architecture
|
||||
|
||||
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed architecture documentation.
|
||||
|
||||
**Directory Structure:**
|
||||
- `/alembic` - Alembic db migrations
|
||||
- `/api` - FastAPI REST endpoints + `container.py` composition root
|
||||
- `/cli` - Typer CLI + `container.py` composition root
|
||||
- `/deps` - Feature-scoped FastAPI dependencies (config, db, projects, repositories, services, importers)
|
||||
- `/importers` - Import functionality for Claude, ChatGPT, and other sources
|
||||
- `/markdown` - Markdown parsing and processing
|
||||
- `/mcp` - MCP server + `container.py` composition root + `clients/` typed API clients
|
||||
- `/models` - SQLAlchemy ORM models
|
||||
- `/repository` - Data access layer
|
||||
- `/schemas` - Pydantic models for validation
|
||||
- `/services` - Business logic layer
|
||||
- `/sync` - File synchronization services + `coordinator.py` for lifecycle management
|
||||
- `/plugins/claude-code` - Claude Code plugin marketplace package, hooks, skills, and agent harness
|
||||
- `/skills` - Canonical framework-agnostic Basic Memory `SKILL.md` source
|
||||
- `/integrations/hermes` - Hermes memory-provider plugin
|
||||
- `/integrations/openclaw` - OpenClaw npm/TypeScript plugin
|
||||
|
||||
**Composition Roots:**
|
||||
Each entrypoint (API, MCP, CLI) has a composition root that:
|
||||
- Reads `ConfigManager` (the only place that reads global config)
|
||||
- Resolves runtime mode via `RuntimeMode` enum (TEST > CLOUD > LOCAL)
|
||||
- Provides dependencies to downstream code explicitly
|
||||
|
||||
**Typed API Clients (MCP):**
|
||||
MCP tools use typed clients in `mcp/clients/` to communicate with the API:
|
||||
- `KnowledgeClient` - Entity CRUD operations
|
||||
- `SearchClient` - Search operations
|
||||
- `MemoryClient` - Context building
|
||||
- `DirectoryClient` - Directory listing
|
||||
- `ResourceClient` - Resource reading
|
||||
- `ProjectClient` - Project management
|
||||
|
||||
Flow: MCP Tool → Typed Client → HTTP API → Router → Service → Repository
|
||||
|
||||
### Development Notes
|
||||
|
||||
- MCP tools are defined in src/basic_memory/mcp/tools/
|
||||
- MCP prompts are defined in src/basic_memory/mcp/prompts/
|
||||
- MCP tools should be atomic, composable operations
|
||||
- Use `textwrap.dedent()` for multi-line string formatting in prompts and tools
|
||||
- MCP Prompts are used to invoke tools and format content with instructions for an LLM
|
||||
- Schema changes require Alembic migrations
|
||||
- SQLite is used for indexing and full text search, files are source of truth
|
||||
- Testing uses pytest with asyncio support (strict mode)
|
||||
- Unit tests (`tests/`) use mocks when necessary; integration tests (`test-int/`) use real implementations
|
||||
- By default, tests run against SQLite (fast, no Docker needed)
|
||||
- Set `BASIC_MEMORY_TEST_POSTGRES=1` to run against Postgres (uses testcontainers - Docker required)
|
||||
- Each test runs in a standalone environment with isolated database and tmp_path directory
|
||||
- CI runs SQLite and Postgres tests in parallel for faster feedback
|
||||
- Performance benchmarks are in `test-int/test_sync_performance_benchmark.py`
|
||||
- Use pytest markers: `@pytest.mark.benchmark` for benchmarks, `@pytest.mark.slow` for slow tests
|
||||
- **Coverage must stay at 100%**: Write tests for new code. Only use `# pragma: no cover` when tests would require excessive mocking (e.g., TYPE_CHECKING blocks, error handlers that need failure injection, runtime-mode-dependent code paths)
|
||||
|
||||
### Async Client Pattern (Important!)
|
||||
|
||||
**MCP tools use `get_project_client()` for per-project routing:**
|
||||
|
||||
```python
|
||||
from basic_memory.mcp.project_context import get_project_client
|
||||
|
||||
@mcp.tool()
|
||||
async def my_tool(project: str | None = None, context: Context | None = None):
|
||||
async with get_project_client(project, context) as (client, active_project):
|
||||
# client is routed based on project's mode (local ASGI or cloud HTTP)
|
||||
response = await call_get(client, "/path")
|
||||
return response
|
||||
```
|
||||
|
||||
**CLI commands and non-project-scoped code use `get_client()` directly:**
|
||||
|
||||
```python
|
||||
from basic_memory.mcp.async_client import get_client
|
||||
|
||||
async def my_cli_command():
|
||||
async with get_client() as client:
|
||||
response = await call_get(client, "/path")
|
||||
return response
|
||||
|
||||
# Per-project routing (when project name is known):
|
||||
async with get_client(project_name="research") as client:
|
||||
...
|
||||
```
|
||||
|
||||
**Do NOT use:**
|
||||
- ❌ `from basic_memory.mcp.async_client import client` (deprecated module-level client)
|
||||
- ❌ Manual auth header management
|
||||
- ❌ `inject_auth_header()` (deleted)
|
||||
- ❌ Separate `get_client()` + `get_active_project()` in MCP tools (use `get_project_client()` instead)
|
||||
|
||||
**Key principles:**
|
||||
- Auth happens at client creation, not per-request
|
||||
- Proper resource management via context managers
|
||||
- Per-project routing: each project can be LOCAL or CLOUD independently
|
||||
- Cloud projects use API key (`cloud_api_key` in config) as Bearer token
|
||||
- Routing priority: factory injection > force-local > per-project cloud > global cloud > local ASGI
|
||||
- Factory pattern enables dependency injection for cloud consolidation
|
||||
|
||||
**For cloud app integration:**
|
||||
```python
|
||||
from basic_memory.mcp import async_client
|
||||
|
||||
# Set custom factory before importing tools
|
||||
async_client.set_client_factory(your_custom_factory)
|
||||
```
|
||||
|
||||
See SPEC-16 for full context manager refactor details.
|
||||
|
||||
### Release Process
|
||||
|
||||
Releases are driven by `just release` / `just beta` — never by a bare `git tag`. The recipes bump version metadata, run pre-flight checks, commit, tag, and push. GitHub Actions then publishes to PyPI and updates the Homebrew formula.
|
||||
|
||||
**Stable release:**
|
||||
|
||||
```
|
||||
just release v0.21.3
|
||||
```
|
||||
|
||||
The recipe runs `just lint` + `just typecheck`, then updates every release manifest through `scripts/update_versions.py`: `src/basic_memory/__init__.py`, `server.json`, the root Claude marketplace, the Claude Code plugin manifest and local marketplace, the Hermes `plugin.yaml`, and the OpenClaw `package.json`. It commits as `chore: update version to X.Y.Z for vX.Y.Z release`, creates the `vX.Y.Z` tag, and pushes both the commit and the tag to `origin/main`. After the tag lands, the `Release` workflow builds the Python package, publishes to PyPI, creates the GitHub release with auto-generated notes, publishes the OpenClaw npm package, and updates the Homebrew formula. The recipe finishes by printing the post-release tasks the workflow doesn't cover.
|
||||
|
||||
**Beta release:** `just beta v0.21.3b1` — same flow with a beta-suffixed tag. PyPI consumers install with `pip install basic-memory --pre`.
|
||||
|
||||
**Release dry run:** `just release-dry-run v0.21.4` previews the consolidated version update without writing files.
|
||||
|
||||
**Development builds:** every commit to `main` publishes a `0.21.3.dev26+468a22f`-style version to PyPI automatically via `.github/workflows/dev-release.yml`. No human action.
|
||||
|
||||
**Do not tag releases by hand.** A bare `git tag vX.Y.Z` skips the in-code version bump. Package metadata is still correct (uv-dynamic-versioning derives it from the git tag) but `basic-memory --version` reports the previous release, which is what happened with v0.21.2 → v0.21.3.
|
||||
|
||||
**Post-release tasks** the recipe surfaces but doesn't run:
|
||||
- `docs.basicmemory.com` — add notes to `src/pages/latest-releases.mdx`
|
||||
- `basicmachines.co` — bump version in `src/components/sections/hero.tsx`
|
||||
- MCP Registry — `mcp-publisher publish` from the repo root
|
||||
|
||||
See `.claude/commands/release/release.md` (and `beta.md`, `release-check.md`, `changelog.md` alongside it) for the full release + post-release runbook, including the slash commands.
|
||||
|
||||
## BASIC MEMORY PRODUCT USAGE
|
||||
|
||||
### Knowledge Structure
|
||||
|
||||
- Entity: Any concept, document, or idea represented as a markdown file
|
||||
- Observation: A categorized fact about an entity (`- [category] content`)
|
||||
- Relation: A directional link between entities (`- relation_type [[Target]]`)
|
||||
- Frontmatter: YAML metadata at the top of markdown files
|
||||
- Knowledge representation follows precise markdown format:
|
||||
- Observations with [category] prefixes
|
||||
- Relations with WikiLinks [[Entity]]
|
||||
- Frontmatter with metadata
|
||||
|
||||
### Basic Memory Commands
|
||||
|
||||
**Local Commands:**
|
||||
- Check sync status: `basic-memory status`
|
||||
- Doctor check (file <-> DB loop): `basic-memory doctor`
|
||||
- Import from Claude: `basic-memory import claude conversations`
|
||||
- Import from ChatGPT: `basic-memory import chatgpt`
|
||||
- Import from Memory JSON: `basic-memory import memory-json`
|
||||
- Tool access: `basic-memory tool` (provides CLI access to MCP tools)
|
||||
- Continue: `basic-memory tool continue-conversation --topic="search"`
|
||||
|
||||
**Project Management:**
|
||||
- List projects: `basic-memory project list`
|
||||
- Add project: `basic-memory project add "name" ~/path`
|
||||
- Project info: `basic-memory project info`
|
||||
- Set cloud mode: `basic-memory project set-cloud "name"`
|
||||
- Set local mode: `basic-memory project set-local "name"`
|
||||
- One-way sync (local -> cloud): `basic-memory project sync`
|
||||
- Bidirectional sync: `basic-memory project bisync`
|
||||
- Integrity check: `basic-memory project check`
|
||||
|
||||
**Cloud Commands (requires subscription):**
|
||||
- Authenticate (global): `basic-memory cloud login`
|
||||
- Logout (global): `basic-memory cloud logout`
|
||||
- Check cloud status: `basic-memory cloud status`
|
||||
- Setup cloud sync: `basic-memory cloud setup`
|
||||
- Save API key: `basic-memory cloud set-key bmc_...`
|
||||
- Create API key: `basic-memory cloud create-key "name"`
|
||||
- Manage snapshots: `basic-memory cloud snapshot [create|list|delete|show|browse]`
|
||||
- Restore from snapshot: `basic-memory cloud restore <path> --snapshot <id>`
|
||||
|
||||
**Cloud Sync Commands (Personal and Team workspaces):**
|
||||
- Fetch cloud changes (cloud -> local): `basic-memory cloud pull --name "name"` (Team-safe; additive, never deletes local)
|
||||
- Upload local changes (local -> cloud): `basic-memory cloud push --name "name"` (Team-safe; additive, never deletes cloud)
|
||||
- Resolve conflicts on push/pull: `--on-conflict [fail|keep-local|keep-cloud|keep-both]` (default `fail` lists conflicts and aborts, git-style)
|
||||
- One-way mirror (local -> cloud): `basic-memory cloud sync --name "name"` (Personal workspaces only; deletes cloud files missing locally)
|
||||
- Two-way mirror (local <-> cloud): `basic-memory cloud bisync --name "name"` (Personal workspaces only)
|
||||
|
||||
### MCP Capabilities
|
||||
|
||||
- Basic Memory exposes these MCP tools to LLMs:
|
||||
|
||||
**Content Management:**
|
||||
- `write_note(title, content, directory, tags)` - Create/update markdown notes with semantic observations and relations
|
||||
- `read_note(identifier, page, page_size)` - Read notes by title, permalink, or memory:// URL with knowledge graph awareness
|
||||
- `read_content(path)` - Read raw file content (text, images, binaries) without knowledge graph processing
|
||||
- `view_note(identifier, page, page_size)` - View notes as formatted artifacts for better readability
|
||||
- `edit_note(identifier, operation, content)` - Edit notes incrementally (append, prepend, find/replace, replace_section)
|
||||
- `move_note(identifier, destination_path, is_directory)` - Move notes or directories to new locations, updating database and maintaining links
|
||||
- `delete_note(identifier, is_directory)` - Delete notes or directories from the knowledge base
|
||||
|
||||
**Knowledge Graph Navigation:**
|
||||
- `build_context(url, depth, timeframe)` - Navigate the knowledge graph via memory:// URLs for conversation continuity
|
||||
- `recent_activity(type, depth, timeframe)` - Get recently updated information with specified timeframe (e.g., "1d", "1 week")
|
||||
- `list_directory(dir_name, depth, file_name_glob)` - Browse directory contents with filtering and depth control
|
||||
|
||||
**Search & Discovery:**
|
||||
- `search_notes(query, page, page_size, search_type, types, entity_types, after_date)` - Full-text search across all content with advanced filtering options
|
||||
|
||||
**Project Management:**
|
||||
- `list_memory_projects()` - List all available projects with their status
|
||||
- `create_memory_project(project_name, project_path, set_default)` - Create new Basic Memory projects
|
||||
- `delete_project(project_name)` - Delete a project from configuration
|
||||
|
||||
**Visualization:**
|
||||
- `canvas(nodes, edges, title, directory)` - Generate Obsidian canvas files for knowledge graph visualization
|
||||
|
||||
**ChatGPT-Compatible Tools:**
|
||||
- `search(query)` - Search across knowledge base (OpenAI actions compatible)
|
||||
- `fetch(id)` - Fetch full content of a search result document
|
||||
|
||||
- MCP Prompts for better AI interaction:
|
||||
- `ai_assistant_guide()` - Guidance on effectively using Basic Memory tools for AI assistants
|
||||
- `continue_conversation(topic, timeframe)` - Continue previous conversations with relevant historical context
|
||||
- `search(query, after_date)` - Search with detailed, formatted results for better context understanding
|
||||
- `recent_activity(timeframe)` - View recently changed items with formatted output
|
||||
|
||||
### Cloud Features (v0.15.0+)
|
||||
|
||||
Basic Memory now supports cloud synchronization and storage (requires active subscription):
|
||||
|
||||
**Authentication:**
|
||||
- JWT-based authentication with subscription validation
|
||||
- Secure session management with token refresh
|
||||
- Support for multiple cloud projects
|
||||
|
||||
**Bidirectional Sync:**
|
||||
- rclone bisync integration for two-way synchronization
|
||||
- Conflict resolution and integrity verification
|
||||
- Real-time sync with change detection
|
||||
- Mount/unmount cloud storage for direct file access
|
||||
|
||||
**Cloud Project Management:**
|
||||
- Create and manage projects in the cloud
|
||||
- Toggle between local and cloud modes
|
||||
- Per-project sync configuration
|
||||
- Subscription-based access control
|
||||
|
||||
**Security & Performance:**
|
||||
- Removed .env file loading for improved security
|
||||
- .gitignore integration (respects gitignored files)
|
||||
- WAL mode for SQLite performance
|
||||
- Background relation resolution (non-blocking startup)
|
||||
- API performance optimizations (SPEC-11)
|
||||
|
||||
**Per-Project Cloud Routing:**
|
||||
|
||||
Individual projects can be routed through the cloud while others stay local, using an API key:
|
||||
|
||||
```bash
|
||||
# Save API key and set project to cloud mode
|
||||
basic-memory cloud set-key bmc_abc123...
|
||||
basic-memory project set-cloud research # route through cloud
|
||||
basic-memory project set-local research # revert to local
|
||||
```
|
||||
|
||||
MCP tools use `get_project_client()` which automatically routes based on the project's mode. Cloud projects use the `cloud_api_key` from config as Bearer token.
|
||||
|
||||
**CLI Routing Flags (Global Cloud Mode):**
|
||||
|
||||
When global cloud mode is enabled, CLI commands route to the cloud API by default. Use `--local` and `--cloud` flags to override:
|
||||
|
||||
```bash
|
||||
# Force local routing (ignore cloud mode)
|
||||
basic-memory status --local
|
||||
basic-memory project list --local
|
||||
|
||||
# Force cloud routing (when cloud mode is disabled)
|
||||
basic-memory status --cloud
|
||||
basic-memory project info my-project --cloud
|
||||
```
|
||||
|
||||
Key behaviors:
|
||||
- The local MCP server (`basic-memory mcp`) automatically uses local routing
|
||||
- This allows simultaneous use of local Claude Desktop and cloud-based clients
|
||||
- Some commands (like `project default`, `project sync-config`, `project move`) require `--local` in cloud mode since they modify local configuration
|
||||
- Environment variable `BASIC_MEMORY_FORCE_LOCAL=true` forces local routing globally
|
||||
- Per-project cloud routing via API key works independently of global cloud mode
|
||||
|
||||
## AI-Human Collaborative Development
|
||||
|
||||
Basic Memory emerged from and enables a new kind of development process that combines human and AI capabilities. Instead
|
||||
of using AI just for code generation, we've developed a true collaborative workflow:
|
||||
|
||||
1. AI (LLM) writes initial implementation based on specifications and context
|
||||
2. Human reviews, runs tests, and commits code with any necessary adjustments
|
||||
3. Knowledge persists across conversations using Basic Memory's knowledge graph
|
||||
4. Development continues seamlessly across different AI sessions with consistent context
|
||||
5. Results improve through iterative collaboration and shared understanding
|
||||
|
||||
This approach has allowed us to tackle more complex challenges and build a more robust system than either humans or AI
|
||||
could achieve independently.
|
||||
|
||||
**Problem-Solving Guidance:**
|
||||
- If a solution isn't working after reasonable effort, suggest alternative approaches
|
||||
- Don't persist with a problematic library or pattern when better alternatives exist
|
||||
- Example: When py-pglite caused cascading test failures, switching to testcontainers-postgres was the right call
|
||||
|
||||
## GitHub Integration
|
||||
|
||||
Basic Memory has taken AI-Human collaboration to the next level by integrating Claude directly into the development workflow through GitHub:
|
||||
|
||||
### GitHub MCP Tools
|
||||
|
||||
Using the GitHub Model Context Protocol server, Claude can now:
|
||||
|
||||
- **Repository Management**:
|
||||
- View repository files and structure
|
||||
- Read file contents
|
||||
- Create new branches
|
||||
- Create and update files
|
||||
|
||||
- **Issue Management**:
|
||||
- Create new issues
|
||||
- Comment on existing issues
|
||||
- Close and update issues
|
||||
- Search across issues
|
||||
|
||||
- **Pull Request Workflow**:
|
||||
- Create pull requests
|
||||
- Review code changes
|
||||
- Add comments to PRs
|
||||
|
||||
This integration enables Claude to participate as a full team member in the development process, not just as a code generation tool. Claude's GitHub account ([bm-claudeai](https://github.com/bm-claudeai)) is a member of the Basic Machines organization with direct contributor access to the codebase.
|
||||
|
||||
### Collaborative Development Process
|
||||
|
||||
With GitHub integration, the development workflow includes:
|
||||
|
||||
1. **Direct code review** - Claude can analyze PRs and provide detailed feedback
|
||||
2. **Contribution tracking** - All of Claude's contributions are properly attributed in the Git history
|
||||
3. **Branch management** - Claude can create feature branches for implementations
|
||||
4. **Documentation maintenance** - Claude can keep documentation updated as the code evolves
|
||||
5. **Code Commits**: ALWAYS sign off commits with `git commit -s`
|
||||
6. **Pull Request Titles**: PR titles must follow the semantic format enforced by `.github/workflows/pr-title.yml`: `type(scope): summary`
|
||||
- Allowed types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`
|
||||
- Allowed scopes: `core`, `cli`, `api`, `mcp`, `sync`, `ui`, `ci`, `deps`, `installer`, `plugins`, `skills`, `integrations`
|
||||
- Example: `fix(cli): propagate cloud workspace routing`
|
||||
|
||||
This level of integration represents a new paradigm in AI-human collaboration, where the AI assistant becomes a full-fledged team member rather than just a tool for generating code snippets.
|
||||
@@ -1,42 +0,0 @@
|
||||
# OAuth Quick Start
|
||||
|
||||
Basic Memory supports OAuth authentication for secure access control. For detailed documentation, see [OAuth Authentication Guide](docs/OAuth%20Authentication%20Guide.md).
|
||||
|
||||
## Quick Test with MCP Inspector
|
||||
|
||||
```bash
|
||||
# 1. Set a consistent secret key
|
||||
export FASTMCP_AUTH_SECRET_KEY="test-secret-key"
|
||||
|
||||
# 2. Start server with OAuth
|
||||
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
|
||||
|
||||
# 3. In another terminal, get a test token
|
||||
export FASTMCP_AUTH_SECRET_KEY="test-secret-key" # Same key!
|
||||
basic-memory auth test-auth
|
||||
|
||||
# 4. Copy the access token and use in MCP Inspector:
|
||||
# - Server URL: http://localhost:8000/mcp
|
||||
# - Transport: streamable-http
|
||||
# - Custom Headers:
|
||||
# Authorization: Bearer YOUR_ACCESS_TOKEN
|
||||
# Accept: application/json, text/event-stream
|
||||
```
|
||||
|
||||
## OAuth Endpoints
|
||||
|
||||
- `GET /authorize` - Authorization endpoint
|
||||
- `POST /token` - Token exchange endpoint
|
||||
- `GET /.well-known/oauth-authorization-server` - OAuth metadata
|
||||
|
||||
## Common Issues
|
||||
|
||||
1. **401 Unauthorized**: Make sure you're using the same secret key for both server and client
|
||||
2. **404 Not Found**: Use `/authorize` not `/auth/authorize`
|
||||
3. **Token Invalid**: Tokens don't persist across server restarts with basic provider
|
||||
|
||||
## Documentation
|
||||
|
||||
- [OAuth Authentication Guide](docs/OAuth%20Authentication%20Guide.md) - Complete setup guide
|
||||
- [Supabase OAuth Setup](docs/Supabase%20OAuth%20Setup.md) - Production deployment
|
||||
- [External OAuth Providers](docs/External%20OAuth%20Providers.md) - GitHub, Google integration
|
||||
@@ -1,34 +1,71 @@
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
https://developercertificate.org/
|
||||
# Contributor License Agreement
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
## Copyright Assignment and License Grant
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
By signing this Contributor License Agreement ("Agreement"), you accept and agree to the following terms and conditions
|
||||
for your present and future Contributions submitted
|
||||
to Basic Machines LLC. Except for the license granted herein to Basic Machines LLC and recipients of software
|
||||
distributed by Basic Machines LLC, you reserve all right,
|
||||
title, and interest in and to your Contributions.
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
### 1. Definitions
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this
|
||||
Agreement with Basic Machines LLC.
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work,
|
||||
that is intentionally submitted by You to Basic
|
||||
Machines LLC for inclusion in, or documentation of, any of the products owned or managed by Basic Machines LLC (the "
|
||||
Work").
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
### 2. Grant of Copyright License
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
Subject to the terms and conditions of this Agreement, You hereby grant to Basic Machines LLC and to recipients of
|
||||
software distributed by Basic Machines LLC a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the
|
||||
Work, and to permit persons to whom the Work is furnished to do so.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
### 3. Assignment of Copyright
|
||||
|
||||
You hereby assign to Basic Machines LLC all right, title, and interest worldwide in all Copyright covering your
|
||||
Contributions. Basic Machines LLC may license the
|
||||
Contributions under any license terms, including copyleft, permissive, commercial, or proprietary licenses.
|
||||
|
||||
### 4. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this Agreement, You hereby grant to Basic Machines LLC and to recipients of
|
||||
software distributed by Basic Machines LLC a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to
|
||||
make, have made, use, offer to sell, sell, import, and
|
||||
otherwise transfer the Work.
|
||||
|
||||
### 5. Developer Certificate of Origin
|
||||
|
||||
By making a Contribution to this project, You certify that:
|
||||
|
||||
(a) The Contribution was created in whole or in part by You and You have the right to submit it under this Agreement; or
|
||||
|
||||
(b) The Contribution is based upon previous work that, to the best of Your knowledge, is covered under an appropriate
|
||||
open source license and You have the right under that
|
||||
license to submit that work with modifications, whether created in whole or in part by You, under this Agreement; or
|
||||
|
||||
(c) The Contribution was provided directly to You by some other person who certified (a), (b) or (c) and You have not
|
||||
modified it.
|
||||
|
||||
(d) You understand and agree that this project and the Contribution are public and that a record of the Contribution (
|
||||
including all personal information You submit with
|
||||
it, including Your sign-off) is maintained indefinitely and may be redistributed consistent with this project or the
|
||||
open source license(s) involved.
|
||||
|
||||
### 6. Representations
|
||||
|
||||
You represent that you are legally entitled to grant the above license and assignment. If your employer(s) has rights to
|
||||
intellectual property that you create that
|
||||
includes your Contributions, you represent that you have received permission to make Contributions on behalf of that
|
||||
employer, or that your employer has waived such rights
|
||||
for your Contributions to Basic Machines LLC.
|
||||
|
||||
---
|
||||
|
||||
This Agreement is effective as of the date you first submit a Contribution to Basic Machines LLC.
|
||||
|
||||
@@ -1,246 +0,0 @@
|
||||
# CLAUDE.md - Basic Memory Project Guide
|
||||
|
||||
## Project Overview
|
||||
|
||||
Basic Memory is a local-first knowledge management system built on the Model Context Protocol (MCP). It enables
|
||||
bidirectional communication between LLMs (like Claude) and markdown files, creating a personal knowledge graph that can
|
||||
be traversed using links between documents.
|
||||
|
||||
## CODEBASE DEVELOPMENT
|
||||
|
||||
### Project information
|
||||
|
||||
See the [README.md](README.md) file for a project overview.
|
||||
|
||||
### Build and Test Commands
|
||||
|
||||
- Install: `just install` or `pip install -e ".[dev]"`
|
||||
- Run tests: `uv run pytest -p pytest_mock -v` or `just test`
|
||||
- Single test: `pytest tests/path/to/test_file.py::test_function_name`
|
||||
- Lint: `just lint` or `ruff check . --fix`
|
||||
- Type check: `just type-check` or `uv run pyright`
|
||||
- Format: `just format` or `uv run ruff format .`
|
||||
- Run all code checks: `just check` (runs lint, format, type-check, test)
|
||||
- Create db migration: `just migration "Your migration message"`
|
||||
- Run development MCP Inspector: `just run-inspector`
|
||||
|
||||
### Code Style Guidelines
|
||||
|
||||
- Line length: 100 characters max
|
||||
- Python 3.12+ with full type annotations
|
||||
- Format with ruff (consistent styling)
|
||||
- Import order: standard lib, third-party, local imports
|
||||
- Naming: snake_case for functions/variables, PascalCase for classes
|
||||
- Prefer async patterns with SQLAlchemy 2.0
|
||||
- Use Pydantic v2 for data validation and schemas
|
||||
- CLI uses Typer for command structure
|
||||
- API uses FastAPI for endpoints
|
||||
- Follow the repository pattern for data access
|
||||
- Tools communicate to api routers via the httpx ASGI client (in process)
|
||||
- avoid using "private" functions in modules or classes (prepended with _)
|
||||
|
||||
### Codebase Architecture
|
||||
|
||||
- `/alembic` - Alembic db migrations
|
||||
- `/api` - FastAPI implementation of REST endpoints
|
||||
- `/cli` - Typer command-line interface
|
||||
- `/markdown` - Markdown parsing and processing
|
||||
- `/mcp` - Model Context Protocol server implementation
|
||||
- `/models` - SQLAlchemy ORM models
|
||||
- `/repository` - Data access layer
|
||||
- `/schemas` - Pydantic models for validation
|
||||
- `/services` - Business logic layer
|
||||
- `/sync` - File synchronization services
|
||||
|
||||
### Development Notes
|
||||
|
||||
- MCP tools are defined in src/basic_memory/mcp/tools/
|
||||
- MCP prompts are defined in src/basic_memory/mcp/prompts/
|
||||
- MCP tools should be atomic, composable operations
|
||||
- Use `textwrap.dedent()` for multi-line string formatting in prompts and tools
|
||||
- MCP Prompts are used to invoke tools and format content with instructions for an LLM
|
||||
- Schema changes require Alembic migrations
|
||||
- SQLite is used for indexing and full text search, files are source of truth
|
||||
- Testing uses pytest with asyncio support (strict mode)
|
||||
- Test database uses in-memory SQLite
|
||||
- Avoid creating mocks in tests in most circumstances.
|
||||
- Each test runs in a standalone environment with in memory SQLite and tmp_file directory
|
||||
- Do not use mocks in tests if possible. Tests run with an in memory sqlite db, so they are not needed. See fixtures in conftest.py
|
||||
|
||||
## BASIC MEMORY PRODUCT USAGE
|
||||
|
||||
### Knowledge Structure
|
||||
|
||||
- Entity: Any concept, document, or idea represented as a markdown file
|
||||
- Observation: A categorized fact about an entity (`- [category] content`)
|
||||
- Relation: A directional link between entities (`- relation_type [[Target]]`)
|
||||
- Frontmatter: YAML metadata at the top of markdown files
|
||||
- Knowledge representation follows precise markdown format:
|
||||
- Observations with [category] prefixes
|
||||
- Relations with WikiLinks [[Entity]]
|
||||
- Frontmatter with metadata
|
||||
|
||||
### Basic Memory Commands
|
||||
|
||||
- Sync knowledge: `basic-memory sync` or `basic-memory sync --watch`
|
||||
- Import from Claude: `basic-memory import claude conversations`
|
||||
- Import from ChatGPT: `basic-memory import chatgpt`
|
||||
- Import from Memory JSON: `basic-memory import memory-json`
|
||||
- Check sync status: `basic-memory status`
|
||||
- Tool access: `basic-memory tools` (provides CLI access to MCP tools)
|
||||
- Guide: `basic-memory tools basic-memory-guide`
|
||||
- Continue: `basic-memory tools continue-conversation --topic="search"`
|
||||
|
||||
### MCP Capabilities
|
||||
|
||||
- Basic Memory exposes these MCP tools to LLMs:
|
||||
|
||||
**Content Management:**
|
||||
- `write_note(title, content, folder, tags)` - Create/update markdown notes with semantic observations and relations
|
||||
- `read_note(identifier, page, page_size)` - Read notes by title, permalink, or memory:// URL with knowledge graph awareness
|
||||
- `edit_note(identifier, operation, content)` - Edit notes incrementally (append, prepend, find/replace, section replace)
|
||||
- `move_note(identifier, destination_path)` - Move notes with database consistency and search reindexing
|
||||
- `view_note(identifier)` - Display notes as formatted artifacts for better readability in Claude Desktop
|
||||
- `read_content(path)` - Read raw file content (text, images, binaries) without knowledge graph processing
|
||||
- `delete_note(identifier)` - Delete notes from knowledge base
|
||||
|
||||
**Project Management:**
|
||||
- `list_memory_projects()` - List all available projects with status indicators
|
||||
- `switch_project(project_name)` - Switch to different project context during conversations
|
||||
- `get_current_project()` - Show currently active project with statistics
|
||||
- `create_memory_project(name, path, set_default)` - Create new Basic Memory projects
|
||||
- `delete_project(name)` - Delete projects from configuration and database
|
||||
- `set_default_project(name)` - Set default project in config
|
||||
- `sync_status()` - Check file synchronization status and background operations
|
||||
|
||||
**Knowledge Graph Navigation:**
|
||||
- `build_context(url, depth, timeframe)` - Navigate the knowledge graph via memory:// URLs for conversation continuity
|
||||
- `recent_activity(type, depth, timeframe)` - Get recently updated information with specified timeframe (e.g., "1d", "1 week")
|
||||
- `list_directory(dir_name, depth, file_name_glob)` - List directory contents with filtering and depth control
|
||||
|
||||
**Search & Discovery:**
|
||||
- `search_notes(query, page, page_size)` - Full-text search across all content with filtering options
|
||||
|
||||
**Visualization:**
|
||||
- `canvas(nodes, edges, title, folder)` - Generate Obsidian canvas files for knowledge graph visualization
|
||||
|
||||
- MCP Prompts for better AI interaction:
|
||||
- `ai_assistant_guide()` - Guidance on effectively using Basic Memory tools for AI assistants
|
||||
- `continue_conversation(topic, timeframe)` - Continue previous conversations with relevant historical context
|
||||
- `search_notes(query, after_date)` - Search with detailed, formatted results for better context understanding
|
||||
- `recent_activity(timeframe)` - View recently changed items with formatted output
|
||||
- `json_canvas_spec()` - Full JSON Canvas specification for Obsidian visualization
|
||||
|
||||
## AI-Human Collaborative Development
|
||||
|
||||
Basic Memory emerged from and enables a new kind of development process that combines human and AI capabilities. Instead
|
||||
of using AI just for code generation, we've developed a true collaborative workflow:
|
||||
|
||||
1. AI (LLM) writes initial implementation based on specifications and context
|
||||
2. Human reviews, runs tests, and commits code with any necessary adjustments
|
||||
3. Knowledge persists across conversations using Basic Memory's knowledge graph
|
||||
4. Development continues seamlessly across different AI sessions with consistent context
|
||||
5. Results improve through iterative collaboration and shared understanding
|
||||
|
||||
This approach has allowed us to tackle more complex challenges and build a more robust system than either humans or AI
|
||||
could achieve independently.
|
||||
|
||||
## GitHub Integration
|
||||
|
||||
Basic Memory uses Claude directly into the development workflow through GitHub:
|
||||
|
||||
### GitHub MCP Tools
|
||||
|
||||
Using the GitHub Model Context Protocol server, Claude can:
|
||||
|
||||
- **Repository Management**:
|
||||
- View repository files and structure
|
||||
- Read file contents
|
||||
- Create new branches
|
||||
- Create and update files
|
||||
|
||||
- **Issue Management**:
|
||||
- Create new issues
|
||||
- Comment on existing issues
|
||||
- Close and update issues
|
||||
- Search across issues
|
||||
|
||||
- **Pull Request Workflow**:
|
||||
- Create pull requests
|
||||
- Review code changes
|
||||
- Add comments to PRs
|
||||
|
||||
This integration enables Claude to participate as a full team member in the development process, not just as a code
|
||||
generation tool. Claude's GitHub account ([bm-claudeai](https://github.com/bm-claudeai)) is a member of the Basic
|
||||
Machines organization with direct contributor access to the codebase.
|
||||
|
||||
### Collaborative Development Process
|
||||
|
||||
With GitHub integration, the development workflow includes:
|
||||
|
||||
1. **Direct code review** - Claude can analyze PRs and provide detailed feedback
|
||||
2. **Contribution tracking** - All of Claude's contributions are properly attributed in the Git history
|
||||
3. **Branch management** - Claude can create feature branches for implementations
|
||||
4. **Documentation maintenance** - Claude can keep documentation updated as the code evolves
|
||||
|
||||
With this integration, the AI assistant is a full-fledged team member rather than just a tool for generating code
|
||||
snippets.
|
||||
|
||||
|
||||
### Basic Memory Pro
|
||||
|
||||
Basic Memory Pro is a desktop GUI application that wraps the basic-memory CLI/MCP tools:
|
||||
|
||||
- Built with Tauri (Rust), React (TypeScript), and a Python FastAPI sidecar
|
||||
- Provides visual knowledge graph exploration and project management
|
||||
- Uses the same core codebase but adds a desktop-friendly interface
|
||||
- Project configuration is shared between CLI and Pro versions
|
||||
- Multiple project support with visual switching interface
|
||||
|
||||
local repo: /Users/phernandez/dev/basicmachines/basic-memory-pro
|
||||
github: https://github.com/basicmachines-co/basic-memory-pro
|
||||
|
||||
## Release and Version Management
|
||||
|
||||
Basic Memory uses `uv-dynamic-versioning` for automatic version management based on git tags:
|
||||
|
||||
### Version Types
|
||||
- **Development versions**: Automatically generated from commits (e.g., `0.12.4.dev26+468a22f`)
|
||||
- **Beta releases**: Created by tagging with beta suffixes (e.g., `v0.13.0b1`, `v0.13.0rc1`)
|
||||
- **Stable releases**: Created by tagging with version numbers (e.g., `v0.13.0`)
|
||||
|
||||
### Release Workflows
|
||||
|
||||
#### Development Builds (Automatic)
|
||||
- Triggered on every push to `main` branch
|
||||
- Publishes dev versions like `0.12.4.dev26+468a22f` to PyPI
|
||||
- Allows continuous testing of latest changes
|
||||
- Users install with: `pip install basic-memory --pre --force-reinstall`
|
||||
|
||||
#### Beta/RC Releases (Manual)
|
||||
- Create beta tag: `git tag v0.13.0b1 && git push origin v0.13.0b1`
|
||||
- Automatically builds and publishes to PyPI as pre-release
|
||||
- Users install with: `pip install basic-memory --pre`
|
||||
- Use for milestone testing before stable release
|
||||
|
||||
#### Stable Releases (Automated)
|
||||
- Use the automated release system: `just release v0.13.0`
|
||||
- Includes comprehensive quality checks (lint, format, type-check, tests)
|
||||
- Automatically updates version in `__init__.py`
|
||||
- Creates git tag and pushes to GitHub
|
||||
- Triggers GitHub Actions workflow for PyPI publication
|
||||
- Users install with: `pip install basic-memory`
|
||||
|
||||
**Manual method (legacy):**
|
||||
- Create version tag: `git tag v0.13.0 && git push origin v0.13.0`
|
||||
|
||||
### For Development
|
||||
- **Automated releases**: Use `just release v0.13.x` for stable releases and `just beta v0.13.0b1` for beta releases
|
||||
- **Quality gates**: All releases require passing lint, format, type-check, and test suites
|
||||
- **Version management**: Versions automatically derived from git tags via `uv-dynamic-versioning`
|
||||
- **Configuration**: `pyproject.toml` uses `dynamic = ["version"]`
|
||||
- **Release automation**: `__init__.py` updated automatically during release process
|
||||
- **CI/CD**: GitHub Actions handles building and PyPI publication
|
||||
|
||||
## Development Notes
|
||||
- make sure you sign off on commits
|
||||
@@ -27,13 +27,25 @@ project and how to get started as a developer.
|
||||
|
||||
> **Note**: Basic Memory uses [just](https://just.systems) as a modern command runner. Install with `brew install just` or `cargo install just`.
|
||||
|
||||
3. **Run the Tests**:
|
||||
3. **Activate the Virtual Environment**
|
||||
```bash
|
||||
# Run all tests
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
4. **Run the Tests**:
|
||||
```bash
|
||||
# Run all tests with unified coverage (unit + integration)
|
||||
just test
|
||||
# or
|
||||
uv run pytest -p pytest_mock -v
|
||||
|
||||
|
||||
# Run unit tests only (fast, no coverage)
|
||||
just test-unit
|
||||
|
||||
# Run integration tests only (fast, no coverage)
|
||||
just test-int
|
||||
|
||||
# Generate HTML coverage report
|
||||
just coverage
|
||||
|
||||
# Run a specific test
|
||||
pytest tests/path/to/test_file.py::test_function_name
|
||||
```
|
||||
@@ -129,7 +141,7 @@ agreement to the DCO.
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
- **Python Version**: Python 3.12+ with full type annotations
|
||||
- **Python Version**: Python 3.12+ with full type annotations (3.12+ required for type parameter syntax)
|
||||
- **Line Length**: 100 characters maximum
|
||||
- **Formatting**: Use ruff for consistent styling
|
||||
- **Import Order**: Standard lib, third-party, local imports
|
||||
@@ -139,46 +151,78 @@ agreement to the DCO.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
- **Coverage Target**: We aim for 100% test coverage for all code
|
||||
### Test Structure
|
||||
|
||||
Basic Memory uses two test directories with unified coverage reporting:
|
||||
|
||||
- **`tests/`**: Unit tests that test individual components in isolation
|
||||
- Fast execution with extensive mocking
|
||||
- Test individual functions, classes, and modules
|
||||
- Run with: `just test-unit` (no coverage, fast)
|
||||
|
||||
- **`test-int/`**: Integration tests that test real-world scenarios
|
||||
- Test full workflows with real database and file operations
|
||||
- Include performance benchmarks
|
||||
- More realistic but slower than unit tests
|
||||
- Run with: `just test-int` (no coverage, fast)
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests with unified coverage report
|
||||
just test
|
||||
|
||||
# Run only unit tests (fast iteration)
|
||||
just test-unit
|
||||
|
||||
# Run only integration tests
|
||||
just test-int
|
||||
|
||||
# Generate HTML coverage report
|
||||
just coverage
|
||||
|
||||
# Run specific test
|
||||
pytest tests/path/to/test_file.py::test_function_name
|
||||
|
||||
# Run tests excluding benchmarks
|
||||
pytest -m "not benchmark"
|
||||
|
||||
# Run only benchmark tests
|
||||
pytest -m benchmark test-int/test_sync_performance_benchmark.py
|
||||
```
|
||||
|
||||
### Performance Benchmarks
|
||||
|
||||
The `test-int/test_sync_performance_benchmark.py` file contains performance benchmarks that measure sync and indexing speed:
|
||||
|
||||
- `test_benchmark_sync_100_files` - Small repository performance
|
||||
- `test_benchmark_sync_500_files` - Medium repository performance
|
||||
- `test_benchmark_sync_1000_files` - Large repository performance (marked slow)
|
||||
- `test_benchmark_resync_no_changes` - Re-sync performance baseline
|
||||
|
||||
Run benchmarks with:
|
||||
```bash
|
||||
# Run all benchmarks (excluding slow ones)
|
||||
pytest test-int/test_sync_performance_benchmark.py -v -m "benchmark and not slow"
|
||||
|
||||
# Run all benchmarks including slow ones
|
||||
pytest test-int/test_sync_performance_benchmark.py -v -m benchmark
|
||||
|
||||
# Run specific benchmark
|
||||
pytest test-int/test_sync_performance_benchmark.py::test_benchmark_sync_100_files -v
|
||||
```
|
||||
|
||||
See `test-int/BENCHMARKS.md` for detailed benchmark documentation.
|
||||
|
||||
### Testing Best Practices
|
||||
|
||||
- **Coverage Target**: We aim for high test coverage for all code
|
||||
- **Test Framework**: Use pytest for unit and integration tests
|
||||
- **Mocking**: Use pytest-mock for mocking dependencies only when necessary
|
||||
- **Mocking**: Avoid mocking in integration tests; use sparingly in unit tests
|
||||
- **Edge Cases**: Test both normal operation and edge cases
|
||||
- **Database Testing**: Use in-memory SQLite for testing database operations
|
||||
- **Fixtures**: Use async pytest fixtures for setup and teardown
|
||||
|
||||
## Release Process
|
||||
|
||||
Basic Memory uses automatic versioning based on git tags with `uv-dynamic-versioning`. Here's how releases work:
|
||||
|
||||
### Version Management
|
||||
- **Development versions**: Automatically generated from git commits (e.g., `0.12.4.dev26+468a22f`)
|
||||
- **Beta releases**: Created by tagging with beta suffixes (e.g., `git tag v0.13.0b1`)
|
||||
- **Stable releases**: Created by tagging with version numbers (e.g., `git tag v0.13.0`)
|
||||
|
||||
### Release Workflows
|
||||
|
||||
#### Development Builds
|
||||
- Automatically published to PyPI on every commit to `main`
|
||||
- Version format: `0.12.4.dev26+468a22f` (base version + dev + commit count + hash)
|
||||
- Users install with: `pip install basic-memory --pre --force-reinstall`
|
||||
|
||||
#### Beta Releases
|
||||
1. Create and push a beta tag: `git tag v0.13.0b1 && git push origin v0.13.0b1`
|
||||
2. GitHub Actions automatically builds and publishes to PyPI
|
||||
3. Users install with: `pip install basic-memory --pre`
|
||||
|
||||
#### Stable Releases
|
||||
1. Create and push a version tag: `git tag v0.13.0 && git push origin v0.13.0`
|
||||
2. GitHub Actions automatically:
|
||||
- Builds the package with version `0.13.0`
|
||||
- Creates GitHub release with auto-generated notes
|
||||
- Publishes to PyPI
|
||||
3. Users install with: `pip install basic-memory`
|
||||
|
||||
### For Contributors
|
||||
- No manual version bumping required
|
||||
- Versions are automatically derived from git tags
|
||||
- Focus on code changes, not version management
|
||||
- **Markers**: Use `@pytest.mark.benchmark` for benchmarks, `@pytest.mark.slow` for slow tests
|
||||
|
||||
## Creating Issues
|
||||
|
||||
|
||||
@@ -1,16 +1,52 @@
|
||||
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
|
||||
FROM python:3.12-slim
|
||||
FROM python:3.12-slim-bookworm
|
||||
|
||||
# Build arguments for user ID and group ID (defaults to 1000)
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
|
||||
# Copy uv from official image
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||
|
||||
# Set environment variables
|
||||
# UV_PYTHON_INSTALL_DIR ensures Python is installed to a persistent location
|
||||
# that survives in the final image (not in /root/.local which gets lost)
|
||||
# UV_PYTHON_PREFERENCE=only-managed tells uv to use its managed Python version
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
UV_PYTHON_INSTALL_DIR=/python \
|
||||
UV_PYTHON_PREFERENCE=only-managed
|
||||
|
||||
# Create a group and user with the provided UID/GID
|
||||
# Check if the GID already exists, if not create appgroup
|
||||
RUN (getent group ${GID} || groupadd --gid ${GID} appgroup) && \
|
||||
useradd --uid ${UID} --gid ${GID} --create-home --shell /bin/bash appuser
|
||||
|
||||
# Copy the project into the image
|
||||
ADD . /app
|
||||
|
||||
# Install Python 3.13 explicitly and sync the project
|
||||
WORKDIR /app
|
||||
RUN uv python install 3.13
|
||||
RUN uv sync --locked --python 3.13
|
||||
|
||||
# Copy the project files
|
||||
COPY . .
|
||||
# Create necessary directories and set ownership
|
||||
RUN mkdir -p /app/data/basic-memory /app/.basic-memory && \
|
||||
chown -R appuser:${GID} /app
|
||||
|
||||
# Install pip and build dependencies
|
||||
RUN pip install --upgrade pip \
|
||||
&& pip install . --no-cache-dir --ignore-installed
|
||||
# Set default data directory and add venv to PATH
|
||||
ENV BASIC_MEMORY_HOME=/app/data/basic-memory \
|
||||
BASIC_MEMORY_PROJECT_ROOT=/app/data \
|
||||
PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
# Expose port if necessary (e.g., uv might use a port, but MCP over stdio so not needed here)
|
||||
# Switch to the non-root user
|
||||
USER appuser
|
||||
|
||||
# Use the basic-memory entrypoint to run the MCP server
|
||||
CMD ["basic-memory", "mcp"]
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD basic-memory --version || exit 1
|
||||
|
||||
# Use the basic-memory entrypoint to run the MCP server with default SSE transport
|
||||
CMD ["basic-memory", "mcp", "--transport", "sse", "--host", "0.0.0.0", "--port", "8000"]
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
# Note Format Reference
|
||||
|
||||
Every document in Basic Memory is a plain Markdown file. Files are the source of truth — changes to files automatically update the knowledge graph in the database. You maintain complete ownership, files work with git, and knowledge persists independently of any AI conversation.
|
||||
|
||||
## Document Structure
|
||||
|
||||
A note has three parts: YAML frontmatter, content (observations), and relations.
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
type: note
|
||||
tags: [coffee, brewing]
|
||||
permalink: coffee-brewing-methods
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Observations
|
||||
- [method] Pour over provides more flavor clarity than French press
|
||||
- [technique] Water temperature at 205°F extracts optimal compounds #brewing
|
||||
- [preference] Ethiopian beans work well with lighter roasts (personal experience)
|
||||
|
||||
## Relations
|
||||
- relates_to [[Coffee Bean Origins]]
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- contrasts_with [[Tea Brewing Methods]]
|
||||
```
|
||||
|
||||
The `## Observations` and `## Relations` headings are conventional but not required — the parser detects observations and relations by their syntax patterns anywhere in the document.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
YAML metadata between `---` fences at the top of the file.
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `title` | No | filename stem | Used for linking and references. Auto-set from filename if missing. |
|
||||
| `type` | No | `note` | Entity type. Used for schema resolution and filtering. |
|
||||
| `tags` | No | `[]` | List or comma-separated string. Used for organization and search. |
|
||||
| `permalink` | No | generated from title | Stable identifier. Persists even if the file moves. |
|
||||
| `schema` | No | none | Schema attachment — dict (inline), string (reference), or omitted (implicit). |
|
||||
|
||||
Custom fields are allowed. Any key not in the standard set is stored as `entity_metadata` and indexed for search and filtering.
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
tags: [startups, essays, lisp]
|
||||
permalink: paul-graham
|
||||
status: active
|
||||
source: wikipedia
|
||||
---
|
||||
```
|
||||
|
||||
Here `status` and `source` are custom fields stored in `entity_metadata`.
|
||||
|
||||
### Frontmatter Value Handling
|
||||
|
||||
YAML automatically converts some values to native types. Basic Memory normalizes them:
|
||||
|
||||
- Date strings (`2025-10-24`) → kept as ISO format strings
|
||||
- Numbers (`1.0`) → converted to strings
|
||||
- Booleans (`true`) → converted to strings (`"True"`)
|
||||
- Lists and dicts → preserved, items normalized recursively
|
||||
|
||||
This prevents errors when downstream code expects string values.
|
||||
|
||||
## Observations
|
||||
|
||||
An observation is a categorized fact about the entity. Written as a Markdown list item.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```
|
||||
- [category] content text #tag1 #tag2 (context)
|
||||
```
|
||||
|
||||
| Part | Required | Description |
|
||||
|------|----------|-------------|
|
||||
| `[category]` | Yes | Classification in square brackets. Any text except `[]()` chars. |
|
||||
| content | Yes | The fact or statement. |
|
||||
| `#tags` | No | Inline tags. Space-separated, each starting with `#`. |
|
||||
| `(context)` | No | Parenthesized text at end of line. Supporting details or source. |
|
||||
|
||||
### Examples
|
||||
|
||||
```markdown
|
||||
- [tech] Uses SQLite for storage #database
|
||||
- [design] Follows local-first architecture #architecture
|
||||
- [decision] Selected bcrypt for passwords #security (based on OWASP audit)
|
||||
- [name] Paul Graham
|
||||
- [expertise] Startups
|
||||
- [expertise] Lisp
|
||||
- [expertise] Essay writing
|
||||
```
|
||||
|
||||
Array-like fields use repeated categories — multiple `[expertise]` observations above.
|
||||
|
||||
### What Is Not an Observation
|
||||
|
||||
The parser excludes these list item patterns:
|
||||
|
||||
| Pattern | Example | Reason |
|
||||
|---------|---------|--------|
|
||||
| Checkboxes | `- [ ] Todo item`, `- [x] Done`, `- [-] Cancelled` | Task list syntax |
|
||||
| Markdown links | `- [text](url)` | URL link syntax |
|
||||
| Bare wiki links | `- [[Target]]` | Treated as a relation instead |
|
||||
|
||||
A list item with `#tags` but no `[category]` is still parsed — the tags are extracted and the category defaults to `Note`.
|
||||
|
||||
## Relations
|
||||
|
||||
Relations connect documents to form the knowledge graph. There are two kinds.
|
||||
|
||||
### Explicit Relations
|
||||
|
||||
Written as list items with a relation type and a `[[wiki link]]` target.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```
|
||||
- relation_type [[Target Entity]] (context)
|
||||
```
|
||||
|
||||
| Part | Required | Description |
|
||||
|------|----------|-------------|
|
||||
| `relation_type` | No | Text before `[[`. Defaults to `relates_to` if omitted. |
|
||||
| `[[Target]]` | Yes | Wiki link to the target entity. Matched by title or permalink. |
|
||||
| `(context)` | No | Parenthesized text after `]]`. Supporting details. |
|
||||
|
||||
### Examples
|
||||
|
||||
```markdown
|
||||
- implements [[Search Design]]
|
||||
- depends_on [[Database Schema]]
|
||||
- works_at [[Y Combinator]] (co-founder)
|
||||
- [[Some Entity]]
|
||||
```
|
||||
|
||||
The last example — a bare `[[wiki link]]` in a list item — gets relation type `relates_to`.
|
||||
|
||||
Common relation types:
|
||||
- `implements`, `depends_on`, `relates_to`, `inspired_by`
|
||||
- `extends`, `part_of`, `contains`, `pairs_with`
|
||||
- `works_at`, `authored`, `collaborated_with`
|
||||
|
||||
Any text works as a relation type. These are conventions, not a fixed set.
|
||||
|
||||
### Inline References
|
||||
|
||||
Wiki links appearing in regular prose (not as list items) create implicit `links_to` relations.
|
||||
|
||||
```markdown
|
||||
This builds on [[Core Design]] and uses [[Utility Functions]].
|
||||
```
|
||||
|
||||
This creates two relations: `links_to [[Core Design]]` and `links_to [[Utility Functions]]`.
|
||||
|
||||
### Forward References
|
||||
|
||||
Relations can link to entities that don't exist yet. Basic Memory resolves them when the target is created.
|
||||
|
||||
## Permalinks and memory:// URLs
|
||||
|
||||
Every document has a unique **permalink** — a stable identifier derived from its title. You can set one explicitly in frontmatter, or let the system generate it.
|
||||
|
||||
```yaml
|
||||
permalink: auth-approaches-2024
|
||||
```
|
||||
|
||||
Permalinks form the basis of `memory://` URLs:
|
||||
|
||||
```
|
||||
memory://auth-approaches-2024 # By permalink
|
||||
memory://Authentication Approaches # By title (auto-resolves)
|
||||
memory://project/auth-approaches # By path
|
||||
```
|
||||
|
||||
Pattern matching is supported:
|
||||
|
||||
```
|
||||
memory://auth* # Starts with "auth"
|
||||
memory://*/approaches # Ends with "approaches"
|
||||
memory://project/*/requirements # Nested wildcard
|
||||
```
|
||||
|
||||
## Schemas
|
||||
|
||||
Schemas declare the expected structure of a note — which observation categories and relation types a well-formed note should have. They use Picoschema, a compact notation from Google's Dotprompt that fits naturally in YAML frontmatter.
|
||||
|
||||
### Picoschema Syntax
|
||||
|
||||
```yaml
|
||||
schema:
|
||||
name: string, full name # required field with description
|
||||
email?: string, contact email # ? = optional
|
||||
role?: string, job title
|
||||
works_at?: Organization, employer # capitalized type = entity reference
|
||||
tags?(array): string, categories # array of type
|
||||
status?(enum): [active, inactive] # enum with allowed values
|
||||
metadata?(object): # nested object
|
||||
updated_at?: string
|
||||
source?: string
|
||||
```
|
||||
|
||||
| Notation | Meaning | Example |
|
||||
|----------|---------|---------|
|
||||
| `field: type` | Required field | `name: string` |
|
||||
| `field?: type` | Optional field | `role?: string` |
|
||||
| `field(array): type` | Array of values | `expertise(array): string` |
|
||||
| `field?(enum): [vals]` | Enum with allowed values | `status?(enum): [active, inactive]` |
|
||||
| `field?(object):` | Nested object with sub-fields | `metadata?(object):` |
|
||||
| `, description` | Description after comma | `name: string, full name` |
|
||||
| `EntityName` | Capitalized type = entity reference | `works_at?: Organization` |
|
||||
|
||||
**Scalar types:** `string`, `integer`, `number`, `boolean`, `any`
|
||||
|
||||
Any type not in that set whose first letter is uppercase is treated as an entity reference (a relation target).
|
||||
|
||||
### Schema-to-Note Mapping
|
||||
|
||||
Schemas validate against existing observation/relation syntax. Note authors don't learn new syntax.
|
||||
|
||||
| Schema Declaration | Maps To | Example in Note |
|
||||
|--------------------|---------|-----------------|
|
||||
| `field: string` | Observation `[field] value` | `- [name] Paul Graham` |
|
||||
| `field?(array): string` | Multiple `[field]` observations | `- [expertise] Lisp` (repeated) |
|
||||
| `field?: EntityType` | Relation `field [[Target]]` | `- works_at [[Y Combinator]]` |
|
||||
| `field?(array): EntityType` | Multiple `field` relations | `- authored [[Book]]` (repeated) |
|
||||
| `tags` | Frontmatter `tags` array | `tags: [startups, essays]` |
|
||||
| `field?(enum): [vals]` | Observation `[field] value` where value is in the set | `- [status] active` |
|
||||
|
||||
Observations and relations not covered by the schema are valid — schemas describe a subset, not a straitjacket.
|
||||
|
||||
### Schema Attachment
|
||||
|
||||
Three ways to attach a schema to a note, resolved in priority order:
|
||||
|
||||
**1. Inline schema** — `schema` is a dict in frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Team Standup 2024-01-15
|
||||
type: meeting
|
||||
schema:
|
||||
attendees(array): string, who was there
|
||||
decisions(array): string, what was decided
|
||||
action_items(array): string, follow-ups
|
||||
blockers?(array): string, anything stuck
|
||||
---
|
||||
```
|
||||
|
||||
Good for one-off structured notes or prototyping a schema before extracting it.
|
||||
|
||||
**2. Explicit reference** — `schema` is a string naming a schema note:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Basic Memory
|
||||
schema: SoftwareProject
|
||||
---
|
||||
```
|
||||
|
||||
or by permalink:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: LLM Memory Patterns
|
||||
schema: schema/research-project
|
||||
---
|
||||
```
|
||||
|
||||
Use when the note's `type` differs from the schema it should validate against, or when multiple schema variants exist.
|
||||
|
||||
**3. Implicit by type** — no `schema` field, resolved by matching `type`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
---
|
||||
```
|
||||
|
||||
The system looks up a schema note where `entity: Person`. If found, it applies. If not, no validation occurs.
|
||||
|
||||
**4. No schema** — perfectly fine. Most notes don't need one.
|
||||
|
||||
### Schema Notes
|
||||
|
||||
A schema is itself a Basic Memory note with `type: schema`. It lives anywhere (though `schema/` is the conventional directory).
|
||||
|
||||
```yaml
|
||||
# schema/Person.md
|
||||
---
|
||||
title: Person
|
||||
type: schema
|
||||
entity: Person
|
||||
version: 1
|
||||
schema:
|
||||
name: string, full name
|
||||
role?: string, job title or position
|
||||
works_at?: Organization, employer
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
settings:
|
||||
validation: warn
|
||||
---
|
||||
|
||||
# Person
|
||||
|
||||
A human individual in the knowledge graph.
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `type` | Yes | Must be `schema` |
|
||||
| `entity` | Yes | The entity type this schema describes (e.g., `Person`) |
|
||||
| `version` | No | Schema version number (default: `1`) |
|
||||
| `schema` | Yes | Picoschema dict defining the fields |
|
||||
| `settings.validation` | No | Validation mode (default: `warn`) |
|
||||
|
||||
Schema notes are regular notes — they show up in search, can have observations and relations, and participate in the knowledge graph.
|
||||
|
||||
### Validation Modes
|
||||
|
||||
| Mode | Behavior |
|
||||
|------|----------|
|
||||
| `warn` | Warnings in output, doesn't block (default) |
|
||||
| `strict` | Errors that block sync, for CI/CD enforcement |
|
||||
| `off` | No validation |
|
||||
|
||||
### Validation Output
|
||||
|
||||
```
|
||||
$ bm schema validate people/ada-lovelace.md
|
||||
|
||||
⚠ Person schema validation:
|
||||
- Missing required field: name (expected [name] observation)
|
||||
- Missing optional field: role
|
||||
- Missing optional field: works_at (no relation found)
|
||||
|
||||
ℹ Unmatched observations: [fact] ×2, [born] ×1
|
||||
ℹ Unmatched relations: collaborated_with
|
||||
```
|
||||
|
||||
"Unmatched" items are informational — observations and relations the schema doesn't cover.
|
||||
|
||||
### Schema Inference
|
||||
|
||||
Generate schemas from existing notes by analyzing observation and relation frequency:
|
||||
|
||||
```
|
||||
$ bm schema infer Person
|
||||
|
||||
Analyzing 30 notes with type: Person...
|
||||
|
||||
Observations found:
|
||||
[name] 30/30 100% → name: string
|
||||
[role] 27/30 90% → role?: string
|
||||
[expertise] 18/30 60% → expertise?(array): string
|
||||
[email] 8/30 27% → email?: string
|
||||
|
||||
Relations found:
|
||||
works_at 22/30 73% → works_at?: Organization
|
||||
|
||||
Suggested schema:
|
||||
name: string, full name
|
||||
role?: string, job title
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
works_at?: Organization, employer
|
||||
|
||||
Save to schema/Person.md? [y/n]
|
||||
```
|
||||
|
||||
Frequency thresholds:
|
||||
- **100% present** → required field
|
||||
- **25%+ present** → optional field
|
||||
- **Below 25%** → excluded from suggestion
|
||||
|
||||
### Schema Drift Detection
|
||||
|
||||
Track how usage patterns shift over time:
|
||||
|
||||
```
|
||||
$ bm schema diff Person
|
||||
|
||||
Schema drift detected:
|
||||
|
||||
+ expertise: now in 81% of notes (was 12%)
|
||||
- department: dropped to 3% of notes
|
||||
~ works_at: cardinality changed (one → many)
|
||||
|
||||
Update schema? [y/n/review]
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Simple Note (No Schema)
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Project Ideas
|
||||
type: note
|
||||
tags: [ideas, brainstorm]
|
||||
---
|
||||
|
||||
# Project Ideas
|
||||
|
||||
## Observations
|
||||
- [idea] Build a CLI tool for markdown linting #tooling
|
||||
- [idea] Create a recipe knowledge base #cooking
|
||||
- [priority] Focus on developer tools first (Q1 goal)
|
||||
|
||||
## Relations
|
||||
- inspired_by [[Developer Workflow Research]]
|
||||
- part_of [[Q1 Planning]]
|
||||
```
|
||||
|
||||
### Schema-Validated Note
|
||||
|
||||
Schema at `schema/Person.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Person
|
||||
type: schema
|
||||
entity: Person
|
||||
version: 1
|
||||
schema:
|
||||
name: string, full name
|
||||
role?: string, job title or position
|
||||
works_at?: Organization, employer
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
settings:
|
||||
validation: warn
|
||||
---
|
||||
|
||||
# Person
|
||||
|
||||
A human individual in the knowledge graph.
|
||||
```
|
||||
|
||||
Note at `people/paul-graham.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
tags: [startups, essays, lisp]
|
||||
---
|
||||
|
||||
# Paul Graham
|
||||
|
||||
## Observations
|
||||
- [name] Paul Graham
|
||||
- [role] Essayist and investor
|
||||
- [expertise] Startups
|
||||
- [expertise] Lisp
|
||||
- [expertise] Essay writing
|
||||
- [fact] Created Viaweb, the first web app
|
||||
|
||||
## Relations
|
||||
- works_at [[Y Combinator]]
|
||||
- authored [[Hackers and Painters]]
|
||||
```
|
||||
|
||||
The `[fact]` observation and `authored` relation are not in the schema — they're valid, just unmatched. The schema only checks that `[name]` exists (required) and looks for optional fields like `[role]`, `[expertise]`, and `works_at`.
|
||||
|
||||
### Inline Schema Note
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Team Standup 2024-01-15
|
||||
type: meeting
|
||||
schema:
|
||||
attendees(array): string, who was there
|
||||
decisions(array): string, what was decided
|
||||
action_items(array): string, follow-ups
|
||||
blockers?(array): string, anything stuck
|
||||
---
|
||||
|
||||
# Team Standup 2024-01-15
|
||||
|
||||
## Observations
|
||||
- [attendees] Paul
|
||||
- [attendees] Sarah
|
||||
- [decisions] Ship v2 by Friday
|
||||
- [action_items] Paul to review PR #42
|
||||
- [blockers] Waiting on API credentials
|
||||
```
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- mcp-name: io.github.basicmachines-co/basic-memory -->
|
||||
[](https://www.gnu.org/licenses/agpl-3.0)
|
||||
[](https://badge.fury.io/py/basic-memory)
|
||||
[](https://www.python.org/downloads/)
|
||||
@@ -5,276 +6,313 @@
|
||||
[](https://github.com/astral-sh/ruff)
|
||||

|
||||

|
||||
[](https://smithery.ai/server/@basicmachines-co/basic-memory)
|
||||
|
||||
## Skip the install — try Basic Memory in the cloud
|
||||
|
||||
Claude, Codex, or Cursor connected in 30 seconds. No Python, no JSON, no
|
||||
terminal. **$15.00/mo locked in for life** (12.50/mo yearly pricing). 7-day free
|
||||
trial — cancel any time before day 7 if it's not for you. Beta pricing —
|
||||
sign up now and your rate never goes up. OSS users: code `BMFOSS` takes
|
||||
another 20% off for 3 months.
|
||||
|
||||
[Start free trial →](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme&utm_content=banner)
|
||||
|
||||
### Basic Memory Teams is now available!
|
||||
|
||||
Give your team a single, shared cloud workspace. Knowledge isn't confined to one person — anything a teammate writes is immediately available to everyone else and to their AI assistants.
|
||||
Edit a note together in real time, hand work off between humans and agents, and build one connected knowledge base instead of scattered copies. Same pricing - start with one user and add more as needed.
|
||||
|
||||
---
|
||||
|
||||
# Basic Memory
|
||||
|
||||
Basic Memory lets you build persistent knowledge through natural conversations with Large Language Models (LLMs) like
|
||||
Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
|
||||
enable any compatible LLM to read and write to your local knowledge base.
|
||||
### Your AI never forgets again.
|
||||
|
||||
- Website: https://basicmemory.com
|
||||
- Company: https://basicmachines.co
|
||||
- Documentation: https://memory.basicmachines.co
|
||||
- Discord: https://discord.gg/tyvKNccgqN
|
||||
- YouTube: https://www.youtube.com/@basicmachines-co
|
||||
Pick up right where you left off — in Claude, Codex, Cursor, ChatGPT, or
|
||||
anything that speaks [MCP](https://modelcontextprotocol.io). Your knowledge
|
||||
lives as Markdown files that both you and your AI can read, write, and
|
||||
search.
|
||||
|
||||
## Pick up your conversation right where you left off
|
||||
- **Local-first.** Plain text on your disk. Forever.
|
||||
- **Two-way.** AI and humans write to the same files; sync keeps them in step.
|
||||
- **A real knowledge graph.** Observations and wikilinks compound into context.
|
||||
- **Semantic search.** Find notes by meaning, not just keywords.
|
||||
- **MCP-native.** Works with every major AI client and IDE.
|
||||
- **Progressive tool discovery.** Every tool is tagged with behavior hints
|
||||
(read-only, destructive, idempotent) so agents pick the right tool on
|
||||
demand — no wasted context trying things to see what they do.
|
||||
- **Cloud, optional.** Sync across devices when you want — never required.
|
||||
|
||||
- AI assistants can load context from local files in a new conversation
|
||||
- Notes are saved locally as Markdown files in real time
|
||||
- No project knowledge or special prompting required
|
||||
## Get started
|
||||
|
||||
Pick the path that fits you. Both run the same product on the same Markdown.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th width="50%">☁️ Cloud</th>
|
||||
<th width="50%">💻 Local install</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
|
||||
**30 seconds.** Sign up, connect your AI client, done.
|
||||
|
||||
- Works in any browser
|
||||
- Mobile, web, desktop
|
||||
- Cross-device sync built in
|
||||
- We handle hosting, backups, snapshots
|
||||
|
||||
**$15.00/mo locked for life** · 7-day free trial · cancel any time
|
||||
|
||||
[**Start free trial →**](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme&utm_content=quickstart)
|
||||
|
||||
</td>
|
||||
<td valign="top">
|
||||
|
||||
**2 minutes.** Install, configure your AI client, run.
|
||||
|
||||
- Free forever (AGPL-3.0)
|
||||
- All data on your disk
|
||||
- Air-gapped friendly
|
||||
- Requires Python via [`uv`](https://docs.astral.sh/uv/)
|
||||
|
||||
```bash
|
||||
uv tool install basic-memory
|
||||
```
|
||||
|
||||
[**Configure your client ↓**](#connect-your-ai-client)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## What people are saying
|
||||
|
||||
> Basic Memory changed my whole relationship with LLMs. I switched from GPT
|
||||
> and Gemini to exclusively Claude and Claude Code because of this
|
||||
> integration and am completely revamping all our company's processes around
|
||||
> a Basic Memory workflow.
|
||||
>
|
||||
> — **Alex**, TrainerDay
|
||||
|
||||
> Basic Memory is the missing 'wow' factor in AI chatbots. Now I can't
|
||||
> imagine Claude or Claude Code without it.
|
||||
>
|
||||
> — **Caleb**, Caleb Picker Consulting
|
||||
|
||||
> I don't code without Basic Memory anymore. It's such a time saver to be
|
||||
> able to refer to projects I don't currently have active and keep a running
|
||||
> log of all my learnings and ProTips.
|
||||
>
|
||||
> — **@groksrc**, Developer
|
||||
|
||||
More on [basicmemory.com](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme).
|
||||
|
||||
## Basic Memory Cloud
|
||||
|
||||
The hosted version of Basic Memory. Same product, same Markdown files, same
|
||||
MCP tools — we just host the database, run the sync, and put it on your
|
||||
phone.
|
||||
|
||||
### What you get
|
||||
|
||||
- **Every device, same brain.** Your knowledge graph on web, mobile, and
|
||||
desktop. No copy-paste between machines.
|
||||
- **Connect any MCP client.** Claude Desktop, Claude Code, Codex, Cursor,
|
||||
ChatGPT (Custom GPTs), VS Code — one-click connect from the web app.
|
||||
- **Bidirectional sync to local.** Edit on your phone, see it in Obsidian on
|
||||
your laptop. rclone-powered with conflict resolution.
|
||||
- **Snapshots and backups.** Point-in-time restore. Browse history. Never
|
||||
lose a note.
|
||||
- **No lock-in.** Your notes are plain Markdown. Export to local Markdown any
|
||||
time — same files, same format, same wikilinks. Cancel anytime, your data
|
||||
stays yours.
|
||||
|
||||
Built on WorkOS AuthKit, Neon Postgres, and Tigris S3.
|
||||
|
||||
### Pricing
|
||||
|
||||
**$15.00/mo, locked in for the life of your subscription** (regular price
|
||||
$19). Sign up during beta and the rate never goes up — as long as you stay
|
||||
subscribed, you keep the price. One plan, no tiers, no surprise upgrades.
|
||||
Unlimited notes, unlimited projects, every feature.
|
||||
|
||||
- 7-day free trial. Cancel any time before day 7 if it's not for you.
|
||||
- Cancel anytime after that too — export your notes whenever you want.
|
||||
- OSS users: code `BMFOSS` for another 20% off for 3 months (~$11.40/mo).
|
||||
|
||||
[**Start your 7-day free trial →**](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme&utm_content=cloud-section)
|
||||
|
||||
## Cloud vs. local
|
||||
|
||||
| | Cloud | Local |
|
||||
|---|---|---|
|
||||
| **Setup time** | 30 seconds | 2 minutes (requires Python) |
|
||||
| **Cost** | $15.00/mo, locked for life (7-day trial) | Free |
|
||||
| **Storage** | We host (Tigris S3) | Your disk |
|
||||
| **Cross-device sync** | Built in | Manual (Git, Syncthing, etc.) |
|
||||
| **Mobile access** | Yes (web + app) | No |
|
||||
| **Air-gapped** | No | Yes |
|
||||
| **Your data stays yours** | Yes — export anytime | Yes — already there |
|
||||
| **Source code** | AGPL-3.0 | AGPL-3.0 |
|
||||
| **Snapshots & backups** | Built in | Roll your own |
|
||||
|
||||
Both paths use the same OSS engine and the same Markdown files. There's no
|
||||
lock-in either way — flip between them when your needs change.
|
||||
|
||||
## Works with the tools you already use
|
||||
|
||||
| Client | Transport | Notes |
|
||||
|---|---|---|
|
||||
| Cloud web app | https | Sign in at basicmemory.com — no install |
|
||||
| [Claude Desktop](#claude-desktop) | stdio/https | macOS / Windows / Linux |
|
||||
| [Claude Code](#claude-code) | stdio/https | `claude mcp add` |
|
||||
| [Codex](#codex-cli) | stdio/https | OpenAI's coding agent |
|
||||
| [Cursor](#cursor) | stdio/https | `.cursor/mcp.json` |
|
||||
| [VS Code](#vs-code) | stdio/https | Native MCP support |
|
||||
| [ChatGPT](#chatgpt) | https | Custom GPT actions (`search` / `fetch`) |
|
||||
| [Obsidian](#obsidian) | — | Reads/writes the same Markdown directly |
|
||||
| Anything MCP | stdio/https | If it speaks MCP, it works |
|
||||
|
||||
## Official agent packages
|
||||
|
||||
This repository is also the canonical home for Basic Memory's host-native
|
||||
agent packages. The core Python package, Claude Code plugin, shared skills,
|
||||
Hermes plugin, and OpenClaw plugin all ship from the same source tree.
|
||||
|
||||
Maintainers can verify the whole consolidated surface from the repo root:
|
||||
|
||||
```bash
|
||||
just package-check
|
||||
```
|
||||
|
||||
Package-local justfiles are also available when working inside one host:
|
||||
|
||||
```bash
|
||||
just package-check-claude-code
|
||||
just package-check-skills
|
||||
just package-check-hermes
|
||||
just package-check-openclaw
|
||||
```
|
||||
|
||||
### Claude Code plugin
|
||||
|
||||
The Claude Code plugin is the bridge between Claude's working memory and Basic
|
||||
Memory — session-start briefings, pre-compaction checkpoints, an opt-in capture
|
||||
output style, and `/basic-memory:bm-setup` · `:remember` · `:share` · `:status`.
|
||||
|
||||
**Connect the Basic Memory MCP server first** — see [Connect your AI
|
||||
client](#connect-your-ai-client). The plugin's hooks and skills call it, so it's a
|
||||
hard prerequisite. Then add the marketplace and install:
|
||||
|
||||
```bash
|
||||
claude plugin marketplace add basicmachines-co/basic-memory \
|
||||
--sparse .claude-plugin plugins/claude-code
|
||||
claude plugin install basic-memory@basicmachines-co
|
||||
```
|
||||
|
||||
Source: [`plugins/claude-code`](plugins/claude-code).
|
||||
|
||||
### Shared skills
|
||||
|
||||
Framework-agnostic `SKILL.md` files live in [`skills/`](skills). If your
|
||||
Skills CLI supports repository subdirectory sources:
|
||||
|
||||
```bash
|
||||
npx skills add basicmachines-co/basic-memory/skills
|
||||
```
|
||||
|
||||
If your installed Skills CLI cannot load that source, update the CLI or copy
|
||||
the `memory-*` directories from `skills/` into your agent's skills directory.
|
||||
|
||||
### Hermes
|
||||
|
||||
Hermes keeps its native plugin shape under [`integrations/hermes`](integrations/hermes):
|
||||
|
||||
```bash
|
||||
hermes plugins install basicmachines-co/basic-memory --path integrations/hermes
|
||||
```
|
||||
|
||||
If your Hermes build lacks subpath installs, use the final deprecated
|
||||
`basicmachines-co/hermes-basic-memory` pointer release until host support
|
||||
lands.
|
||||
|
||||
### OpenClaw
|
||||
|
||||
OpenClaw stays package-native and publishes from
|
||||
[`integrations/openclaw`](integrations/openclaw):
|
||||
|
||||
```bash
|
||||
openclaw plugins install @basicmemory/openclaw-basic-memory
|
||||
```
|
||||
|
||||
## Pick up where you left off
|
||||
|
||||
https://github.com/user-attachments/assets/a55d8238-8dd0-454a-be4c-8860dbbd0ddc
|
||||
|
||||
## Quick Start
|
||||
## Connect your AI client
|
||||
|
||||
```bash
|
||||
# Install with uv (recommended)
|
||||
uv tool install basic-memory
|
||||
If you went the [Cloud](#get-started) route, the web app walks you through
|
||||
client connect. The snippets below are for local installs.
|
||||
|
||||
# Configure Claude Desktop (edit ~/Library/Application Support/Claude/claude_desktop_config.json)
|
||||
# Add this to your config:
|
||||
### Claude Desktop
|
||||
|
||||
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"mcp"
|
||||
]
|
||||
"args": ["basic-memory", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
# Now in Claude Desktop, you can:
|
||||
# - Write notes with "Create a note about coffee brewing methods"
|
||||
# - Read notes with "What do I know about pour over coffee?"
|
||||
# - Search with "Find information about Ethiopian beans"
|
||||
|
||||
```
|
||||
|
||||
You can view shared context via files in `~/basic-memory` (default directory location).
|
||||
Restart Claude Desktop. Notes live in `~/basic-memory` by default.
|
||||
|
||||
### Alternative Installation via Smithery
|
||||
<details>
|
||||
<summary><b>Claude Code, Codex CLI, Cursor, VS Code, ChatGPT, Obsidian</b></summary>
|
||||
|
||||
You can use [Smithery](https://smithery.ai/server/@basicmachines-co/basic-memory) to automatically configure Basic
|
||||
Memory for Claude Desktop:
|
||||
### Claude Code
|
||||
|
||||
```bash
|
||||
npx -y @smithery/cli install @basicmachines-co/basic-memory --client claude
|
||||
claude mcp add basic-memory -- uvx basic-memory mcp
|
||||
```
|
||||
|
||||
This installs and configures Basic Memory without requiring manual edits to the Claude Desktop configuration file. Note: The Smithery installation uses their hosted MCP server, while your data remains stored locally as Markdown files.
|
||||
For the full memory bridge — session briefings, pre-compaction checkpoints, and
|
||||
the `/basic-memory:*` commands — also install the [Claude Code
|
||||
plugin](#claude-code-plugin) on top of this.
|
||||
|
||||
### Glama.ai
|
||||
### Codex CLI
|
||||
|
||||
<a href="https://glama.ai/mcp/servers/o90kttu9ym">
|
||||
<img width="380" height="200" src="https://glama.ai/mcp/servers/o90kttu9ym/badge" alt="basic-memory MCP server" />
|
||||
</a>
|
||||
Add to `~/.codex/config.toml`:
|
||||
|
||||
## Why Basic Memory?
|
||||
|
||||
Most LLM interactions are ephemeral - you ask a question, get an answer, and everything is forgotten. Each conversation
|
||||
starts fresh, without the context or knowledge from previous ones. Current workarounds have limitations:
|
||||
|
||||
- Chat histories capture conversations but aren't structured knowledge
|
||||
- RAG systems can query documents but don't let LLMs write back
|
||||
- Vector databases require complex setups and often live in the cloud
|
||||
- Knowledge graphs typically need specialized tools to maintain
|
||||
|
||||
Basic Memory addresses these problems with a simple approach: structured Markdown files that both humans and LLMs can
|
||||
read
|
||||
and write to. The key advantages:
|
||||
|
||||
- **Local-first:** All knowledge stays in files you control
|
||||
- **Bi-directional:** Both you and the LLM read and write to the same files
|
||||
- **Structured yet simple:** Uses familiar Markdown with semantic patterns
|
||||
- **Traversable knowledge graph:** LLMs can follow links between topics
|
||||
- **Standard formats:** Works with existing editors like Obsidian
|
||||
- **Lightweight infrastructure:** Just local files indexed in a local SQLite database
|
||||
|
||||
With Basic Memory, you can:
|
||||
|
||||
- Have conversations that build on previous knowledge
|
||||
- Create structured notes during natural conversations
|
||||
- Have conversations with LLMs that remember what you've discussed before
|
||||
- Navigate your knowledge graph semantically
|
||||
- Keep everything local and under your control
|
||||
- Use familiar tools like Obsidian to view and edit notes
|
||||
- Build a personal knowledge base that grows over time
|
||||
|
||||
## How It Works in Practice
|
||||
|
||||
Let's say you're exploring coffee brewing methods and want to capture your knowledge. Here's how it works:
|
||||
|
||||
1. Start by chatting normally:
|
||||
|
||||
```
|
||||
I've been experimenting with different coffee brewing methods. Key things I've learned:
|
||||
|
||||
- Pour over gives more clarity in flavor than French press
|
||||
- Water temperature is critical - around 205°F seems best
|
||||
- Freshly ground beans make a huge difference
|
||||
```toml
|
||||
[mcp_servers.basic-memory]
|
||||
command = "uvx"
|
||||
args = ["basic-memory", "mcp"]
|
||||
```
|
||||
|
||||
... continue conversation.
|
||||
### Cursor
|
||||
|
||||
2. Ask the LLM to help structure this knowledge:
|
||||
Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
|
||||
|
||||
```
|
||||
"Let's write a note about coffee brewing methods."
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": ["basic-memory", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
LLM creates a new Markdown file on your system (which you can see instantly in Obsidian or your editor):
|
||||
### VS Code
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
permalink: coffee-brewing-methods
|
||||
tags:
|
||||
- coffee
|
||||
- brewing
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Observations
|
||||
|
||||
- [method] Pour over provides more clarity and highlights subtle flavors
|
||||
- [technique] Water temperature at 205°F (96°C) extracts optimal compounds
|
||||
- [principle] Freshly ground beans preserve aromatics and flavor
|
||||
|
||||
## Relations
|
||||
|
||||
- relates_to [[Coffee Bean Origins]]
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- affects [[Flavor Extraction]]
|
||||
```
|
||||
|
||||
The note embeds semantic content and links to other topics via simple Markdown formatting.
|
||||
|
||||
3. You see this file on your computer in real time in the current project directory (default `~/$HOME/basic-memory`).
|
||||
|
||||
- Realtime sync is enabled by default starting with v0.12.0
|
||||
- Project switching during conversations is supported starting with v0.13.0
|
||||
|
||||
4. In a chat with the LLM, you can reference a topic:
|
||||
|
||||
```
|
||||
Look at `coffee-brewing-methods` for context about pour over coffee
|
||||
```
|
||||
|
||||
The LLM can now build rich context from the knowledge graph. For example:
|
||||
|
||||
```
|
||||
Following relation 'relates_to [[Coffee Bean Origins]]':
|
||||
- Found information about Ethiopian Yirgacheffe
|
||||
- Notes on Colombian beans' nutty profile
|
||||
- Altitude effects on bean characteristics
|
||||
|
||||
Following relation 'requires [[Proper Grinding Technique]]':
|
||||
- Burr vs. blade grinder comparisons
|
||||
- Grind size recommendations for different methods
|
||||
- Impact of consistent particle size on extraction
|
||||
```
|
||||
|
||||
Each related document can lead to more context, building a rich semantic understanding of your knowledge base.
|
||||
|
||||
This creates a two-way flow where:
|
||||
|
||||
- Humans write and edit Markdown files
|
||||
- LLMs read and write through the MCP protocol
|
||||
- Sync keeps everything consistent
|
||||
- All knowledge stays in local files.
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
Under the hood, Basic Memory:
|
||||
|
||||
1. Stores everything in Markdown files
|
||||
2. Uses a SQLite database for searching and indexing
|
||||
3. Extracts semantic meaning from simple Markdown patterns
|
||||
- Files become `Entity` objects
|
||||
- Each `Entity` can have `Observations`, or facts associated with it
|
||||
- `Relations` connect entities together to form the knowledge graph
|
||||
4. Maintains the local knowledge graph derived from the files
|
||||
5. Provides bidirectional synchronization between files and the knowledge graph
|
||||
6. Implements the Model Context Protocol (MCP) for AI integration
|
||||
7. Exposes tools that let AI assistants traverse and manipulate the knowledge graph
|
||||
8. Uses memory:// URLs to reference entities across tools and conversations
|
||||
|
||||
The file format is just Markdown with some simple markup:
|
||||
|
||||
Each Markdown file has:
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```markdown
|
||||
title: <Entity title>
|
||||
type: <The type of Entity> (e.g. note)
|
||||
permalink: <a uri slug>
|
||||
|
||||
- <optional metadata> (such as tags)
|
||||
```
|
||||
|
||||
### Observations
|
||||
|
||||
Observations are facts about a topic.
|
||||
They can be added by creating a Markdown list with a special format that can reference a `category`, `tags` using a
|
||||
"#" character, and an optional `context`.
|
||||
|
||||
Observation Markdown format:
|
||||
|
||||
```markdown
|
||||
- [category] content #tag (optional context)
|
||||
```
|
||||
|
||||
Examples of observations:
|
||||
|
||||
```markdown
|
||||
- [method] Pour over extracts more floral notes than French press
|
||||
- [tip] Grind size should be medium-fine for pour over #brewing
|
||||
- [preference] Ethiopian beans have bright, fruity flavors (especially from Yirgacheffe)
|
||||
- [fact] Lighter roasts generally contain more caffeine than dark roasts
|
||||
- [experiment] Tried 1:15 coffee-to-water ratio with good results
|
||||
- [resource] James Hoffman's V60 technique on YouTube is excellent
|
||||
- [question] Does water temperature affect extraction of different compounds differently?
|
||||
- [note] My favorite local shop uses a 30-second bloom time
|
||||
```
|
||||
|
||||
### Relations
|
||||
|
||||
Relations are links to other topics. They define how entities connect in the knowledge graph.
|
||||
|
||||
Markdown format:
|
||||
|
||||
```markdown
|
||||
- relation_type [[WikiLink]] (optional context)
|
||||
```
|
||||
|
||||
Examples of relations:
|
||||
|
||||
```markdown
|
||||
- pairs_well_with [[Chocolate Desserts]]
|
||||
- grown_in [[Ethiopia]]
|
||||
- contrasts_with [[Tea Brewing Methods]]
|
||||
- requires [[Burr Grinder]]
|
||||
- improves_with [[Fresh Beans]]
|
||||
- relates_to [[Morning Routine]]
|
||||
- inspired_by [[Japanese Coffee Culture]]
|
||||
- documented_in [[Coffee Journal]]
|
||||
```
|
||||
|
||||
## Using with VS Code
|
||||
For one-click installation, click one of the install buttons below...
|
||||
|
||||
[](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) [](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)
|
||||
|
||||
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.
|
||||
|
||||
### Manual Installation
|
||||
|
||||
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)`.
|
||||
Add to your User Settings (JSON):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -289,134 +327,302 @@ Add the following JSON block to your User Settings (JSON) file in VS Code. You c
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
### ChatGPT
|
||||
|
||||
Basic Memory exposes OpenAI-compatible `search` and `fetch` tools for Custom
|
||||
GPT actions. See the [ChatGPT integration
|
||||
guide](https://docs.basicmemory.com/integrations/chatgpt/?utm_source=github&utm_medium=referral&utm_campaign=readme).
|
||||
|
||||
### Obsidian
|
||||
|
||||
No setup. Point Obsidian at `~/basic-memory` (or your project folder) and the
|
||||
same wikilinks, frontmatter, and Markdown your AI writes appear in your graph
|
||||
view. Edit either side — sync handles the rest.
|
||||
|
||||
</details>
|
||||
|
||||
Try a prompt:
|
||||
|
||||
```
|
||||
"Create a note about our project architecture decisions."
|
||||
"Find information about JWT auth in my notes."
|
||||
"What have I been working on this week?"
|
||||
```
|
||||
|
||||
## What's New
|
||||
|
||||
- **Automatic updates.** Basic Memory keeps itself up to date for `uv tool`
|
||||
and Homebrew installs; `bm update` triggers a manual check.
|
||||
- **Semantic vector search.** Find notes by meaning, not just keywords.
|
||||
Hybrid full-text + vector ranking with FastEmbed embeddings, on SQLite or
|
||||
Postgres.
|
||||
- **Schema system.** Infer, validate, and diff the structure of your
|
||||
knowledge base with `schema_infer`, `schema_validate`, `schema_diff`.
|
||||
- **Per-project cloud routing.** Route individual projects through the cloud
|
||||
while others stay local, via API key (`bm project set-cloud`).
|
||||
- **Smarter editing.** `edit_note` append/prepend auto-creates notes when
|
||||
missing; `write_note` guards against accidental overwrites.
|
||||
- **Richer search results.** Matched chunk text is included so the LLM gets
|
||||
context, not just hits.
|
||||
- **FastMCP 3.0 + tool annotations.** Every tool ships with MCP behavior
|
||||
hints (`readOnlyHint`, `destructiveHint`, `idempotentHint`,
|
||||
`openWorldHint`) so agents can discover capabilities progressively at
|
||||
runtime instead of guessing or burning tokens.
|
||||
- **CLI overhaul.** `--json` output for scripting, workspace-aware commands,
|
||||
and an htop-inspired project dashboard.
|
||||
|
||||
Full [CHANGELOG](CHANGELOG.md) for v0.18 → v0.20.
|
||||
|
||||
## Why Basic Memory
|
||||
|
||||
Most LLM conversations are ephemeral. You ask a question, get an answer, then
|
||||
everything is forgotten. Workarounds have limits:
|
||||
|
||||
- **Chat history** captures conversations but isn't structured knowledge.
|
||||
- **RAG** lets the LLM query your documents but not write back to them.
|
||||
- **Vector DBs** need complex infra and usually live in someone else's cloud.
|
||||
- **Knowledge graphs** need specialized tooling to maintain.
|
||||
|
||||
Basic Memory takes a simpler path: **structured Markdown files that humans
|
||||
and LLMs both read and write.**
|
||||
|
||||
- All knowledge stays in plain files you control.
|
||||
- Both sides read and write to the same files.
|
||||
- Familiar Markdown with semantic patterns — no new format to learn.
|
||||
- A traversable graph the LLM can follow link by link.
|
||||
- Works with the editors you already use (Obsidian, VS Code, anything).
|
||||
- Just files plus a local SQLite index. No servers required.
|
||||
|
||||
## How it works
|
||||
|
||||
You're chatting normally about coffee:
|
||||
|
||||
> I've been experimenting with brewing methods. Pour over gives more clarity
|
||||
> than French press, water at 205°F seems best, and freshly ground beans
|
||||
> make a huge difference.
|
||||
|
||||
Ask the LLM to capture it:
|
||||
|
||||
> "Make a note on coffee brewing methods."
|
||||
|
||||
A Markdown file appears in your project directory in real time:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
permalink: coffee-brewing-methods
|
||||
tags: [coffee, brewing]
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Observations
|
||||
- [method] Pour over highlights subtle flavors over body
|
||||
- [technique] Water at 205°F (96°C) extracts optimal compounds
|
||||
- [principle] Freshly ground beans preserve aromatics
|
||||
|
||||
## Relations
|
||||
- relates_to [[Coffee Bean Origins]]
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- affects [[Flavor Extraction]]
|
||||
```
|
||||
|
||||
Next session, the LLM picks up the thread. It follows the relations to
|
||||
surface what you already know about Ethiopian beans and burr grinders, and
|
||||
builds on it instead of starting over. You see the same files in Obsidian or
|
||||
your editor. Edit them by hand — the AI sees your changes too.
|
||||
|
||||
Real two-way flow: humans edit Markdown, LLMs read/write through MCP, sync
|
||||
keeps everything consistent, and the source of truth is always your files.
|
||||
|
||||
## The Markdown format
|
||||
|
||||
Each file is an `Entity`. Entities have `Observations` (facts about them) and
|
||||
`Relations` (links to other entities). That's the whole grammar.
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: <Entity title>
|
||||
type: note
|
||||
permalink: <uri-slug>
|
||||
tags: [optional, list]
|
||||
---
|
||||
```
|
||||
|
||||
### Observations
|
||||
|
||||
Facts about the entity. Categories in `[brackets]`, tags with `#`, optional
|
||||
context in parens.
|
||||
|
||||
```markdown
|
||||
- [method] Pour over highlights subtle flavors
|
||||
- [tip] Grind medium-fine for V60 #brewing
|
||||
- [fact] Lighter roasts contain more caffeine than dark
|
||||
- [resource] James Hoffmann's V60 technique on YouTube
|
||||
- [question] How does temperature affect compound extraction?
|
||||
```
|
||||
|
||||
### Relations
|
||||
|
||||
Wiki-style links that form the graph. Single-token relation types, or quote
|
||||
multi-word ones.
|
||||
|
||||
```markdown
|
||||
- pairs_well_with [[Chocolate Desserts]]
|
||||
- grown_in [[Ethiopia]]
|
||||
- requires [[Burr Grinder]]
|
||||
- "pairs well with" [[Dark Chocolate]]
|
||||
```
|
||||
|
||||
Bare `- [[Target]]` and prose `- Worth checking out [[Target]]` index as
|
||||
`links_to`. Full reference in the
|
||||
[docs](https://docs.basicmemory.com/getting-started/note-formatting/?utm_source=github&utm_medium=referral&utm_campaign=readme).
|
||||
|
||||
## MCP tools
|
||||
|
||||
Basic Memory exposes these tools to any MCP client. Every tool is annotated
|
||||
with MCP behavior hints (read-only, destructive, idempotent, open-world) so
|
||||
agents can pick the right one without trial-and-error:
|
||||
|
||||
- **Content:** `write_note`, `read_note`, `edit_note`, `move_note`,
|
||||
`delete_note`, `read_content`, `view_note`
|
||||
- **Search & discovery:** `search`, `search_notes`, `recent_activity`,
|
||||
`list_directory`
|
||||
- **Knowledge graph:** `build_context` (navigates `memory://` URLs),
|
||||
`canvas` (Obsidian canvas generation)
|
||||
- **Projects:** `list_memory_projects`, `create_memory_project`,
|
||||
`get_current_project`, `sync_status`
|
||||
- **Schema:** `schema_infer`, `schema_validate`, `schema_diff`
|
||||
- **Cloud:** `cloud_info`, `release_notes`
|
||||
|
||||
All MCP tools default to text output; pass `output_format="json"` for
|
||||
structured responses. Full tool reference in the
|
||||
[docs](https://docs.basicmemory.com/?utm_source=github&utm_medium=referral&utm_campaign=readme).
|
||||
|
||||
## CLI essentials
|
||||
|
||||
```bash
|
||||
# Projects
|
||||
basic-memory project list
|
||||
basic-memory project add research ~/research
|
||||
basic-memory project set-cloud research # route through cloud
|
||||
basic-memory project set-local research # revert
|
||||
|
||||
# Health & maintenance
|
||||
basic-memory status
|
||||
basic-memory doctor # file <-> DB consistency check
|
||||
basic-memory tool edit-note ... # CLI access to MCP tools
|
||||
basic-memory update # check for and install updates
|
||||
|
||||
# Imports
|
||||
basic-memory import claude conversations
|
||||
basic-memory import chatgpt
|
||||
basic-memory import memory-json
|
||||
```
|
||||
|
||||
Routing flags (`--local` / `--cloud`) force a target when you're in mixed
|
||||
mode. Full CLI reference in the
|
||||
[docs](https://docs.basicmemory.com/guides/cli-reference/?utm_source=github&utm_medium=referral&utm_campaign=readme).
|
||||
|
||||
## Auto-updates
|
||||
|
||||
CLI installs check for updates every 24 hours by default and apply them
|
||||
silently (so the MCP server keeps responding).
|
||||
|
||||
- Supported install sources: `uv tool`, Homebrew
|
||||
- Skipped for `uvx` (ephemeral runtime managed by uv)
|
||||
- Manual: `bm update` (check + apply) or `bm update --check` (check only)
|
||||
|
||||
Disable in `~/.basic-memory/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": ["basic-memory", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "auto_update": false }
|
||||
```
|
||||
|
||||
## Using with Claude Desktop
|
||||
## Telemetry
|
||||
|
||||
Basic Memory is built using the MCP (Model Context Protocol) and works with the Claude desktop app (https://claude.ai/):
|
||||
Minimal, anonymous events to understand the CLI-to-cloud conversion funnel.
|
||||
|
||||
1. Configure Claude Desktop to use Basic Memory:
|
||||
**What we collect:** cloud promo impressions, cloud login attempts and
|
||||
outcomes, promo opt-out events.
|
||||
|
||||
Edit your MCP configuration file (usually located at `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
for OS X):
|
||||
**What we don't:** file contents, note titles, knowledge base data, PII, IP
|
||||
addresses, per-command or per-tool tracking.
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Events go to our [Umami Cloud](https://umami.is) instance (open-source,
|
||||
privacy-focused) on a background thread — never blocks the CLI.
|
||||
|
||||
If you want to use a specific project (see [Multiple Projects](docs/User%20Guide.md#multiple-projects)), update your
|
||||
Claude Desktop
|
||||
config:
|
||||
Opt out:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"--project",
|
||||
"your-project-name",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Sync your knowledge:
|
||||
|
||||
Basic Memory will sync the files in your project in real time if you make manual edits.
|
||||
|
||||
3. In Claude Desktop, the LLM can now use these tools:
|
||||
|
||||
```
|
||||
write_note(title, content, folder, tags) - Create or update notes
|
||||
read_note(identifier, page, page_size) - Read notes by title or permalink
|
||||
edit_note(identifier, operation, content) - Edit notes incrementally (append, prepend, find/replace)
|
||||
move_note(identifier, destination_path) - Move notes with database consistency
|
||||
view_note(identifier) - Display notes as formatted artifacts for better readability
|
||||
build_context(url, depth, timeframe) - Navigate knowledge graph via memory:// URLs
|
||||
search_notes(query, page, page_size) - Search across your knowledge base
|
||||
recent_activity(type, depth, timeframe) - Find recently updated information
|
||||
canvas(nodes, edges, title, folder) - Generate knowledge visualizations
|
||||
list_memory_projects() - List all available projects with status
|
||||
switch_project(project_name) - Switch to different project context
|
||||
get_current_project() - Show current project and statistics
|
||||
create_memory_project(name, path, set_default) - Create new projects
|
||||
delete_project(name) - Delete projects from configuration
|
||||
set_default_project(name) - Set default project
|
||||
sync_status() - Check file synchronization status
|
||||
```
|
||||
|
||||
5. Example prompts to try:
|
||||
|
||||
```
|
||||
"Create a note about our project architecture decisions"
|
||||
"Find information about JWT authentication in my notes"
|
||||
"Create a canvas visualization of my project components"
|
||||
"Read my notes on the authentication system"
|
||||
"What have I been working on in the past week?"
|
||||
"Switch to my work-notes project"
|
||||
"List all my available projects"
|
||||
"Edit my coffee brewing note to add a new technique"
|
||||
"Move my old meeting notes to the archive folder"
|
||||
```
|
||||
|
||||
## Futher info
|
||||
|
||||
See the [Documentation](https://memory.basicmachines.co/) for more info, including:
|
||||
|
||||
- [Complete User Guide](https://memory.basicmachines.co/docs/user-guide)
|
||||
- [CLI tools](https://memory.basicmachines.co/docs/cli-reference)
|
||||
- [Managing multiple Projects](https://memory.basicmachines.co/docs/cli-reference#project)
|
||||
- [Importing data from OpenAI/Claude Projects](https://memory.basicmachines.co/docs/cli-reference#import)
|
||||
|
||||
## Installation Options
|
||||
|
||||
### Stable Release
|
||||
```bash
|
||||
pip install basic-memory
|
||||
export BASIC_MEMORY_NO_PROMOS=1
|
||||
```
|
||||
|
||||
### Beta/Pre-releases
|
||||
This disables promos and all telemetry.
|
||||
|
||||
## Logging
|
||||
|
||||
Basic Memory uses [Loguru](https://github.com/Delgan/loguru). Defaults vary
|
||||
by entry point:
|
||||
|
||||
| Entry point | Default | Why |
|
||||
|---|---|---|
|
||||
| CLI commands | File only | Doesn't interfere with command output |
|
||||
| MCP server | File only | Stdout would corrupt JSON-RPC |
|
||||
| API server | File (local) or stdout (cloud) | Docker/cloud uses stdout |
|
||||
|
||||
Log file: `~/.basic-memory/basic-memory.log` (10MB rotation, 10 days
|
||||
retention).
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `BASIC_MEMORY_LOG_LEVEL` | `INFO` | DEBUG / INFO / WARNING / ERROR |
|
||||
| `BASIC_MEMORY_CLOUD_MODE` | `false` | API logs to stdout with structured context |
|
||||
| `BASIC_MEMORY_FORCE_LOCAL` | `false` | Force local API routing |
|
||||
| `BASIC_MEMORY_FORCE_CLOUD` | `false` | Force cloud API routing |
|
||||
| `BASIC_MEMORY_EXPLICIT_ROUTING` | `false` | Mark route selection as explicit |
|
||||
| `BASIC_MEMORY_ENV` | `dev` | Set to `test` for test mode (stderr only) |
|
||||
| `BASIC_MEMORY_NO_PROMOS` | `false` | Disable cloud promos and telemetry |
|
||||
| `BASIC_MEMORY_IMPORT_UPLOAD_MAX_BYTES` | `104857600` | Max uploaded import size |
|
||||
|
||||
```bash
|
||||
pip install basic-memory --pre
|
||||
BASIC_MEMORY_LOG_LEVEL=DEBUG basic-memory sync
|
||||
tail -f ~/.basic-memory/basic-memory.log
|
||||
```
|
||||
|
||||
### Development Builds
|
||||
Development versions are automatically published on every commit to main with versions like `0.12.4.dev26+468a22f`:
|
||||
## Development
|
||||
|
||||
Basic Memory supports SQLite (default, fast, no Docker) and Postgres
|
||||
(via testcontainers — Docker required).
|
||||
|
||||
```bash
|
||||
pip install basic-memory --pre --force-reinstall
|
||||
just install # Install with dev dependencies
|
||||
just test-sqlite # All tests, SQLite
|
||||
just test-postgres # All tests, Postgres (testcontainers)
|
||||
just test # Both backends
|
||||
just fast-check # fix/format/typecheck + impacted tests
|
||||
just doctor # File <-> DB consistency check (temp config)
|
||||
just package-check # Claude Code, skills, Hermes, OpenClaw package checks
|
||||
just lint
|
||||
just typecheck # Pyright (primary)
|
||||
just typecheck-ty # ty (supplemental)
|
||||
just format
|
||||
just check # All quality checks
|
||||
just migration "msg" # New Alembic migration
|
||||
```
|
||||
|
||||
Tests use pytest markers: `windows`, `benchmark`, `smoke`. See
|
||||
[justfile](justfile) for the full list.
|
||||
|
||||
Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
AGPL-3.0
|
||||
|
||||
Contributions are welcome. See the [Contributing](CONTRIBUTING.md) guide for info about setting up the project locally
|
||||
and submitting PRs.
|
||||
[AGPL-3.0](LICENSE).
|
||||
|
||||
## Star History
|
||||
|
||||
@@ -428,4 +634,4 @@ and submitting PRs.
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
Built with ♥️ by Basic Machines
|
||||
Built with ♥️ by [Basic Machines](https://basicmachines.co?utm_source=github&utm_medium=referral&utm_campaign=readme)
|
||||
|
||||
@@ -8,6 +8,71 @@
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Use this section to tell people how to report a vulnerability.
|
||||
If you find a vulnerability, please contact hello@basicmachines.co.
|
||||
|
||||
If you find a vulnerability, please contact hello@basicmachines.co
|
||||
Please do not open a public GitHub issue for security vulnerabilities. We aim
|
||||
to respond within 72 hours and will coordinate a fix and disclosure timeline
|
||||
with you.
|
||||
|
||||
## Threat Model
|
||||
|
||||
Basic Memory is a local-first MCP server that reads and writes markdown files
|
||||
inside configured project directories. It runs on your machine with your user
|
||||
permissions, so local configuration deserves the same care as any other
|
||||
developer tool that can access your files.
|
||||
|
||||
### What Basic Memory Controls
|
||||
|
||||
- Filesystem-touching tools validate paths against the configured project root
|
||||
with `validate_project_path()`, resolved paths, and `Path.is_relative_to()`.
|
||||
Path traversal attempts such as `../../etc/passwd` are blocked at this layer.
|
||||
- Scan optimizations in `sync_service.py` call `find` through
|
||||
`asyncio.create_subprocess_exec()` with explicit argument lists. Project paths
|
||||
are passed as data, not interpolated into shell strings.
|
||||
- Auto-update code uses hardcoded commands, list-form arguments, and
|
||||
`stdin=DEVNULL`. User-controlled strings do not reach a shell there.
|
||||
|
||||
### MCP Client-Side Risk
|
||||
|
||||
Recent MCP ecosystem research has highlighted a client-side pattern where an
|
||||
MCP host can be configured to run arbitrary commands as "servers." That risk is
|
||||
in the host configuration, not in notes or Basic Memory tool input.
|
||||
|
||||
The recommended Basic Memory MCP configuration uses a known command with
|
||||
explicit arguments:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": ["basic-memory", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Only add MCP server entries from sources you trust. Avoid inline shell scripts
|
||||
or command strings copied from untrusted sources. Treat third-party MCP server
|
||||
configuration with the same scrutiny as any locally executed program.
|
||||
|
||||
Related ecosystem context:
|
||||
|
||||
- OX Security: The Mother of All AI Supply Chains
|
||||
- CSO Online: RCE by design: MCP architectural choice haunts AI agent ecosystem
|
||||
|
||||
### Out Of Scope
|
||||
|
||||
- Basic Memory does not execute note content as code. Notes are returned as
|
||||
data to the LLM.
|
||||
- Basic Memory does not open network ports by default. The MCP server uses
|
||||
stdio; the optional REST API is intended for localhost use.
|
||||
- Basic Memory is designed for single-user local knowledge bases and does not
|
||||
implement access controls between operating-system users.
|
||||
|
||||
## Secure Configuration Checklist
|
||||
|
||||
- MCP config `command` points to `uvx` or a trusted binary, not a shell string.
|
||||
- Project paths in Basic Memory config come from trusted local configuration.
|
||||
- If exposing the REST API, bind it only to localhost.
|
||||
- Review any third-party MCP servers before adding them to your host config.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Docker Compose configuration for Basic Memory with PostgreSQL
|
||||
# Use this for local development and testing with Postgres backend.
|
||||
#
|
||||
# The Postgres backend requires the pgvector extension (semantic search).
|
||||
# This image bundles pgvector; plain postgres:17 will not work for vector search.
|
||||
#
|
||||
# Usage:
|
||||
# docker-compose -f docker-compose-postgres.yml up -d
|
||||
# docker-compose -f docker-compose-postgres.yml down
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg17
|
||||
container_name: basic-memory-postgres
|
||||
environment:
|
||||
# Local development/test credentials - NOT for production
|
||||
# These values are referenced by tests and justfile commands
|
||||
POSTGRES_DB: basic_memory
|
||||
POSTGRES_USER: basic_memory_user
|
||||
POSTGRES_PASSWORD: dev_password # Simple password for local testing only
|
||||
ports:
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U basic_memory_user -d basic_memory"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
# Named volume for Postgres data
|
||||
postgres_data:
|
||||
driver: local
|
||||
|
||||
# Named volume for persistent configuration
|
||||
# Database will be stored in Postgres, not in this volume
|
||||
basic-memory-config:
|
||||
driver: local
|
||||
|
||||
# Network configuration (optional)
|
||||
# networks:
|
||||
# basic-memory-net:
|
||||
# driver: bridge
|
||||
@@ -0,0 +1,85 @@
|
||||
# Docker Compose configuration for Basic Memory
|
||||
# See docs/Docker.md for detailed setup instructions
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
basic-memory:
|
||||
# Use pre-built image (recommended for most users)
|
||||
image: ghcr.io/basicmachines-co/basic-memory:latest
|
||||
|
||||
# Uncomment to build locally instead:
|
||||
# build: .
|
||||
|
||||
container_name: basic-memory-server
|
||||
|
||||
# Volume mounts for knowledge directories and persistent data
|
||||
volumes:
|
||||
|
||||
# Persistent storage for configuration and database
|
||||
# Container runs as `appuser` (Dockerfile USER directive), so the CLI
|
||||
# config dir lives under /home/appuser, not /root.
|
||||
- basic-memory-config:/home/appuser/.basic-memory:rw
|
||||
|
||||
# Mount your knowledge directory (required)
|
||||
# Change './knowledge' to your actual Obsidian vault or knowledge directory
|
||||
- ./knowledge:/app/data:rw
|
||||
|
||||
# OPTIONAL: Mount additional knowledge directories for multiple projects
|
||||
# - ./work-notes:/app/data/work:rw
|
||||
# - ./personal-notes:/app/data/personal:rw
|
||||
|
||||
# You can edit the project config manually in the mounted config volume
|
||||
# The default project will be configured to use /app/data
|
||||
environment:
|
||||
# Project configuration
|
||||
- BASIC_MEMORY_DEFAULT_PROJECT=main
|
||||
|
||||
# Enable real-time file synchronization (recommended for Docker)
|
||||
- BASIC_MEMORY_SYNC_CHANGES=true
|
||||
|
||||
# Logging configuration
|
||||
- BASIC_MEMORY_LOG_LEVEL=INFO
|
||||
|
||||
# Sync delay in milliseconds (adjust for performance vs responsiveness)
|
||||
- BASIC_MEMORY_SYNC_DELAY=1000
|
||||
|
||||
# Port exposure for HTTP transport (only needed if not using STDIO)
|
||||
ports:
|
||||
- "8000:8000"
|
||||
|
||||
# Command with SSE transport (configurable via environment variables above)
|
||||
# IMPORTANT: The SSE and streamable-http endpoints are not secured
|
||||
command: ["basic-memory", "mcp", "--transport", "sse", "--host", "0.0.0.0", "--port", "8000"]
|
||||
|
||||
# Container management
|
||||
restart: unless-stopped
|
||||
|
||||
# Health monitoring
|
||||
healthcheck:
|
||||
test: ["CMD", "basic-memory", "--version"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# Optional: Resource limits
|
||||
# deploy:
|
||||
# resources:
|
||||
# limits:
|
||||
# memory: 512M
|
||||
# cpus: '0.5'
|
||||
# reservations:
|
||||
# memory: 256M
|
||||
# cpus: '0.25'
|
||||
|
||||
volumes:
|
||||
# Named volume for persistent configuration and database
|
||||
# This ensures your configuration and knowledge graph persist across container restarts
|
||||
basic-memory-config:
|
||||
driver: local
|
||||
|
||||
# Network configuration (optional)
|
||||
# networks:
|
||||
# basic-memory-net:
|
||||
# driver: bridge
|
||||
@@ -1,431 +0,0 @@
|
||||
---
|
||||
title: AI Assistant Guide
|
||||
type: note
|
||||
permalink: docs/ai-assistant-guide
|
||||
---
|
||||
> Note: This is an optional document that can be copy/pasted into the project knowledge for an LLM to provide a full description of how it can work with Basic Memory. It is provided as a helpful resource. The tools contain extensive usage description prompts with enable the LLM to understand them.
|
||||
|
||||
You can [download](https://github.com/basicmachines-co/basic-memory/blob/main/docs/AI%20Assistant%20Guide.md) the contents of this file from GitHub
|
||||
# AI Assistant Guide for Basic Memory
|
||||
|
||||
This guide helps you, the AI assistant, use Basic Memory tools effectively when working with users. It covers reading, writing, and navigating knowledge through the Model Context Protocol (MCP).
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Essential Tools:**
|
||||
- `write_note()` - Create/update notes (primary tool)
|
||||
- `read_note()` - Read existing content
|
||||
- `search_notes()` - Find information
|
||||
- `edit_note()` - Modify existing notes incrementally (v0.13.0)
|
||||
- `move_note()` - Organize files with database consistency (v0.13.0)
|
||||
|
||||
**Project Management (v0.13.0):**
|
||||
- `list_projects()` - Show available projects
|
||||
- `switch_project()` - Change active project
|
||||
- `get_current_project()` - Current project info
|
||||
|
||||
**Key Principles:**
|
||||
1. **Build connections** - Rich knowledge graphs > isolated notes
|
||||
2. **Ask permission** - "Would you like me to record this?"
|
||||
3. **Use exact titles** - For accurate `[[WikiLinks]]`
|
||||
4. **Leverage v0.13.0** - Edit incrementally, organize proactively, switch projects contextually
|
||||
|
||||
## Overview
|
||||
|
||||
Basic Memory allows you and users to record context in local Markdown files, building a rich knowledge base through natural conversations. The system automatically creates a semantic knowledge graph from simple text patterns.
|
||||
|
||||
- **Local-First**: All data is stored in plain text files on the user's computer
|
||||
- **Real-Time**: Users see content updates immediately
|
||||
- **Bi-Directional**: Both you and users can read and edit notes
|
||||
- **Semantic**: Simple patterns create a structured knowledge graph
|
||||
- **Persistent**: Knowledge persists across sessions and conversations
|
||||
|
||||
## The Importance of the Knowledge Graph
|
||||
|
||||
Basic Memory's value comes from connections between notes, not just the notes themselves. When writing notes, your primary goal should be creating a rich, interconnected knowledge graph.
|
||||
|
||||
When creating content, focus on:
|
||||
|
||||
1. **Increasing Semantic Density**: Add multiple observations and relations to each note
|
||||
2. **Using Accurate References**: Aim to reference existing entities by their exact titles
|
||||
3. **Creating Forward References**: Feel free to reference entities that don't exist yet - Basic Memory will resolve these when they're created later
|
||||
4. **Creating Bidirectional Links**: When appropriate, connect entities from both directions
|
||||
5. **Using Meaningful Categories**: Add semantic context with appropriate observation categories
|
||||
6. **Choosing Precise Relations**: Use specific relation types that convey meaning
|
||||
|
||||
Remember that a knowledge graph with 10 heavily connected notes is more valuable than 20 isolated notes. Your job is to help build these connections.
|
||||
|
||||
## Core Tools Reference
|
||||
|
||||
### Essential Content Management
|
||||
|
||||
**Writing knowledge** (most important tool):
|
||||
```
|
||||
write_note(
|
||||
title="Search Design",
|
||||
content="# Search Design\n...",
|
||||
folder="specs", # Optional
|
||||
tags=["search", "design"], # v0.13.0: now searchable!
|
||||
project="work-notes" # v0.13.0: target specific project
|
||||
)
|
||||
```
|
||||
|
||||
**Reading knowledge:**
|
||||
```
|
||||
read_note("Search Design") # By title
|
||||
read_note("specs/search-design") # By path
|
||||
read_note("memory://specs/search") # By memory URL
|
||||
```
|
||||
|
||||
**Viewing notes as formatted artifacts (Claude Desktop):**
|
||||
```
|
||||
view_note("Search Design") # Creates readable artifact
|
||||
view_note("specs/search-design") # By permalink
|
||||
view_note("memory://specs/search") # By memory URL
|
||||
```
|
||||
|
||||
**Incremental editing** (v0.13.0):
|
||||
```
|
||||
edit_note(
|
||||
identifier="Search Design", # Must be EXACT title/permalink (strict matching)
|
||||
operation="append", # append, prepend, find_replace, replace_section
|
||||
content="\n## New Section\nContent here..."
|
||||
)
|
||||
```
|
||||
**⚠️ Important:** `edit_note` requires exact identifiers (no fuzzy matching). Use `search_notes()` first if uncertain.
|
||||
|
||||
**File organization** (v0.13.0):
|
||||
```
|
||||
move_note(
|
||||
identifier="Old Note", # Must be EXACT title/permalink (strict matching)
|
||||
destination="archive/old-note.md" # Folders created automatically
|
||||
)
|
||||
```
|
||||
**⚠️ Important:** `move_note` requires exact identifiers (no fuzzy matching). Use `search_notes()` first if uncertain.
|
||||
|
||||
### Project Management (v0.13.0)
|
||||
|
||||
```
|
||||
list_projects() # Show available projects
|
||||
switch_project("work-notes") # Change active project
|
||||
get_current_project() # Current project info
|
||||
```
|
||||
|
||||
### Search & Discovery
|
||||
|
||||
```
|
||||
search_notes("authentication system") # v0.13.0: includes frontmatter tags
|
||||
build_context("memory://specs/search") # Follow knowledge graph connections
|
||||
recent_activity(timeframe="1 week") # Check what's been updated
|
||||
```
|
||||
|
||||
## memory:// URLs Explained
|
||||
|
||||
Basic Memory uses a special URL format to reference entities in the knowledge graph:
|
||||
|
||||
- `memory://title` - Reference by title
|
||||
- `memory://folder/title` - Reference by folder and title
|
||||
- `memory://permalink` - Reference by permalink
|
||||
- `memory://path/relation_type/*` - Follow all relations of a specific type
|
||||
- `memory://path/*/target` - Find all entities with relations to target
|
||||
|
||||
## Semantic Markdown Format
|
||||
|
||||
Knowledge is encoded in standard markdown using simple patterns:
|
||||
|
||||
**Observations** - Facts about an entity:
|
||||
```markdown
|
||||
- [category] This is an observation #tag1 #tag2 (optional context)
|
||||
```
|
||||
|
||||
**Relations** - Links between entities:
|
||||
```markdown
|
||||
- relation_type [[Target Entity]] (optional context)
|
||||
```
|
||||
|
||||
**Common Categories & Relation Types:**
|
||||
- Categories: `[idea]`, `[decision]`, `[question]`, `[fact]`, `[requirement]`, `[technique]`, `[recipe]`, `[preference]`
|
||||
- Relations: `relates_to`, `implements`, `requires`, `extends`, `part_of`, `pairs_with`, `inspired_by`, `originated_from`
|
||||
|
||||
## When to Record Context
|
||||
|
||||
**Always consider recording context when**:
|
||||
|
||||
1. Users make decisions or reach conclusions
|
||||
2. Important information emerges during conversation
|
||||
3. Multiple related topics are discussed
|
||||
4. The conversation contains information that might be useful later
|
||||
5. Plans, tasks, or action items are mentioned
|
||||
|
||||
**Protocol for recording context**:
|
||||
|
||||
1. Identify valuable information in the conversation
|
||||
2. Ask the user: "Would you like me to record our discussion about [topic] in Basic Memory?"
|
||||
3. If they agree, use `write_note` to capture the information
|
||||
4. If they decline, continue without recording
|
||||
5. Let the user know when information has been recorded: "I've saved our discussion about [topic] to Basic Memory."
|
||||
|
||||
## Understanding User Interactions
|
||||
|
||||
Users will interact with Basic Memory in patterns like:
|
||||
|
||||
1. **Creating knowledge**:
|
||||
```
|
||||
Human: "Let's write up what we discussed about search."
|
||||
|
||||
You: I'll create a note capturing our discussion about the search functionality.
|
||||
[Use write_note() to record the conversation details]
|
||||
```
|
||||
|
||||
2. **Referencing existing knowledge**:
|
||||
```
|
||||
Human: "Take a look at memory://specs/search"
|
||||
|
||||
You: I'll examine that information.
|
||||
[Use build_context() to gather related information]
|
||||
[Then read_note() to access specific content]
|
||||
```
|
||||
|
||||
3. **Finding information**:
|
||||
```
|
||||
Human: "What were our decisions about auth?"
|
||||
|
||||
You: Let me find that information for you.
|
||||
[Use search_notes() to find relevant notes]
|
||||
[Then build_context() to understand connections]
|
||||
```
|
||||
|
||||
4. **Editing existing notes (v0.13.0)**:
|
||||
```
|
||||
Human: "Add a section about deployment to my API documentation"
|
||||
|
||||
You: I'll add that section to your existing documentation.
|
||||
[Use edit_note() with operation="append" to add new content]
|
||||
```
|
||||
|
||||
5. **Project management (v0.13.0)**:
|
||||
```
|
||||
Human: "Switch to my work project and show recent activity"
|
||||
|
||||
You: I'll switch to your work project and check what's been updated recently.
|
||||
[Use switch_project() then recent_activity()]
|
||||
```
|
||||
|
||||
6. **File organization (v0.13.0)**:
|
||||
```
|
||||
Human: "Move my old meeting notes to the archive folder"
|
||||
|
||||
You: I'll organize those notes for you.
|
||||
[Use move_note() to relocate files with database consistency]
|
||||
```
|
||||
|
||||
## Key Things to Remember
|
||||
|
||||
1. **Files are Truth**
|
||||
- All knowledge lives in local files on the user's computer
|
||||
- Users can edit files outside your interaction
|
||||
- Changes need to be synced by the user (usually automatic)
|
||||
- Always verify information is current with `recent_activity()`
|
||||
|
||||
2. **Building Context Effectively**
|
||||
- Start with specific entities
|
||||
- Follow meaningful relations
|
||||
- Check recent changes
|
||||
- Build context incrementally
|
||||
- Combine related information
|
||||
|
||||
3. **Writing Knowledge Wisely**
|
||||
- Same title+folder overwrites existing notes
|
||||
- Structure with clear headings and semantic markup
|
||||
- Use tags for searchability (v0.13.0: frontmatter tags indexed)
|
||||
- Keep files organized in logical folders
|
||||
|
||||
4. **Leverage v0.13.0 Features**
|
||||
- **Edit incrementally**: Use `edit_note()` for small changes vs rewriting
|
||||
- **Switch projects**: Change context when user mentions different work areas
|
||||
- **Organize proactively**: Move old content to archive folders
|
||||
- **Cross-project operations**: Create notes in specific projects while maintaining context
|
||||
|
||||
## Common Knowledge Patterns
|
||||
|
||||
### Capturing Decisions
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
tags: [coffee, brewing, pour-over, techniques] # v0.13.0: Now searchable!
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Context
|
||||
I've experimented with various brewing methods including French press, pour over, and espresso.
|
||||
|
||||
## Decision
|
||||
Pour over is my preferred method for light to medium roasts because it highlights subtle flavors and offers more control over the extraction.
|
||||
|
||||
## Observations
|
||||
- [technique] Blooming the coffee grounds for 30 seconds improves extraction #brewing
|
||||
- [preference] Water temperature between 195-205°F works best #temperature
|
||||
- [equipment] Gooseneck kettle provides better control of water flow #tools
|
||||
- [timing] Total brew time of 3-4 minutes produces optimal extraction #process
|
||||
|
||||
## Relations
|
||||
- pairs_with [[Light Roast Beans]]
|
||||
- contrasts_with [[French Press Method]]
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- part_of [[Morning Coffee Routine]]
|
||||
```
|
||||
|
||||
### Recording Project Structure
|
||||
|
||||
```markdown
|
||||
# Garden Planning
|
||||
|
||||
## Overview
|
||||
This document outlines the garden layout and planting strategy for this season.
|
||||
|
||||
## Observations
|
||||
- [structure] Raised beds in south corner for sun exposure #layout
|
||||
- [structure] Drip irrigation system installed for efficiency #watering
|
||||
- [pattern] Companion planting used to deter pests naturally #technique
|
||||
|
||||
## Relations
|
||||
- contains [[Vegetable Section]]
|
||||
- contains [[Herb Garden]]
|
||||
- implements [[Organic Gardening Principles]]
|
||||
```
|
||||
|
||||
### Technical Discussions
|
||||
|
||||
```markdown
|
||||
# Recipe Improvement Discussion
|
||||
|
||||
## Key Points
|
||||
Discussed strategies for improving the chocolate chip cookie recipe.
|
||||
|
||||
## Observations
|
||||
- [issue] Cookies spread too thin when baked at 350°F #texture
|
||||
- [solution] Chilling dough for 24 hours improves flavor and reduces spreading #technique
|
||||
- [decision] Will use brown butter instead of regular butter #flavor
|
||||
|
||||
## Relations
|
||||
- improves [[Basic Cookie Recipe]]
|
||||
- inspired_by [[Bakery-Style Cookies]]
|
||||
- pairs_with [[Homemade Ice Cream]]
|
||||
```
|
||||
|
||||
## v0.13.0 Workflow Examples
|
||||
|
||||
### Multi-Project Conversations
|
||||
|
||||
**User:** "I need to update my work documentation and also add a personal recipe note."
|
||||
|
||||
**Workflow:**
|
||||
1. `list_projects()` - Check available projects
|
||||
2. `write_note(title="Sprint Planning", project="work-notes")` - Work content
|
||||
3. `write_note(title="Weekend Recipes", project="personal")` - Personal content
|
||||
|
||||
### Incremental Note Building
|
||||
|
||||
**User:** "Add a troubleshooting section to my setup guide."
|
||||
|
||||
**Workflow:**
|
||||
1. `edit_note(identifier="Setup Guide", operation="append", content="\n## Troubleshooting\n...")`
|
||||
|
||||
**User:** "Update the authentication section in my API docs."
|
||||
|
||||
**Workflow:**
|
||||
1. `edit_note(identifier="API Documentation", operation="replace_section", section="## Authentication")`
|
||||
|
||||
### Smart File Organization
|
||||
|
||||
**User:** "My notes are getting messy in the main folder."
|
||||
|
||||
**Workflow:**
|
||||
1. `move_note("Old Meeting Notes", "archive/2024/old-meetings.md")`
|
||||
2. `move_note("Project Notes", "projects/client-work/notes.md")`
|
||||
|
||||
### Creating Effective Relations
|
||||
|
||||
When creating relations:
|
||||
1. **Reference existing entities** by their exact title: `[[Exact Title]]`
|
||||
2. **Create forward references** to entities that don't exist yet - they'll be linked automatically when created
|
||||
3. **Search first** to find existing entities to reference
|
||||
4. **Use meaningful relation types**: `implements`, `requires`, `part_of` vs generic `relates_to`
|
||||
|
||||
**Example workflow:**
|
||||
1. `search_notes("travel")` to find existing travel-related notes
|
||||
2. Reference found entities: `- part_of [[Japan Travel Guide]]`
|
||||
3. Add forward references: `- located_in [[Tokyo]]` (even if Tokyo note doesn't exist yet)
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
**Missing Content:**
|
||||
- Try `search_notes()` with broader terms if `read_note()` fails
|
||||
- Use fuzzy matching: search for partial titles
|
||||
|
||||
**Forward References:**
|
||||
- These are normal! Basic Memory links them automatically when target notes are created
|
||||
- Inform users: "I've created forward references that will be linked when you create those notes"
|
||||
|
||||
**Sync Issues:**
|
||||
- If information seems outdated, suggest `basic-memory sync`
|
||||
- Use `recent_activity()` to check if content is current
|
||||
|
||||
**Strict Mode for Edit/Move Operations:**
|
||||
- `edit_note()` and `move_note()` require **exact identifiers** (no fuzzy matching for safety)
|
||||
- If identifier not found: use `search_notes()` first to find the exact title/permalink
|
||||
- Error messages will guide you to find correct identifiers
|
||||
- Example workflow:
|
||||
```
|
||||
# ❌ This might fail if identifier isn't exact
|
||||
edit_note("Meeting Note", "append", "content")
|
||||
|
||||
# ✅ Safe approach: search first, then use exact result
|
||||
results = search_notes("meeting")
|
||||
edit_note("Meeting Notes 2024", "append", "content") # Use exact title from search
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Proactively Record Context**
|
||||
- Offer to capture important discussions
|
||||
- Record decisions, rationales, and conclusions
|
||||
- Link to related topics
|
||||
- Ask for permission first: "Would you like me to save our discussion about [topic]?"
|
||||
- Confirm when complete: "I've saved our discussion to Basic Memory"
|
||||
|
||||
2. **Create a Rich Semantic Graph**
|
||||
- **Add meaningful observations**: Include at least 3-5 categorized observations in each note
|
||||
- **Create deliberate relations**: Connect each note to at least 2-3 related entities
|
||||
- **Use existing entities**: Before creating a new relation, search for existing entities
|
||||
- **Verify wikilinks**: When referencing `[[Entity]]`, use exact titles of existing notes
|
||||
- **Check accuracy**: Use `search_notes()` or `recent_activity()` to confirm entity titles
|
||||
- **Use precise relation types**: Choose specific relation types that convey meaning (e.g., "implements" instead of "relates_to")
|
||||
- **Consider bidirectional relations**: When appropriate, create inverse relations in both entities
|
||||
|
||||
3. **Structure Content Thoughtfully**
|
||||
- Use clear, descriptive titles
|
||||
- Organize with logical sections (Context, Decision, Implementation, etc.)
|
||||
- Include relevant context and background
|
||||
- Add semantic observations with appropriate categories
|
||||
- Use a consistent format for similar types of notes
|
||||
- Balance detail with conciseness
|
||||
|
||||
4. **Navigate Knowledge Effectively**
|
||||
- Start with specific searches
|
||||
- Follow relation paths
|
||||
- Combine information from multiple sources
|
||||
- Verify information is current
|
||||
- Build a complete picture before responding
|
||||
|
||||
5. **Help Users Maintain Their Knowledge**
|
||||
- Suggest organizing related topics
|
||||
- Identify potential duplicates
|
||||
- Recommend adding relations between topics
|
||||
- Offer to create summaries of scattered information
|
||||
- Suggest potential missing relations: "I notice this might relate to [topic], would you like me to add that connection?"
|
||||
|
||||
|
||||
Built with ♥️ by Basic Machines
|
||||
@@ -0,0 +1,442 @@
|
||||
# Basic Memory Architecture
|
||||
|
||||
This document describes the architectural patterns and composition structure of Basic Memory.
|
||||
|
||||
## Overview
|
||||
|
||||
Basic Memory is a local-first knowledge management system with three entrypoints:
|
||||
- **API** - FastAPI REST server for HTTP access
|
||||
- **MCP** - Model Context Protocol server for LLM integration
|
||||
- **CLI** - Typer command-line interface
|
||||
|
||||
Each entrypoint uses a **composition root** pattern to manage configuration and dependencies.
|
||||
|
||||
## Composition Roots
|
||||
|
||||
### What is a Composition Root?
|
||||
|
||||
A composition root is the single place in an application where dependencies are wired together. In Basic Memory, each entrypoint has its own composition root that:
|
||||
|
||||
1. Reads configuration from `ConfigManager`
|
||||
2. Resolves runtime mode (local/test)
|
||||
3. Creates and provides dependencies to downstream code
|
||||
|
||||
**Key principle**: Only composition roots read global configuration. All other modules receive configuration explicitly.
|
||||
|
||||
### Container Structure
|
||||
|
||||
Each entrypoint has a container dataclass in its package:
|
||||
|
||||
```
|
||||
src/basic_memory/
|
||||
├── api/
|
||||
│ └── container.py # ApiContainer
|
||||
├── mcp/
|
||||
│ └── container.py # McpContainer
|
||||
├── cli/
|
||||
│ └── container.py # CliContainer
|
||||
└── runtime.py # RuntimeMode enum and resolver
|
||||
```
|
||||
|
||||
### Container Pattern
|
||||
|
||||
All containers follow the same structure:
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class Container:
|
||||
config: BasicMemoryConfig
|
||||
mode: RuntimeMode
|
||||
|
||||
@classmethod
|
||||
def create(cls) -> "Container":
|
||||
"""Create container by reading ConfigManager."""
|
||||
config = ConfigManager().config
|
||||
mode = resolve_runtime_mode(is_test_env=config.is_test_env)
|
||||
return cls(config=config, mode=mode)
|
||||
|
||||
@property
|
||||
def some_computed_property(self) -> bool:
|
||||
"""Derived values based on config and mode."""
|
||||
return self.mode.is_local and self.config.some_setting
|
||||
|
||||
# Module-level singleton
|
||||
_container: Container | None = None
|
||||
|
||||
def get_container() -> Container:
|
||||
if _container is None:
|
||||
raise RuntimeError("Container not initialized")
|
||||
return _container
|
||||
|
||||
def set_container(container: Container) -> None:
|
||||
global _container
|
||||
_container = container
|
||||
```
|
||||
|
||||
### Runtime Mode Resolution
|
||||
|
||||
The `RuntimeMode` enum centralizes mode detection:
|
||||
|
||||
```python
|
||||
class RuntimeMode(Enum):
|
||||
LOCAL = "local"
|
||||
CLOUD = "cloud"
|
||||
TEST = "test"
|
||||
|
||||
@property
|
||||
def is_cloud(self) -> bool:
|
||||
return self == RuntimeMode.CLOUD
|
||||
|
||||
@property
|
||||
def is_local(self) -> bool:
|
||||
return self == RuntimeMode.LOCAL
|
||||
|
||||
@property
|
||||
def is_test(self) -> bool:
|
||||
return self == RuntimeMode.TEST
|
||||
```
|
||||
|
||||
Resolution follows this precedence in local app flows: **TEST > LOCAL**
|
||||
|
||||
```python
|
||||
def resolve_runtime_mode(is_test_env: bool) -> RuntimeMode:
|
||||
if is_test_env:
|
||||
return RuntimeMode.TEST
|
||||
return RuntimeMode.LOCAL
|
||||
```
|
||||
|
||||
**Note**: `RuntimeMode` determines global behavior (e.g., whether to start file sync).
|
||||
Per-project routing is orthogonal: individual projects can be set to `cloud` mode via `ProjectMode`,
|
||||
which affects client routing in `get_client(project_name=...)` without changing global runtime mode.
|
||||
`RuntimeMode.CLOUD` may remain for compatibility, but standard local runtime resolution does not select it.
|
||||
|
||||
## Dependencies Package
|
||||
|
||||
### Structure
|
||||
|
||||
The `deps/` package provides FastAPI dependencies organized by feature:
|
||||
|
||||
```
|
||||
src/basic_memory/deps/
|
||||
├── __init__.py # Re-exports for backwards compatibility
|
||||
├── config.py # Configuration access
|
||||
├── db.py # Database/session management
|
||||
├── projects.py # Project resolution
|
||||
├── repositories.py # Data access layer
|
||||
├── services.py # Business logic layer
|
||||
└── importers.py # Import functionality
|
||||
```
|
||||
|
||||
### Usage in Routers
|
||||
|
||||
```python
|
||||
from basic_memory.deps.services import get_entity_service
|
||||
from basic_memory.deps.projects import get_project_config
|
||||
|
||||
@router.get("/entities/{id}")
|
||||
async def get_entity(
|
||||
id: int,
|
||||
entity_service: EntityService = Depends(get_entity_service),
|
||||
project: ProjectConfig = Depends(get_project_config),
|
||||
):
|
||||
return await entity_service.get(id)
|
||||
```
|
||||
|
||||
### Backwards Compatibility
|
||||
|
||||
The old `deps.py` file still exists as a thin re-export shim:
|
||||
|
||||
```python
|
||||
# deps.py - backwards compatibility shim
|
||||
from basic_memory.deps import *
|
||||
```
|
||||
|
||||
New code should import from specific submodules (`basic_memory.deps.services`) for clarity.
|
||||
|
||||
## MCP Tools Architecture
|
||||
|
||||
### Typed API Clients
|
||||
|
||||
MCP tools communicate with the API through typed clients that encapsulate HTTP paths and response validation:
|
||||
|
||||
```
|
||||
src/basic_memory/mcp/clients/
|
||||
├── __init__.py # Re-exports all clients
|
||||
├── base.py # BaseClient with common logic
|
||||
├── knowledge.py # KnowledgeClient - entity CRUD
|
||||
├── search.py # SearchClient - search operations
|
||||
├── memory.py # MemoryClient - context building
|
||||
├── directory.py # DirectoryClient - directory listing
|
||||
├── resource.py # ResourceClient - resource reading
|
||||
└── project.py # ProjectClient - project management
|
||||
```
|
||||
|
||||
### Client Pattern
|
||||
|
||||
Each client encapsulates API paths and validates responses:
|
||||
|
||||
```python
|
||||
class KnowledgeClient(BaseClient):
|
||||
"""Client for knowledge/entity operations."""
|
||||
|
||||
async def resolve_entity(self, identifier: str) -> int:
|
||||
"""Resolve identifier to entity ID."""
|
||||
response = await call_get(
|
||||
self.http_client,
|
||||
f"{self._base_path}/resolve/{identifier}",
|
||||
)
|
||||
return int(response.text)
|
||||
|
||||
async def get_entity(self, entity_id: int) -> EntityResponse:
|
||||
"""Get entity by ID."""
|
||||
response = await call_get(
|
||||
self.http_client,
|
||||
f"{self._base_path}/entities/{entity_id}",
|
||||
)
|
||||
return EntityResponse.model_validate(response.json())
|
||||
```
|
||||
|
||||
### Tool → Client → API Flow
|
||||
|
||||
```
|
||||
MCP Tool (thin adapter)
|
||||
↓
|
||||
Typed Client (encapsulates paths, validates responses)
|
||||
↓
|
||||
HTTP API (FastAPI router)
|
||||
↓
|
||||
Service Layer (business logic)
|
||||
↓
|
||||
Repository Layer (data access)
|
||||
```
|
||||
|
||||
Example tool using typed client:
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
async def search_notes(
|
||||
query: str,
|
||||
project: str | None = None,
|
||||
metadata_filters: dict | None = None,
|
||||
tags: list[str] | None = None,
|
||||
status: str | None = None,
|
||||
) -> SearchResponse:
|
||||
async with get_project_client(project, context) as (client, active_project):
|
||||
# Import client inside function to avoid circular imports
|
||||
from basic_memory.mcp.clients import SearchClient
|
||||
from basic_memory.schemas.search import SearchQuery
|
||||
|
||||
search_query = SearchQuery(
|
||||
text=query,
|
||||
metadata_filters=metadata_filters,
|
||||
tags=tags,
|
||||
status=status,
|
||||
)
|
||||
search_client = SearchClient(client, active_project.external_id)
|
||||
return await search_client.search(search_query.model_dump())
|
||||
```
|
||||
|
||||
### Per-Project Client Routing
|
||||
|
||||
`get_project_client()` from `mcp/project_context.py` is an async context manager that:
|
||||
1. Resolves the project name from config (no network call)
|
||||
2. Creates the correctly-routed client based on the project's mode (local ASGI or cloud HTTP with API key)
|
||||
3. Validates the project via the API
|
||||
4. Yields `(client, active_project)` tuple
|
||||
|
||||
This solves the bootstrap problem: you need the project name to choose the right client (local vs cloud), but you need the client to validate the project exists.
|
||||
|
||||
```python
|
||||
from basic_memory.mcp.project_context import get_project_client
|
||||
|
||||
async with get_project_client(project, context) as (client, active_project):
|
||||
# client is routed based on project's mode (local or cloud)
|
||||
# active_project is validated via the API
|
||||
...
|
||||
```
|
||||
|
||||
## Sync Coordination
|
||||
|
||||
### SyncCoordinator
|
||||
|
||||
The `SyncCoordinator` centralizes sync/watch lifecycle management:
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class SyncCoordinator:
|
||||
"""Coordinates file sync and watch operations."""
|
||||
|
||||
status: SyncStatus = SyncStatus.NOT_STARTED
|
||||
sync_task: asyncio.Task | None = None
|
||||
watch_service: WatchService | None = None
|
||||
|
||||
async def start(self, ...):
|
||||
"""Start sync and watch operations."""
|
||||
|
||||
async def stop(self):
|
||||
"""Stop all sync operations gracefully."""
|
||||
|
||||
def get_status_info(self) -> dict:
|
||||
"""Get current sync status for observability."""
|
||||
```
|
||||
|
||||
### Status Enum
|
||||
|
||||
```python
|
||||
class SyncStatus(Enum):
|
||||
NOT_STARTED = "not_started"
|
||||
STARTING = "starting"
|
||||
RUNNING = "running"
|
||||
STOPPING = "stopping"
|
||||
STOPPED = "stopped"
|
||||
ERROR = "error"
|
||||
```
|
||||
|
||||
## Project Resolution
|
||||
|
||||
### ProjectResolver
|
||||
|
||||
Unified project selection across all entrypoints:
|
||||
|
||||
```python
|
||||
class ProjectResolver:
|
||||
"""Resolves which project to use based on context."""
|
||||
|
||||
def resolve(
|
||||
self,
|
||||
explicit_project: str | None = None,
|
||||
) -> ResolvedProject:
|
||||
"""Resolve project using three-tier hierarchy:
|
||||
1. Explicit project parameter
|
||||
2. Default project from config
|
||||
3. Single available project
|
||||
"""
|
||||
```
|
||||
|
||||
### Resolution Modes
|
||||
|
||||
```python
|
||||
class ResolutionMode(Enum):
|
||||
EXPLICIT = "explicit" # User specified project
|
||||
DEFAULT = "default" # Using configured default
|
||||
SINGLE_PROJECT = "single" # Only one project exists
|
||||
FALLBACK = "fallback" # Using first available
|
||||
```
|
||||
|
||||
## Testing Patterns
|
||||
|
||||
### Container Testing
|
||||
|
||||
Each container has corresponding tests:
|
||||
|
||||
```
|
||||
tests/
|
||||
├── api/test_api_container.py
|
||||
├── mcp/test_mcp_container.py
|
||||
└── cli/test_cli_container.py
|
||||
```
|
||||
|
||||
Tests verify:
|
||||
- Container creation from config
|
||||
- Runtime mode properties
|
||||
- Container accessor functions (get/set)
|
||||
|
||||
### Mocking Typed Clients
|
||||
|
||||
When testing MCP tools, mock at the client level:
|
||||
|
||||
```python
|
||||
def test_search_notes(monkeypatch):
|
||||
import basic_memory.mcp.clients as clients_mod
|
||||
|
||||
class MockSearchClient:
|
||||
async def search(self, query):
|
||||
return SearchResponse(results=[...])
|
||||
|
||||
monkeypatch.setattr(clients_mod, "SearchClient", MockSearchClient)
|
||||
```
|
||||
|
||||
## Design Principles
|
||||
|
||||
### 1. Explicit Dependencies
|
||||
|
||||
Modules receive configuration explicitly rather than reading globals:
|
||||
|
||||
```python
|
||||
# Good - explicit injection
|
||||
async def sync_files(config: BasicMemoryConfig):
|
||||
...
|
||||
|
||||
# Avoid - hidden global access
|
||||
async def sync_files():
|
||||
config = ConfigManager().config # Hidden coupling
|
||||
```
|
||||
|
||||
### 2. Single Responsibility
|
||||
|
||||
Each layer has a clear responsibility:
|
||||
- **Containers**: Wire dependencies
|
||||
- **Clients**: Encapsulate HTTP communication
|
||||
- **Services**: Business logic
|
||||
- **Repositories**: Data access
|
||||
- **Tools/Routers**: Thin adapters
|
||||
|
||||
### 3. Deferred Imports
|
||||
|
||||
To avoid circular imports, typed clients are imported inside functions:
|
||||
|
||||
```python
|
||||
async def my_tool():
|
||||
async with get_client() as client:
|
||||
# Import here to avoid circular dependency
|
||||
from basic_memory.mcp.clients import KnowledgeClient
|
||||
|
||||
knowledge_client = KnowledgeClient(client, project_id)
|
||||
```
|
||||
|
||||
### 4. Backwards Compatibility
|
||||
|
||||
When refactoring, maintain backwards compatibility via shims:
|
||||
|
||||
```python
|
||||
# Old module becomes a shim
|
||||
from basic_memory.new_location import *
|
||||
|
||||
# Docstring explains migration path
|
||||
"""
|
||||
DEPRECATED: Import from basic_memory.new_location instead.
|
||||
This shim will be removed in a future version.
|
||||
"""
|
||||
```
|
||||
|
||||
## File Organization
|
||||
|
||||
```
|
||||
src/basic_memory/
|
||||
├── api/
|
||||
│ ├── container.py # API composition root
|
||||
│ ├── routers/ # FastAPI routers
|
||||
│ └── ...
|
||||
├── mcp/
|
||||
│ ├── container.py # MCP composition root
|
||||
│ ├── clients/ # Typed API clients
|
||||
│ ├── tools/ # MCP tool definitions
|
||||
│ └── server.py # MCP server setup
|
||||
├── cli/
|
||||
│ ├── container.py # CLI composition root
|
||||
│ ├── app.py # Typer app
|
||||
│ └── commands/ # CLI command groups
|
||||
├── deps/
|
||||
│ ├── config.py # Config dependencies
|
||||
│ ├── db.py # Database dependencies
|
||||
│ ├── projects.py # Project dependencies
|
||||
│ ├── repositories.py # Repository dependencies
|
||||
│ ├── services.py # Service dependencies
|
||||
│ └── importers.py # Importer dependencies
|
||||
├── sync/
|
||||
│ ├── coordinator.py # SyncCoordinator
|
||||
│ └── ...
|
||||
├── runtime.py # RuntimeMode resolution
|
||||
├── project_resolver.py # Unified project selection
|
||||
└── config.py # Configuration management
|
||||
```
|
||||
@@ -1,414 +0,0 @@
|
||||
---
|
||||
title: CLI Reference
|
||||
type: note
|
||||
permalink: docs/cli-reference
|
||||
---
|
||||
|
||||
# CLI Reference
|
||||
|
||||
Basic Memory provides command line tools for managing your knowledge base. This reference covers the available commands and their options.
|
||||
|
||||
## Core Commands
|
||||
|
||||
### auth (New in v0.13.0)
|
||||
|
||||
Manage OAuth authentication for secure remote access:
|
||||
|
||||
```bash
|
||||
# Test authentication setup
|
||||
basic-memory auth test-auth
|
||||
|
||||
# Register OAuth client
|
||||
basic-memory auth register-client
|
||||
```
|
||||
|
||||
Supports multiple authentication providers:
|
||||
- **Basic Provider**: For development and testing
|
||||
- **Supabase Provider**: For production deployments
|
||||
- **External Providers**: GitHub, Google integration framework
|
||||
|
||||
See [[OAuth Authentication Guide]] for complete setup instructions.
|
||||
|
||||
### sync
|
||||
|
||||
Keeps files and the knowledge graph in sync:
|
||||
|
||||
```bash
|
||||
# Basic sync
|
||||
basic-memory sync
|
||||
|
||||
# Watch for changes
|
||||
basic-memory sync --watch
|
||||
|
||||
# Show detailed sync information
|
||||
basic-memory sync --verbose
|
||||
```
|
||||
|
||||
Options:
|
||||
- `--watch`: Continuously monitor for changes
|
||||
- `--verbose`: Show detailed output
|
||||
|
||||
**Note**:
|
||||
|
||||
As of the v0.12.0 release syncing will occur in real time when the mcp process starts.
|
||||
- The real time sync means that it is no longer necessary to run the `basic-memory sync --watch` process in a a terminal to sync changes to the db (so the AI can see them). This will be done automatically.
|
||||
|
||||
This behavior can be changed via the config. The config file for Basic Memory is in the home directory under `.basic-memory/config.json`.
|
||||
|
||||
To change the properties, set the following values:
|
||||
```
|
||||
~/.basic-memory/config.json
|
||||
{
|
||||
"sync_changes": false,
|
||||
}
|
||||
```
|
||||
|
||||
Thanks for using Basic Memory!
|
||||
### import (Enhanced in v0.13.0)
|
||||
|
||||
Imports external knowledge sources with support for project targeting:
|
||||
|
||||
```bash
|
||||
# Claude conversations
|
||||
basic-memory import claude conversations
|
||||
|
||||
# Claude projects
|
||||
basic-memory import claude projects
|
||||
|
||||
# ChatGPT history
|
||||
basic-memory import chatgpt
|
||||
|
||||
# Memory JSON format
|
||||
basic-memory import memory-json /path/to/memory.json
|
||||
|
||||
# Import to specific project (v0.13.0)
|
||||
basic-memory --project=work import claude conversations
|
||||
```
|
||||
|
||||
**New in v0.13.0:**
|
||||
- **Project Targeting**: Import directly to specific projects
|
||||
- **Real-time Sync**: Imported content available immediately
|
||||
- **Unified Database**: All imports stored in centralized database
|
||||
|
||||
> **Note**: Changes sync automatically - no manual sync required in v0.13.0.
|
||||
### status
|
||||
|
||||
Shows system status information:
|
||||
|
||||
```bash
|
||||
# Basic status check
|
||||
basic-memory status
|
||||
|
||||
# Detailed status
|
||||
basic-memory status --verbose
|
||||
|
||||
# JSON output
|
||||
basic-memory status --json
|
||||
```
|
||||
|
||||
|
||||
### project (Enhanced in v0.13.0)
|
||||
|
||||
Manage multiple projects with the new unified database architecture. Projects can now be switched instantly during conversations without restart.
|
||||
|
||||
```bash
|
||||
# List all configured projects with status
|
||||
basic-memory project list
|
||||
|
||||
# Create a new project
|
||||
basic-memory project create work ~/work-basic-memory
|
||||
|
||||
# Set the default project
|
||||
basic-memory project set-default work
|
||||
|
||||
# Delete a project (doesn't delete files)
|
||||
basic-memory project delete personal
|
||||
|
||||
# Show detailed project statistics
|
||||
basic-memory project info
|
||||
```
|
||||
|
||||
**New in v0.13.0:**
|
||||
- **Unified Database**: All projects share a single database for better performance
|
||||
- **Instant Switching**: Switch projects during conversations without restart
|
||||
- **Enhanced Commands**: Updated project commands with better status information
|
||||
- **Project Statistics**: Detailed info about entities, observations, and relations
|
||||
|
||||
#### Using Projects in Commands
|
||||
|
||||
All commands support the `--project` flag to specify which project to use:
|
||||
|
||||
```bash
|
||||
# Sync a specific project
|
||||
basic-memory --project=work sync
|
||||
|
||||
# Run MCP server for a specific project
|
||||
basic-memory --project=personal mcp
|
||||
```
|
||||
|
||||
You can also set the `BASIC_MEMORY_PROJECT` environment variable:
|
||||
|
||||
```bash
|
||||
BASIC_MEMORY_PROJECT=work basic-memory sync
|
||||
```
|
||||
|
||||
### tool (Enhanced in v0.13.0)
|
||||
|
||||
Direct access to MCP tools via CLI with new editing and file management capabilities:
|
||||
|
||||
```bash
|
||||
# Create notes
|
||||
basic-memory tool write-note --title "My Note" --content "Content here"
|
||||
|
||||
# Edit notes incrementally (v0.13.0)
|
||||
echo "New content" | basic-memory tool edit-note --title "My Note" --operation append
|
||||
|
||||
# Move notes (v0.13.0)
|
||||
basic-memory tool move-note --identifier "My Note" --destination "archive/my-note.md"
|
||||
|
||||
# Search notes
|
||||
basic-memory tool search-notes --query "authentication"
|
||||
|
||||
# Project management (v0.13.0)
|
||||
basic-memory tool list-projects
|
||||
basic-memory tool switch-project --project-name "work"
|
||||
```
|
||||
|
||||
**New in v0.13.0:**
|
||||
- **edit-note**: Incremental editing (append, prepend, find/replace, section replace)
|
||||
- **move-note**: File management with database consistency
|
||||
- **Project tools**: list-projects, switch-project, get-current-project
|
||||
- **Cross-project operations**: Use `--project` flag with any tool
|
||||
|
||||
### help
|
||||
|
||||
The full list of commands and help for each can be viewed with the `--help` argument.
|
||||
|
||||
```
|
||||
✗ basic-memory --help
|
||||
|
||||
Usage: basic-memory [OPTIONS] COMMAND [ARGS]...
|
||||
|
||||
Basic Memory - Local-first personal knowledge management system.
|
||||
|
||||
╭─ Options ─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ --project -p TEXT Specify which project to use │
|
||||
│ [env var: BASIC_MEMORY_PROJECT] │
|
||||
│ [default: None] │
|
||||
│ --version -V Show version information and exit. │
|
||||
│ --install-completion Install completion for the current shell. │
|
||||
│ --show-completion Show completion for the current shell, to copy it or │
|
||||
│ customize the installation. │
|
||||
│ --help Show this message and exit. │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭─ Commands ────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ auth OAuth authentication management (v0.13.0) │
|
||||
│ sync Sync knowledge files with the database │
|
||||
│ status Show sync status between files and database │
|
||||
│ reset Reset database (drop all tables and recreate) │
|
||||
│ mcp Run the MCP server for Claude Desktop integration │
|
||||
│ import Import data from various sources │
|
||||
│ tool Direct access to MCP tools via CLI │
|
||||
│ project Manage multiple Basic Memory projects │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
## Initial Setup
|
||||
|
||||
```bash
|
||||
# Install Basic Memory
|
||||
uv install basic-memory
|
||||
|
||||
# First sync
|
||||
basic-memory sync
|
||||
|
||||
# Start watching mode
|
||||
basic-memory sync --watch
|
||||
```
|
||||
|
||||
> **Important**: You need to install Basic Memory via `uv` or `pip` to use the command line tools, see [[Getting Started with Basic Memory#Installation]].
|
||||
|
||||
## Regular Usage
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
basic-memory status
|
||||
|
||||
# Import new content
|
||||
basic-memory import claude conversations
|
||||
|
||||
# Sync changes
|
||||
basic-memory sync
|
||||
|
||||
# Sync changes continuously
|
||||
basic-memory sync --watch
|
||||
```
|
||||
|
||||
## Maintenance Tasks
|
||||
|
||||
```bash
|
||||
# Check system status in detail
|
||||
basic-memory status --verbose
|
||||
|
||||
# Full resync of all files
|
||||
basic-memory sync
|
||||
|
||||
# Import updates to specific folder
|
||||
basic-memory import claude conversations --folder new
|
||||
```
|
||||
|
||||
|
||||
## Using stdin with Basic Memory's `write_note` Tool
|
||||
|
||||
The `write-note` tool supports reading content from standard input (stdin), allowing for more flexible workflows when creating or updating notes in your Basic Memory knowledge base.
|
||||
|
||||
### Use Cases
|
||||
|
||||
This feature is particularly useful for:
|
||||
|
||||
1. **Piping output from other commands** directly into Basic Memory notes
|
||||
2. **Creating notes with multi-line content** without having to escape quotes or special characters
|
||||
3. **Integrating with AI assistants** like Claude Code that can generate content and pipe it to Basic Memory
|
||||
4. **Processing text data** from files or other sources
|
||||
|
||||
### Basic Usage
|
||||
|
||||
#### Method 1: Using a Pipe
|
||||
|
||||
You can pipe content from another command into `write_note`:
|
||||
|
||||
```bash
|
||||
# Pipe output of a command into a new note
|
||||
echo "# My Note\n\nThis is a test note" | basic-memory tool write-note --title "Test Note" --folder "notes"
|
||||
|
||||
# Pipe output of a file into a new note
|
||||
cat README.md | basic-memory tool write-note --title "Project README" --folder "documentation"
|
||||
|
||||
# Process text through other tools before saving as a note
|
||||
cat data.txt | grep "important" | basic-memory tool write-note --title "Important Data" --folder "data"
|
||||
```
|
||||
|
||||
#### Method 2: Using Heredoc Syntax
|
||||
|
||||
For multi-line content, you can use heredoc syntax:
|
||||
|
||||
```bash
|
||||
# Create a note with heredoc
|
||||
cat << EOF | basic-memory tool write_note --title "Project Ideas" --folder "projects"
|
||||
# Project Ideas for Q2
|
||||
|
||||
## AI Integration
|
||||
- Improve recommendation engine
|
||||
- Add semantic search to product catalog
|
||||
|
||||
## Infrastructure
|
||||
- Migrate to Kubernetes
|
||||
- Implement CI/CD pipeline
|
||||
EOF
|
||||
```
|
||||
|
||||
#### Method 3: Input Redirection
|
||||
|
||||
You can redirect input from a file:
|
||||
|
||||
```bash
|
||||
# Create a note from file content
|
||||
basic-memory tool write-note --title "Meeting Notes" --folder "meetings" < meeting_notes.md
|
||||
```
|
||||
|
||||
## Integration with Claude Code
|
||||
|
||||
This feature works well with Claude Code in the terminal:
|
||||
|
||||
### cli
|
||||
|
||||
In a Claude Code session, let Claude know he can use the basic-memory tools, then he can execute them via the cli:
|
||||
|
||||
```
|
||||
⏺ Bash(echo "# Test Note from Claude\n\nThis is a test note created by Claude to test the stdin functionality." | basic-memory tool write-note --title "Claude Test Note" --folder "test" --tags "test" --tags "claude")…
|
||||
⎿ # Created test/Claude Test Note.md (23e00eec)
|
||||
permalink: test/claude-test-note
|
||||
|
||||
## Tags
|
||||
- test, claude
|
||||
|
||||
```
|
||||
|
||||
### MCP
|
||||
|
||||
Claude code can also now use mcp tools, so it can use any of the basic-memory tool natively. To install basic-memory in Claude Code:
|
||||
|
||||
Run
|
||||
```
|
||||
claude mcp add basic-memory basic-memory mcp
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
➜ ~ claude mcp add basic-memory basic-memory mcp
|
||||
Added stdio MCP server basic-memory with command: basic-memory mcp to project config
|
||||
➜ ~ claude mcp list
|
||||
basic-memory: basic-memory mcp
|
||||
```
|
||||
|
||||
You can then use the `/mcp` command in the REPL:
|
||||
|
||||
```
|
||||
/mcp
|
||||
⎿ MCP Server Status
|
||||
|
||||
• basic-memory: connected
|
||||
```
|
||||
|
||||
## Version Management (New in v0.13.0)
|
||||
|
||||
Basic Memory v0.13.0 introduces automatic version management and multiple installation options:
|
||||
|
||||
```bash
|
||||
# Stable releases
|
||||
pip install basic-memory
|
||||
|
||||
# Beta/pre-releases
|
||||
pip install basic-memory --pre
|
||||
|
||||
# Latest development builds (auto-published)
|
||||
pip install basic-memory --pre --force-reinstall
|
||||
|
||||
# Check current version
|
||||
basic-memory --version
|
||||
```
|
||||
|
||||
**Version Types:**
|
||||
- **Stable**: `0.13.0` (manual git tags)
|
||||
- **Beta**: `0.13.0b1` (manual git tags)
|
||||
- **Development**: `0.12.4.dev26+468a22f` (automatic from commits)
|
||||
|
||||
## Troubleshooting Common Issues
|
||||
|
||||
### Sync Conflicts
|
||||
|
||||
If you encounter a file changed during sync error:
|
||||
1. Check the file referenced in the error message
|
||||
2. Resolve any conflicts manually
|
||||
3. Run sync again
|
||||
|
||||
### Import Errors
|
||||
|
||||
If import fails:
|
||||
1. Check that the source file is in the correct format
|
||||
2. Verify permissions on the target directory
|
||||
3. Use --verbose flag for detailed error information
|
||||
|
||||
### Status Issues
|
||||
|
||||
If status shows problems:
|
||||
1. Note any unresolved relations or warnings
|
||||
2. Run a full sync to attempt automatic resolution
|
||||
3. Check file permissions if database access errors occur
|
||||
|
||||
|
||||
## Relations
|
||||
- used_by [[Getting Started with Basic Memory]] (Installation instructions)
|
||||
- complements [[User Guide]] (How to use Basic Memory)
|
||||
- relates_to [[Introduction to Basic Memory]] (System overview)
|
||||
@@ -1,107 +0,0 @@
|
||||
---
|
||||
title: Canvas Visualizations
|
||||
type: note
|
||||
permalink: docs/canvas
|
||||
tags:
|
||||
- visualization
|
||||
- mapping
|
||||
- obsidian
|
||||
---
|
||||
|
||||
# Canvas Visualizations
|
||||
|
||||
Basic Memory can create visual knowledge maps using Obsidian's Canvas feature. These visualizations help you understand relationships between concepts, map out processes, and visualize your knowledge structure.
|
||||
|
||||
## Creating Canvas Visualizations
|
||||
|
||||
Ask Claude to create a visualization by describing what you want to map:
|
||||
|
||||
```
|
||||
You: "Create a canvas visualization of my project components and their relationships."
|
||||
|
||||
You: "Make a concept map showing the main themes from our discussion about climate change."
|
||||
|
||||
You: "Can you make a canvas diagram of the perfect pour over method?"
|
||||
```
|
||||
|
||||
![[Canvas.png]]
|
||||
|
||||
## Types of Visualizations
|
||||
|
||||
Basic Memory can create several types of visual maps:
|
||||
|
||||
### Document Maps
|
||||
Visualize connections between your notes and documents
|
||||
|
||||
### Concept Maps
|
||||
Create visual representations of ideas and their relationships
|
||||
|
||||
### Process Diagrams
|
||||
Map workflows, sequences, and procedures
|
||||
|
||||
### Thematic Analysis
|
||||
Organize ideas around central themes
|
||||
|
||||
### Relationship Networks
|
||||
Show how different entities relate to each other
|
||||
|
||||
## Visualization Sources
|
||||
|
||||
Claude can create visualizations based on:
|
||||
|
||||
### Documents in Your Knowledge Base
|
||||
```
|
||||
You: "Create a canvas showing the connections between my project planning documents"
|
||||
```
|
||||
|
||||
### Conversation Content
|
||||
```
|
||||
You: "Make a canvas visualization of the main points we just discussed"
|
||||
```
|
||||
|
||||
### Search Results
|
||||
```
|
||||
You: "Find all my notes about psychology and create a visual map of the concepts"
|
||||
```
|
||||
|
||||
### Themes and Relationships
|
||||
```
|
||||
You: "Create a visual map showing how different philosophical schools relate to each other"
|
||||
```
|
||||
|
||||
## Visualization Workflow
|
||||
|
||||
1. **Request a visualization** by describing what you want to see
|
||||
2. **Claude creates the canvas file** in your Basic Memory directory
|
||||
3. **Open the file in Obsidian** to view the visualization
|
||||
4. **Refine the visualization** by asking Claude for adjustments:
|
||||
```
|
||||
You: "Could you reorganize the canvas to group related components together?"
|
||||
|
||||
You: "Please add more detail about the connection between these two concepts."
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
Behind the scenes, Claude:
|
||||
|
||||
1. Creates a `.canvas` file in JSON format
|
||||
2. Adds nodes for each concept or document
|
||||
3. Creates edges to represent relationships
|
||||
4. Sets positions for visual clarity
|
||||
5. Includes any relevant metadata
|
||||
|
||||
The resulting file is fully compatible with Obsidian's Canvas feature and can be edited directly in Obsidian.
|
||||
|
||||
## Tips for Effective Visualizations
|
||||
|
||||
- **Be specific** about what you want to visualize
|
||||
- **Specify the level of detail** you need
|
||||
- **Mention the visualization type** you want (concept map, process flow, etc.)
|
||||
- **Start simple** and ask for refinements
|
||||
- **Provide context** about what documents or concepts to include
|
||||
|
||||
## Relations
|
||||
- enhances [[Obsidian Integration]] (Using Basic Memory with Obsidian)
|
||||
- visualizes [[Knowledge Format]] (The structure of your knowledge)
|
||||
- complements [[User Guide]] (Ways to use Basic Memory)
|
||||
@@ -1,335 +0,0 @@
|
||||
# Claude.ai Integration Guide
|
||||
|
||||
This guide explains how to connect Basic Memory to Claude.ai, enabling Claude to read and write to your personal knowledge base.
|
||||
|
||||
## Overview
|
||||
|
||||
When connected to Claude.ai, Basic Memory provides:
|
||||
- Persistent memory across conversations
|
||||
- Knowledge graph navigation
|
||||
- Note-taking and search capabilities
|
||||
- File organization and management
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Basic Memory MCP server with OAuth enabled
|
||||
2. Public HTTPS URL (or tunneling service for testing)
|
||||
3. Claude.ai account (Free, Pro, or Enterprise)
|
||||
|
||||
## Quick Start (Testing)
|
||||
|
||||
### 1. Start MCP Server with OAuth
|
||||
|
||||
```bash
|
||||
# Enable OAuth with basic provider
|
||||
export FASTMCP_AUTH_ENABLED=true
|
||||
export FASTMCP_AUTH_PROVIDER=basic
|
||||
|
||||
# Start server on all interfaces
|
||||
basic-memory mcp --transport streamable-http --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### 2. Make Server Accessible
|
||||
|
||||
For testing, use ngrok:
|
||||
|
||||
```bash
|
||||
# Install ngrok
|
||||
brew install ngrok # macOS
|
||||
# or download from https://ngrok.com
|
||||
|
||||
# Create tunnel
|
||||
ngrok http 8000
|
||||
```
|
||||
|
||||
Note the HTTPS URL (e.g., `https://abc123.ngrok.io`)
|
||||
|
||||
### 3. Register OAuth Client
|
||||
|
||||
```bash
|
||||
# Register a client for Claude
|
||||
basic-memory auth register-client --client-id claude-ai
|
||||
|
||||
# Save the credentials!
|
||||
# Client ID: claude-ai
|
||||
# Client Secret: xxx...
|
||||
```
|
||||
|
||||
### 4. Connect in Claude.ai
|
||||
|
||||
1. Go to Claude.ai → Settings → Integrations
|
||||
2. Click "Add More"
|
||||
3. Enter your server URL: `https://abc123.ngrok.io/mcp`
|
||||
4. Click "Connect"
|
||||
5. Authorize the connection
|
||||
|
||||
### 5. Use in Conversations
|
||||
|
||||
- Click the tools icon (🔧) in the chat
|
||||
- Select "Basic Memory"
|
||||
- Try commands like:
|
||||
- "Create a note about our meeting"
|
||||
- "Search for project ideas"
|
||||
- "Show recent notes"
|
||||
|
||||
## Production Setup
|
||||
|
||||
### 1. Deploy with Supabase Auth
|
||||
|
||||
```bash
|
||||
# .env file
|
||||
FASTMCP_AUTH_ENABLED=true
|
||||
FASTMCP_AUTH_PROVIDER=supabase
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_ANON_KEY=your-anon-key
|
||||
SUPABASE_SERVICE_KEY=your-service-key
|
||||
```
|
||||
|
||||
### 2. Deploy to Cloud
|
||||
|
||||
Options for deployment:
|
||||
|
||||
#### Vercel
|
||||
```json
|
||||
// vercel.json
|
||||
{
|
||||
"functions": {
|
||||
"api/mcp.py": {
|
||||
"runtime": "python3.9"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Railway
|
||||
```bash
|
||||
# Install Railway CLI
|
||||
brew install railway
|
||||
|
||||
# Deploy
|
||||
railway init
|
||||
railway up
|
||||
```
|
||||
|
||||
#### Docker
|
||||
```dockerfile
|
||||
FROM python:3.12
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install -e .
|
||||
CMD ["basic-memory", "mcp", "--transport", "streamable-http"]
|
||||
```
|
||||
|
||||
### 3. Configure for Organization
|
||||
|
||||
For Claude.ai Enterprise:
|
||||
|
||||
1. **Admin Setup**:
|
||||
- Go to Organizational Settings
|
||||
- Navigate to Integrations
|
||||
- Add MCP server URL for all users
|
||||
- Configure allowed scopes
|
||||
|
||||
2. **User Permissions**:
|
||||
- Users connect individually
|
||||
- Each user has their own auth token
|
||||
- Scopes determine access level
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### 1. Use HTTPS
|
||||
- Required for OAuth
|
||||
- Encrypt all data in transit
|
||||
- Use proper SSL certificates
|
||||
|
||||
### 2. Implement Scopes
|
||||
```bash
|
||||
# Configure required scopes
|
||||
FASTMCP_AUTH_REQUIRED_SCOPES=read,write
|
||||
|
||||
# User-specific scopes
|
||||
read: Can search and read notes
|
||||
write: Can create and update notes
|
||||
admin: Can manage all data
|
||||
```
|
||||
|
||||
### 3. Token Security
|
||||
- Short-lived access tokens (1 hour)
|
||||
- Refresh token rotation
|
||||
- Secure token storage
|
||||
|
||||
### 4. Rate Limiting
|
||||
```python
|
||||
# In your MCP server
|
||||
from fastapi import HTTPException
|
||||
from slowapi import Limiter
|
||||
|
||||
limiter = Limiter(key_func=get_remote_address)
|
||||
|
||||
@app.get("/mcp")
|
||||
@limiter.limit("100/minute")
|
||||
async def mcp_endpoint():
|
||||
# Handle MCP requests
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### 1. Custom Tools
|
||||
|
||||
Create specialized tools for Claude:
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
async def analyze_notes(topic: str) -> str:
|
||||
"""Analyze all notes on a specific topic."""
|
||||
# Search and analyze implementation
|
||||
return analysis
|
||||
```
|
||||
|
||||
### 2. Context Preservation
|
||||
|
||||
Use memory:// URLs to maintain context:
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
async def continue_conversation(memory_url: str) -> str:
|
||||
"""Continue from a previous conversation."""
|
||||
context = await build_context(memory_url)
|
||||
return context
|
||||
```
|
||||
|
||||
### 3. Multi-User Support
|
||||
|
||||
With Supabase, each user has isolated data:
|
||||
|
||||
```sql
|
||||
-- Row-level security
|
||||
CREATE POLICY "Users see own notes"
|
||||
ON notes FOR SELECT
|
||||
USING (auth.uid() = user_id);
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Issues
|
||||
|
||||
1. **"Failed to connect"**
|
||||
- Verify server is running
|
||||
- Check HTTPS is working
|
||||
- Confirm OAuth is enabled
|
||||
|
||||
2. **"Authorization failed"**
|
||||
- Check client credentials
|
||||
- Verify redirect URLs
|
||||
- Review OAuth logs
|
||||
|
||||
3. **"No tools available"**
|
||||
- Ensure MCP tools are registered
|
||||
- Check required scopes
|
||||
- Verify transport type
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable detailed logging:
|
||||
|
||||
```bash
|
||||
# Server side
|
||||
export FASTMCP_LOG_LEVEL=DEBUG
|
||||
export LOGURU_LEVEL=DEBUG
|
||||
|
||||
# Check logs
|
||||
tail -f logs/mcp.log
|
||||
```
|
||||
|
||||
### Test Connection
|
||||
|
||||
```bash
|
||||
# Test OAuth flow
|
||||
curl https://your-server.com/mcp/.well-known/oauth-authorization-server
|
||||
|
||||
# Should return OAuth metadata
|
||||
{
|
||||
"issuer": "https://your-server.com",
|
||||
"authorization_endpoint": "https://your-server.com/auth/authorize",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Regular Backups**
|
||||
- Export your knowledge base
|
||||
- Use version control
|
||||
- Multiple storage locations
|
||||
|
||||
2. **Access Control**
|
||||
- Principle of least privilege
|
||||
- Regular token rotation
|
||||
- Audit access logs
|
||||
|
||||
3. **Performance**
|
||||
- Index frequently searched fields
|
||||
- Optimize large knowledge bases
|
||||
- Use caching where appropriate
|
||||
|
||||
4. **User Experience**
|
||||
- Clear tool descriptions
|
||||
- Helpful error messages
|
||||
- Quick response times
|
||||
|
||||
## Examples
|
||||
|
||||
### Creating Notes
|
||||
|
||||
```
|
||||
User: Create a note about the meeting with the product team
|
||||
|
||||
Claude: I'll create a note about your meeting with the product team.
|
||||
|
||||
[Uses write_note tool]
|
||||
|
||||
Note created: "Meeting with Product Team - 2024-01-15"
|
||||
Location: Work/Meetings/
|
||||
|
||||
I've documented the meeting notes. The note includes the date, attendees, and key discussion points.
|
||||
```
|
||||
|
||||
### Searching Knowledge
|
||||
|
||||
```
|
||||
User: What did we discuss about the API redesign?
|
||||
|
||||
Claude: Let me search for information about the API redesign.
|
||||
|
||||
[Uses search_notes tool]
|
||||
|
||||
I found 3 relevant notes about the API redesign:
|
||||
|
||||
1. "API Redesign Proposal" (2024-01-10)
|
||||
- RESTful architecture
|
||||
- Version 2.0 specifications
|
||||
- Migration timeline
|
||||
|
||||
2. "Technical Review: API Changes" (2024-01-12)
|
||||
- Breaking changes documented
|
||||
- Backwards compatibility plan
|
||||
|
||||
3. "Meeting: API Implementation" (2024-01-14)
|
||||
- Team assignments
|
||||
- Q1 deliverables
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Set up production deployment
|
||||
2. Configure organizational access
|
||||
3. Create custom tools for your workflow
|
||||
4. Implement advanced security features
|
||||
5. Monitor usage and performance
|
||||
|
||||
## Resources
|
||||
|
||||
- [Basic Memory Documentation](../README.md)
|
||||
- [OAuth Setup Guide](OAuth%20Authentication.md)
|
||||
- [MCP Specification](https://modelcontextprotocol.io)
|
||||
- [Claude.ai Help Center](https://support.anthropic.com)
|
||||
@@ -0,0 +1,365 @@
|
||||
# Docker Setup Guide
|
||||
|
||||
Basic Memory can be run in Docker containers to provide a consistent, isolated environment for your knowledge management
|
||||
system. This is particularly useful for integrating with existing Dockerized MCP servers or for deployment scenarios.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option 1: Using Pre-built Images (Recommended)
|
||||
|
||||
Basic Memory provides pre-built Docker images on GitHub Container Registry that are automatically updated with each release.
|
||||
|
||||
1. **Use the official image directly:**
|
||||
```bash
|
||||
docker run -d \
|
||||
--name basic-memory-server \
|
||||
-p 8000:8000 \
|
||||
-v /path/to/your/obsidian-vault:/app/data:rw \
|
||||
-v basic-memory-config:/app/.basic-memory:rw \
|
||||
ghcr.io/basicmachines-co/basic-memory:latest
|
||||
```
|
||||
|
||||
2. **Or use Docker Compose with the pre-built image:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
basic-memory:
|
||||
image: ghcr.io/basicmachines-co/basic-memory:latest
|
||||
container_name: basic-memory-server
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- /path/to/your/obsidian-vault:/app/data:rw
|
||||
- basic-memory-config:/app/.basic-memory:rw
|
||||
environment:
|
||||
- BASIC_MEMORY_DEFAULT_PROJECT=main
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### Option 2: Using Docker Compose (Building Locally)
|
||||
|
||||
1. **Clone the repository:**
|
||||
```bash
|
||||
git clone https://github.com/basicmachines-co/basic-memory.git
|
||||
cd basic-memory
|
||||
```
|
||||
|
||||
2. **Update the docker-compose.yml:**
|
||||
Edit the volume mount to point to your Obsidian vault:
|
||||
```yaml
|
||||
volumes:
|
||||
# Change './obsidian-vault' to your actual directory path
|
||||
- /path/to/your/obsidian-vault:/app/data:rw
|
||||
```
|
||||
|
||||
3. **Start the container:**
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Option 3: Using Docker CLI
|
||||
|
||||
```bash
|
||||
# Build the image
|
||||
docker build -t basic-memory .
|
||||
|
||||
# Run with volume mounting
|
||||
docker run -d \
|
||||
--name basic-memory-server \
|
||||
-v /path/to/your/obsidian-vault:/app/data:rw \
|
||||
-v basic-memory-config:/app/.basic-memory:rw \
|
||||
-e BASIC_MEMORY_DEFAULT_PROJECT=main \
|
||||
basic-memory
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Volume Mounts
|
||||
|
||||
Basic Memory requires several volume mounts for proper operation:
|
||||
|
||||
1. **Knowledge Directory** (Required):
|
||||
```yaml
|
||||
- /path/to/your/obsidian-vault:/app/data:rw
|
||||
```
|
||||
Mount your Obsidian vault or knowledge base directory.
|
||||
|
||||
2. **Configuration and Database** (Recommended):
|
||||
```yaml
|
||||
- basic-memory-config:/app/.basic-memory:rw
|
||||
```
|
||||
Persistent storage for configuration and SQLite database.
|
||||
|
||||
You can edit the basic-memory config.json file located in the /app/.basic-memory/config.json after Basic Memory starts.
|
||||
|
||||
3. **Multiple Projects** (Optional):
|
||||
```yaml
|
||||
- /path/to/project1:/app/data/project1:rw
|
||||
- /path/to/project2:/app/data/project2:rw
|
||||
```
|
||||
|
||||
You can edit the basic-memory config.json file located in the /app/.basic-memory/config.json
|
||||
|
||||
## CLI Commands via Docker
|
||||
|
||||
You can run Basic Memory CLI commands inside the container using `docker exec`:
|
||||
|
||||
### Basic Commands
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
docker exec basic-memory-server basic-memory status
|
||||
|
||||
# Sync files
|
||||
docker exec basic-memory-server basic-memory sync
|
||||
|
||||
# Show help
|
||||
docker exec basic-memory-server basic-memory --help
|
||||
```
|
||||
|
||||
### Managing Projects with Volume Mounts
|
||||
|
||||
When using Docker volumes, you'll need to configure projects to point to your mounted directories:
|
||||
|
||||
1. **Check current configuration:**
|
||||
```bash
|
||||
docker exec basic-memory-server cat /app/.basic-memory/config.json
|
||||
```
|
||||
|
||||
2. **Add a project for your mounted volume:**
|
||||
```bash
|
||||
# If you mounted /path/to/your/vault to /app/data
|
||||
docker exec basic-memory-server basic-memory project create my-vault /app/data
|
||||
|
||||
# Set it as default
|
||||
docker exec basic-memory-server basic-memory project set-default my-vault
|
||||
```
|
||||
|
||||
3. **Sync the new project:**
|
||||
```bash
|
||||
docker exec basic-memory-server basic-memory sync
|
||||
```
|
||||
|
||||
### Example: Setting up an Obsidian Vault
|
||||
|
||||
If you mounted your Obsidian vault like this in docker-compose.yml:
|
||||
```yaml
|
||||
volumes:
|
||||
- /Users/yourname/Documents/ObsidianVault:/app/data:rw
|
||||
```
|
||||
|
||||
Then configure it:
|
||||
```bash
|
||||
# Create project pointing to mounted vault
|
||||
docker exec basic-memory-server basic-memory project create obsidian /app/data
|
||||
|
||||
# Set as default
|
||||
docker exec basic-memory-server basic-memory project set-default obsidian
|
||||
|
||||
# Sync to index all files
|
||||
docker exec basic-memory-server basic-memory sync
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Configure Basic Memory using environment variables:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
|
||||
# Default project
|
||||
- BASIC_MEMORY_DEFAULT_PROJECT=main
|
||||
|
||||
# Enable real-time sync
|
||||
- BASIC_MEMORY_SYNC_CHANGES=true
|
||||
|
||||
# Logging level
|
||||
- BASIC_MEMORY_LOG_LEVEL=INFO
|
||||
|
||||
# Sync delay in milliseconds
|
||||
- BASIC_MEMORY_SYNC_DELAY=1000
|
||||
```
|
||||
|
||||
## File Permissions
|
||||
|
||||
### Linux/macOS
|
||||
|
||||
The Docker container now runs as a non-root user to avoid file ownership issues. By default, the container uses UID/GID 1000, but you can customize this to match your user:
|
||||
|
||||
```bash
|
||||
# Build with custom UID/GID to match your user
|
||||
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) -t basic-memory .
|
||||
|
||||
# Or use docker-compose with build args
|
||||
```
|
||||
|
||||
**Example docker-compose.yml with custom user:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
basic-memory:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
UID: 1000 # Replace with your UID
|
||||
GID: 1000 # Replace with your GID
|
||||
container_name: basic-memory-server
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- /path/to/your/obsidian-vault:/app/data:rw
|
||||
- basic-memory-config:/app/.basic-memory:rw
|
||||
environment:
|
||||
- BASIC_MEMORY_DEFAULT_PROJECT=main
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
**Using pre-built images:**
|
||||
If using the pre-built image from GitHub Container Registry, files will be created with UID/GID 1000. You can either:
|
||||
|
||||
1. Change your local directory ownership to match:
|
||||
```bash
|
||||
sudo chown -R 1000:1000 /path/to/your/obsidian-vault
|
||||
```
|
||||
|
||||
2. Or build your own image with custom UID/GID as shown above.
|
||||
|
||||
### Windows
|
||||
|
||||
When using Docker Desktop on Windows, ensure the directories are shared:
|
||||
|
||||
1. Open Docker Desktop
|
||||
2. Go to Settings → Resources → File Sharing
|
||||
3. Add your knowledge directory path
|
||||
4. Apply & Restart
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **File Watching Not Working:**
|
||||
- Ensure volume mounts are read-write (`:rw`)
|
||||
- Check directory permissions
|
||||
- On Linux, may need to increase inotify limits:
|
||||
```bash
|
||||
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
|
||||
sudo sysctl -p
|
||||
```
|
||||
|
||||
2. **Configuration Not Persisting:**
|
||||
- Use named volumes for `/app/.basic-memory`
|
||||
- Check volume mount permissions
|
||||
|
||||
3. **Network Connectivity:**
|
||||
- For HTTP transport, ensure port 8000 is exposed
|
||||
- Check firewall settings
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Run with debug logging:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- BASIC_MEMORY_LOG_LEVEL=DEBUG
|
||||
```
|
||||
|
||||
View logs:
|
||||
|
||||
```bash
|
||||
docker-compose logs -f basic-memory
|
||||
```
|
||||
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Docker Security:**
|
||||
The container runs as a non-root user (UID/GID 1000 by default) for improved security. You can customize the user ID using build arguments to match your local user.
|
||||
|
||||
2. **Volume Permissions:**
|
||||
Ensure mounted directories have appropriate permissions and don't expose sensitive data. With the non-root container, files will be created with the specified user ownership.
|
||||
|
||||
3. **Network Security:**
|
||||
If using HTTP transport, consider using reverse proxy with SSL/TLS and authentication if the endpoint is available on
|
||||
a network.
|
||||
|
||||
4. **IMPORTANT:** The HTTP endpoints have no authorization. They should not be exposed on a public network.
|
||||
|
||||
## Integration Examples
|
||||
|
||||
### Claude Desktop with Docker
|
||||
|
||||
The recommended way to connect Claude Desktop to the containerized Basic Memory is using `mcp-proxy`, which converts the HTTP transport to STDIO that Claude Desktop expects:
|
||||
|
||||
1. **Start the Docker container:**
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
2. **Configure Claude Desktop** to use mcp-proxy:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"mcp-proxy",
|
||||
"http://localhost:8000/mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
For Docker-specific issues:
|
||||
|
||||
1. Check the [troubleshooting section](#troubleshooting) above
|
||||
2. Review container logs: `docker-compose logs basic-memory`
|
||||
3. Verify volume mounts: `docker inspect basic-memory-server`
|
||||
4. Test file permissions: `docker exec basic-memory-server ls -la /app`
|
||||
|
||||
For general Basic Memory support, see the main [README](../README.md)
|
||||
and [documentation](https://memory.basicmachines.co/).
|
||||
|
||||
## GitHub Container Registry Images
|
||||
|
||||
### Available Images
|
||||
|
||||
Pre-built Docker images are available on GitHub Container Registry at [`ghcr.io/basicmachines-co/basic-memory`](https://github.com/basicmachines-co/basic-memory/pkgs/container/basic-memory).
|
||||
|
||||
**Supported architectures:**
|
||||
- `linux/amd64` (Intel/AMD x64)
|
||||
- `linux/arm64` (ARM64, including Apple Silicon)
|
||||
|
||||
**Available tags:**
|
||||
- `latest` - Latest stable release
|
||||
- `v0.13.8`, `v0.13.7`, etc. - Specific version tags
|
||||
- `v0.13`, `v0.12`, etc. - Major.minor tags
|
||||
|
||||
### Automated Builds
|
||||
|
||||
Docker images are automatically built and published when new releases are tagged:
|
||||
|
||||
1. **Release Process:** When a git tag matching `v*` (e.g., `v0.13.8`) is pushed, the CI workflow automatically:
|
||||
- Builds multi-platform Docker images
|
||||
- Pushes to GitHub Container Registry with appropriate tags
|
||||
- Uses native GitHub integration for seamless publishing
|
||||
|
||||
2. **CI/CD Pipeline:** The Docker workflow includes:
|
||||
- Multi-platform builds (AMD64 and ARM64)
|
||||
- Layer caching for faster builds
|
||||
- Automatic tagging with semantic versioning
|
||||
- Security scanning and optimization
|
||||
|
||||
### Setup Requirements (For Maintainers)
|
||||
|
||||
GitHub Container Registry integration is automatic for this repository:
|
||||
|
||||
1. **No external setup required** - GHCR is natively integrated with GitHub
|
||||
2. **Automatic permissions** - Uses `GITHUB_TOKEN` with `packages: write` permission
|
||||
3. **Public by default** - Images are automatically public for public repositories
|
||||
|
||||
The Docker CI workflow (`.github/workflows/docker.yml`) handles everything automatically when version tags are pushed.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Basic Memory Engineering Style
|
||||
|
||||
Style is how we make code easier to verify. Prefer explicit, typed, local-first code that
|
||||
preserves the file system as the source of truth while keeping the database, API, and MCP
|
||||
surfaces in sync.
|
||||
|
||||
## Design Center
|
||||
|
||||
- Basic Memory is local-first. Markdown files are the durable source; SQLite/Postgres indexes
|
||||
are derived state that should be rebuilt or reconciled from files when needed.
|
||||
- Keep the existing boundary order: CLI/MCP/API entrypoints compose dependencies, services own
|
||||
business behavior, repositories own database access, and file services own filesystem writes.
|
||||
- MCP tools should remain atomic and composable. They should call API routers through typed MCP
|
||||
clients, not reach around into services.
|
||||
- Prefer small, explicit abstractions that match a real domain boundary. Avoid object
|
||||
hierarchies when a function, dataclass, type alias, or protocol describes the concept better.
|
||||
|
||||
## Types And Data
|
||||
|
||||
- Use full type annotations and Python 3.12 syntax. Introduce `type` aliases for repeated
|
||||
structured shapes, callback signatures, or domain concepts that would otherwise become
|
||||
anonymous `dict[str, Any]` values.
|
||||
- Use dataclasses for internal values, operation inputs, and service results. Prefer
|
||||
`frozen=True` when the value should not change and `slots=True` when identity/dynamic
|
||||
attributes are not needed.
|
||||
- Use Pydantic v2 at boundaries that validate, serialize, or deserialize data: API payloads,
|
||||
CLI/MCP schemas, configuration, and persistence-adjacent schemas.
|
||||
- Use narrow `Protocol`s when a caller needs a capability rather than a concrete repository or
|
||||
service. Keep protocols small enough that fake implementations in tests are obvious.
|
||||
- Avoid speculative `getattr`, broad casts, or `Any` as a way to paper over uncertainty. Read
|
||||
the model or schema definition and make the type relationship explicit.
|
||||
|
||||
## Control Flow And Resources
|
||||
|
||||
- Fail fast when an invariant is broken. Do not swallow exceptions, add warning-only error
|
||||
handling, or introduce fallback behavior unless the user explicitly agrees to that behavior.
|
||||
- Keep control flow simple and close to the domain decision. Push `if` statements up into the
|
||||
function that owns orchestration; keep leaf helpers focused on computation or one side effect.
|
||||
- Make async/resource boundaries visible with context managers and explicit lifecycles. Do not
|
||||
start background work without a clear owner, cancellation story, and verification path.
|
||||
- Keep file mutations centralized through the existing file utilities/services so checksum,
|
||||
atomic write, and index synchronization behavior stays coherent.
|
||||
|
||||
## Testing And Verification
|
||||
|
||||
- Use evidence-first testing, not mechanical TDD. For bugs and risky behavior, add or update a
|
||||
regression test that would catch the failure. For small documentation-only edits, use the
|
||||
relevant doc/repo hygiene checks.
|
||||
- Prefer tests that exercise real code paths. Use mocks, doubles, or `monkeypatch` only when
|
||||
the external boundary would be slow, nondeterministic, or impossible to trigger directly.
|
||||
- Keep coverage at 100% for new code. Use `# pragma: no cover` only for code that would require
|
||||
disproportionate mocking and is covered through an integration or runtime path.
|
||||
- Start with targeted commands, then widen as risk grows: focused pytest, `just fast-check`,
|
||||
`just doctor`, package checks for agent packaging changes, and full SQLite/Postgres gates
|
||||
when behavior crosses shared boundaries.
|
||||
|
||||
## Comments And Names
|
||||
|
||||
- Name values after the domain concept they carry: project, entity, permalink, tenant, route,
|
||||
checksum, observation, relation, batch, or index state.
|
||||
- Comments should say why a branch, invariant, retry, lifecycle, or compatibility constraint
|
||||
exists. Section headers are useful when a function or file has clear phases.
|
||||
- Avoid comments that restate the code. If a comment cannot explain a decision, simplify the
|
||||
code or improve the name instead.
|
||||
@@ -1,355 +0,0 @@
|
||||
---
|
||||
title: Getting Started with Basic Memory
|
||||
type: note
|
||||
permalink: docs/getting-started
|
||||
---
|
||||
|
||||
# Getting Started with Basic Memory
|
||||
|
||||
This guide will help you install Basic Memory, configure it with Claude Desktop, and create your first knowledge notes
|
||||
through conversations.
|
||||
|
||||
Basic Memory uses the [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) to connect with LLMs.
|
||||
It can be used with any service that supports the MCP, but Claude Desktop works especially well.
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
The easiest way to install basic memory is via `uv`. See the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).
|
||||
|
||||
### 1. Install Basic Memory
|
||||
|
||||
**v0.13.0 offers multiple installation options:**
|
||||
|
||||
```bash
|
||||
# Stable release (recommended)
|
||||
uv tool install basic-memory
|
||||
# or: pip install basic-memory
|
||||
|
||||
# Beta releases (new features, testing)
|
||||
pip install basic-memory --pre
|
||||
|
||||
# Development builds (latest changes)
|
||||
pip install basic-memory --pre --force-reinstall
|
||||
```
|
||||
|
||||
**Version Information:**
|
||||
- **Stable**: Latest tested release (e.g., `0.13.0`)
|
||||
- **Beta**: Pre-release versions (e.g., `0.13.0b1`)
|
||||
- **Development**: Auto-published from git commits (e.g., `0.12.4.dev26+468a22f`)
|
||||
|
||||
> **Important**: You need to install Basic Memory using one of the commands above to use the command line tools.
|
||||
|
||||
Using `uv tool install` will install the basic-memory package in a standalone virtual environment. See the [UV docs](https://docs.astral.sh/uv/concepts/tools/) for more info.
|
||||
|
||||
### 2. Configure Claude Desktop
|
||||
|
||||
Edit your Claude Desktop config, located at `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Restart Claude Desktop**. You should see Basic Memory tools available in the "tools" menu in Claude Desktop (the little hammer icon in the bottom-right corner of the chat interface). Click it to view available tools.
|
||||
#### Fix Path to uv
|
||||
|
||||
If you get an error that says `ENOENT` , this most likely means Claude Desktop could not find your `uv` installation. Make sure that you have `uv` installed per the instructions above, then:
|
||||
|
||||
**Step 1: Find the absolute path to uvx**
|
||||
|
||||
Open Terminal and run:
|
||||
|
||||
```bash
|
||||
which uvx
|
||||
```
|
||||
|
||||
This will show you the full path (e.g., `/Users/yourusername/.cargo/bin/uvx`).
|
||||
|
||||
**Step 2: Edit Claude Desktop Configuration**
|
||||
|
||||
Edit the Claude Desktop config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-memory": {
|
||||
"command": "/absolute/path/to/uvx",
|
||||
"args": [
|
||||
"basic-memory",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Replace `/absolute/path/to/uvx` with the actual path you found in Step 1.
|
||||
|
||||
**Step 3: Restart Claude Desktop**
|
||||
|
||||
Close and reopen Claude Desktop for the changes to take effect.
|
||||
|
||||
### 3. Sync changes in real time
|
||||
|
||||
> **Note**: The service will sync changes from your project directory in real time so they available for the AI assistant.
|
||||
|
||||
To disable realtime sync, you can update the config. See [[CLI Reference#sync]].
|
||||
### 4. Staying Updated
|
||||
|
||||
To update Basic Memory when new versions are released:
|
||||
|
||||
```bash
|
||||
# Update stable release
|
||||
uv tool upgrade basic-memory
|
||||
# or: pip install --upgrade basic-memory
|
||||
|
||||
# Update to latest beta (v0.13.0)
|
||||
pip install --upgrade basic-memory --pre
|
||||
|
||||
# Get latest development build
|
||||
pip install --upgrade basic-memory --pre --force-reinstall
|
||||
```
|
||||
|
||||
**v0.13.0 Update Benefits:**
|
||||
- **Fluid project switching** during conversations
|
||||
- **Advanced note editing** capabilities
|
||||
- **Smart file management** with move operations
|
||||
- **Enhanced search** with frontmatter tag support
|
||||
|
||||
> **Note**: After updating, restart Claude Desktop for changes to take effect. No sync restart needed in v0.13.0.
|
||||
|
||||
### 5. Multi-Project Setup (Enhanced in v0.13.0)
|
||||
|
||||
By default, Basic Memory creates a project in `~/basic-memory`. v0.13.0 introduces **fluid project management** - switch between projects instantly during conversations.
|
||||
|
||||
```
|
||||
# Create a new project
|
||||
basic-memory project create work ~/work-basic-memory
|
||||
|
||||
# Set the default project
|
||||
basic-memory project set-default work
|
||||
|
||||
# List all projects with status
|
||||
basic-memory project list
|
||||
|
||||
# Get detailed project information
|
||||
basic-memory project info
|
||||
```
|
||||
|
||||
**New in v0.13.0:**
|
||||
- **Instant switching**: Change projects during conversations without restart
|
||||
- **Unified database**: All projects in single `~/.basic-memory/memory.db`
|
||||
- **Better performance**: Optimized queries and reduced file I/O
|
||||
- **Session context**: Maintains active project throughout conversations
|
||||
|
||||
## Troubleshooting Installation
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Claude Says "No Basic Memory Tools Available"
|
||||
|
||||
If Claude cannot find Basic Memory tools:
|
||||
|
||||
1. **Check absolute paths**: Ensure you're using complete absolute paths to uvx in the Claude Desktop configuration
|
||||
2. **Verify installation**: Run `basic-memory --version` in Terminal to confirm Basic Memory is installed
|
||||
3. **Restart applications**: Restart both Terminal and Claude Desktop after making configuration changes
|
||||
4. **Check sync status**: You can view the sync status by running `basic-memory status
|
||||
.
|
||||
#### Permission Issues
|
||||
|
||||
If you encounter permission errors:
|
||||
|
||||
1. Check that Basic Memory has access to create files in your home directory
|
||||
2. Ensure Claude Desktop has permission to execute the uvx command
|
||||
|
||||
## Creating Your First Knowledge Note
|
||||
|
||||
1. **Open Claude Desktop** and start a new conversation.
|
||||
|
||||
2. **Have a natural conversation** about any topic:
|
||||
```
|
||||
You: "Let's talk about coffee brewing methods I've been experimenting with."
|
||||
Claude: "I'd be happy to discuss coffee brewing methods..."
|
||||
You: "I've found that pour over gives more flavor clarity than French press..."
|
||||
```
|
||||
|
||||
3. **Ask Claude to create a note**:
|
||||
```
|
||||
You: "Could you create a note summarizing what we've discussed about coffee brewing?"
|
||||
```
|
||||
|
||||
4. **Confirm note creation**:
|
||||
Claude will confirm when the note has been created and where it's stored.
|
||||
|
||||
5. **View the created file** in your `~/basic-memory` directory using any text editor or Obsidian.
|
||||
The file structure will look similar to:
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
permalink: coffee-brewing-methods
|
||||
tags: [coffee, brewing, equipment] # v0.13.0: Now searchable!
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Observations
|
||||
- [method] Pour over provides more clarity...
|
||||
- [technique] Water temperature at 205°F...
|
||||
|
||||
## Relations
|
||||
- relates_to [[Other Coffee Topics]]
|
||||
```
|
||||
|
||||
**v0.13.0 Improvements:**
|
||||
- **Real-time sync**: Changes appear immediately, no background sync needed
|
||||
- **Searchable tags**: Frontmatter tags are now indexed for search
|
||||
- **Better file organization**: Enhanced file management capabilities
|
||||
|
||||
## Using Special Prompts
|
||||
|
||||
Basic Memory includes special prompts that help you start conversations with context from your knowledge base:
|
||||
|
||||
### Continue Conversation
|
||||
|
||||
To resume a previous topic:
|
||||
|
||||
```
|
||||
You: "Let's continue our conversation about coffee brewing."
|
||||
```
|
||||
|
||||
This prompt triggers Claude to:
|
||||
|
||||
1. Search your knowledge base for relevant content about coffee brewing
|
||||
2. Build context from these documents
|
||||
3. Resume the conversation with full awareness of previous discussions
|
||||
|
||||
### Recent Activity
|
||||
|
||||
To see what you've been working on:
|
||||
|
||||
```
|
||||
You: "What have we been discussing recently?"
|
||||
```
|
||||
|
||||
This prompt causes Claude to:
|
||||
|
||||
1. Retrieve documents modified in the recent past
|
||||
2. Summarize the topics and main points
|
||||
3. Offer to continue any of those discussions
|
||||
|
||||
### Search
|
||||
|
||||
To find specific information:
|
||||
|
||||
```
|
||||
You: "Find information about pour over coffee methods."
|
||||
```
|
||||
|
||||
Claude will:
|
||||
|
||||
1. Search your knowledge base for relevant documents
|
||||
2. Summarize the key findings
|
||||
3. Offer to explore specific documents in more detail
|
||||
|
||||
See [[User Guide#Using Special Prompts]] for further information.
|
||||
|
||||
## Using Your Knowledge Base
|
||||
|
||||
### Referencing Knowledge
|
||||
|
||||
In future conversations, reference your existing knowledge:
|
||||
|
||||
```
|
||||
You: "What water temperature did we decide was optimal for coffee brewing?"
|
||||
```
|
||||
|
||||
Or directly reference notes using memory:// URLs:
|
||||
|
||||
```
|
||||
You: "Take a look at memory://coffee-brewing-methods and let's discuss how to improve my technique."
|
||||
```
|
||||
|
||||
### Building On Previous Knowledge (Enhanced in v0.13.0)
|
||||
|
||||
Basic Memory enables continuous knowledge building:
|
||||
|
||||
1. **Reference previous discussions** in new conversations
|
||||
2. **Edit notes incrementally** without rewriting entire documents
|
||||
3. **Move and organize notes** as your knowledge base grows
|
||||
4. **Switch between projects** instantly during conversations
|
||||
5. **Search by tags** to find related content quickly
|
||||
6. **Create connections** between related topics
|
||||
7. **Follow relationships** to build comprehensive context
|
||||
|
||||
### v0.13.0 Workflow Examples
|
||||
|
||||
**Incremental Editing:**
|
||||
```
|
||||
You: "Add a section about espresso to my coffee brewing notes"
|
||||
Claude: [Uses edit_note to append new section]
|
||||
```
|
||||
|
||||
**File Organization:**
|
||||
```
|
||||
You: "Move my old meeting notes to an archive folder"
|
||||
Claude: [Uses move_note with database consistency]
|
||||
```
|
||||
|
||||
**Project Switching:**
|
||||
```
|
||||
You: "Switch to my work project and show recent activity"
|
||||
Claude: [Switches projects and shows work-specific content]
|
||||
```
|
||||
|
||||
## Importing Existing Conversations
|
||||
|
||||
Import your existing AI conversations:
|
||||
|
||||
```bash
|
||||
# From Claude
|
||||
basic-memory import claude conversations
|
||||
|
||||
# From ChatGPT
|
||||
basic-memory import chatgpt
|
||||
```
|
||||
|
||||
After importing, changes sync automatically in real-time. You can see project statistics by running `basic-memory project info`.
|
||||
|
||||
## Quick Tips
|
||||
|
||||
### General Usage
|
||||
- Basic Memory syncs changes in real-time (no manual sync needed)
|
||||
- Use special prompts (Continue Conversation, Recent Activity, Search) to start contextual discussions
|
||||
- Build connections between notes for a richer knowledge graph
|
||||
- Use direct `memory://` URLs with permalinks for precise context
|
||||
- Review and edit AI-generated notes for accuracy
|
||||
|
||||
### v0.13.0 Features
|
||||
- **Switch projects instantly**: "Switch to my work project" - no restart needed
|
||||
- **Edit notes incrementally**: "Add a section about..." instead of rewriting
|
||||
- **Organize with moves**: "Move this to my archive folder" with database consistency
|
||||
- **Search by tags**: Frontmatter tags are now searchable
|
||||
- **Try beta builds**: `pip install basic-memory --pre` for latest features
|
||||
|
||||
## Next Steps
|
||||
|
||||
After getting started, explore these areas:
|
||||
|
||||
1. **Read the [[User Guide]]** for comprehensive usage instructions
|
||||
2. **Understand the [[Knowledge Format]]** to learn how knowledge is structured
|
||||
3. **Set up [[Obsidian Integration]]** for visual knowledge navigation
|
||||
4. **Learn about [[Canvas]]** visualizations for mapping concepts
|
||||
5. **Review the [[CLI Reference]]** for command line tools
|
||||
6. **Explore [[OAuth Authentication Guide]]** for secure remote access (v0.13.0)
|
||||
7. **Set up multiple projects** for different knowledge areas (v0.13.0)
|
||||
@@ -1,207 +0,0 @@
|
||||
---
|
||||
title: Knowledge Format
|
||||
type: note
|
||||
permalink: docs/knowledge-format
|
||||
tags:
|
||||
- architecture
|
||||
- patterns
|
||||
- knowledge
|
||||
- design
|
||||
---
|
||||
|
||||
# Knowledge Format
|
||||
|
||||
Basic Memory uses standard Markdown with simple semantic patterns to create a knowledge graph. This document details the file structure and patterns used to organize knowledge.
|
||||
|
||||
## File-First Architecture
|
||||
|
||||
All knowledge in Basic Memory is stored in plain text Markdown files:
|
||||
|
||||
- Files are the source of truth for all knowledge
|
||||
- Changes to files automatically update the knowledge graph
|
||||
- You maintain complete ownership and control
|
||||
- Files work with git and other version control systems
|
||||
- Knowledge persists independently of any AI conversation
|
||||
|
||||
## Core Document Structure
|
||||
|
||||
Every document uses this basic structure:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Document Title
|
||||
type: note
|
||||
tags: [tag1, tag2]
|
||||
permalink: custom-path
|
||||
---
|
||||
|
||||
# Document Title
|
||||
|
||||
Regular markdown content...
|
||||
|
||||
## Observations
|
||||
- [category] Content with #tags (optional context)
|
||||
|
||||
## Relations
|
||||
- relation_type [[Other Document]] (optional context)
|
||||
```
|
||||
|
||||
### Frontmatter
|
||||
|
||||
The YAML frontmatter at the top of each file defines essential metadata:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Document Title # Used for linking and references
|
||||
type: note # Document type
|
||||
tags: [tag1, tag2] # For organization and searching
|
||||
permalink: custom-link # Optional custom URL path
|
||||
---
|
||||
```
|
||||
|
||||
The title is particularly important as it's used to create links between documents.
|
||||
|
||||
### Observations
|
||||
|
||||
Observations are facts or statements about a topic:
|
||||
|
||||
```markdown
|
||||
## Observations
|
||||
- [tech] Uses SQLite for storage #database
|
||||
- [design] Follows local-first architecture #architecture
|
||||
- [decision] Selected bcrypt for passwords #security (Based on audit)
|
||||
```
|
||||
|
||||
Each observation contains:
|
||||
- **Category** in [brackets] - classifies the information type
|
||||
- **Content text** - the main information
|
||||
- Optional **#tags** - additional categorization
|
||||
- Optional **(context)** - supporting details
|
||||
|
||||
Common categories include:
|
||||
- `[tech]`: Technical details
|
||||
- `[design]`: Architecture decisions
|
||||
- `[feature]`: User capabilities
|
||||
- `[decision]`: Choices that were made
|
||||
- `[principle]`: Fundamental concepts
|
||||
- `[method]`: Approaches or techniques
|
||||
- `[preference]`: Personal opinions
|
||||
|
||||
### Relations
|
||||
|
||||
Relations connect documents to form the knowledge graph:
|
||||
|
||||
```markdown
|
||||
## Relations
|
||||
- implements [[Search Design]]
|
||||
- depends_on [[Database Schema]]
|
||||
- relates_to [[User Interface]]
|
||||
```
|
||||
|
||||
You can also create inline references:
|
||||
```markdown
|
||||
This builds on [[Core Design]] and uses [[Utility Functions]].
|
||||
```
|
||||
|
||||
Common relation types include:
|
||||
- `implements`: Implementation of a specification
|
||||
- `depends_on`: Required dependency
|
||||
- `relates_to`: General connection
|
||||
- `inspired_by`: Source of ideas
|
||||
- `extends`: Enhancement
|
||||
- `part_of`: Component relationship
|
||||
- `contains`: Hierarchical relationship
|
||||
- `pairs_with`: Complementary relationship
|
||||
|
||||
## Knowledge Graph
|
||||
|
||||
Basic Memory automatically builds a knowledge graph from your document connections:
|
||||
|
||||
- Each document becomes a node in the graph
|
||||
- Relations create edges between nodes
|
||||
- Relation types add semantic meaning to connections
|
||||
- Forward references can link to documents that don't exist yet
|
||||
|
||||
This graph enables rich context building and navigation across your knowledge base.
|
||||
|
||||
## Permalinks and memory:// URLs
|
||||
|
||||
Every document in Basic Memory has a unique permalink that serves as its stable identifier:
|
||||
|
||||
### How Permalinks Work
|
||||
|
||||
- **Automatically assigned**: The system generates a permalink for each document
|
||||
- **Based on title**: By default, derived from the document title
|
||||
- **Always unique**: If conflicts exist, the system adds a suffix to ensure uniqueness
|
||||
- **Stable reference**: Remains the same even if the file moves in the directory structure
|
||||
- **Used in memory:// URLs**: Forms the basis of the memory:// addressing scheme
|
||||
|
||||
You can specify a custom permalink in the frontmatter:
|
||||
```yaml
|
||||
---
|
||||
title: Authentication Approaches
|
||||
permalink: auth-approaches-2024
|
||||
---
|
||||
```
|
||||
|
||||
If not specified, one will be generated automatically from the title, if the note has has a frontmatter section.
|
||||
|
||||
By default a notes' permalink value will not change if the file is moved. It's a **stable** identifier :). But if you'd rather permalinks are always updated when a file moves, you can set the config setting in the global config.
|
||||
|
||||
The config file for Basic Memory is in the home directory under `.basic-memory/config.json`.
|
||||
|
||||
To change the behavior, set the following value:
|
||||
```
|
||||
~/.basic-memory/config.json
|
||||
{
|
||||
"update_permalinks_on_move": true
|
||||
}
|
||||
```
|
||||
|
||||
### Using memory:// URLs
|
||||
|
||||
The memory:// URL scheme provides a reliable way to reference knowledge:
|
||||
|
||||
```
|
||||
memory://auth-approaches-2024 # Direct access by permalink
|
||||
memory://Authentication Approaches # Access by title (automatically resolves)
|
||||
memory://project/auth-approaches # Access by path
|
||||
```
|
||||
|
||||
Memory URLs support pattern matching for more powerful queries:
|
||||
|
||||
```
|
||||
memory://auth* # All documents with permalinks starting with "auth"
|
||||
memory://*/approaches # All documents with permalinks ending with "approaches"
|
||||
memory://project/*/requirements # All requirements documents in the project folder
|
||||
memory://docs/search/implements/* # Follow all implements relations from search docs
|
||||
```
|
||||
|
||||
This addressing scheme ensures content remains accessible even as your knowledge base evolves and files are reorganized.
|
||||
|
||||
## File Organization
|
||||
|
||||
Organize files in any structure that suits your needs:
|
||||
|
||||
```
|
||||
docs/
|
||||
architecture/
|
||||
design.md
|
||||
patterns.md
|
||||
features/
|
||||
search.md
|
||||
auth.md
|
||||
```
|
||||
|
||||
You can:
|
||||
- Group by topic in folders
|
||||
- Use a flat structure with descriptive filenames
|
||||
- Tag files for easier discovery
|
||||
- Add custom metadata in frontmatter
|
||||
|
||||
The system will build the semantic knowledge graph regardless of how you organize your files.
|
||||
|
||||
## Relations
|
||||
- implemented_by [[User Guide]] (How to work with this format)
|
||||
- relates_to [[Getting Started with Basic Memory]] (Setup instructions)
|
||||
- explained_in [[Introduction to Basic Memory]] (Overview of the system)
|
||||
@@ -0,0 +1,512 @@
|
||||
# Note Format Reference
|
||||
|
||||
Every document in Basic Memory is a plain Markdown file. Files are the source of truth — changes to files automatically update the knowledge graph in the database. You maintain complete ownership, files work with git, and knowledge persists independently of any AI conversation.
|
||||
|
||||
## Document Structure
|
||||
|
||||
A note has three parts: YAML frontmatter, content (observations), and relations.
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
type: note
|
||||
tags: [coffee, brewing]
|
||||
permalink: coffee-brewing-methods
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
## Observations
|
||||
- [method] Pour over provides more flavor clarity than French press
|
||||
- [technique] Water temperature at 205°F extracts optimal compounds #brewing
|
||||
- [preference] Ethiopian beans work well with lighter roasts (personal experience)
|
||||
|
||||
## Relations
|
||||
- relates_to [[Coffee Bean Origins]]
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- contrasts_with [[Tea Brewing Methods]]
|
||||
```
|
||||
|
||||
The `## Observations` and `## Relations` headings are conventional but not required — the parser detects observations and relations by their syntax patterns anywhere in the document.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
YAML metadata between `---` fences at the top of the file.
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `title` | No | filename stem | Used for linking and references. Auto-set from filename if missing. |
|
||||
| `type` | No | `note` | Entity type. Used for schema resolution and filtering. |
|
||||
| `tags` | No | `[]` | List or comma-separated string. Used for organization and search. |
|
||||
| `permalink` | No | generated from title | Stable identifier. Persists even if the file moves. |
|
||||
| `schema` | No | none | Schema attachment — dict (inline), string (reference), or omitted (implicit). |
|
||||
|
||||
Custom fields are allowed. Any key not in the standard set is stored as `entity_metadata` and indexed for search and filtering.
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
tags: [startups, essays, lisp]
|
||||
permalink: paul-graham
|
||||
status: active
|
||||
source: wikipedia
|
||||
---
|
||||
```
|
||||
|
||||
Here `status` and `source` are custom fields stored in `entity_metadata`.
|
||||
|
||||
### Frontmatter Value Handling
|
||||
|
||||
YAML automatically converts some values to native types. Basic Memory normalizes them:
|
||||
|
||||
- Date strings (`2025-10-24`) → kept as ISO format strings
|
||||
- Numbers (`1.0`) → converted to strings
|
||||
- Booleans (`true`) → converted to strings (`"True"`)
|
||||
- Lists and dicts → preserved, items normalized recursively
|
||||
|
||||
This prevents errors when downstream code expects string values.
|
||||
|
||||
## Observations
|
||||
|
||||
An observation is a categorized fact about the entity. Written as a Markdown list item.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```
|
||||
- [category] content text #tag1 #tag2 (context)
|
||||
```
|
||||
|
||||
| Part | Required | Description |
|
||||
|------|----------|-------------|
|
||||
| `[category]` | Yes | Classification in square brackets. Any text except `[]()` chars. |
|
||||
| content | Yes | The fact or statement. |
|
||||
| `#tags` | No | Inline tags. Space-separated, each starting with `#`. |
|
||||
| `(context)` | No | Parenthesized text at end of line. Supporting details or source. |
|
||||
|
||||
### Examples
|
||||
|
||||
```markdown
|
||||
- [tech] Uses SQLite for storage #database
|
||||
- [design] Follows local-first architecture #architecture
|
||||
- [decision] Selected bcrypt for passwords #security (based on OWASP audit)
|
||||
- [name] Paul Graham
|
||||
- [expertise] Startups
|
||||
- [expertise] Lisp
|
||||
- [expertise] Essay writing
|
||||
```
|
||||
|
||||
Array-like fields use repeated categories — multiple `[expertise]` observations above.
|
||||
|
||||
### What Is Not an Observation
|
||||
|
||||
The parser excludes these list item patterns:
|
||||
|
||||
| Pattern | Example | Reason |
|
||||
|---------|---------|--------|
|
||||
| Checkboxes | `- [ ] Todo item`, `- [x] Done`, `- [-] Cancelled` | Task list syntax |
|
||||
| Markdown links | `- [text](url)` | URL link syntax |
|
||||
| Bare wiki links | `- [[Target]]` | Treated as a `links_to` relation instead |
|
||||
|
||||
A list item with `#tags` but no `[category]` is still parsed — the tags are extracted and the category defaults to `Note`.
|
||||
|
||||
## Relations
|
||||
|
||||
Relations connect documents to form the knowledge graph. There are two kinds.
|
||||
|
||||
### Explicit Relations
|
||||
|
||||
Written as list items with a relation type and a `[[wiki link]]` target. Unquoted
|
||||
relation types are single tokens. Quote relation types that contain spaces.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```
|
||||
- relation_type [[Target Entity]] (context)
|
||||
- "multi word relation type" [[Target Entity]] (context)
|
||||
- 'multi word relation type' [[Target Entity]] (context)
|
||||
```
|
||||
|
||||
| Part | Required | Description |
|
||||
|------|----------|-------------|
|
||||
| `relation_type` | Yes | Single unquoted token before `[[`, or quoted text for multi-word labels. |
|
||||
| `[[Target]]` | Yes | Wiki link to the target entity. Matched by title or permalink. |
|
||||
| `(context)` | No | Parenthesized text after `]]`. Supporting details. |
|
||||
|
||||
### Examples
|
||||
|
||||
Explicit relations:
|
||||
|
||||
```markdown
|
||||
- implements [[Search Design]]
|
||||
- depends_on [[Database Schema]]
|
||||
- works_at [[Y Combinator]] (co-founder)
|
||||
- "based on" [[Customer Interview]]
|
||||
- 'in response to' [[Incident Review]]
|
||||
```
|
||||
|
||||
Bare wiki links and prose list items create implicit `links_to` relations:
|
||||
|
||||
```markdown
|
||||
- [[Some Entity]]
|
||||
- some other thing [[Some Entity]]
|
||||
```
|
||||
|
||||
Both examples above create `links_to [[Some Entity]]`. Use quotes when the words before
|
||||
`[[` are meant to be a multi-word relation type.
|
||||
|
||||
Common relation types:
|
||||
- `implements`, `depends_on`, `relates_to`, `inspired_by`
|
||||
- `extends`, `part_of`, `contains`, `pairs_with`
|
||||
- `works_at`, `authored`, `collaborated_with`
|
||||
|
||||
Any single-token text or quoted text works as a relation type. These are conventions,
|
||||
not a fixed set.
|
||||
|
||||
### Inline References
|
||||
|
||||
Wiki links appearing in regular prose create implicit `links_to` relations. This includes
|
||||
list items that do not match the explicit relation grammar above.
|
||||
|
||||
```markdown
|
||||
This builds on [[Core Design]] and uses [[Utility Functions]].
|
||||
- We should revisit [[Search Design]] after the API changes.
|
||||
```
|
||||
|
||||
This creates three relations: `links_to [[Core Design]]`, `links_to [[Utility Functions]]`,
|
||||
and `links_to [[Search Design]]`.
|
||||
|
||||
### Forward References
|
||||
|
||||
Relations can link to entities that don't exist yet. Basic Memory resolves them when the target is created.
|
||||
|
||||
## Permalinks and memory:// URLs
|
||||
|
||||
Every document has a unique **permalink** — a stable identifier derived from its title. You can set one explicitly in frontmatter, or let the system generate it.
|
||||
|
||||
```yaml
|
||||
permalink: auth-approaches-2024
|
||||
```
|
||||
|
||||
Permalinks form the basis of `memory://` URLs:
|
||||
|
||||
```
|
||||
memory://auth-approaches-2024 # By permalink
|
||||
memory://Authentication Approaches # By title (auto-resolves)
|
||||
memory://project/auth-approaches # By path
|
||||
```
|
||||
|
||||
Pattern matching is supported:
|
||||
|
||||
```
|
||||
memory://auth* # Starts with "auth"
|
||||
memory://*/approaches # Ends with "approaches"
|
||||
memory://project/*/requirements # Nested wildcard
|
||||
```
|
||||
|
||||
## Schemas
|
||||
|
||||
Schemas declare the expected structure of a note — which observation categories and relation types a well-formed note should have. They use Picoschema, a compact notation from Google's Dotprompt that fits naturally in YAML frontmatter.
|
||||
|
||||
### Picoschema Syntax
|
||||
|
||||
```yaml
|
||||
schema:
|
||||
name: string, full name # required field with description
|
||||
email?: string, contact email # ? = optional
|
||||
role?: string, job title
|
||||
works_at?: Organization, employer # capitalized type = entity reference
|
||||
tags?(array): string, categories # array of type
|
||||
status?(enum): [active, inactive] # enum with allowed values
|
||||
metadata?(object): # nested object
|
||||
updated_at?: string
|
||||
source?: string
|
||||
```
|
||||
|
||||
| Notation | Meaning | Example |
|
||||
|----------|---------|---------|
|
||||
| `field: type` | Required field | `name: string` |
|
||||
| `field?: type` | Optional field | `role?: string` |
|
||||
| `field(array): type` | Array of values | `expertise(array): string` |
|
||||
| `field?(enum): [vals]` | Enum with allowed values | `status?(enum): [active, inactive]` |
|
||||
| `field?(object):` | Nested object with sub-fields | `metadata?(object):` |
|
||||
| `, description` | Description after comma | `name: string, full name` |
|
||||
| `EntityName` | Capitalized type = entity reference | `works_at?: Organization` |
|
||||
|
||||
**Scalar types:** `string`, `integer`, `number`, `boolean`, `any`
|
||||
|
||||
Any type not in that set whose first letter is uppercase is treated as an entity reference (a relation target).
|
||||
|
||||
### Schema-to-Note Mapping
|
||||
|
||||
Schemas validate against existing observation/relation syntax. Note authors don't learn new syntax.
|
||||
|
||||
| Schema Declaration | Maps To | Example in Note |
|
||||
|--------------------|---------|-----------------|
|
||||
| `field: string` | Observation `[field] value` | `- [name] Paul Graham` |
|
||||
| `field?(array): string` | Multiple `[field]` observations | `- [expertise] Lisp` (repeated) |
|
||||
| `field?: EntityType` | Relation `field [[Target]]` | `- works_at [[Y Combinator]]` |
|
||||
| `field?(array): EntityType` | Multiple `field` relations | `- authored [[Book]]` (repeated) |
|
||||
| `tags` | Frontmatter `tags` array | `tags: [startups, essays]` |
|
||||
| `field?(enum): [vals]` | Observation `[field] value` where value is in the set | `- [status] active` |
|
||||
|
||||
Observations and relations not covered by the schema are valid — schemas describe a subset, not a straitjacket.
|
||||
|
||||
### Schema Attachment
|
||||
|
||||
Three ways to attach a schema to a note, resolved in priority order:
|
||||
|
||||
**1. Inline schema** — `schema` is a dict in frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Team Standup 2024-01-15
|
||||
type: meeting
|
||||
schema:
|
||||
attendees(array): string, who was there
|
||||
decisions(array): string, what was decided
|
||||
action_items(array): string, follow-ups
|
||||
blockers?(array): string, anything stuck
|
||||
---
|
||||
```
|
||||
|
||||
Good for one-off structured notes or prototyping a schema before extracting it.
|
||||
|
||||
**2. Explicit reference** — `schema` is a string naming a schema note:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Basic Memory
|
||||
schema: SoftwareProject
|
||||
---
|
||||
```
|
||||
|
||||
or by permalink:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: LLM Memory Patterns
|
||||
schema: schema/research-project
|
||||
---
|
||||
```
|
||||
|
||||
Use when the note's `type` differs from the schema it should validate against, or when multiple schema variants exist.
|
||||
|
||||
**3. Implicit by type** — no `schema` field, resolved by matching `type`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
---
|
||||
```
|
||||
|
||||
The system looks up a schema note where `entity: Person`. If found, it applies. If not, no validation occurs.
|
||||
|
||||
**4. No schema** — perfectly fine. Most notes don't need one.
|
||||
|
||||
### Schema Notes
|
||||
|
||||
A schema is itself a Basic Memory note with `type: schema`. It lives anywhere (though `schema/` is the conventional directory).
|
||||
|
||||
```yaml
|
||||
# schema/Person.md
|
||||
---
|
||||
title: Person
|
||||
type: schema
|
||||
entity: Person
|
||||
version: 1
|
||||
schema:
|
||||
name: string, full name
|
||||
role?: string, job title or position
|
||||
works_at?: Organization, employer
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
settings:
|
||||
validation: warn
|
||||
---
|
||||
|
||||
# Person
|
||||
|
||||
A human individual in the knowledge graph.
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `type` | Yes | Must be `schema` |
|
||||
| `entity` | Yes | The entity type this schema describes (e.g., `Person`) |
|
||||
| `version` | No | Schema version number (default: `1`) |
|
||||
| `schema` | Yes | Picoschema dict defining the fields |
|
||||
| `settings.validation` | No | Validation mode (default: `warn`) |
|
||||
|
||||
Schema notes are regular notes — they show up in search, can have observations and relations, and participate in the knowledge graph.
|
||||
|
||||
### Validation Modes
|
||||
|
||||
| Mode | Behavior |
|
||||
|------|----------|
|
||||
| `warn` | Warnings in output, doesn't block (default) |
|
||||
| `strict` | Errors that block sync, for CI/CD enforcement |
|
||||
| `off` | No validation |
|
||||
|
||||
### Validation Output
|
||||
|
||||
```
|
||||
$ bm schema validate people/ada-lovelace.md
|
||||
|
||||
⚠ Person schema validation:
|
||||
- Missing required field: name (expected [name] observation)
|
||||
- Missing optional field: role
|
||||
- Missing optional field: works_at (no relation found)
|
||||
|
||||
ℹ Unmatched observations: [fact] ×2, [born] ×1
|
||||
ℹ Unmatched relations: collaborated_with
|
||||
```
|
||||
|
||||
"Unmatched" items are informational — observations and relations the schema doesn't cover.
|
||||
|
||||
### Schema Inference
|
||||
|
||||
Generate schemas from existing notes by analyzing observation and relation frequency:
|
||||
|
||||
```
|
||||
$ bm schema infer Person
|
||||
|
||||
Analyzing 30 notes with type: Person...
|
||||
|
||||
Observations found:
|
||||
[name] 30/30 100% → name: string
|
||||
[role] 27/30 90% → role?: string
|
||||
[expertise] 18/30 60% → expertise?(array): string
|
||||
[email] 8/30 27% → email?: string
|
||||
|
||||
Relations found:
|
||||
works_at 22/30 73% → works_at?: Organization
|
||||
|
||||
Suggested schema:
|
||||
name: string, full name
|
||||
role?: string, job title
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
works_at?: Organization, employer
|
||||
|
||||
Save to schema/Person.md? [y/n]
|
||||
```
|
||||
|
||||
Frequency thresholds:
|
||||
- **100% present** → required field
|
||||
- **25%+ present** → optional field
|
||||
- **Below 25%** → excluded from suggestion
|
||||
|
||||
### Schema Drift Detection
|
||||
|
||||
Track how usage patterns shift over time:
|
||||
|
||||
```
|
||||
$ bm schema diff Person
|
||||
|
||||
Schema drift detected:
|
||||
|
||||
+ expertise: now in 81% of notes (was 12%)
|
||||
- department: dropped to 3% of notes
|
||||
~ works_at: cardinality changed (one → many)
|
||||
|
||||
Update schema? [y/n/review]
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Simple Note (No Schema)
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Project Ideas
|
||||
type: note
|
||||
tags: [ideas, brainstorm]
|
||||
---
|
||||
|
||||
# Project Ideas
|
||||
|
||||
## Observations
|
||||
- [idea] Build a CLI tool for markdown linting #tooling
|
||||
- [idea] Create a recipe knowledge base #cooking
|
||||
- [priority] Focus on developer tools first (Q1 goal)
|
||||
|
||||
## Relations
|
||||
- inspired_by [[Developer Workflow Research]]
|
||||
- part_of [[Q1 Planning]]
|
||||
```
|
||||
|
||||
### Schema-Validated Note
|
||||
|
||||
Schema at `schema/Person.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Person
|
||||
type: schema
|
||||
entity: Person
|
||||
version: 1
|
||||
schema:
|
||||
name: string, full name
|
||||
role?: string, job title or position
|
||||
works_at?: Organization, employer
|
||||
expertise?(array): string, areas of knowledge
|
||||
email?: string, contact email
|
||||
settings:
|
||||
validation: warn
|
||||
---
|
||||
|
||||
# Person
|
||||
|
||||
A human individual in the knowledge graph.
|
||||
```
|
||||
|
||||
Note at `people/paul-graham.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Paul Graham
|
||||
type: Person
|
||||
tags: [startups, essays, lisp]
|
||||
---
|
||||
|
||||
# Paul Graham
|
||||
|
||||
## Observations
|
||||
- [name] Paul Graham
|
||||
- [role] Essayist and investor
|
||||
- [expertise] Startups
|
||||
- [expertise] Lisp
|
||||
- [expertise] Essay writing
|
||||
- [fact] Created Viaweb, the first web app
|
||||
|
||||
## Relations
|
||||
- works_at [[Y Combinator]]
|
||||
- authored [[Hackers and Painters]]
|
||||
```
|
||||
|
||||
The `[fact]` observation and `authored` relation are not in the schema — they're valid, just unmatched. The schema only checks that `[name]` exists (required) and looks for optional fields like `[role]`, `[expertise]`, and `works_at`.
|
||||
|
||||
### Inline Schema Note
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Team Standup 2024-01-15
|
||||
type: meeting
|
||||
schema:
|
||||
attendees(array): string, who was there
|
||||
decisions(array): string, what was decided
|
||||
action_items(array): string, follow-ups
|
||||
blockers?(array): string, anything stuck
|
||||
---
|
||||
|
||||
# Team Standup 2024-01-15
|
||||
|
||||
## Observations
|
||||
- [attendees] Paul
|
||||
- [attendees] Sarah
|
||||
- [decisions] Ship v2 by Friday
|
||||
- [action_items] Paul to review PR #42
|
||||
- [blockers] Waiting on API credentials
|
||||
```
|
||||
@@ -1,259 +0,0 @@
|
||||
# OAuth Authentication Guide
|
||||
|
||||
Basic Memory MCP server supports OAuth 2.1 authentication for secure access control. This guide covers setup, testing, and production deployment.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Enable OAuth
|
||||
|
||||
```bash
|
||||
# Set environment variable
|
||||
export FASTMCP_AUTH_ENABLED=true
|
||||
|
||||
# Or use .env file
|
||||
echo "FASTMCP_AUTH_ENABLED=true" >> .env
|
||||
```
|
||||
|
||||
### 2. Start the Server
|
||||
|
||||
```bash
|
||||
basic-memory mcp --transport streamable-http
|
||||
```
|
||||
|
||||
### 3. Test with MCP Inspector
|
||||
|
||||
Since the basic auth provider uses in-memory storage with per-instance secret keys, you'll need to use a consistent approach:
|
||||
|
||||
#### Option A: Use Environment Variable for Secret Key
|
||||
|
||||
```bash
|
||||
# Set a fixed secret key for testing
|
||||
export FASTMCP_AUTH_SECRET_KEY="your-test-secret-key"
|
||||
|
||||
# Start the server
|
||||
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
|
||||
|
||||
# In another terminal, register a client
|
||||
basic-memory auth register-client --client-id=test-client
|
||||
|
||||
# Get a token using the same secret key
|
||||
basic-memory auth test-auth
|
||||
```
|
||||
|
||||
#### Option B: Use the Built-in Test Endpoint
|
||||
|
||||
```bash
|
||||
# Start server with OAuth
|
||||
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
|
||||
|
||||
# Register a client and get token in one step
|
||||
curl -X POST http://localhost:8000/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"client_metadata": {"client_name": "Test Client"}}'
|
||||
|
||||
# Use the returned client_id and client_secret
|
||||
curl -X POST http://localhost:8000/token \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
|
||||
```
|
||||
|
||||
### 4. Configure MCP Inspector
|
||||
|
||||
1. Open MCP Inspector
|
||||
2. Configure:
|
||||
- Server URL: `http://localhost:8000/mcp/` (note the trailing slash!)
|
||||
- Transport: `streamable-http`
|
||||
- Custom Headers:
|
||||
```
|
||||
Authorization: Bearer YOUR_ACCESS_TOKEN
|
||||
Accept: application/json, text/event-stream
|
||||
```
|
||||
|
||||
## OAuth Endpoints
|
||||
|
||||
The server provides these OAuth endpoints automatically:
|
||||
|
||||
- `GET /authorize` - Authorization endpoint
|
||||
- `POST /token` - Token exchange endpoint
|
||||
- `GET /.well-known/oauth-authorization-server` - OAuth metadata
|
||||
- `POST /register` - Client registration (if enabled)
|
||||
- `POST /revoke` - Token revocation (if enabled)
|
||||
|
||||
## OAuth Flow
|
||||
|
||||
### Standard Authorization Code Flow
|
||||
|
||||
1. **Get Authorization Code**:
|
||||
```bash
|
||||
curl "http://localhost:8000/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8000/callback&response_type=code&code_challenge=YOUR_CHALLENGE&code_challenge_method=S256"
|
||||
```
|
||||
|
||||
2. **Exchange Code for Token**:
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/token \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&code_verifier=YOUR_VERIFIER"
|
||||
```
|
||||
|
||||
3. **Use Access Token**:
|
||||
```bash
|
||||
curl http://localhost:8000/mcp \
|
||||
-H "Authorization: Bearer ACCESS_TOKEN"
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Using Supabase Auth
|
||||
|
||||
For production, use Supabase for persistent auth storage:
|
||||
|
||||
```bash
|
||||
# Configure environment
|
||||
FASTMCP_AUTH_ENABLED=true
|
||||
FASTMCP_AUTH_PROVIDER=supabase
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_ANON_KEY=your-anon-key
|
||||
SUPABASE_SERVICE_KEY=your-service-key
|
||||
|
||||
# Start server
|
||||
basic-memory mcp --transport streamable-http --host 0.0.0.0
|
||||
```
|
||||
|
||||
### Security Requirements
|
||||
|
||||
1. **HTTPS Required**: OAuth requires HTTPS in production (localhost exception for testing)
|
||||
2. **PKCE Support**: Claude.ai requires PKCE for authorization
|
||||
3. **Token Expiration**: Access tokens expire after 1 hour
|
||||
4. **Scopes**: Supported scopes are `read`, `write`, and `admin`
|
||||
|
||||
## Connecting from Claude.ai
|
||||
|
||||
1. **Deploy with HTTPS**:
|
||||
```bash
|
||||
# Use ngrok for testing
|
||||
ngrok http 8000
|
||||
|
||||
# Or deploy to cloud provider
|
||||
```
|
||||
|
||||
2. **Configure in Claude.ai**:
|
||||
- Go to Settings → Integrations
|
||||
- Click "Add More"
|
||||
- Enter: `https://your-server.com/mcp`
|
||||
- Click "Connect"
|
||||
- Authorize in the popup window
|
||||
|
||||
## Debugging
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **401 Unauthorized**:
|
||||
- Check token is valid and not expired
|
||||
- Verify secret key consistency
|
||||
- Ensure bearer token format: `Authorization: Bearer TOKEN`
|
||||
|
||||
2. **404 on Auth Endpoints**:
|
||||
- Endpoints are at root, not under `/auth`
|
||||
- Use `/authorize` not `/auth/authorize`
|
||||
|
||||
3. **Token Validation Fails**:
|
||||
- Basic provider uses in-memory storage
|
||||
- Tokens don't persist across server restarts
|
||||
- Use same secret key for testing
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Check OAuth metadata
|
||||
curl http://localhost:8000/.well-known/oauth-authorization-server
|
||||
|
||||
# Enable debug logging
|
||||
export FASTMCP_LOG_LEVEL=DEBUG
|
||||
|
||||
# Test token directly
|
||||
curl http://localhost:8000/mcp \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-v
|
||||
```
|
||||
|
||||
## Provider Options
|
||||
|
||||
- **basic**: In-memory storage (development only)
|
||||
- **supabase**: Recommended for production
|
||||
- **github**: GitHub OAuth integration
|
||||
- **google**: Google OAuth integration
|
||||
|
||||
## Example Test Script
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import asyncio
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
|
||||
async def test_oauth_flow():
|
||||
"""Test the full OAuth flow"""
|
||||
client_id = "test-client"
|
||||
client_secret = "test-secret"
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
# 1. Get authorization code
|
||||
auth_response = await client.get(
|
||||
"http://localhost:8000/authorize",
|
||||
params={
|
||||
"client_id": client_id,
|
||||
"redirect_uri": "http://localhost:8000/callback",
|
||||
"response_type": "code",
|
||||
"code_challenge": "test-challenge",
|
||||
"code_challenge_method": "S256",
|
||||
"state": "test-state"
|
||||
}
|
||||
)
|
||||
|
||||
# Extract code from redirect URL
|
||||
redirect_url = auth_response.headers.get("Location")
|
||||
parsed = urlparse(redirect_url)
|
||||
code = parse_qs(parsed.query)["code"][0]
|
||||
|
||||
# 2. Exchange for token
|
||||
token_response = await client.post(
|
||||
"http://localhost:8000/token",
|
||||
data={
|
||||
"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"client_id": client_id,
|
||||
"client_secret": client_secret,
|
||||
"code_verifier": "test-verifier",
|
||||
"redirect_uri": "http://localhost:8000/callback"
|
||||
}
|
||||
)
|
||||
|
||||
tokens = token_response.json()
|
||||
print(f"Access token: {tokens['access_token']}")
|
||||
|
||||
# 3. Test MCP endpoint
|
||||
mcp_response = await client.post(
|
||||
"http://localhost:8000/mcp",
|
||||
headers={"Authorization": f"Bearer {tokens['access_token']}"},
|
||||
json={"method": "initialize", "params": {}}
|
||||
)
|
||||
|
||||
print(f"MCP Response: {mcp_response.status_code}")
|
||||
|
||||
asyncio.run(test_oauth_flow())
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `FASTMCP_AUTH_ENABLED` | Enable OAuth authentication | `false` |
|
||||
| `FASTMCP_AUTH_PROVIDER` | OAuth provider type | `basic` |
|
||||
| `FASTMCP_AUTH_SECRET_KEY` | JWT signing key (basic provider) | Random |
|
||||
| `FASTMCP_AUTH_ISSUER_URL` | OAuth issuer URL | `http://localhost:8000` |
|
||||
| `FASTMCP_AUTH_REQUIRED_SCOPES` | Required scopes (comma-separated) | `read,write` |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Supabase OAuth Setup](./Supabase%20OAuth%20Setup.md) - Production auth setup
|
||||
- [External OAuth Providers](./External%20OAuth%20Providers.md) - GitHub, Google integration
|
||||
- [MCP OAuth Specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) - Official spec
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
title: Obsidian Integration
|
||||
type: note
|
||||
permalink: docs/obsidian-integration
|
||||
---
|
||||
|
||||
# Obsidian Integration
|
||||
|
||||
Basic Memory integrates seamlessly with [Obsidian](https://obsidian.md), providing powerful visualization and navigation capabilities for your knowledge graph.
|
||||
|
||||
## Setup
|
||||
|
||||
### Creating an Obsidian Vault
|
||||
|
||||
1. Download and install [Obsidian](https://obsidian.md)
|
||||
2. Create a new vault
|
||||
3. Point it to your Basic Memory directory (~/basic-memory by default)
|
||||
4. Enable core plugins like Graph View, Backlinks, and Tags
|
||||
|
||||
## Visualization Features
|
||||
|
||||
### Graph View
|
||||
|
||||
Obsidian's Graph View provides a visual representation of your knowledge network:
|
||||
|
||||
- Each document appears as a node
|
||||
- Relations appear as connections between nodes
|
||||
- Colors can be customized to distinguish types
|
||||
- Filters let you focus on specific aspects
|
||||
- Local graphs show connections for individual documents
|
||||
|
||||
### Backlinks
|
||||
|
||||
Obsidian automatically tracks references between documents:
|
||||
|
||||
- View all documents that reference the current one
|
||||
- See the exact context of each reference
|
||||
- Navigate easily through connections
|
||||
- Track how concepts relate to each other
|
||||
|
||||
### Tag Explorer
|
||||
|
||||
Use tags to organize and filter content:
|
||||
|
||||
- View all tags in your knowledge base
|
||||
- See how many documents use each tag
|
||||
- Filter documents by tag combinations
|
||||
- Create hierarchical tag structures
|
||||
|
||||
## Knowledge Elements
|
||||
|
||||
Basic Memory's knowledge format works natively with Obsidian:
|
||||
|
||||
### Wiki Links
|
||||
|
||||
```markdown
|
||||
## Relations
|
||||
- implements [[Search Design]]
|
||||
- depends_on [[Database Schema]]
|
||||
```
|
||||
|
||||
These display as clickable links in Obsidian and appear in the graph view.
|
||||
|
||||
### Observations with Tags
|
||||
|
||||
```markdown
|
||||
## Observations
|
||||
- [tech] Using SQLite #database
|
||||
- [design] Local-first #architecture
|
||||
```
|
||||
|
||||
Tags become searchable and filterable in Obsidian's tag pane.
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Document Title
|
||||
type: note
|
||||
tags: [search, design]
|
||||
---
|
||||
```
|
||||
|
||||
Frontmatter provides metadata for Obsidian to use in search and filtering.
|
||||
|
||||
## Canvas Integration
|
||||
|
||||
Basic Memory can create [Obsidian Canvas](https://obsidian.md/canvas) files:
|
||||
|
||||
1. Ask Claude to create a visualization:
|
||||
```
|
||||
You: "Create a canvas showing the structure of our project components."
|
||||
```
|
||||
|
||||
2. Claude generates a .canvas file in your knowledge base
|
||||
|
||||
3. Open the file in Obsidian to view and edit the visual representation
|
||||
|
||||
4. Canvas files maintain references to your documents
|
||||
|
||||
## Recommended Plugins
|
||||
|
||||
These Obsidian plugins work especially well with Basic Memory:
|
||||
|
||||
- **Dataview**: Query your knowledge base programmatically
|
||||
- **Kanban**: Organize tasks from knowledge files
|
||||
- **Calendar**: View and navigate temporal knowledge
|
||||
- **Templates**: Create consistent knowledge structures
|
||||
|
||||
## Workflow Suggestions
|
||||
|
||||
### Daily Notes
|
||||
|
||||
```markdown
|
||||
# 2024-01-21
|
||||
|
||||
## Progress
|
||||
- Updated [[Search Design]]
|
||||
- Fixed [[Bug Report 123]]
|
||||
|
||||
## Notes
|
||||
- [idea] Better indexing #enhancement
|
||||
- [todo] Update docs #documentation
|
||||
|
||||
## Links
|
||||
- relates_to [[Current Sprint]]
|
||||
- updates [[Project Status]]
|
||||
```
|
||||
|
||||
### Project Tracking
|
||||
|
||||
```markdown
|
||||
# Current Sprint
|
||||
|
||||
## Tasks
|
||||
- [ ] Update [[Search]]
|
||||
- [ ] Fix [[Auth Bug]]
|
||||
|
||||
## Tags
|
||||
#sprint #planning #current
|
||||
```
|
||||
|
||||
## Relations
|
||||
- enhances [[Introduction to Basic Memory]] (Overview of system)
|
||||
- relates_to [[Canvas]] (Visual knowledge mapping)
|
||||
- complements [[User Guide]] (Using Basic Memory)
|
||||
@@ -0,0 +1,147 @@
|
||||
# Simplified Local/Cloud Routing
|
||||
|
||||
## Context
|
||||
|
||||
Basic Memory now uses explicit, project-aware routing without a global cloud-mode toggle.
|
||||
Routing is determined by command-level flags and project mode, not by a global `cloud_mode` state.
|
||||
|
||||
This document is the canonical contract for local/cloud routing behavior in CLI, MCP, and API-adjacent clients.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Remove global `cloud_mode` from runtime/routing semantics.
|
||||
2. Keep MCP HTTP/SSE local-only; let stdio honor per-project routing.
|
||||
3. Make CLI routing explicit and easy to reason about.
|
||||
4. Support projects that exist in both local and cloud without ambiguity.
|
||||
|
||||
## Routing Contract
|
||||
|
||||
Routing is resolved in this order:
|
||||
|
||||
1. Injected client factory (for composition/integration contexts)
|
||||
2. Explicit routing override (`--local` / `--cloud` or env vars below)
|
||||
3. Project-scoped routing (`project.mode`) when a project is known
|
||||
4. Default local routing
|
||||
|
||||
### Routing Environment Variables
|
||||
|
||||
- `BASIC_MEMORY_FORCE_LOCAL=true`: force local transport
|
||||
- `BASIC_MEMORY_FORCE_CLOUD=true`: force cloud proxy transport
|
||||
- `BASIC_MEMORY_EXPLICIT_ROUTING=true`: marks routing as explicitly chosen for this command
|
||||
|
||||
When explicit routing is active, project mode does not override the selected route.
|
||||
|
||||
## Config Semantics
|
||||
|
||||
- `project.mode` is the only config-based routing signal for project-scoped operations.
|
||||
- Legacy `cloud_mode` values may be encountered during migration/loading but are not used for routing behavior.
|
||||
- Normalization saves remove stale `cloud_mode` from `~/.basic-memory/config.json`.
|
||||
|
||||
### Example Config
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": {
|
||||
"main": {
|
||||
"path": "/Users/me/basic-memory",
|
||||
"mode": "local",
|
||||
"local_sync_path": null,
|
||||
"bisync_initialized": false,
|
||||
"last_sync": null
|
||||
},
|
||||
"specs": {
|
||||
"path": "specs",
|
||||
"mode": "cloud",
|
||||
"local_sync_path": "/Users/me/dev/specs",
|
||||
"bisync_initialized": true,
|
||||
"last_sync": "2026-02-06T17:36:38.544153"
|
||||
}
|
||||
},
|
||||
"default_project": "main",
|
||||
"cloud_api_key": "bmc_abc123...",
|
||||
"cloud_host": "https://cloud.basicmemory.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud Commands Are Auth-Only
|
||||
|
||||
`bm cloud login`, `bm cloud logout`, and `bm cloud status` manage authentication state.
|
||||
|
||||
- `bm cloud login`
|
||||
- performs OAuth device flow
|
||||
- stores/refreshes token material
|
||||
- may verify cloud health/subscription
|
||||
- does not change routing defaults
|
||||
- `bm cloud logout`
|
||||
- removes stored OAuth session tokens
|
||||
- does not change routing defaults
|
||||
- `bm cloud status`
|
||||
- reports auth state (API key, OAuth token validity)
|
||||
- runs health checks only when credentials are available
|
||||
|
||||
## MCP Transport Routing
|
||||
|
||||
### Stdio (default)
|
||||
|
||||
`bm mcp --transport stdio` uses natural per-project routing.
|
||||
|
||||
- Local-mode projects route through the in-process ASGI transport.
|
||||
- Cloud-mode projects route to the cloud proxy with Bearer auth (API key).
|
||||
- No explicit routing env vars are injected by the CLI command.
|
||||
- Externally-set env vars are honored (e.g. `BASIC_MEMORY_FORCE_CLOUD=true` for cloud deployments).
|
||||
- Users who need all projects forced local can set `BASIC_MEMORY_FORCE_LOCAL=true` externally.
|
||||
|
||||
### HTTP and SSE Transports
|
||||
|
||||
`bm mcp --transport streamable-http` and `bm mcp --transport sse` always route locally.
|
||||
|
||||
These transports set explicit local routing (`BASIC_MEMORY_FORCE_LOCAL=true` and
|
||||
`BASIC_MEMORY_EXPLICIT_ROUTING=true`) before starting the server. This prevents cloud
|
||||
routing regardless of project mode, since HTTP/SSE serve as local API endpoints.
|
||||
|
||||
## Project List UX for Dual Presence
|
||||
|
||||
Projects may exist in both local and cloud. `bm project list` should display that clearly in one row per logical
|
||||
project identity, with explicit source/target signals.
|
||||
|
||||
Recommended display contract:
|
||||
|
||||
1. Keep one row per normalized project name/permalink.
|
||||
2. Show both local and cloud presence as separate columns/indicators.
|
||||
3. Show an explicit `MCP (stdio)` target column that always resolves to `local`.
|
||||
4. Keep CLI route semantics explicit:
|
||||
- no flags: default local for non-project commands
|
||||
- `--cloud`: force cloud
|
||||
- `--local`: force local
|
||||
|
||||
## Project LS Targeting
|
||||
|
||||
`bm project ls` should clearly identify which project instance is being listed.
|
||||
|
||||
Targeting rules:
|
||||
|
||||
1. No routing flags: list local project files.
|
||||
2. `--cloud`: list cloud project files.
|
||||
3. `--local`: list local project files (explicit override).
|
||||
4. Output should label the active target (`LOCAL` or `CLOUD`) in heading or status line.
|
||||
|
||||
## Runtime Mode
|
||||
|
||||
Runtime mode is no longer a cloud/local routing switch for local app flows.
|
||||
|
||||
- `resolve_runtime_mode(is_test_env)` resolves to:
|
||||
- `TEST` when running in test environment
|
||||
- `LOCAL` otherwise
|
||||
- `RuntimeMode.CLOUD` may remain for compatibility with existing tests/call sites but is not selected by normal local
|
||||
runtime resolution.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
1. Loading config with legacy `cloud_mode` succeeds.
|
||||
2. Saving config strips legacy `cloud_mode`.
|
||||
3. `--local/--cloud` always override per-project mode for that command.
|
||||
4. No-project + no-flags commands route local by default.
|
||||
5. `bm cloud login/logout` do not toggle routing behavior.
|
||||
6. `bm mcp` stdio routes per-project mode; HTTP/SSE remain local-forced.
|
||||
7. `bm project list` communicates dual local/cloud presence without ambiguity.
|
||||
8. `bm project ls` output identifies route target explicitly.
|
||||
@@ -1,311 +0,0 @@
|
||||
# Supabase OAuth Setup for Basic Memory
|
||||
|
||||
This guide explains how to set up Supabase as the OAuth provider for Basic Memory MCP server in production.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. A Supabase project (create one at [supabase.com](https://supabase.com))
|
||||
2. Basic Memory MCP server deployed
|
||||
3. Environment variables configuration
|
||||
|
||||
## Overview
|
||||
|
||||
The Supabase OAuth provider offers:
|
||||
- Production-ready authentication with persistent storage
|
||||
- User management through Supabase Auth
|
||||
- JWT token validation
|
||||
- Integration with Supabase's security features
|
||||
- Support for social logins (GitHub, Google, etc.)
|
||||
|
||||
## Setup Steps
|
||||
|
||||
### 1. Get Supabase Credentials
|
||||
|
||||
From your Supabase project dashboard:
|
||||
|
||||
1. Go to Settings > API
|
||||
2. Copy these values:
|
||||
- `Project URL` → `SUPABASE_URL`
|
||||
- `anon public` key → `SUPABASE_ANON_KEY`
|
||||
- `service_role` key → `SUPABASE_SERVICE_KEY` (keep this secret!)
|
||||
- JWT secret → `SUPABASE_JWT_SECRET` (under Settings > API > JWT Settings)
|
||||
|
||||
### 2. Configure Environment Variables
|
||||
|
||||
Create a `.env` file:
|
||||
|
||||
```bash
|
||||
# Enable OAuth
|
||||
FASTMCP_AUTH_ENABLED=true
|
||||
FASTMCP_AUTH_PROVIDER=supabase
|
||||
|
||||
# Your MCP server URL
|
||||
FASTMCP_AUTH_ISSUER_URL=https://your-mcp-server.com
|
||||
|
||||
# Supabase configuration
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_ANON_KEY=your-anon-key
|
||||
SUPABASE_SERVICE_KEY=your-service-key
|
||||
SUPABASE_JWT_SECRET=your-jwt-secret
|
||||
|
||||
# Allowed OAuth clients (comma-separated)
|
||||
SUPABASE_ALLOWED_CLIENTS=web-app,mobile-app,cli-tool
|
||||
|
||||
# Required scopes
|
||||
FASTMCP_AUTH_REQUIRED_SCOPES=read,write
|
||||
```
|
||||
|
||||
### 3. Create OAuth Clients Table (Optional)
|
||||
|
||||
For production, create a table to store OAuth clients in Supabase:
|
||||
|
||||
```sql
|
||||
CREATE TABLE oauth_clients (
|
||||
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||
client_id TEXT UNIQUE NOT NULL,
|
||||
client_secret TEXT NOT NULL,
|
||||
name TEXT,
|
||||
redirect_uris TEXT[],
|
||||
allowed_scopes TEXT[],
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create an index for faster lookups
|
||||
CREATE INDEX idx_oauth_clients_client_id ON oauth_clients(client_id);
|
||||
|
||||
-- RLS policies
|
||||
ALTER TABLE oauth_clients ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Only service role can manage clients
|
||||
CREATE POLICY "Service role can manage clients" ON oauth_clients
|
||||
FOR ALL USING (auth.jwt()->>'role' = 'service_role');
|
||||
```
|
||||
|
||||
### 4. Set Up Auth Flow
|
||||
|
||||
The Supabase OAuth provider handles the following flow:
|
||||
|
||||
1. **Client Authorization Request**
|
||||
```
|
||||
GET /authorize?client_id=web-app&redirect_uri=https://app.com/callback
|
||||
```
|
||||
|
||||
2. **Redirect to Supabase Auth**
|
||||
- User authenticates with Supabase (email/password, magic link, or social login)
|
||||
- Supabase redirects back to your MCP server
|
||||
|
||||
3. **Token Exchange**
|
||||
```
|
||||
POST /token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=authorization_code&code=xxx&client_id=web-app
|
||||
```
|
||||
|
||||
4. **Access Protected Resources**
|
||||
```
|
||||
GET /mcp
|
||||
Authorization: Bearer <access_token>
|
||||
```
|
||||
|
||||
### 5. Enable Social Logins (Optional)
|
||||
|
||||
In Supabase dashboard:
|
||||
|
||||
1. Go to Authentication > Providers
|
||||
2. Enable desired providers (GitHub, Google, etc.)
|
||||
3. Configure OAuth apps for each provider
|
||||
4. Users can now log in via social providers
|
||||
|
||||
### 6. User Management
|
||||
|
||||
Supabase provides:
|
||||
- User registration and login
|
||||
- Password reset flows
|
||||
- Email verification
|
||||
- User metadata storage
|
||||
- Admin APIs for user management
|
||||
|
||||
Access user data in your MCP tools:
|
||||
|
||||
```python
|
||||
# In your MCP tool
|
||||
async def get_user_info(ctx: Context):
|
||||
# The token is already validated by the OAuth middleware
|
||||
user_id = ctx.auth.user_id
|
||||
email = ctx.auth.email
|
||||
|
||||
# Use Supabase client to get more user data if needed
|
||||
user = await supabase.auth.admin.get_user_by_id(user_id)
|
||||
return user
|
||||
```
|
||||
|
||||
### 7. Production Deployment
|
||||
|
||||
1. **Environment Security**
|
||||
- Never expose `SUPABASE_SERVICE_KEY`
|
||||
- Use environment variables, not hardcoded values
|
||||
- Rotate keys periodically
|
||||
|
||||
2. **HTTPS Required**
|
||||
- Always use HTTPS in production
|
||||
- Configure proper SSL certificates
|
||||
|
||||
3. **Rate Limiting**
|
||||
- Implement rate limiting for auth endpoints
|
||||
- Use Supabase's built-in rate limiting
|
||||
|
||||
4. **Monitoring**
|
||||
- Monitor auth logs in Supabase dashboard
|
||||
- Set up alerts for suspicious activity
|
||||
|
||||
## Testing
|
||||
|
||||
### Local Development
|
||||
|
||||
For local testing with Supabase:
|
||||
|
||||
```bash
|
||||
# Start MCP server with Supabase auth
|
||||
FASTMCP_AUTH_ENABLED=true \
|
||||
FASTMCP_AUTH_PROVIDER=supabase \
|
||||
SUPABASE_URL=http://localhost:54321 \
|
||||
SUPABASE_ANON_KEY=your-local-anon-key \
|
||||
bm mcp --transport streamable-http
|
||||
```
|
||||
|
||||
### Test Authentication Flow
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import asyncio
|
||||
|
||||
async def test_supabase_auth():
|
||||
# 1. Register/login with Supabase directly
|
||||
supabase_url = "https://your-project.supabase.co"
|
||||
|
||||
# 2. Get MCP authorization URL
|
||||
response = await httpx.get(
|
||||
"http://localhost:8000/authorize",
|
||||
params={
|
||||
"client_id": "web-app",
|
||||
"redirect_uri": "http://localhost:3000/callback",
|
||||
"response_type": "code",
|
||||
}
|
||||
)
|
||||
|
||||
# 3. User logs in via Supabase
|
||||
# 4. Exchange code for MCP tokens
|
||||
# 5. Access protected resources
|
||||
|
||||
asyncio.run(test_supabase_auth())
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom User Metadata
|
||||
|
||||
Store additional user data in Supabase:
|
||||
|
||||
```sql
|
||||
-- Add custom fields to auth.users
|
||||
ALTER TABLE auth.users
|
||||
ADD COLUMN IF NOT EXISTS metadata JSONB DEFAULT '{}';
|
||||
|
||||
-- Or create a separate profiles table
|
||||
CREATE TABLE profiles (
|
||||
id UUID REFERENCES auth.users PRIMARY KEY,
|
||||
username TEXT UNIQUE,
|
||||
avatar_url TEXT,
|
||||
bio TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Row Level Security (RLS)
|
||||
|
||||
Protect user data with RLS:
|
||||
|
||||
```sql
|
||||
-- Users can only access their own data
|
||||
CREATE POLICY "Users can view own profile" ON profiles
|
||||
FOR SELECT USING (auth.uid() = id);
|
||||
|
||||
CREATE POLICY "Users can update own profile" ON profiles
|
||||
FOR UPDATE USING (auth.uid() = id);
|
||||
```
|
||||
|
||||
### Custom Claims
|
||||
|
||||
Add custom claims to JWT tokens:
|
||||
|
||||
```sql
|
||||
-- Function to add custom claims
|
||||
CREATE OR REPLACE FUNCTION custom_jwt_claims()
|
||||
RETURNS JSON AS $$
|
||||
BEGIN
|
||||
RETURN json_build_object(
|
||||
'user_role', current_setting('request.jwt.claims')::json->>'user_role',
|
||||
'permissions', current_setting('request.jwt.claims')::json->>'permissions'
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Invalid JWT Secret**
|
||||
- Ensure `SUPABASE_JWT_SECRET` matches your Supabase project
|
||||
- Check Settings > API > JWT Settings in Supabase dashboard
|
||||
|
||||
2. **CORS Errors**
|
||||
- Configure CORS in your MCP server
|
||||
- Add allowed origins in Supabase dashboard
|
||||
|
||||
3. **Token Validation Fails**
|
||||
- Verify tokens are being passed correctly
|
||||
- Check token expiration times
|
||||
- Ensure scopes match requirements
|
||||
|
||||
4. **User Not Found**
|
||||
- Confirm user exists in Supabase Auth
|
||||
- Check if email is verified (if required)
|
||||
- Verify client permissions
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
export FASTMCP_LOG_LEVEL=DEBUG
|
||||
export SUPABASE_LOG_LEVEL=debug
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Secure Keys**: Never commit secrets to version control
|
||||
2. **Least Privilege**: Use minimal required scopes
|
||||
3. **Token Rotation**: Implement refresh token rotation
|
||||
4. **Audit Logs**: Monitor authentication events
|
||||
5. **Rate Limiting**: Protect against brute force attacks
|
||||
6. **HTTPS Only**: Always use encrypted connections
|
||||
|
||||
## Migration from Basic Auth
|
||||
|
||||
To migrate from the basic auth provider:
|
||||
|
||||
1. Export existing user data
|
||||
2. Import users into Supabase Auth
|
||||
3. Update client applications to use new auth flow
|
||||
4. Gradually transition users to Supabase login
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Set up email templates in Supabase
|
||||
- Configure password policies
|
||||
- Implement MFA (multi-factor authentication)
|
||||
- Add social login providers
|
||||
- Create admin dashboard for user management
|
||||
@@ -1,243 +0,0 @@
|
||||
---
|
||||
title: Technical Information
|
||||
type: note
|
||||
permalink: docs/technical-information
|
||||
---
|
||||
|
||||
# Technical Information
|
||||
|
||||
This document provides technical details about Basic Memory's implementation, licensing, and integration with the Model Context Protocol (MCP).
|
||||
|
||||
## Architecture
|
||||
|
||||
Basic Memory consists of:
|
||||
|
||||
1. **Core Knowledge Engine**: Parses and indexes Markdown files
|
||||
2. **SQLite Database**: Provides fast querying and search
|
||||
3. **MCP Server**: Implements the Model Context Protocol
|
||||
4. **CLI Tools**: Command-line utilities for management
|
||||
5. **Sync Service**: Monitors file changes and updates the database
|
||||
|
||||
The system follows a file-first architecture where all knowledge is represented in standard Markdown files and the database serves as a secondary index.
|
||||
|
||||
## Model Context Protocol (MCP)
|
||||
|
||||
Basic Memory implements the [Model Context Protocol](https://github.com/modelcontextprotocol/spec), an open standard for enabling AI models to access external tools:
|
||||
|
||||
- **Standardized Interface**: Common protocol for tool integration
|
||||
- **Tool Registration**: Basic Memory registers as a tool provider
|
||||
- **Asynchronous Communication**: Enables efficient interaction with AI models
|
||||
- **Standardized Schema**: Structured data exchange format
|
||||
|
||||
Integration with Claude Desktop uses the MCP to grant Claude access to your knowledge base through a set of specialized tools that search, read, and write knowledge.
|
||||
|
||||
## Licensing
|
||||
|
||||
Basic Memory is licensed under the [GNU Affero General Public License v3.0 (AGPL-3.0)](https://www.gnu.org/licenses/agpl-3.0.en.html):
|
||||
|
||||
- **Free Software**: You can use, study, share, and modify the software
|
||||
- **Copyleft**: Derivative works must be distributed under the same license
|
||||
- **Network Use**: Network users must be able to receive the source code
|
||||
- **Commercial Use**: Allowed, subject to license requirements
|
||||
|
||||
The AGPL license ensures Basic Memory remains open source while protecting against proprietary forks.
|
||||
|
||||
## Source Code
|
||||
|
||||
Basic Memory is developed as an open-source project:
|
||||
|
||||
- **GitHub Repository**: [https://github.com/basicmachines-co/basic-memory](https://github.com/basicmachines-co/basic-memory)
|
||||
- **Issue Tracker**: Report bugs and request features on GitHub
|
||||
- **Contributions**: Pull requests are welcome following the contributing guidelines
|
||||
- **Documentation**: Source for this documentation is also available in the repository
|
||||
|
||||
## Data Storage and Privacy
|
||||
|
||||
Basic Memory is designed with privacy as a core principle:
|
||||
|
||||
- **Local-First**: All data remains on your local machine
|
||||
- **No Cloud Dependency**: No remote servers or accounts required
|
||||
- **Telemetry**: Optional and disabled by default
|
||||
- **Standard Formats**: All data is stored in standard file formats you control
|
||||
|
||||
## Implementation Details
|
||||
|
||||
Knowledge in Basic Memory is organized as a semantic graph:
|
||||
|
||||
1. **Entities** - Distinct concepts represented by Markdown documents
|
||||
2. **Observations** - Categorized facts and information about entities
|
||||
3. **Relations** - Connections between entities that form the knowledge graph
|
||||
|
||||
This structure emerges from simple text patterns in standard Markdown:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
type: note
|
||||
permalink: coffee/coffee-brewing-methods
|
||||
tags:
|
||||
- '#coffee'
|
||||
- '#brewing'
|
||||
- '#methods'
|
||||
- '#demo'
|
||||
---
|
||||
|
||||
# Coffee Brewing Methods
|
||||
|
||||
An exploration of different coffee brewing techniques, their characteristics, and how they affect flavor extraction.
|
||||
|
||||
## Overview
|
||||
|
||||
Coffee brewing is both an art and a science. Different brewing methods extract different compounds from coffee beans,
|
||||
resulting in unique flavor profiles, body, and mouthfeel. The key variables in any brewing method are:
|
||||
|
||||
- Grind size
|
||||
- Water temperature
|
||||
- Brew time
|
||||
- Coffee-to-water ratio
|
||||
- Agitation/turbulence
|
||||
|
||||
## Observations
|
||||
|
||||
- [principle] Coffee extraction follows a predictable pattern: acids extract first, then sugars, then bitter compounds
|
||||
#extraction
|
||||
- [method] Pour over methods generally produce cleaner, brighter cups with more distinct flavor notes #clarity
|
||||
|
||||
## Relations
|
||||
|
||||
- requires [[Proper Grinding Technique]]
|
||||
- affects [[Flavor Extraction]]
|
||||
```
|
||||
|
||||
Becomes
|
||||
|
||||
```json
|
||||
{
|
||||
"entities": [
|
||||
{
|
||||
"permalink": "coffee/coffee-brewing-methods",
|
||||
"title": "Coffee Brewing Methods",
|
||||
"file_path": "Coffee Notes/Coffee Brewing Methods.md",
|
||||
"entity_type": "note",
|
||||
"entity_metadata": {
|
||||
"title": "Coffee Brewing Methods",
|
||||
"type": "note",
|
||||
"permalink": "coffee/coffee-brewing-methods",
|
||||
"tags": "['#coffee', '#brewing', '#methods', '#demo']"
|
||||
},
|
||||
"checksum": "bfa32a0f23fa124b53f0694c344d2788b0ce50bd090b55b6d738401d2a349e4c",
|
||||
"content_type": "text/markdown",
|
||||
"observations": [
|
||||
{
|
||||
"category": "principle",
|
||||
"content": "Coffee extraction follows a predictable pattern: acids extract first, then sugars, then bitter compounds #extraction",
|
||||
"tags": [
|
||||
"extraction"
|
||||
],
|
||||
"permalink": "coffee/coffee-brewing-methods/observations/principle/coffee-extraction-follows-a-predictable-pattern-acids-extract-first-then-sugars-then-bitter-compounds-extraction"
|
||||
},
|
||||
{
|
||||
"category": "method",
|
||||
"content": "Pour over methods generally produce cleaner, brighter cups with more distinct flavor notes #clarity",
|
||||
"tags": [
|
||||
"clarity"
|
||||
],
|
||||
"permalink": "coffee/coffee-brewing-methods/observations/method/pour-over-methods-generally-produce-cleaner-brighter-cups-with-more-distinct-flavor-notes-clarity"
|
||||
}
|
||||
],
|
||||
"relations": [
|
||||
{
|
||||
"from_id": "coffee/coffee-bean-origins",
|
||||
"to_id": "coffee/coffee-brewing-methods",
|
||||
"relation_type": "pairs_with",
|
||||
"permalink": "coffee/coffee-bean-origins/pairs-with/coffee/coffee-brewing-methods",
|
||||
"to_name": "Coffee Brewing Methods"
|
||||
},
|
||||
{
|
||||
"from_id": "coffee/flavor-extraction",
|
||||
"to_id": "coffee/coffee-brewing-methods",
|
||||
"relation_type": "affected_by",
|
||||
"permalink": "coffee/flavor-extraction/affected-by/coffee/coffee-brewing-methods",
|
||||
"to_name": "Coffee Brewing Methods"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-03-06T14:01:23.445071",
|
||||
"updated_at": "2025-03-06T13:34:48.563606"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Basic Memory understands how to build context via its semantic graph.
|
||||
|
||||
### Entity Model
|
||||
|
||||
Basic Memory's core data model consists of:
|
||||
|
||||
- **Entities**: Documents in your knowledge base
|
||||
- **Observations**: Facts or statements about entities
|
||||
- **Relations**: Connections between entities
|
||||
- **Tags**: Additional categorization for entities and observations
|
||||
|
||||
The system parses Markdown files to extract this structured information while preserving the human-readable format.
|
||||
|
||||
### Files as Source of Truth
|
||||
|
||||
Plain Markdown files store all knowledge, making it accessible with any text editor and easy to version with git.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User((User)) <--> |Conversation| Claude["Claude or other LLM"]
|
||||
Claude <-->|API Calls| BMCP["Basic Memory MCP Server"]
|
||||
|
||||
subgraph "Local Storage"
|
||||
KnowledgeFiles["Markdown Files - Source of Truth"]
|
||||
KnowledgeIndex[(Knowledge Graph SQLite Index)]
|
||||
end
|
||||
|
||||
BMCP <-->|"write_note() read_note()"| KnowledgeFiles
|
||||
BMCP <-->|"search_notes() build_context()"| KnowledgeIndex
|
||||
KnowledgeFiles <-.->|Sync Process| KnowledgeIndex
|
||||
KnowledgeFiles <-->|Direct Editing| Editors((Text Editors & Git))
|
||||
|
||||
User -.->|"Complete control, Privacy preserved"| KnowledgeFiles
|
||||
|
||||
|
||||
class Claude primary
|
||||
class BMCP secondary
|
||||
class KnowledgeFiles tertiary
|
||||
class KnowledgeIndex quaternary
|
||||
class User,Editors user`;
|
||||
```
|
||||
|
||||
### Sqlite Database
|
||||
|
||||
A local SQLite database maintains the knowledge graph topology for fast queries and semantic traversal without cloud dependencies. It contains:
|
||||
- db tables for the knowledge graph schema
|
||||
- a search index table enabling full text search across the knowledge base
|
||||
|
||||
|
||||
### Sync Process
|
||||
|
||||
The sync process:
|
||||
|
||||
1. Detects changes to files in the knowledge directory
|
||||
2. Parses modified files to extract structured data
|
||||
3. Updates the SQLite database with changes
|
||||
4. Resolves forward references when new entities are created
|
||||
5. Updates the search index for fast querying
|
||||
|
||||
### Search Engine
|
||||
|
||||
The search functionality:
|
||||
|
||||
1. Uses a combination of full-text search and semantic matching
|
||||
2. Indexes observations, relations, and content
|
||||
3. Supports wildcards and pattern matching in memory:// URLs
|
||||
4. Traverses the knowledge graph to follow relationships
|
||||
5. Ranks results by relevance to the query
|
||||
|
||||
## Relations
|
||||
- relates_to [[Welcome to Basic memory]] (Overview)
|
||||
- relates_to [[CLI Reference]] (Command line tools)
|
||||
- implements [[Knowledge Format]] (File structure and format)
|
||||
@@ -1,657 +0,0 @@
|
||||
---
|
||||
title: User Guide
|
||||
type: note
|
||||
permalink: docs/user-guide
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
This guide explains how to effectively use Basic Memory in your daily workflow, from creating knowledge through
|
||||
conversations to building a rich semantic network.
|
||||
|
||||
## Basic Memory Workflow
|
||||
|
||||
Using Basic Memory follows a natural cycle:
|
||||
|
||||
1. **Have conversations** with AI assistants like Claude
|
||||
2. **Capture knowledge** in Markdown files
|
||||
3. **Build connections** between pieces of knowledge
|
||||
4. **Reference your knowledge** in future conversations
|
||||
5. **Edit files directly** when needed
|
||||
6. **Sync changes** automatically
|
||||
|
||||
## Creating Knowledge
|
||||
|
||||
### Through Conversations
|
||||
|
||||
To create knowledge during conversations with Claude:
|
||||
|
||||
```
|
||||
You: We've covered several authentication approaches. Could you create a note summarizing what we've discussed?
|
||||
|
||||
Claude: I'll create a note summarizing our authentication discussion.
|
||||
```
|
||||
|
||||
This creates a Markdown file in your `~/basic-memory` directory with semantic markup.
|
||||
|
||||
### Direct File Creation
|
||||
|
||||
You can create files directly:
|
||||
|
||||
1. Create a new Markdown file in your `~/basic-memory` directory
|
||||
2. Add frontmatter with title, type, and optional tags
|
||||
3. Structure content with observations and relations
|
||||
4. Save the file
|
||||
5. Run `basic-memory sync` if not in watch mode
|
||||
|
||||
## Using Special Prompts
|
||||
|
||||
Basic Memory includes several special prompts that help you leverage your knowledge base more effectively. In apps like
|
||||
Claude Desktop, these prompts trigger specific tools to search and analyze your knowledge base.
|
||||
|
||||
### Continue Conversation
|
||||
|
||||
When you want to pick up where you left off on a topic:
|
||||
|
||||
```
|
||||
You: Let's continue our conversation about authentication systems.
|
||||
```
|
||||
|
||||
Behind the scenes:
|
||||
|
||||
- Claude searches your knowledge base for content about "authentication systems"
|
||||
- It retrieves relevant documents and their relations
|
||||
- It analyzes the context to understand where you left off
|
||||
- It builds a comprehensive picture of what you've previously discussed
|
||||
- It can then resume the conversation with all that context
|
||||
|
||||
This is particularly useful when:
|
||||
|
||||
- Starting a new session days or weeks after your last discussion
|
||||
- Switching between multiple ongoing projects
|
||||
- Building on previous work without repeating yourself
|
||||
|
||||
### Recent Activity
|
||||
|
||||
To get an overview of what you've been working on:
|
||||
|
||||
```
|
||||
You: What have we been discussing recently?
|
||||
```
|
||||
|
||||
Behind the scenes:
|
||||
|
||||
- Claude retrieves documents modified recently
|
||||
- It analyzes patterns and themes
|
||||
- It summarizes the key topics and changes
|
||||
- It offers to continue working on any of those topics
|
||||
|
||||
This is useful for:
|
||||
|
||||
- Coming back after a break
|
||||
- Getting a quick reminder of ongoing projects
|
||||
- Deciding what to work on next
|
||||
|
||||
### Search
|
||||
|
||||
To find specific information in your knowledge base:
|
||||
|
||||
```
|
||||
You: Find information about JWT authentication in my notes.
|
||||
```
|
||||
|
||||
Behind the scenes:
|
||||
|
||||
- Claude performs a semantic search for "JWT authentication"
|
||||
- It retrieves and ranks the most relevant documents
|
||||
- It summarizes the key findings
|
||||
- It offers to explore specific areas in more detail
|
||||
|
||||
This is useful for:
|
||||
|
||||
- Finding specific information quickly
|
||||
- Exploring what you know about a topic
|
||||
- Starting work on an existing topic
|
||||
|
||||
### Example
|
||||
|
||||
Choose "Continue Conversation"
|
||||
![[prompt 1.png|500]]
|
||||
|
||||
Enter a topic
|
||||
![[prompt2.png|500]]
|
||||
|
||||
Give instructions
|
||||
![[prompt3.png|500]]
|
||||
|
||||
Claude Desktop lets you send a prompt to provide context. You can use this at the beginning of a chat to preload context
|
||||
without needing to copy paste all the time. By using one of the supplied prompts, Basic Memory will search the knowledge
|
||||
base and give the AI instructions for how to build context.
|
||||
|
||||
Choose "Continue Conversation":
|
||||
|
||||
![[prompt 1.png|500]]
|
||||
|
||||
Enter a topic:
|
||||
|
||||
![[prompt2.png|500]]
|
||||
|
||||
Give optional additional instructions:
|
||||
|
||||
![[prompt3.png|500]]
|
||||
|
||||
Claude can build context from the supplied topic. This works independently of Claude Project information. All the
|
||||
context comes from your local knowledge base.
|
||||
|
||||
![[prompt4.png|500]]
|
||||
|
||||
## Searching Your Knowledge Base
|
||||
|
||||
Basic Memory provides multiple ways to search and explore your knowledge base:
|
||||
|
||||
### Natural Language Search
|
||||
|
||||
The simplest way to search is to ask Claude directly:
|
||||
|
||||
```
|
||||
You: What do I know about authentication methods?
|
||||
```
|
||||
|
||||
Claude will search your knowledge base semantically and return relevant information.
|
||||
|
||||
### Search Prompt
|
||||
|
||||
Use the dedicated search prompt for more focused searches:
|
||||
|
||||
```
|
||||
You: Search for "JWT authentication"
|
||||
```
|
||||
|
||||
This triggers a specialized search that returns precise results with document titles, relevant excerpts, and offers to
|
||||
explore specific documents.
|
||||
|
||||
### Boolean Search
|
||||
|
||||
For more precise searches, use boolean operators to refine your queries:
|
||||
|
||||
```
|
||||
You: Search for "authentication AND OAuth NOT basic"
|
||||
```
|
||||
|
||||
Basic Memory supports standard boolean operators:
|
||||
|
||||
- **AND**: Find documents containing both terms
|
||||
```
|
||||
You: Search for "python AND flask"
|
||||
```
|
||||
This finds documents containing both "python" and "flask"
|
||||
|
||||
- **OR**: Find documents containing either term
|
||||
```
|
||||
You: Search for "python OR javascript"
|
||||
```
|
||||
This finds documents containing either "python" or "javascript"
|
||||
|
||||
- **NOT**: Exclude documents containing specific terms
|
||||
```
|
||||
You: Search for "python NOT django"
|
||||
```
|
||||
This finds documents containing "python" but excludes those containing "django"
|
||||
|
||||
- **Grouping with parentheses**: Control operator precedence
|
||||
```
|
||||
You: Search for "(python OR javascript) AND web"
|
||||
```
|
||||
This finds documents about web development that mention either Python or JavaScript
|
||||
|
||||
Boolean search is particularly useful for:
|
||||
|
||||
- Narrowing down results in large knowledge bases
|
||||
- Finding specific combinations of concepts
|
||||
- Excluding irrelevant content from search results
|
||||
- Creating complex queries for precise information retrieval
|
||||
|
||||
### Memory URL Pattern Matching
|
||||
|
||||
For advanced searches, use memory:// URL patterns with wildcards:
|
||||
|
||||
```
|
||||
You: Look at memory://auth* and summarize all authentication approaches.
|
||||
```
|
||||
|
||||
Pattern matching supports:
|
||||
|
||||
- **Wildcards**: `memory://auth*` matches all permalinks starting with "auth"
|
||||
- **Path patterns**: `memory://project/*/auth` matches auth documents in any project subfolder
|
||||
- **Relation traversal**: `memory://auth-system/implements/*` finds all documents that implement the auth system
|
||||
|
||||
### Combining Search with Context Building
|
||||
|
||||
The most powerful searches build comprehensive context by following relationships:
|
||||
|
||||
```
|
||||
You: Search for JWT authentication and then follow all implementation relations.
|
||||
```
|
||||
|
||||
This builds a complete picture by:
|
||||
|
||||
1. Finding documents about JWT authentication
|
||||
2. Following implementation relationships from those documents
|
||||
3. Building a complete picture of how JWT is implemented across your system
|
||||
|
||||
### Search Best Practices
|
||||
|
||||
For effective searching:
|
||||
|
||||
1. **Be specific** with search terms and phrases
|
||||
2. **Use boolean operators** to refine searches and find precise information
|
||||
3. **Use technical terms** when searching for technical content
|
||||
4. **Follow up** on search results by asking for more details about specific documents
|
||||
5. **Combine approaches** by starting with search and then using memory:// URLs for precision
|
||||
6. **Use relation traversal** to explore connected concepts after finding initial documents
|
||||
|
||||
## Referencing Knowledge
|
||||
|
||||
### Using memory:// URLs
|
||||
|
||||
Reference specific knowledge directly:
|
||||
|
||||
```
|
||||
You: Please look at memory://authentication-approaches and suggest which approach would be best for our mobile app.
|
||||
```
|
||||
|
||||
### Natural Language References
|
||||
|
||||
Reference knowledge conversationally:
|
||||
|
||||
```
|
||||
You: What did we decide about authentication for the project?
|
||||
```
|
||||
|
||||
### Advanced References
|
||||
|
||||
Follow connections across your knowledge graph:
|
||||
|
||||
```
|
||||
You: Look at memory://project-architecture and check related documents to give me a complete picture.
|
||||
```
|
||||
|
||||
## Working with Files
|
||||
|
||||
### File Location and Organization
|
||||
|
||||
By default, Basic Memory stores files in `~/basic-memory`:
|
||||
|
||||
- Browse this directory in your file explorer
|
||||
- Organize files into subfolders
|
||||
- Use git for version control
|
||||
|
||||
### File Format
|
||||
|
||||
Each knowledge file follows this structure:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Authentication Approaches
|
||||
type: note
|
||||
tags: [security, architecture]
|
||||
permalink: authentication-approaches
|
||||
---
|
||||
|
||||
# Authentication Approaches
|
||||
|
||||
A comparison of authentication methods.
|
||||
|
||||
## Observations
|
||||
|
||||
- [approach] JWT provides stateless authentication #security
|
||||
- [limitation] Session tokens require server-side storage #infrastructure
|
||||
|
||||
## Relations
|
||||
|
||||
- implements [[Security Requirements]]
|
||||
- affects [[User Login Flow]]
|
||||
```
|
||||
|
||||
### Editing Files
|
||||
|
||||
Modify files in any text editor:
|
||||
|
||||
1. Open the file in your preferred editor
|
||||
2. Make changes to content, observations, or relations
|
||||
3. Save the file
|
||||
4. Basic Memory detects changes automatically when running in watch mode
|
||||
|
||||
## Building a Knowledge Graph
|
||||
|
||||
The value of Basic Memory comes from connections between pieces of knowledge.
|
||||
|
||||
### Creating Relations
|
||||
|
||||
When creating or editing notes, build connections:
|
||||
|
||||
```markdown
|
||||
## Relations
|
||||
|
||||
- implements [[Security Requirements]]
|
||||
- depends_on [[User Authentication]]
|
||||
```
|
||||
|
||||
Relations can be:
|
||||
|
||||
- Hierarchical (part_of, contains)
|
||||
- Directional (implements, depends_on)
|
||||
- Associative (relates_to, similar_to)
|
||||
- Temporal (precedes, follows)
|
||||
|
||||
Relations are also created via regular wiki-link style links within the body text.
|
||||
|
||||
### Forward References
|
||||
|
||||
Reference documents that don't exist yet:
|
||||
|
||||
```markdown
|
||||
- will_impact [[Future Feature]]
|
||||
```
|
||||
|
||||
These references resolve automatically when you create the referenced document.
|
||||
|
||||
## Conversation Continuity
|
||||
|
||||
Basic Memory maintains context across different conversations.
|
||||
|
||||
### Starting New Sessions with Context
|
||||
|
||||
When starting a new conversation with Claude, you can:
|
||||
|
||||
1. **Use special prompts** like "Continue conversation about..." or "What were we working on?"
|
||||
2. **Reference specific documents** with memory:// URLs
|
||||
3. **Ask about recent work** with "What have we been discussing recently?"
|
||||
4. **Search for specific topics** with "Find information about..."
|
||||
|
||||
### Long-Term Projects
|
||||
|
||||
Maintain context for complex projects over time:
|
||||
|
||||
1. **Document key decisions** as you make them
|
||||
2. **Create relationships** between project components
|
||||
3. **Reference past decisions** when implementing features
|
||||
4. **Update documentation** as the project evolves
|
||||
|
||||
### Tips for Effective Continuity
|
||||
|
||||
1. **Be specific about topics** when continuing a conversation
|
||||
2. **Reference documents directly** with memory:// URLs for precision
|
||||
3. **Create summary notes** after important discussions
|
||||
4. **Update existing notes** rather than creating duplicates
|
||||
5. **Build robust connections** between related topics
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Note Editing (New in v0.13.0)
|
||||
|
||||
**Edit notes incrementally without rewriting entire documents:**
|
||||
|
||||
```
|
||||
💬 "Add a new section about deployment to my API documentation"
|
||||
🤖 [Uses edit_note to append new section]
|
||||
|
||||
💬 "Update the date at the top of my meeting notes"
|
||||
🤖 [Uses edit_note to prepend new timestamp]
|
||||
|
||||
💬 "Replace the implementation section in my design doc"
|
||||
🤖 [Uses edit_note to replace specific section]
|
||||
```
|
||||
|
||||
Available editing operations:
|
||||
- **Append**: Add content to end of notes
|
||||
- **Prepend**: Add content to beginning of notes
|
||||
- **Replace Section**: Replace content under specific headers
|
||||
- **Find & Replace**: Simple text replacements with validation
|
||||
|
||||
### File Management (New in v0.13.0)
|
||||
|
||||
**Move and organize notes with full database consistency:**
|
||||
|
||||
```
|
||||
💬 "Move my old meeting notes to the archive folder"
|
||||
🤖 [Uses move_note with automatic folder creation and database updates]
|
||||
|
||||
💬 "Reorganize my project files into a better structure"
|
||||
🤖 [Moves files while maintaining search indexes and links]
|
||||
```
|
||||
|
||||
Move operations include:
|
||||
- **Database Consistency**: Updates file paths, permalinks, and checksums
|
||||
- **Search Reindexing**: Maintains search functionality after moves
|
||||
- **Folder Creation**: Automatically creates destination directories
|
||||
- **Project Isolation**: Moves are contained within the current project
|
||||
- **Rollback Protection**: Ensures data integrity during failed operations
|
||||
|
||||
### Enhanced Search (New in v0.13.0)
|
||||
|
||||
**Frontmatter tags are now searchable:**
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Coffee Brewing Methods
|
||||
tags: [coffee, brewing, equipment]
|
||||
---
|
||||
```
|
||||
|
||||
Now searchable by: "coffee", "brewing", "equipment", or "Coffee Brewing Methods"
|
||||
|
||||
### Importing External Knowledge
|
||||
|
||||
Import existing conversations:
|
||||
|
||||
```bash
|
||||
# From Claude
|
||||
basic-memory import claude conversations
|
||||
|
||||
# From ChatGPT
|
||||
basic-memory import chatgpt
|
||||
|
||||
# Target specific projects (v0.13.0)
|
||||
basic-memory --project=work import claude conversations
|
||||
```
|
||||
|
||||
After importing, changes sync automatically in real-time.
|
||||
|
||||
### Obsidian Integration
|
||||
|
||||
Use with [Obsidian](https://obsidian.md):
|
||||
|
||||
1. Point Obsidian to your `~/basic-memory` directory
|
||||
2. Use Obsidian's graph view to visualize your knowledge network
|
||||
3. All changes sync back to Basic Memory
|
||||
|
||||
### Canvas Visualizations
|
||||
|
||||
Create visual knowledge maps:
|
||||
|
||||
```
|
||||
You: Could you create a canvas visualization of our project components?
|
||||
```
|
||||
|
||||
This generates an Obsidian canvas file showing the relationships between concepts.
|
||||
|
||||
### Advanced Memory URI Patterns
|
||||
|
||||
Use wildcards and patterns:
|
||||
|
||||
```
|
||||
You: Review memory://project/*/requirements to summarize all project requirements.
|
||||
```
|
||||
|
||||
## Command Line Interface
|
||||
|
||||
### Sync Commands
|
||||
|
||||
```bash
|
||||
# One-time sync
|
||||
basic-memory sync
|
||||
|
||||
# Watch for changes
|
||||
basic-memory sync --watch
|
||||
```
|
||||
|
||||
### Status and Information
|
||||
|
||||
```bash
|
||||
# Check system status
|
||||
basic-memory status
|
||||
|
||||
# View CLI help
|
||||
basic-memory --help
|
||||
```
|
||||
|
||||
### Import Commands
|
||||
|
||||
```bash
|
||||
# Import from Claude
|
||||
basic-memory import claude conversations
|
||||
|
||||
# Import from ChatGPT
|
||||
basic-memory import chatgpt
|
||||
```
|
||||
|
||||
## Multiple Projects (v0.13.0)
|
||||
|
||||
Basic Memory v0.13.0 introduces **fluid project management** - the ability to switch between projects instantly during conversations without restart. This allows you to maintain separate knowledge graphs for different purposes while seamlessly switching between them.
|
||||
|
||||
### Instant Project Switching (New in v0.13.0)
|
||||
|
||||
**Switch projects during conversations:**
|
||||
|
||||
```
|
||||
💬 "What projects do I have?"
|
||||
🤖 Available projects:
|
||||
• main (current, default)
|
||||
• work-notes
|
||||
• personal-journal
|
||||
• code-snippets
|
||||
|
||||
💬 "Switch to work-notes"
|
||||
🤖 ✓ Switched to work-notes project
|
||||
|
||||
Project Summary:
|
||||
• 47 entities
|
||||
• 125 observations
|
||||
• 23 relations
|
||||
|
||||
💬 "What did I work on yesterday?"
|
||||
🤖 [Shows recent activity from work-notes project]
|
||||
```
|
||||
|
||||
### Project-Specific Operations (New in v0.13.0)
|
||||
|
||||
Some MCP tools support optional project parameters for targeting specific projects:
|
||||
|
||||
```
|
||||
💬 "Create a note about this meeting in my personal-notes project"
|
||||
🤖 [Creates note in personal-notes project]
|
||||
|
||||
💬 "Switch to my work project"
|
||||
🤖 [Switches project context, then all operations work within that project]
|
||||
```
|
||||
|
||||
**Note**: Operations like search, move, and edit work within the currently active project. To work with content in different projects, switch to that project first or use the project parameter where supported.
|
||||
|
||||
### Managing Projects
|
||||
|
||||
```bash
|
||||
# List all configured projects
|
||||
basic-memory project list
|
||||
|
||||
# Add a new project
|
||||
basic-memory project create work ~/work-basic-memory
|
||||
|
||||
# Set the default project
|
||||
basic-memory project set-default work
|
||||
|
||||
# Remove a project (doesn't delete files)
|
||||
basic-memory project delete personal
|
||||
|
||||
# Show current project statistics
|
||||
basic-memory project info
|
||||
```
|
||||
|
||||
### Using Projects in Commands
|
||||
|
||||
All commands support the `--project` flag to specify which project to use:
|
||||
|
||||
```bash
|
||||
# Sync a specific project
|
||||
basic-memory --project=work sync
|
||||
|
||||
# Run MCP server for a specific project
|
||||
basic-memory --project=personal mcp
|
||||
```
|
||||
|
||||
You can also set the `BASIC_MEMORY_PROJECT` environment variable:
|
||||
|
||||
```bash
|
||||
BASIC_MEMORY_PROJECT=work basic-memory sync
|
||||
```
|
||||
|
||||
### Unified Database Architecture (New in v0.13.0)
|
||||
|
||||
Basic Memory v0.13.0 uses a unified database architecture:
|
||||
|
||||
- **Single Database**: All projects share `~/.basic-memory/memory.db`
|
||||
- **Project Isolation**: Proper data separation with project context
|
||||
- **Better Performance**: Optimized queries and reduced file I/O
|
||||
- **Easier Backup**: Single database file contains all project data
|
||||
- **Session Context**: Maintains active project throughout conversations
|
||||
|
||||
## Workflow Tips
|
||||
|
||||
### General Workflow
|
||||
1. **Project Organization**: Use multiple projects to separate different areas (work, personal, research)
|
||||
2. **Session Context**: Switch projects during conversations without restart (v0.13.0)
|
||||
3. **Real-time Sync**: Changes sync automatically - no need to run watch mode
|
||||
4. **Review Content**: Edit AI-created content for accuracy
|
||||
5. **Build Connections**: Create rich relationships between related ideas
|
||||
6. **Use Special Prompts**: Start conversations with context from your knowledge base
|
||||
|
||||
### v0.13.0 Workflow Enhancements
|
||||
7. **Incremental Editing**: Use edit_note for small changes instead of rewriting entire documents
|
||||
8. **File Organization**: Move and reorganize notes as your knowledge base grows
|
||||
9. **Project-Specific Creation**: Create notes in specific projects using project parameters
|
||||
10. **Search Tags**: Use frontmatter tags to improve content discoverability
|
||||
11. **Project Statistics**: Monitor project growth and activity with project info commands
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Sync Issues
|
||||
|
||||
If changes aren't showing up:
|
||||
|
||||
1. Run `basic-memory status` to check system state
|
||||
2. Try a manual sync with `basic-memory sync`
|
||||
|
||||
### Missing Content
|
||||
|
||||
If content isn't found:
|
||||
|
||||
1. Check the exact path and permalink
|
||||
2. Try searching with more general terms
|
||||
3. Verify the file exists in your knowledge base
|
||||
|
||||
### Relation Problems
|
||||
|
||||
If relations aren't working:
|
||||
|
||||
1. Ensure exact title matching in [[WikiLinks]]
|
||||
2. Check for typos in relation types
|
||||
3. Verify both documents exist
|
||||
|
||||
## Relations
|
||||
|
||||
- implements [[Knowledge Format]] (How knowledge is structured)
|
||||
- relates_to [[Getting Started with Basic Memory]] (Setup and first steps)
|
||||
- relates_to [[Canvas]] (Creating visual knowledge maps)
|
||||
- relates_to [[CLI Reference]] (Command line tools)
|
||||
- enhanced_in_v0.13.0 [[OAuth Authentication Guide]] (Production authentication)
|
||||
- enhanced_in_v0.13.0 [[Project Management]] (Multi-project workflows)
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
title: Introduction to Basic Memory
|
||||
type: docs
|
||||
permalink: docs/introduction
|
||||
tags:
|
||||
- documentation
|
||||
- index
|
||||
- overview
|
||||
---
|
||||
|
||||
# BASIC MEMORY
|
||||
|
||||
Basic Memory is a knowledge management system that allows you to build a persistent semantic graph from conversations
|
||||
with AI assistants. All knowledge is stored in standard Markdown files on your computer, giving you full control and
|
||||
ownership of your data.
|
||||
|
||||
Basic Memory connects you and AI assistants through shared knowledge:
|
||||
|
||||
1. **Captures knowledge** from natural conversations with AI assistants
|
||||
2. **Structures information** using simple semantic patterns in Markdown
|
||||
3. **Enables knowledge reuse** across different conversations and sessions
|
||||
4. **Maintains persistence** through local files you control completely
|
||||
|
||||
Both you and AI assistants like Claude can read from and write to the same knowledge base, creating a continuous
|
||||
learning environment where each conversation builds upon previous ones.
|
||||
|
||||
## Pick up your conversation right where you left off
|
||||
|
||||
- AI assistants can load context from local files in a new conversation
|
||||
- Notes are saved locally as Markdown files in real time
|
||||
- No project knowledge or special prompting required
|
||||
|
||||
![[Claude-Obsidian-Demo.mp4]]
|
||||
|
||||
Basic Memory uses:
|
||||
|
||||
- **Files as the source of truth** - Everything is stored in plain Markdown files
|
||||
- **Git-compatible storage** - All knowledge can be versioned, branched, and merged
|
||||
- **Local SQLite database** - For fast indexing and searching only (not primary storage)
|
||||
- **Model Context Protocol (MCP)** - For seamless AI assistant integration
|
||||
|
||||
Basic Memory gives you complete control over your knowledge:
|
||||
|
||||
- **Local-first storage** - All knowledge lives on your computer
|
||||
- **Standard file formats** - Plain Markdown compatible with any editor
|
||||
- **Directory organization** - Knowledge stored in `~/basic-memory` by default
|
||||
- **Version control ready** - Use git for history, branching, and collaboration
|
||||
- **Edit anywhere** - Modify files with any text editor or Obsidian
|
||||
|
||||
Changes to files automatically sync with the knowledge graph, and AI assistants can see your edits in conversations.
|
||||
|
||||
## Documentation Map
|
||||
|
||||
Continue exploring Basic Memory with these guides:
|
||||
|
||||
- Installation and setup [[Getting Started with Basic Memory]]
|
||||
- Comprehensive usage instructions [[User Guide]]
|
||||
- Detailed explanation of knowledge structure [[Knowledge Format]]
|
||||
- Obsidian integration guide [[Obsidian Integration]]
|
||||
- Canvas visualization guide [[Canvas]]
|
||||
- Command line tool reference [[CLI Reference]]
|
||||
- Reference for AI assistants using Basic Memory [[AI Assistant Guide]]
|
||||
- Technical implementation details [[Technical Information]]
|
||||
|
||||
## Next Steps
|
||||
|
||||
Start with the [[Getting Started with Basic Memory]] guide to install Basic Memory and configure it with your AI
|
||||
assistant.
|
||||
|
Before Width: | Height: | Size: 374 KiB |
|
Before Width: | Height: | Size: 908 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 302 KiB |
|
Before Width: | Height: | Size: 337 KiB |
|
Before Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
@@ -0,0 +1,241 @@
|
||||
# Character Handling and Conflict Resolution
|
||||
|
||||
Basic Memory handles various character encoding scenarios and file naming conventions to provide consistent permalink generation and conflict resolution. This document explains how the system works and how to resolve common character-related issues.
|
||||
|
||||
## Overview
|
||||
|
||||
Basic Memory uses a sophisticated system to generate permalinks from file paths while maintaining consistency across different operating systems and character encodings. The system normalizes file paths and generates unique permalinks to prevent conflicts.
|
||||
|
||||
## Character Normalization Rules
|
||||
|
||||
### 1. Permalink Generation
|
||||
|
||||
When Basic Memory processes a file path, it applies these normalization rules:
|
||||
|
||||
```
|
||||
Original: "Finance/My Investment Strategy.md"
|
||||
Permalink: "finance/my-investment-strategy"
|
||||
```
|
||||
|
||||
**Transformation process:**
|
||||
1. Remove file extension (`.md`)
|
||||
2. Convert to lowercase (case-insensitive)
|
||||
3. Replace spaces with hyphens
|
||||
4. Replace underscores with hyphens
|
||||
5. Handle international characters (transliteration for Latin, preservation for non-Latin)
|
||||
6. Convert camelCase to kebab-case
|
||||
|
||||
### 2. International Character Support
|
||||
|
||||
**Latin characters with diacritics** are transliterated:
|
||||
- `ø` → `o` (Søren → soren)
|
||||
- `ü` → `u` (Müller → muller)
|
||||
- `é` → `e` (Café → cafe)
|
||||
- `ñ` → `n` (Niño → nino)
|
||||
|
||||
**Non-Latin characters** are preserved:
|
||||
- Chinese: `中文/测试文档.md` → `中文/测试文档`
|
||||
- Japanese: `日本語/文書.md` → `日本語/文書`
|
||||
|
||||
## Common Conflict Scenarios
|
||||
|
||||
### 1. Hyphen vs Space Conflicts
|
||||
|
||||
**Problem:** Files with existing hyphens conflict with generated permalinks from spaces.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
File 1: "basic memory bug.md" → permalink: "basic-memory-bug"
|
||||
File 2: "basic-memory-bug.md" → permalink: "basic-memory-bug" (CONFLICT!)
|
||||
```
|
||||
|
||||
**Resolution:** The system automatically resolves this by adding suffixes:
|
||||
```
|
||||
File 1: "basic memory bug.md" → permalink: "basic-memory-bug"
|
||||
File 2: "basic-memory-bug.md" → permalink: "basic-memory-bug-1"
|
||||
```
|
||||
|
||||
**Best Practice:** Choose consistent naming conventions within your project.
|
||||
|
||||
### 2. Case Sensitivity Conflicts
|
||||
|
||||
**Problem:** Different case variations that normalize to the same permalink.
|
||||
|
||||
**Example on macOS:**
|
||||
```
|
||||
Directory: Finance/investment.md
|
||||
Directory: finance/investment.md (different on filesystem, same permalink)
|
||||
```
|
||||
|
||||
**Resolution:** Basic Memory detects case conflicts and prevents them during sync operations with helpful error messages.
|
||||
|
||||
**Best Practice:** Use consistent casing for directory and file names.
|
||||
|
||||
### 3. Character Encoding Conflicts
|
||||
|
||||
**Problem:** Different Unicode normalizations of the same logical character.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
File 1: "café.md" (é as single character)
|
||||
File 2: "café.md" (e + combining accent)
|
||||
```
|
||||
|
||||
**Resolution:** Basic Memory normalizes Unicode characters using NFD normalization to detect these conflicts.
|
||||
|
||||
### 4. Forward Slash Conflicts
|
||||
|
||||
**Problem:** Forward slashes in frontmatter or file names interpreted as path separators.
|
||||
|
||||
**Example:**
|
||||
```yaml
|
||||
---
|
||||
permalink: finance/investment/strategy
|
||||
---
|
||||
```
|
||||
|
||||
**Resolution:** Basic Memory validates frontmatter permalinks and warns about path separator conflicts.
|
||||
|
||||
## Error Messages and Troubleshooting
|
||||
|
||||
### "UNIQUE constraint failed: entity.file_path, entity.project_id"
|
||||
|
||||
**Cause:** Two entities trying to use the same file path within a project.
|
||||
|
||||
**Common scenarios:**
|
||||
1. File move operation where destination is already occupied
|
||||
2. Case sensitivity differences on macOS
|
||||
3. Character encoding conflicts
|
||||
4. Concurrent file operations
|
||||
|
||||
**Resolution steps:**
|
||||
1. Check for duplicate file names with different cases
|
||||
2. Look for files with similar names but different character encodings
|
||||
3. Rename conflicting files to have unique names
|
||||
4. Run sync again after resolving conflicts
|
||||
|
||||
### "File path conflict detected during move"
|
||||
|
||||
**Cause:** Enhanced conflict detection preventing potential database integrity violations.
|
||||
|
||||
**What this means:** The system detected that moving a file would create a conflict before attempting the database operation.
|
||||
|
||||
**Resolution:** Follow the specific guidance in the error message, which will indicate the type of conflict detected.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. File Naming Conventions
|
||||
|
||||
**Recommended patterns:**
|
||||
- Use consistent casing (prefer lowercase)
|
||||
- Use hyphens instead of spaces for multi-word files
|
||||
- Avoid special characters that could conflict with path separators
|
||||
- Be consistent with directory structure casing
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
✅ Good:
|
||||
- finance/investment-strategy.md
|
||||
- projects/basic-memory-features.md
|
||||
- docs/api-reference.md
|
||||
|
||||
❌ Problematic:
|
||||
- Finance/Investment Strategy.md (mixed case, spaces)
|
||||
- finance/Investment Strategy.md (inconsistent case)
|
||||
- docs/API/Reference.md (mixed case directories)
|
||||
```
|
||||
|
||||
### 2. Permalink Management
|
||||
|
||||
**Custom permalinks in frontmatter:**
|
||||
```yaml
|
||||
---
|
||||
type: knowledge
|
||||
permalink: custom-permalink-name
|
||||
---
|
||||
```
|
||||
|
||||
**Guidelines:**
|
||||
- Use lowercase permalinks
|
||||
- Use hyphens for word separation
|
||||
- Avoid path separators unless creating sub-paths
|
||||
- Ensure uniqueness within your project
|
||||
|
||||
### 3. Directory Structure
|
||||
|
||||
**Consistent casing:**
|
||||
```
|
||||
✅ Good:
|
||||
finance/
|
||||
investment-strategies.md
|
||||
portfolio-management.md
|
||||
|
||||
❌ Problematic:
|
||||
Finance/ (capital F)
|
||||
investment-strategies.md
|
||||
finance/ (lowercase f)
|
||||
portfolio-management.md
|
||||
```
|
||||
|
||||
## Migration and Cleanup
|
||||
|
||||
### Identifying Conflicts
|
||||
|
||||
Use Basic Memory's built-in conflict detection:
|
||||
|
||||
```bash
|
||||
# Sync will report conflicts
|
||||
basic-memory sync
|
||||
|
||||
# Check sync status for warnings
|
||||
basic-memory status
|
||||
```
|
||||
|
||||
### Resolving Existing Conflicts
|
||||
|
||||
1. **Identify conflicting files** from sync error messages
|
||||
2. **Choose consistent naming convention** for your project
|
||||
3. **Rename files** to follow the convention
|
||||
4. **Re-run sync** to verify resolution
|
||||
|
||||
### Bulk Renaming Strategy
|
||||
|
||||
For projects with many conflicts:
|
||||
|
||||
1. **Backup your project** before making changes
|
||||
2. **Standardize on lowercase** file and directory names
|
||||
3. **Replace spaces with hyphens** in file names
|
||||
4. **Use consistent character encoding** (UTF-8)
|
||||
5. **Test sync after each batch** of changes
|
||||
|
||||
## System Enhancements
|
||||
|
||||
### Recent Improvements (v0.13+)
|
||||
|
||||
1. **Enhanced conflict detection** before database operations
|
||||
2. **Improved error messages** with specific resolution guidance
|
||||
3. **Character normalization utilities** for consistent handling
|
||||
4. **File swap detection** for complex move scenarios
|
||||
5. **Proactive conflict warnings** during permalink resolution
|
||||
|
||||
### Monitoring and Logging
|
||||
|
||||
The system now provides detailed logging for conflict resolution:
|
||||
|
||||
```
|
||||
DEBUG: Detected potential file path conflicts for 'Finance/Investment.md': ['finance/investment.md']
|
||||
WARNING: File path conflict detected during move: entity_id=123 trying to move from 'old.md' to 'new.md'
|
||||
```
|
||||
|
||||
These logs help identify and resolve conflicts before they cause sync failures.
|
||||
|
||||
## Support and Resources
|
||||
|
||||
If you encounter character-related conflicts not covered in this guide:
|
||||
|
||||
1. **Check the logs** for specific conflict details
|
||||
2. **Review error messages** for resolution guidance
|
||||
3. **Report issues** with examples of the conflicting files
|
||||
4. **Consider the file naming best practices** outlined above
|
||||
|
||||
The Basic Memory system is designed to handle most character conflicts automatically while providing clear guidance for manual resolution when needed.
|
||||