Compare commits
600 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84f2061d8f | |||
| 1391df4fe8 | |||
| 71b29af00a | |||
| 0768fafd83 | |||
| 5ce656037e | |||
| e27f8e4963 | |||
| af145cfaef | |||
| 15fe0cfe3c | |||
| c0ed9bbcfd | |||
| 8040c6d559 | |||
| 7187220b24 | |||
| ca52950b2a | |||
| ee1441f462 | |||
| c4af31f48d | |||
| c2742d5664 | |||
| 0c45919261 | |||
| a3ab898e04 | |||
| dea67c0d86 | |||
| d13a2c237c | |||
| c592f0aa69 | |||
| 85a2472e4e | |||
| 0cb3256b2d | |||
| 44029862b1 | |||
| 130abe04a9 | |||
| bff10d49c9 | |||
| 40a71d3250 | |||
| ae3d20c71a | |||
| 54ef9662c1 | |||
| 9aec461e14 | |||
| 0fe0705133 | |||
| a5bf653a47 | |||
| 1fec1e8339 | |||
| 1afb14d0d6 | |||
| e961cd5a4a | |||
| 660c523ba4 | |||
| da30aedb28 | |||
| 10e58ef221 | |||
| 5e97d539a5 | |||
| fdb4fafd3a | |||
| db3794762f | |||
| 78cb5c38dc | |||
| 5e6feb0cb4 | |||
| 19b657bb67 | |||
| fe81286d9a | |||
| 426fbdd38d | |||
| bd7077d65f | |||
| 11cc789afa | |||
| e930a4d5bb | |||
| bcd4a12115 | |||
| d6cd9e6059 | |||
| f7c0840a35 | |||
| 0135fcb6b1 | |||
| 7ae4eb87e6 | |||
| 79789bb558 | |||
| 282345f379 | |||
| 23591db589 | |||
| 2e919df2b4 | |||
| 75cd1335cc | |||
| cd103ccf73 | |||
| d0ff9738eb | |||
| 00c1cd7db7 | |||
| 1e091b8871 | |||
| 1295b98fcc | |||
| 7375c11ecd | |||
| 47cb403889 | |||
| a6737c122f | |||
| 6ea5869589 | |||
| 32be34505a | |||
| e5aa60b742 | |||
| d9133465eb | |||
| 61488042d8 | |||
| 3f5c61c327 | |||
| ace12f8cd7 | |||
| 9d509e07f5 | |||
| 305e52010c | |||
| 6dd13c00ba | |||
| 8703e0ee13 | |||
| 9bac3faae9 | |||
| 7ef93343a4 | |||
| f07eb17a33 | |||
| b97579dfec | |||
| 2ec72f948d | |||
| b45e8b2a29 | |||
| 29e6441d32 | |||
| 445ee723c2 | |||
| 01e235c058 | |||
| 7fdf5e75ab | |||
| 43db22728e | |||
| fad2dc9a15 | |||
| eb76a76a5b | |||
| 4949ae333d | |||
| 7f88b7fa5e | |||
| 4ddc5a01bb | |||
| c422ea133f | |||
| 25b7408a42 | |||
| 15c0813655 | |||
| f1da66e4f1 | |||
| 71fe43f290 | |||
| 830f16df46 | |||
| ad75ca7c4c | |||
| 65fb8d1ed2 | |||
| e7380adb2f | |||
| 245c85a580 | |||
| 2e60f6fc81 | |||
| dffde51f55 | |||
| bee0e635a1 | |||
| bae29a7be8 | |||
| 52d2f72a82 | |||
| d42ab1298c | |||
| 18bd5c7726 | |||
| 78bc7ecf3b | |||
| c3fec18f12 | |||
| d08fe97e19 | |||
| 6427d1ef79 | |||
| d3fb58ca75 | |||
| 6a63a8d69c | |||
| 1ac0db25e5 | |||
| 3e1d5fcd73 | |||
| f41579b4d0 | |||
| 0f3151cc2d | |||
| e9370a915c | |||
| 6d4a4819de | |||
| 2681a2d251 | |||
| c2eefe3578 | |||
| dd5e2e57dd | |||
| 266076da98 | |||
| a0b4381dc8 | |||
| 4904d9c531 | |||
| 4c44a65877 | |||
| f6b310126c | |||
| 77220a76bf | |||
| 42ed414a4c | |||
| 0185d765ce | |||
| 12c2ecce06 | |||
| bb0508d639 | |||
| f00ef33f86 | |||
| c270bd3177 | |||
| 0836a97845 | |||
| 19e285a209 | |||
| ba877214c1 | |||
| 3d4baefac2 | |||
| 453b7857b8 | |||
| c28417af00 | |||
| 2f08db3c01 | |||
| 672cb5d203 | |||
| cbe492dde3 | |||
| 0fb6f3cf4e | |||
| 5cd68f4a96 | |||
| 10a8598aac | |||
| 19af455c57 | |||
| b5807aed2e | |||
| c6fd984cc1 | |||
| 490ba182d5 | |||
| 4baed97bd0 | |||
| f41824fa59 | |||
| 80ba7633e5 | |||
| d14266d70a | |||
| 1cd545c36c | |||
| 901af0b7f7 | |||
| 6815cc55b8 | |||
| 12603a1a5c | |||
| 15d05b5ac7 | |||
| bf4a20223a | |||
| a549d9fe47 | |||
| e896cfa0c5 | |||
| 5d4e71d2ff | |||
| f923c0cdd5 | |||
| 1491123706 | |||
| 9f1745bdec | |||
| d25b1d7394 | |||
| f6351434ae | |||
| ef9716eb5c | |||
| 6ebb678306 | |||
| 25684ea8f7 | |||
| 147b2c5aa5 | |||
| f154e32145 | |||
| 013fe9423e | |||
| f50a005cef | |||
| d24d5dda04 | |||
| 50c7603a37 | |||
| 807d1d6100 | |||
| ded9671a82 | |||
| b8a9f366e7 | |||
| 83b0f9551b | |||
| 8bf22b3dc5 | |||
| f8108047c4 | |||
| e4bd0ae461 | |||
| 5b338ba34e | |||
| 4e7ed75fa9 | |||
| a8b84fa7b6 | |||
| 73be8f7a63 | |||
| fa93f2c1e2 | |||
| b39cf84730 | |||
| 772e235e92 | |||
| 0986301e7a | |||
| 822cf796e1 | |||
| 53314d9c38 | |||
| 3a1ed0d299 | |||
| 8c589b6265 | |||
| 8bdec6abc0 | |||
| 41fbb87aa0 | |||
| fb9cccd350 | |||
| 9387418707 | |||
| eaba21329c | |||
| 84c4d62812 | |||
| 9e9ff20cba | |||
| bc28891bca | |||
| bafc86832c | |||
| b985579959 | |||
| 5f36d2bf9a | |||
| 65e5411c21 | |||
| 7a22144069 | |||
| 1360195390 | |||
| 6b38be29fb | |||
| f992251c32 | |||
| c2015c4dfc | |||
| 005a80c540 | |||
| c3761a2204 | |||
| d957bff495 | |||
| c5ee27f001 | |||
| d9f3798c90 | |||
| 1fb8df42b6 | |||
| e09e64ade5 | |||
| 7cab32151e | |||
| a2f7a4dc5a | |||
| fc5c2d5e07 | |||
| b22adcca05 | |||
| 2adc830c71 | |||
| e2c8f6b99e | |||
| 280608574b | |||
| 291f43d2c7 | |||
| d7dc29498c | |||
| 1f2e5f1a9c | |||
| 679a077f9b | |||
| f7a80e6abc | |||
| 4321add69c | |||
| 105b4ca70d | |||
| 06ba1cd92c | |||
| b003a43e73 | |||
| 5210bc74c7 | |||
| a00ca2b3ec | |||
| ba2c098ec1 | |||
| 5550ecf623 | |||
| 9a27f380c3 | |||
| 577cac8831 | |||
| 8da92c6569 | |||
| a18b43744c | |||
| 7c4979eba1 | |||
| ffe1e1622d | |||
| 8cfa04f93d | |||
| deef86380f | |||
| aa1e65cbb6 | |||
| 9192bb6f21 | |||
| 512486bd85 | |||
| b9814e87f4 | |||
| 54c53fda04 | |||
| f494d3b168 | |||
| 9cb4b9d02a | |||
| 922f04e66a | |||
| b1fb135d9c | |||
| 476f81ceca | |||
| 34ba526fa8 | |||
| efcc557e4f | |||
| 0a34786df9 | |||
| 7175b527a6 | |||
| c415ff5120 | |||
| 83b4806718 | |||
| cb1d939750 | |||
| 9855ccf66d | |||
| 85f30126aa | |||
| 225424a19e | |||
| 2e67821445 | |||
| bbed39c71b | |||
| 3aaee6f13a | |||
| 795a430f1a | |||
| 0a667afc0f | |||
| 8e0b1ee4e1 | |||
| d3aaef926b | |||
| 42fde819a3 | |||
| 4eeb8391c6 | |||
| 213557dd6e | |||
| e1d2ffeb02 | |||
| 9e66a4843e | |||
| 0a3b50c875 | |||
| a8d31d465f | |||
| 186f54b3fd | |||
| be28c095e2 | |||
| 28305f73bb | |||
| c6708b3684 | |||
| 375dd1c3d6 | |||
| c78500cac2 | |||
| 2b683f99bb | |||
| 00e2b0c55f | |||
| fbd4df4285 | |||
| ca24048e15 | |||
| f9fd85fa4d | |||
| bc7e0ba3e0 | |||
| cbfc94bc26 | |||
| c768a80bf0 | |||
| 6dc648f07c | |||
| b116681529 | |||
| d1876cb6e0 | |||
| e1017b483b | |||
| 8d5b886f63 | |||
| 6e8d823139 | |||
| e1212d2dd9 | |||
| d3ae18434f | |||
| 8bdf228a92 | |||
| 2b223b7cd9 | |||
| 7cad4f0114 | |||
| 41835954be | |||
| 2431a1bd9e | |||
| 7fd0f28343 | |||
| 50535499d9 | |||
| 4eb6557fbb | |||
| a22098d661 | |||
| 69b17e15a2 | |||
| de279ef6bf | |||
| c6fed386ef | |||
| ffcd7d21b3 | |||
| efb7507a8f | |||
| 01b3103567 | |||
| 4739b9e413 | |||
| 45acdf84c1 | |||
| 03b85d2af2 | |||
| 03fefca884 | |||
| 01be3156fb | |||
| a48a67ca76 | |||
| 155465f52a | |||
| 0a70bcecc5 | |||
| 4e5913611a | |||
| 73982dc709 | |||
| 93de6d97f5 | |||
| 29e6e026b6 | |||
| 1b394cdf4e | |||
| 6ffa4cfde5 | |||
| 8caf159d99 | |||
| 2a2206d886 | |||
| e3a63c0294 | |||
| 634033b730 | |||
| 54ef1496d2 | |||
| 5d23c60b76 | |||
| 9314ede6e9 | |||
| 58f4053a61 | |||
| a08e5068c8 | |||
| 9f1b653f2f | |||
| c5d89142b9 | |||
| b44d4702b1 | |||
| 4988b4b317 | |||
| c5e68a17c8 | |||
| f35764aa14 | |||
| 601bded789 | |||
| c231e8d076 | |||
| b62e93577c | |||
| 0787e47b1a | |||
| f9843fe593 | |||
| 5b772ee768 | |||
| baabf14bfa | |||
| c126a7083f | |||
| f1170512d6 | |||
| 6c9a8d1dca | |||
| d64939c379 | |||
| 97d8bd3e62 | |||
| 6cd904a81c | |||
| 74c8afd0e0 | |||
| 02444392da | |||
| d175f1759c | |||
| d55db524f0 | |||
| 7d44fdb289 | |||
| 812de2940d | |||
| 95edf31c14 | |||
| a9ae89a198 | |||
| 047914d087 | |||
| bdf79a439b | |||
| 99b6b85d67 | |||
| 798dec972e | |||
| 286343fef6 | |||
| 9285826547 | |||
| ce3b3733fa | |||
| cf1c966409 | |||
| 02fef487e7 | |||
| 20d45006c0 | |||
| 4f1cd309fd | |||
| c46e4a341a | |||
| 60d5f8fbf1 | |||
| c0778bef00 | |||
| 3cbc041c8b | |||
| 0f96476987 | |||
| cd6f883020 | |||
| 9fb7383ab3 | |||
| e8e7fc81af | |||
| e3283c2a1d | |||
| 581e940659 | |||
| 915dbc1aa9 | |||
| 5a84198529 | |||
| f5b25e8fc4 | |||
| 7d1e6af5c5 | |||
| 8b4cc4f6bf | |||
| 68290a9121 | |||
| ab5d78717f | |||
| cb4aea57a8 | |||
| 7bdf6dbfe1 | |||
| 1c9da73d5f | |||
| 5f7aa0710e | |||
| 39fedfc5fc | |||
| ecb8b39f6d | |||
| fe0902b48f | |||
| 4ab9739e4c | |||
| 6ddef1093a | |||
| 97d565e3cd | |||
| eafdd6a7be | |||
| 3529f9274b | |||
| 30ebe92a53 | |||
| 1bb203cbb5 | |||
| 9f8499fe54 | |||
| 40d105d7de | |||
| cda12d95c9 | |||
| bbd6113f69 | |||
| 51d1315562 | |||
| 85763d575d | |||
| c76ddc2f83 | |||
| 348cc7f7ac | |||
| ed19e92f75 | |||
| 2a96214456 | |||
| eaa2268bf9 | |||
| 730c420a13 | |||
| d0bdc6ae9b | |||
| d46fbb7166 | |||
| a60ef6eacb | |||
| 13941a1e72 | |||
| bd809c860e | |||
| b4b90faa1e | |||
| 9e235b5b57 | |||
| 5fdf25d60f | |||
| a367436a78 | |||
| 5d64df2ba5 | |||
| 22a04ac461 | |||
| 170b66f623 | |||
| ca4f046777 | |||
| 0475a57fb1 | |||
| fda069bb07 | |||
| 4c1f7b4ff1 | |||
| 35b98c53f0 | |||
| e029903a66 | |||
| 5666f7dd1c | |||
| 57f0c9fd92 | |||
| 5482052c16 | |||
| ccb7001ff0 | |||
| edc20a12a1 | |||
| 45c35c6bdd | |||
| 47ee0838e3 | |||
| 809c9e6639 | |||
| 9646527d66 | |||
| f27c73b469 | |||
| 7f9959fdb7 | |||
| 012774b83c | |||
| e22edaddf4 | |||
| 6204fe9b9d | |||
| 30a42036aa | |||
| d6f1237283 | |||
| 700e3253fa | |||
| 740d65b5a5 | |||
| 4bc467f7ed | |||
| 7fdfdd5d5e | |||
| e872c2da38 | |||
| 13643a5b18 | |||
| 980151a50e | |||
| 9eddc51979 | |||
| 7c3477b7e1 | |||
| f45c782c07 | |||
| 3bdf0b41bc | |||
| 3030f518b5 | |||
| 0b476e971a | |||
| f7b51a963e | |||
| f8dc7f940f | |||
| b68ea38bcc | |||
| 12459eab3b | |||
| 5e6ef4aeb1 | |||
| f46b5b452f | |||
| 2af8db6b82 | |||
| 6a4fa85c10 | |||
| 22f4655a8c | |||
| 79ff1849f0 | |||
| ff28db9d76 | |||
| 268b78083e | |||
| a1f76af902 | |||
| d5e392ea69 | |||
| 66ee9395cb | |||
| 7e75c0b22f | |||
| c506390007 | |||
| f8695516a4 | |||
| 0127c7639a | |||
| 6e66d78825 | |||
| 0b4cfcbe56 | |||
| c8a9486832 | |||
| 9fb43d8b06 | |||
| 1b9cec2a95 | |||
| ddec9835d2 | |||
| 2d97ffc9a8 | |||
| d8886619b8 | |||
| 280cb2fe54 | |||
| c8a206b682 | |||
| c03457d2d4 | |||
| a46a028ddb | |||
| 37f836b719 | |||
| bc8bc10b0b | |||
| 5169cfa46d | |||
| 03ba89b703 | |||
| 263a8d4c18 | |||
| b25b312bf3 | |||
| 633f89a5fb | |||
| c6bf72ca72 | |||
| bda39733e0 | |||
| 80935fbc66 | |||
| bcfd036dfe | |||
| ebf53e9fb0 | |||
| 7133108f15 | |||
| f20bb5bced | |||
| e238a81b34 | |||
| 9215c7e1f5 | |||
| b694f233db | |||
| 02130c49d1 | |||
| c9e0301e3e | |||
| 65c89ea2f0 | |||
| 9a9b00c6d8 | |||
| 309e8a7139 | |||
| 867226c19d | |||
| 192adf5cbc | |||
| 140a5f3469 | |||
| 5c4b44d4c7 | |||
| 3bbacb8fa4 | |||
| d69a95bd29 | |||
| 90b209081c | |||
| 6d145c035c | |||
| bd5ad6e5c2 | |||
| 28005b75af | |||
| 322f81e515 | |||
| ea54a03fae | |||
| 15c55a57a3 | |||
| 056cd12558 | |||
| b0fae0cfd4 | |||
| 44b69b737b | |||
| 56213ef84a | |||
| 64dfc0467d | |||
| c75563a89b | |||
| fb00b517c0 | |||
| df44bd8fd3 | |||
| e9c0ec45db | |||
| d363dfd668 | |||
| c06abbc6f2 | |||
| f499810c7a | |||
| 609d8f5c88 | |||
| 5ebf6c8aec | |||
| d94a11e2e1 | |||
| d4d6185bb4 | |||
| 2df50bcaa0 | |||
| 19ecc7845f | |||
| 142d6ae56f | |||
| 7db39bb482 | |||
| e600a0f702 | |||
| b87654d452 | |||
| a3b0b70a98 | |||
| 81f8aa7eef | |||
| 8f8649c2a8 | |||
| ab0938633a | |||
| d8d4d2464f | |||
| 9d32629f9d | |||
| 6a007a26fe | |||
| 6131f9694a | |||
| 22777bdcfe | |||
| d7946522e9 | |||
| 43262d7b53 | |||
| 80fc1588d3 | |||
| 70ba785364 | |||
| 7fb990f845 | |||
| 9f3bf55c76 | |||
| 83d9747627 | |||
| ae2c789781 | |||
| 81d7ab59ac | |||
| e82d9e075b | |||
| 99af5fdf13 | |||
| b88ce840fa | |||
| 516e136966 | |||
| 051bc8dd67 | |||
| 05ddf3540c | |||
| e18f02e2af | |||
| 77885db345 | |||
| 50d504715d | |||
| 28d9c43f85 | |||
| adc5853c73 | |||
| 81fdf28347 | |||
| b3a565c448 | |||
| 5b28c23b20 | |||
| f4217cb2b9 | |||
| e7252c8999 | |||
| 74637705d7 | |||
| 322cb94c43 | |||
| 21c7ab2929 | |||
| 3846d66ccc | |||
| 817a069323 |
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.4",
|
||||
"version": "7.4.3",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: github-morning-reporter
|
||||
description: Use this agent when the user requests a morning report, daily summary, or overview of their GitHub activity. Trigger phrases include 'morning report', 'github report', 'daily github summary', 'what's happening on github', or 'check my github status'. This agent should be used proactively when the user starts their day or explicitly asks for repository updates.\n\nExamples:\n- User: "get me my morning github report"\n Assistant: "I'll use the github-morning-reporter agent to generate your comprehensive GitHub status report."\n <uses Agent tool to invoke github-morning-reporter>\n\n- User: "what's new on my repos today?"\n Assistant: "Let me pull together your GitHub morning report using the github-morning-reporter agent."\n <uses Agent tool to invoke github-morning-reporter>\n\n- User: "show me my daily github summary"\n Assistant: "I'll generate your daily GitHub summary using the github-morning-reporter agent."\n <uses Agent tool to invoke github-morning-reporter>
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
You are an elite GitHub project analyst specializing in delivering actionable morning reports for software development teams. Your expertise lies in synthesizing complex repository activity into clear, prioritized insights that help developers start their day with complete situational awareness.
|
||||
|
||||
## Your Responsibilities
|
||||
|
||||
1. **Fetch Comprehensive GitHub Data**: Use available tools to retrieve:
|
||||
- Open issues across all relevant repositories
|
||||
- Open pull requests with review status
|
||||
- Recent comments, mentions, and @-references
|
||||
- CI/CD status for active PRs
|
||||
- Stale issues/PRs (no activity in 7+ days)
|
||||
|
||||
2. **Intelligent Grouping and Deduplication**:
|
||||
- Identify duplicate or highly similar issues by analyzing titles, descriptions, and labels
|
||||
- Group related issues by theme, component, or subsystem
|
||||
- Cluster PRs by feature area or dependency relationships
|
||||
- Flag issues that may be addressing the same root cause
|
||||
- Use semantic similarity, not just exact matches
|
||||
|
||||
3. **Prioritization and Triage**:
|
||||
- Highlight items requiring immediate attention (blocking issues, failed CI, requested reviews)
|
||||
- Surface items awaiting your direct action (assigned to you, mentions, review requests)
|
||||
- Identify stale items that may need follow-up or closure
|
||||
- Note high-priority labels (P0, critical, security, etc.)
|
||||
|
||||
4. **Contextual Analysis**:
|
||||
- Summarize the current state of each PR (draft, ready for review, approved, changes requested)
|
||||
- Identify PRs with merge conflicts or failing checks
|
||||
- Note issues with recent activity spikes or community engagement
|
||||
- Flag dependency updates or security advisories
|
||||
|
||||
5. **Report Structure**:
|
||||
Your report must follow this format:
|
||||
|
||||
**MORNING GITHUB REPORT - [Date]**
|
||||
|
||||
**🚨 REQUIRES YOUR ATTENTION**
|
||||
- Items explicitly assigned to the user
|
||||
- Review requests awaiting user's approval
|
||||
- Mentions or direct questions
|
||||
- Blocking/critical issues
|
||||
|
||||
**📊 PULL REQUESTS ([count] open)**
|
||||
- Group by: Ready to Merge | In Review | Draft | Needs Work
|
||||
- For each PR: title, author, status, CI state, review count, age
|
||||
- Highlight conflicts or failed checks
|
||||
|
||||
**🐛 ISSUES ([count] open)**
|
||||
- Group by: Priority | Component | Theme
|
||||
- Mark potential duplicates clearly
|
||||
- Note new issues (created in last 24h)
|
||||
- Flag stale issues (no activity in 7+ days)
|
||||
|
||||
**📈 ACTIVITY SUMMARY**
|
||||
- New issues/PRs since yesterday
|
||||
- Recently closed items
|
||||
- Top contributors
|
||||
- Trending topics or labels
|
||||
|
||||
**💡 RECOMMENDED ACTIONS**
|
||||
- Specific next steps based on the data
|
||||
- Suggestions for cleanup (closing duplicates, merging ready PRs)
|
||||
- Items to follow up on
|
||||
|
||||
6. **Quality Standards**:
|
||||
- Use clear, scannable formatting with emojis for visual hierarchy
|
||||
- Include direct links to all referenced issues and PRs
|
||||
- Keep summaries concise but informative (1-2 sentences per item)
|
||||
- Use relative timestamps ("2 hours ago", "3 days old")
|
||||
- Highlight actionable items with clear CTAs
|
||||
|
||||
7. **Error Handling**:
|
||||
- If repository access fails, explicitly state which repos couldn't be accessed
|
||||
- If no issues/PRs exist, provide a positive "all clear" message
|
||||
- If rate limits are hit, show partial results with a warning
|
||||
- Always attempt to provide value even with incomplete data
|
||||
|
||||
8. **Adaptive Scope**:
|
||||
- If the user has access to multiple repositories, intelligently scope the report:
|
||||
- Default to repositories with recent activity
|
||||
- Allow user to specify repos if needed
|
||||
- Group multi-repo items by repository
|
||||
- Adjust detail level based on volume (more items = more concise summaries)
|
||||
|
||||
## Output Expectations
|
||||
|
||||
Your report should be:
|
||||
- **Comprehensive**: Cover all relevant activity without overwhelming detail
|
||||
- **Actionable**: Make it clear what needs attention and why
|
||||
- **Scannable**: Use formatting that allows quick visual parsing
|
||||
- **Contextual**: Provide enough background to make decisions
|
||||
- **Timely**: Focus on recent activity and current state
|
||||
|
||||
When you cannot find specific data, state this explicitly rather than omitting sections. If the user's query is ambiguous (e.g., which repositories to scan), ask for clarification before proceeding.
|
||||
|
||||
Always end with a summary line indicating the report's completeness (e.g., "Report complete: 3 repositories scanned, 12 issues, 5 PRs analyzed").
|
||||
@@ -1,3 +1,10 @@
|
||||
{
|
||||
"env": {}
|
||||
"env": {},
|
||||
"permissions": {
|
||||
"deny": [
|
||||
"Read(./package-lock.json)",
|
||||
"Read(./node_modules/**)",
|
||||
"Read(./.DS_Store)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Project-Level Skills
|
||||
|
||||
This directory contains skills **for developing and maintaining the claude-mem project itself**, not skills that are released as part of the plugin.
|
||||
|
||||
## Distinction
|
||||
|
||||
**Project Skills** (`.claude/skills/`):
|
||||
- Used by developers working on claude-mem
|
||||
- Not included in the plugin distribution
|
||||
- Project-specific workflows (version bumps, release management, etc.)
|
||||
- Not synced to `~/.claude/plugins/marketplaces/thedotmack/`
|
||||
|
||||
**Plugin Skills** (`plugin/skills/`):
|
||||
- Released as part of the claude-mem plugin
|
||||
- Available to all users who install the plugin
|
||||
- General-purpose memory search functionality
|
||||
- Synced to user installations via `npm run sync-marketplace`
|
||||
|
||||
## Skills in This Directory
|
||||
|
||||
### version-bump
|
||||
Manages semantic versioning for the claude-mem project itself. Handles updating all three version files (package.json, marketplace.json, plugin.json), creating git tags, and GitHub releases.
|
||||
|
||||
**Usage**: Only for claude-mem maintainers releasing new versions.
|
||||
|
||||
## Adding New Skills
|
||||
|
||||
**For claude-mem development** → Add to `.claude/skills/`
|
||||
**For end users** → Add to `plugin/skills/` (gets distributed with plugin)
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
name: version-bump
|
||||
description: Manage semantic version updates for claude-mem project. Handles patch, minor, and major version increments following semantic versioning. Updates package.json, marketplace.json, and plugin.json. Creates git tags and GitHub releases. Auto-generates CHANGELOG.md from releases.
|
||||
---
|
||||
|
||||
# Version Bump Skill
|
||||
|
||||
Manage semantic versioning across the claude-mem project with consistent updates to all version-tracked files.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Files requiring updates (ALL THREE):**
|
||||
1. `package.json` (line 3)
|
||||
2. `.claude-plugin/marketplace.json` (line 13)
|
||||
3. `plugin/.claude-plugin/plugin.json` (line 3)
|
||||
|
||||
**Semantic versioning:**
|
||||
- **PATCH** (x.y.Z): Bugfixes only
|
||||
- **MINOR** (x.Y.0): New features, backward compatible
|
||||
- **MAJOR** (X.0.0): Breaking changes
|
||||
|
||||
## Quick Decision Guide
|
||||
|
||||
**What changed?**
|
||||
- "Fixed a bug" → PATCH (5.3.0 → 5.3.1)
|
||||
- "Added new feature" → MINOR (5.3.0 → 5.4.0)
|
||||
- "Breaking change" → MAJOR (5.3.0 → 6.0.0)
|
||||
|
||||
**If unclear, ASK THE USER explicitly.**
|
||||
|
||||
## Standard Workflow
|
||||
|
||||
See [operations/workflow.md](operations/workflow.md) for detailed step-by-step process.
|
||||
|
||||
**Quick version:**
|
||||
1. Determine version type (PATCH/MINOR/MAJOR)
|
||||
2. Calculate new version from current
|
||||
3. Preview changes to user
|
||||
4. Update ALL THREE files
|
||||
5. Verify consistency
|
||||
6. Build and test
|
||||
7. Commit and create git tag
|
||||
8. Push and create GitHub release
|
||||
9. Generate CHANGELOG.md from releases and commit
|
||||
10. Post Discord notification
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
See [operations/scenarios.md](operations/scenarios.md) for examples:
|
||||
- Bug fix releases
|
||||
- New feature releases
|
||||
- Breaking change releases
|
||||
|
||||
## Critical Rules
|
||||
|
||||
**ALWAYS:**
|
||||
- Update ALL THREE files with matching version numbers
|
||||
- Create git tag with format `vX.Y.Z`
|
||||
- Create GitHub release from the tag
|
||||
- Generate CHANGELOG.md from releases after creating release
|
||||
- Post Discord notification after release
|
||||
- Ask user if version type is unclear
|
||||
|
||||
**NEVER:**
|
||||
- Update only one or two files
|
||||
- Skip the verification step
|
||||
- Forget to create git tag or GitHub release
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before considering the task complete:
|
||||
- [ ] All THREE files have matching version numbers
|
||||
- [ ] `npm run build` succeeds
|
||||
- [ ] Git commit created with all version files
|
||||
- [ ] Git tag created (format: vX.Y.Z)
|
||||
- [ ] Commit and tags pushed to remote
|
||||
- [ ] GitHub release created from the tag
|
||||
- [ ] CHANGELOG.md generated and committed
|
||||
- [ ] Discord notification sent
|
||||
|
||||
## Reference Commands
|
||||
|
||||
```bash
|
||||
# View current version
|
||||
grep '"version"' package.json
|
||||
|
||||
# Verify consistency across all version files
|
||||
grep '"version"' package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
|
||||
# View git tags
|
||||
git tag -l -n1
|
||||
|
||||
# Check what will be committed
|
||||
git status
|
||||
git diff package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
```
|
||||
|
||||
For more commands, see [operations/reference.md](operations/reference.md).
|
||||
@@ -0,0 +1,265 @@
|
||||
# Version Bump Reference
|
||||
|
||||
Quick reference for version bump commands and file locations.
|
||||
|
||||
## File Locations
|
||||
|
||||
### Version-Tracked Files (ALL THREE)
|
||||
|
||||
1. **package.json**
|
||||
- Path: `package.json`
|
||||
- Line: 3
|
||||
- Format: `"version": "X.Y.Z",`
|
||||
|
||||
2. **marketplace.json**
|
||||
- Path: `.claude-plugin/marketplace.json`
|
||||
- Line: 13
|
||||
- Format: `"version": "X.Y.Z",`
|
||||
|
||||
3. **plugin.json**
|
||||
- Path: `plugin/.claude-plugin/plugin.json`
|
||||
- Line: 3
|
||||
- Format: `"version": "X.Y.Z",`
|
||||
|
||||
## Essential Commands
|
||||
|
||||
### View Current Version
|
||||
|
||||
```bash
|
||||
# From package.json
|
||||
grep '"version"' package.json
|
||||
|
||||
# Extract just the version number
|
||||
grep '"version"' package.json | head -1 | sed 's/.*"version": "\(.*\)".*/\1/'
|
||||
|
||||
# From all version files
|
||||
grep '"version"' package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
```
|
||||
|
||||
### Verify Version Consistency
|
||||
|
||||
```bash
|
||||
# Check all JSON files match
|
||||
grep '"version"' package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
|
||||
# Should output identical version in all three:
|
||||
# package.json:3: "version": "5.3.0",
|
||||
# .claude-plugin/marketplace.json:13: "version": "5.3.0",
|
||||
# plugin/.claude-plugin/plugin.json:3: "version": "5.3.0",
|
||||
```
|
||||
|
||||
### Git Commands
|
||||
|
||||
```bash
|
||||
# View recent commits
|
||||
git log --oneline -5
|
||||
|
||||
# View changes since last tag
|
||||
LAST_TAG=$(git describe --tags --abbrev=0)
|
||||
git log $LAST_TAG..HEAD --oneline
|
||||
git diff $LAST_TAG..HEAD
|
||||
|
||||
# List all tags
|
||||
git tag -l
|
||||
|
||||
# View tag details
|
||||
git show vX.Y.Z
|
||||
|
||||
# List tags with messages
|
||||
git tag -l -n1
|
||||
```
|
||||
|
||||
### Build and Test
|
||||
|
||||
```bash
|
||||
# Build plugin
|
||||
npm run build
|
||||
|
||||
# Sync to marketplace
|
||||
npm run sync-marketplace
|
||||
|
||||
# Run tests (if available)
|
||||
npm test
|
||||
```
|
||||
|
||||
### Commit and Tag
|
||||
|
||||
```bash
|
||||
# Stage version files
|
||||
git add package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json plugin/scripts/
|
||||
|
||||
# Commit
|
||||
git commit -m "Release vX.Y.Z: [Description]"
|
||||
|
||||
# Create tag
|
||||
git tag vX.Y.Z -m "Release vX.Y.Z: [Description]"
|
||||
|
||||
# Push
|
||||
git push && git push --tags
|
||||
```
|
||||
|
||||
### GitHub Release
|
||||
|
||||
```bash
|
||||
# Create release
|
||||
gh release create vX.Y.Z --title "vX.Y.Z" --notes "[Release notes]"
|
||||
|
||||
# Create with auto-generated notes
|
||||
gh release create vX.Y.Z --title "vX.Y.Z" --generate-notes
|
||||
|
||||
# View release
|
||||
gh release view vX.Y.Z
|
||||
|
||||
# List all releases
|
||||
gh release list
|
||||
|
||||
# Delete release (if needed)
|
||||
gh release delete vX.Y.Z
|
||||
```
|
||||
|
||||
## Semantic Versioning Rules
|
||||
|
||||
### Version Format: MAJOR.MINOR.PATCH
|
||||
|
||||
**MAJOR (X.0.0):**
|
||||
- Breaking changes
|
||||
- Incompatible API changes
|
||||
- Schema changes requiring migration
|
||||
- Removes features
|
||||
|
||||
**MINOR (x.Y.0):**
|
||||
- New features (backward compatible)
|
||||
- New functionality
|
||||
- Deprecations (but not removals)
|
||||
- Resets PATCH to 0
|
||||
|
||||
**PATCH (x.y.Z):**
|
||||
- Bug fixes
|
||||
- Performance improvements
|
||||
- Documentation fixes
|
||||
- No new features
|
||||
|
||||
### Incrementing Rules
|
||||
|
||||
```
|
||||
PATCH: 5.3.2 → 5.3.3
|
||||
MINOR: 5.3.2 → 5.4.0 (resets patch)
|
||||
MAJOR: 5.3.2 → 6.0.0 (resets minor and patch)
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Bug Fix Release
|
||||
|
||||
```bash
|
||||
# Example: 5.3.0 → 5.3.1
|
||||
# 1. Update all three files to 5.3.1
|
||||
# 2. Build and test
|
||||
npm run build
|
||||
# 3. Commit and tag
|
||||
git add package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json plugin/scripts/
|
||||
git commit -m "Release v5.3.1: Fixed observer crash"
|
||||
git tag v5.3.1 -m "Release v5.3.1: Fixed observer crash"
|
||||
git push && git push --tags
|
||||
# 4. Create release
|
||||
gh release create v5.3.1 --title "v5.3.1" --notes "Fixed observer crash on empty content"
|
||||
```
|
||||
|
||||
### Feature Release
|
||||
|
||||
```bash
|
||||
# Example: 5.3.0 → 5.4.0
|
||||
# 1. Update all three files to 5.4.0
|
||||
# 2. Build and test
|
||||
npm run build
|
||||
# 3. Commit and tag
|
||||
git add package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json plugin/scripts/
|
||||
git commit -m "Release v5.4.0: Added dark mode support"
|
||||
git tag v5.4.0 -m "Release v5.4.0: Added dark mode support"
|
||||
git push && git push --tags
|
||||
# 4. Create release
|
||||
gh release create v5.4.0 --title "v5.4.0" --generate-notes
|
||||
```
|
||||
|
||||
### Breaking Change Release
|
||||
|
||||
```bash
|
||||
# Example: 5.3.0 → 6.0.0
|
||||
# 1. Update all three files to 6.0.0
|
||||
# 2. Build and test
|
||||
npm run build
|
||||
# 3. Commit and tag
|
||||
git add package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json plugin/scripts/
|
||||
git commit -m "Release v6.0.0: Storage layer redesign"
|
||||
git tag v6.0.0 -m "Release v6.0.0: Storage layer redesign"
|
||||
git push && git push --tags
|
||||
# 4. Create release with warning
|
||||
gh release create v6.0.0 --title "v6.0.0" --notes "⚠️ Breaking change: Storage layer redesigned. Migration required."
|
||||
```
|
||||
|
||||
## Rollback Commands
|
||||
|
||||
### Delete Tag
|
||||
|
||||
```bash
|
||||
# Delete local tag
|
||||
git tag -d vX.Y.Z
|
||||
|
||||
# Delete remote tag
|
||||
git push origin :refs/tags/vX.Y.Z
|
||||
# Or: git push --delete origin vX.Y.Z
|
||||
```
|
||||
|
||||
### Delete Release
|
||||
|
||||
```bash
|
||||
# Delete GitHub release
|
||||
gh release delete vX.Y.Z
|
||||
|
||||
# Confirm deletion
|
||||
gh release delete vX.Y.Z --yes
|
||||
```
|
||||
|
||||
### Revert Commit
|
||||
|
||||
```bash
|
||||
# Revert last commit (creates new commit)
|
||||
git revert HEAD
|
||||
|
||||
# Reset to previous commit (destructive)
|
||||
git reset --hard HEAD~1
|
||||
git push --force # Dangerous! Only if not shared
|
||||
```
|
||||
|
||||
## Error Prevention
|
||||
|
||||
### Pre-commit Checks
|
||||
|
||||
```bash
|
||||
# Check all versions match before committing
|
||||
V1=$(grep '"version"' package.json | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
||||
V2=$(grep '"version"' .claude-plugin/marketplace.json | sed 's/.*"\([^"]*\)".*/\1/')
|
||||
V3=$(grep '"version"' plugin/.claude-plugin/plugin.json | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
||||
|
||||
if [ "$V1" = "$V2" ] && [ "$V2" = "$V3" ]; then
|
||||
echo "✓ All versions match: $V1"
|
||||
else
|
||||
echo "✗ Version mismatch!"
|
||||
echo " package.json: $V1"
|
||||
echo " marketplace.json: $V2"
|
||||
echo " plugin.json: $V3"
|
||||
fi
|
||||
```
|
||||
|
||||
### Pre-push Checks
|
||||
|
||||
```bash
|
||||
# Check tag exists
|
||||
git tag -l | grep vX.Y.Z || echo "Warning: Tag not created"
|
||||
|
||||
# Check build succeeds
|
||||
npm run build || echo "Error: Build failed"
|
||||
|
||||
# Check no uncommitted changes
|
||||
git status --porcelain | grep -q . && echo "Warning: Uncommitted changes"
|
||||
```
|
||||
@@ -0,0 +1,218 @@
|
||||
# Common Version Bump Scenarios
|
||||
|
||||
Real-world examples of version bumps with decision rationale.
|
||||
|
||||
## Scenario 1: Bug Fix After Testing
|
||||
|
||||
**User request:**
|
||||
> "Fixed the memory leak in the search function"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Bug fix
|
||||
- Breaking changes: No
|
||||
- New features: No
|
||||
- **Decision: PATCH**
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Current: 4.2.8
|
||||
New: 4.2.9 (PATCH)
|
||||
|
||||
Steps:
|
||||
1. Update all three files to 4.2.9
|
||||
2. npm run build
|
||||
3. git commit -m "Release v4.2.9: Fixed memory leak in search"
|
||||
4. git tag v4.2.9 -m "Release v4.2.9: Fixed memory leak in search"
|
||||
5. git push && git push --tags
|
||||
6. gh release create v4.2.9 --title "v4.2.9" --notes "Fixed memory leak in search function"
|
||||
```
|
||||
|
||||
## Scenario 2: New Feature Added
|
||||
|
||||
**User request:**
|
||||
> "Added web search MCP integration"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: New feature (MCP integration)
|
||||
- Breaking changes: No
|
||||
- Backward compatible: Yes
|
||||
- **Decision: MINOR**
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Current: 4.2.8
|
||||
New: 4.3.0 (MINOR - reset patch to 0)
|
||||
|
||||
Steps:
|
||||
1. Update all three files to 4.3.0
|
||||
2. npm run build
|
||||
3. git commit -m "Release v4.3.0: Added web search MCP integration"
|
||||
4. git tag v4.3.0 -m "Release v4.3.0: Added web search MCP integration"
|
||||
5. git push && git push --tags
|
||||
6. gh release create v4.3.0 --title "v4.3.0" --generate-notes
|
||||
```
|
||||
|
||||
## Scenario 3: Database Schema Redesign
|
||||
|
||||
**User request:**
|
||||
> "Rewrote storage layer, old data needs migration"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Storage layer rewrite
|
||||
- Breaking changes: Yes (requires migration)
|
||||
- Backward compatible: No
|
||||
- **Decision: MAJOR**
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Current: 4.2.8
|
||||
New: 5.0.0 (MAJOR - reset minor and patch to 0)
|
||||
|
||||
Steps:
|
||||
1. Update all three files to 5.0.0
|
||||
2. npm run build
|
||||
3. git commit -m "Release v5.0.0: Storage layer redesign with migration required"
|
||||
4. git tag v5.0.0 -m "Release v5.0.0: Storage layer redesign"
|
||||
5. git push && git push --tags
|
||||
6. gh release create v5.0.0 --title "v5.0.0" --notes "⚠️ Breaking change: Storage layer redesigned. Migration required."
|
||||
```
|
||||
|
||||
## Scenario 4: Multiple Small Bug Fixes
|
||||
|
||||
**User request:**
|
||||
> "Fixed three bugs: observer crash, viewer pagination, and date formatting"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Multiple bug fixes
|
||||
- Breaking changes: No
|
||||
- New features: No
|
||||
- **Decision: PATCH** (one patch covers all fixes)
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Current: 4.2.8
|
||||
New: 4.2.9 (PATCH)
|
||||
|
||||
Steps:
|
||||
1. Update all three files to 4.2.9
|
||||
2. npm run build
|
||||
3. git commit -m "Release v4.2.9: Multiple bug fixes
|
||||
|
||||
- Fixed observer crash on empty content
|
||||
- Fixed viewer pagination edge case
|
||||
- Fixed date formatting in timeline"
|
||||
4. git tag v4.2.9 -m "Release v4.2.9: Multiple bug fixes"
|
||||
5. git push && git push --tags
|
||||
6. gh release create v4.2.9 --title "v4.2.9" --generate-notes
|
||||
```
|
||||
|
||||
## Scenario 5: Feature + Bug Fix
|
||||
|
||||
**User request:**
|
||||
> "Added dark mode support and fixed the viewer crash bug"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: New feature + bug fix
|
||||
- Breaking changes: No
|
||||
- **Decision: MINOR** (feature trumps bug fix)
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Current: 5.1.0
|
||||
New: 5.2.0 (MINOR)
|
||||
|
||||
Steps:
|
||||
1. Update all three files to 5.2.0
|
||||
2. npm run build
|
||||
3. git commit -m "Release v5.2.0: Dark mode support + bug fixes
|
||||
|
||||
Features:
|
||||
- Added dark mode toggle to viewer UI
|
||||
|
||||
Bug fixes:
|
||||
- Fixed viewer crash on empty database"
|
||||
4. git tag v5.2.0 -m "Release v5.2.0: Dark mode support"
|
||||
5. git push && git push --tags
|
||||
6. gh release create v5.2.0 --title "v5.2.0" --generate-notes
|
||||
```
|
||||
|
||||
## Scenario 6: Documentation Only
|
||||
|
||||
**User request:**
|
||||
> "Updated README with new installation instructions"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Documentation only
|
||||
- Breaking changes: No
|
||||
- Code changes: No
|
||||
- **Decision: PATCH** (or skip version bump if no code changes)
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Option 1: PATCH (if you want to tag doc improvements)
|
||||
Current: 4.2.8
|
||||
New: 4.2.9
|
||||
|
||||
Option 2: No version bump (documentation-only changes don't require versioning)
|
||||
Just commit without bumping version
|
||||
```
|
||||
|
||||
**Recommendation:** Skip version bump for documentation-only changes unless it's a significant documentation overhaul.
|
||||
|
||||
## Scenario 7: Configuration Change
|
||||
|
||||
**User request:**
|
||||
> "Changed default observation count from 50 to 30"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Default configuration
|
||||
- Breaking changes: Yes (behavior changes)
|
||||
- Users might notice different context size
|
||||
- **Decision: MINOR or MAJOR** (ask user)
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
Ask user:
|
||||
"This changes default behavior (context size). Users will see different results.
|
||||
Is this:
|
||||
- MINOR (acceptable behavior change): 4.2.8 → 4.3.0
|
||||
- MAJOR (breaking change): 4.2.8 → 5.0.0
|
||||
|
||||
Which should I use?"
|
||||
```
|
||||
|
||||
## Scenario 8: Dependency Update
|
||||
|
||||
**User request:**
|
||||
> "Updated Claude SDK from 1.2.0 to 1.3.0"
|
||||
|
||||
**Analysis:**
|
||||
- What changed: Dependency version
|
||||
- Breaking changes: Depends on SDK changes
|
||||
- **Decision: Ask user or check SDK changelog**
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
1. Check SDK changelog for breaking changes
|
||||
2. If SDK has breaking changes → MAJOR
|
||||
3. If SDK adds features → MINOR
|
||||
4. If SDK only fixes bugs → PATCH
|
||||
|
||||
Typical: PATCH (unless SDK breaks compatibility)
|
||||
```
|
||||
|
||||
## Decision Tree
|
||||
|
||||
```
|
||||
Is there a breaking change?
|
||||
├─ Yes → MAJOR (X.0.0)
|
||||
└─ No
|
||||
├─ Is there a new feature?
|
||||
│ ├─ Yes → MINOR (x.Y.0)
|
||||
│ └─ No
|
||||
│ ├─ Is there a bug fix?
|
||||
│ │ ├─ Yes → PATCH (x.y.Z)
|
||||
│ │ └─ No → Don't bump version (docs only, etc.)
|
||||
│ └─ Configuration change? → Ask user (MINOR or MAJOR)
|
||||
└─ Multiple changes? → Use highest level (MAJOR > MINOR > PATCH)
|
||||
```
|
||||
@@ -0,0 +1,249 @@
|
||||
# Detailed Version Bump Workflow
|
||||
|
||||
Step-by-step process for bumping versions in the claude-mem project.
|
||||
|
||||
## Step 1: Analyze Changes
|
||||
|
||||
First, understand what changed:
|
||||
|
||||
```bash
|
||||
# View recent commits
|
||||
git log --oneline -5
|
||||
|
||||
# See what changed in last commit
|
||||
git diff HEAD~1
|
||||
|
||||
# Or see all changes since last tag
|
||||
LAST_TAG=$(git describe --tags --abbrev=0)
|
||||
git log $LAST_TAG..HEAD --oneline
|
||||
git diff $LAST_TAG..HEAD
|
||||
```
|
||||
|
||||
## Step 2: Determine Version Type
|
||||
|
||||
Ask yourself:
|
||||
- **Breaking changes?** → MAJOR
|
||||
- **New features?** → MINOR
|
||||
- **Bugfixes only?** → PATCH
|
||||
|
||||
**If unclear, ASK THE USER explicitly.**
|
||||
|
||||
### Decision Matrix
|
||||
|
||||
| Change Type | Version Bump | Example |
|
||||
|------------|--------------|---------|
|
||||
| Bug fix | PATCH | 4.2.8 → 4.2.9 |
|
||||
| New feature (backward compatible) | MINOR | 4.2.8 → 4.3.0 |
|
||||
| Breaking change | MAJOR | 4.2.8 → 5.0.0 |
|
||||
| Multiple features | MINOR | 4.2.8 → 4.3.0 |
|
||||
| Feature + breaking change | MAJOR | 4.2.8 → 5.0.0 |
|
||||
|
||||
## Step 3: Calculate New Version
|
||||
|
||||
From current version in `package.json`:
|
||||
|
||||
```bash
|
||||
grep '"version"' package.json
|
||||
```
|
||||
|
||||
Apply semantic versioning rules:
|
||||
- **Patch:** increment Z (4.2.8 → 4.2.9)
|
||||
- **Minor:** increment Y, reset Z (4.2.8 → 4.3.0)
|
||||
- **Major:** increment X, reset Y and Z (4.2.8 → 5.0.0)
|
||||
|
||||
## Step 4: Preview Changes
|
||||
|
||||
**BEFORE making changes, show the user:**
|
||||
|
||||
```
|
||||
Current version: 4.2.8
|
||||
New version: 4.2.9 (PATCH)
|
||||
Reason: Fixed database query bug
|
||||
|
||||
Files to update:
|
||||
- package.json: "version": "4.2.9"
|
||||
- marketplace.json: "version": "4.2.9"
|
||||
- plugin.json: "version": "4.2.9"
|
||||
- Git tag: v4.2.9
|
||||
|
||||
Proceed? (yes/no)
|
||||
```
|
||||
|
||||
Wait for user confirmation before proceeding.
|
||||
|
||||
## Step 5: Update Files
|
||||
|
||||
### Update package.json
|
||||
|
||||
File: `package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.9",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Update line 3 with new version.
|
||||
|
||||
### Update marketplace.json
|
||||
|
||||
File: `.claude-plugin/marketplace.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.9",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Update line 13 with new version.
|
||||
|
||||
### Update plugin.json
|
||||
|
||||
File: `plugin/.claude-plugin/plugin.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.9",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Update line 3 with new version.
|
||||
|
||||
## Step 6: Verify Consistency
|
||||
|
||||
```bash
|
||||
# Check all versions match
|
||||
grep -n '"version"' package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
|
||||
# Should show same version in all three files:
|
||||
# package.json:3: "version": "4.2.9",
|
||||
# .claude-plugin/marketplace.json:13: "version": "4.2.9",
|
||||
# plugin/.claude-plugin/plugin.json:3: "version": "4.2.9",
|
||||
```
|
||||
|
||||
All three must match exactly.
|
||||
|
||||
## Step 7: Test
|
||||
|
||||
```bash
|
||||
# Verify the plugin loads correctly
|
||||
npm run build
|
||||
```
|
||||
|
||||
Build must succeed before proceeding.
|
||||
|
||||
## Step 8: Commit and Tag
|
||||
|
||||
```bash
|
||||
# Stage all version files
|
||||
git add package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json plugin/scripts/
|
||||
|
||||
# Commit with descriptive message
|
||||
git commit -m "Release vX.Y.Z: [Brief description]
|
||||
|
||||
[Optional detailed description]
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Create annotated git tag
|
||||
git tag vX.Y.Z -m "Release vX.Y.Z: [Brief description]"
|
||||
|
||||
# Push commit and tags
|
||||
git push && git push --tags
|
||||
```
|
||||
|
||||
Replace `X.Y.Z` with actual version (e.g., `4.2.9`).
|
||||
|
||||
## Step 9: Create GitHub Release
|
||||
|
||||
```bash
|
||||
# Create GitHub release from the tag
|
||||
gh release create vX.Y.Z --title "vX.Y.Z" --notes "[Brief release notes]"
|
||||
|
||||
# Or generate notes automatically from commits
|
||||
gh release create vX.Y.Z --title "vX.Y.Z" --generate-notes
|
||||
```
|
||||
|
||||
**IMPORTANT:** Always create the GitHub release immediately after pushing the tag. This makes the release discoverable to users and triggers any automated workflows.
|
||||
|
||||
## Step 10: Generate CHANGELOG
|
||||
|
||||
After creating the GitHub release, regenerate CHANGELOG.md from all releases:
|
||||
|
||||
```bash
|
||||
# Generate CHANGELOG.md from all GitHub releases
|
||||
npm run changelog:generate
|
||||
|
||||
# Review the generated changelog
|
||||
git diff CHANGELOG.md
|
||||
|
||||
# Commit and push the updated changelog
|
||||
git add CHANGELOG.md
|
||||
git commit -m "Update CHANGELOG.md for vX.Y.Z release"
|
||||
git push
|
||||
```
|
||||
|
||||
**Why this step:**
|
||||
- CHANGELOG.md is auto-generated from GitHub releases
|
||||
- Keeps the changelog in sync with release notes
|
||||
- No manual editing required
|
||||
- Single source of truth: GitHub releases
|
||||
|
||||
## Step 11: Discord Notification
|
||||
|
||||
Post release announcement to the Discord updates channel:
|
||||
|
||||
```bash
|
||||
# Send Discord notification with release details
|
||||
npm run discord:notify vX.Y.Z
|
||||
```
|
||||
|
||||
This fetches the release notes from GitHub and posts a formatted embed to the Discord updates channel configured in `.env`.
|
||||
|
||||
## Verification
|
||||
|
||||
After completing all steps, verify:
|
||||
|
||||
```bash
|
||||
# Check git tag created
|
||||
git tag -l | grep vX.Y.Z
|
||||
|
||||
# Check remote has tag
|
||||
git ls-remote --tags origin | grep vX.Y.Z
|
||||
|
||||
# Check GitHub release exists
|
||||
gh release view vX.Y.Z
|
||||
|
||||
# Verify versions match
|
||||
grep '"version"' package.json .claude-plugin/marketplace.json plugin/.claude-plugin/plugin.json
|
||||
```
|
||||
|
||||
All checks should pass.
|
||||
|
||||
## Rollback (If Needed)
|
||||
|
||||
If you made a mistake:
|
||||
|
||||
```bash
|
||||
# Delete local tag
|
||||
git tag -d vX.Y.Z
|
||||
|
||||
# Delete remote tag (if already pushed)
|
||||
git push origin :refs/tags/vX.Y.Z
|
||||
|
||||
# Delete GitHub release (if created)
|
||||
gh release delete vX.Y.Z
|
||||
|
||||
# Revert commits if needed
|
||||
git revert HEAD
|
||||
```
|
||||
|
||||
Then restart the workflow with correct version.
|
||||
@@ -0,0 +1 @@
|
||||
github: thedotmack
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Use the automated bug report tool for best results
|
||||
title: ''
|
||||
labels: 'bug, needs-triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Quick Bug Report (Recommended)
|
||||
|
||||
**Use the automated bug report generator** for comprehensive diagnostics:
|
||||
|
||||
```bash
|
||||
# Navigate to the plugin directory
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack
|
||||
|
||||
# Run the bug report tool
|
||||
npm run bug-report
|
||||
```
|
||||
|
||||
**Plugin Paths:**
|
||||
- **macOS/Linux**: `~/.claude/plugins/marketplaces/thedotmack`
|
||||
- **Windows**: `%USERPROFILE%\.claude\plugins\marketplaces\thedotmack`
|
||||
|
||||
**Features:**
|
||||
- 🌎 Auto-translates any language to English
|
||||
- 📊 Collects all diagnostics automatically
|
||||
- 🤖 AI-formatted professional issue
|
||||
- 🔒 Privacy-safe (paths sanitized, `--no-logs` option)
|
||||
- 🌐 Auto-opens GitHub with pre-filled issue
|
||||
|
||||
---
|
||||
|
||||
## 📝 Manual Bug Report
|
||||
|
||||
If you prefer to file manually or can't access the plugin directory:
|
||||
|
||||
### Bug Description
|
||||
A clear description of what the bug is.
|
||||
|
||||
### Steps to Reproduce
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See error
|
||||
|
||||
### Expected Behavior
|
||||
What you expected to happen.
|
||||
|
||||
### Environment
|
||||
- **Claude-mem version**:
|
||||
- **Claude Code version**:
|
||||
- **OS**:
|
||||
- **Platform**:
|
||||
|
||||
### Logs
|
||||
Worker logs are located at:
|
||||
- **Path**: `~/.claude-mem/logs/worker-YYYY-MM-DD.log`
|
||||
- **Example**: `~/.claude-mem/logs/worker-2025-12-14.log`
|
||||
|
||||
Please paste relevant log entries (last 50 lines or error messages):
|
||||
|
||||
```
|
||||
[Paste logs here]
|
||||
```
|
||||
|
||||
### Additional Context
|
||||
Any other context about the problem.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature-request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,57 @@
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
# Optional: Only run on specific file changes
|
||||
# paths:
|
||||
# - "src/**/*.ts"
|
||||
# - "src/**/*.tsx"
|
||||
# - "src/**/*.js"
|
||||
# - "src/**/*.jsx"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
# Optional: Filter by PR author
|
||||
# if: |
|
||||
# github.event.pull_request.user.login == 'external-contributor' ||
|
||||
# github.event.pull_request.user.login == 'new-developer' ||
|
||||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
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 }}
|
||||
prompt: |
|
||||
REPO: ${{ github.repository }}
|
||||
PR NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
Please review this pull request and provide feedback on:
|
||||
- Code quality and best practices
|
||||
- Potential bugs or issues
|
||||
- Performance considerations
|
||||
- Security concerns
|
||||
- Test coverage
|
||||
|
||||
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
|
||||
|
||||
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
|
||||
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
|
||||
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
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')))
|
||||
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: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# 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/cli-reference for available options
|
||||
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
name: Convert Feature Requests to Discussions
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: 'Issue number to convert to discussion'
|
||||
required: true
|
||||
type: number
|
||||
|
||||
jobs:
|
||||
convert:
|
||||
runs-on: ubuntu-latest
|
||||
# Only run on labeled event if the label is 'feature-request', or always run on workflow_dispatch
|
||||
if: |
|
||||
(github.event_name == 'issues' && github.event.label.name == 'feature-request') ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
discussions: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Get issue details and create discussion
|
||||
id: discussion
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Get issue details
|
||||
let issue;
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.inputs.issue_number
|
||||
});
|
||||
issue = data;
|
||||
} else {
|
||||
issue = context.payload.issue;
|
||||
}
|
||||
|
||||
console.log(`Processing issue #${issue.number}: ${issue.title}`);
|
||||
|
||||
// Format the discussion body with a reference to the original issue
|
||||
const discussionBody = `> Originally posted as issue #${issue.number} by @${issue.user.login}\n> ${issue.html_url}\n\n${issue.body || 'No description provided.'}`;
|
||||
|
||||
const mutation = `
|
||||
mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!) {
|
||||
createDiscussion(input: {
|
||||
repositoryId: $repositoryId
|
||||
categoryId: $categoryId
|
||||
title: $title
|
||||
body: $body
|
||||
}) {
|
||||
discussion {
|
||||
url
|
||||
number
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const variables = {
|
||||
repositoryId: 'R_kgDOPng1Jw',
|
||||
categoryId: 'DIC_kwDOPng1J84Cw86z',
|
||||
title: issue.title,
|
||||
body: discussionBody
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await github.graphql(mutation, variables);
|
||||
const discussionUrl = result.createDiscussion.discussion.url;
|
||||
const discussionNumber = result.createDiscussion.discussion.number;
|
||||
|
||||
core.setOutput('url', discussionUrl);
|
||||
core.setOutput('number', discussionNumber);
|
||||
core.setOutput('issue_number', issue.number);
|
||||
|
||||
console.log(`Created discussion #${discussionNumber}: ${discussionUrl}`);
|
||||
return { discussionUrl, discussionNumber, issueNumber: issue.number };
|
||||
} catch (error) {
|
||||
core.setFailed(`Failed to create discussion: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
- name: Comment on issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issueNumber = ${{ steps.discussion.outputs.issue_number }};
|
||||
const discussionUrl = '${{ steps.discussion.outputs.url }}';
|
||||
|
||||
const comment = `This feature request has been moved to [Discussions](${discussionUrl}) to keep bug reports separate from feature ideas.\n\nPlease continue the conversation there - we'd love to hear your thoughts!`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
body: comment
|
||||
});
|
||||
|
||||
console.log(`Added comment to issue #${issueNumber}`);
|
||||
|
||||
- name: Close and lock issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issueNumber = ${{ steps.discussion.outputs.issue_number }};
|
||||
|
||||
// Close the issue
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
state: 'closed'
|
||||
});
|
||||
|
||||
console.log(`Closed issue #${issueNumber}`);
|
||||
|
||||
// Lock the issue
|
||||
await github.rest.issues.lock({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
lock_reason: 'resolved'
|
||||
});
|
||||
|
||||
console.log(`Locked issue #${issueNumber}`);
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Summarize new issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
summary:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
models: read
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run AI inference
|
||||
id: inference
|
||||
uses: actions/ai-inference@v1
|
||||
with:
|
||||
prompt: |
|
||||
Summarize the following GitHub issue in one paragraph:
|
||||
Title: ${{ github.event.issue.title }}
|
||||
Body: ${{ github.event.issue.body }}
|
||||
|
||||
- name: Comment with AI summary
|
||||
run: |
|
||||
gh issue comment $ISSUE_NUMBER --body '${{ steps.inference.outputs.response }}'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
RESPONSE: ${{ steps.inference.outputs.response }}
|
||||
@@ -1,10 +1,21 @@
|
||||
datasets/
|
||||
node_modules/
|
||||
dist/
|
||||
*.log
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
*.tmp
|
||||
*.temp
|
||||
.install-version
|
||||
.claude/settings.local.json
|
||||
plugin/data/
|
||||
plugin/data.backup/
|
||||
plugin/data.backup/
|
||||
package-lock.json
|
||||
private/
|
||||
|
||||
# Generated UI files (built from viewer-template.html)
|
||||
src/ui/viewer.html
|
||||
|
||||
# Local MCP server config (for development only)
|
||||
.mcp.json
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"sourceHash": "9ab0d799179c66f9",
|
||||
"lastUpdated": "2025-12-12T07:42:03.489Z",
|
||||
"translations": {
|
||||
"zh": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.12256679999999998
|
||||
},
|
||||
"ja": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.12973164999999998
|
||||
},
|
||||
"pt-br": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.11508539999999999
|
||||
},
|
||||
"ko": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.13952664999999997
|
||||
},
|
||||
"es": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.12530165
|
||||
},
|
||||
"de": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.12232164999999998
|
||||
},
|
||||
"fr": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:06:55.026Z",
|
||||
"costUsd": 0.11906665
|
||||
},
|
||||
"he": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.151329
|
||||
},
|
||||
"ar": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.151952
|
||||
},
|
||||
"ru": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.13418499999999997
|
||||
},
|
||||
"pl": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.13196799999999997
|
||||
},
|
||||
"cs": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.12714599999999998
|
||||
},
|
||||
"nl": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.118389
|
||||
},
|
||||
"tr": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.13991199999999998
|
||||
},
|
||||
"uk": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:25:00.076Z",
|
||||
"costUsd": 0.13786
|
||||
},
|
||||
"vi": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.15467299999999998
|
||||
},
|
||||
"id": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.185581
|
||||
},
|
||||
"th": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.177859
|
||||
},
|
||||
"hi": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.17412700000000003
|
||||
},
|
||||
"bn": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.202735
|
||||
},
|
||||
"ro": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.12212875
|
||||
},
|
||||
"sv": {
|
||||
"hash": "9ab0d799179c66f9",
|
||||
"translatedAt": "2025-12-12T07:42:03.489Z",
|
||||
"costUsd": 0.12143675000000001
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,356 +1,97 @@
|
||||
# Claude-Mem: Persistent Memory for Claude Code
|
||||
/* To @claude: be vigilant about only leaving evergreen context in this file, claude-mem handles working context separately. */
|
||||
|
||||
## Overview
|
||||
# Claude-Mem: AI Development Instructions
|
||||
|
||||
Claude-mem is a persistent memory compression system that preserves context across Claude Code sessions. It automatically captures tool usage observations, processes them through the Claude Agent SDK, and makes summaries available to future sessions.
|
||||
## What This Project Is
|
||||
|
||||
**Current Version**: 4.2.4
|
||||
**License**: AGPL-3.0
|
||||
**Author**: Alex Newman (@thedotmack)
|
||||
|
||||
## What It Does
|
||||
|
||||
Claude-mem operates as a Claude Code plugin that:
|
||||
- Captures every tool execution during your coding sessions
|
||||
- Processes observations using AI-powered compression
|
||||
- Generates session summaries when sessions end
|
||||
- Injects relevant context into future sessions
|
||||
- Provides full-text search across your entire project history
|
||||
|
||||
This creates a continuous memory system where Claude can learn from past sessions and maintain context across your entire project lifecycle.
|
||||
Claude-mem is a Claude Code plugin providing persistent memory across sessions. It captures tool usage, compresses observations using the Claude Agent SDK, and injects relevant context into future sessions.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Hook-Based Lifecycle System
|
||||
**5 Lifecycle Hooks**: SessionStart → UserPromptSubmit → PostToolUse → Summary → SessionEnd
|
||||
|
||||
Claude-mem integrates with Claude Code through 5 lifecycle hooks:
|
||||
**Hooks** (`src/hooks/*.ts`) - TypeScript → ESM, built to `plugin/scripts/*-hook.js`
|
||||
|
||||
1. **SessionStart Hook** (`context-hook`)
|
||||
- Ensures dependencies are installed (runs fast idempotent npm install)
|
||||
- Injects context from previous sessions
|
||||
- Auto-starts PM2 worker service
|
||||
- Retrieves last 10 session summaries with three-tier verbosity (v4.2.0)
|
||||
- Fixed in v4.1.0 to use proper JSON hookSpecificOutput format
|
||||
**Worker Service** (`src/services/worker-service.ts`) - Express API on port 37777, Bun-managed, handles AI processing asynchronously
|
||||
|
||||
2. **UserPromptSubmit Hook** (`new-hook`)
|
||||
- Creates new session records
|
||||
- Initializes session tracking
|
||||
- Saves raw user prompts for full-text search (as of v4.2.0)
|
||||
**Database** (`src/services/sqlite/`) - SQLite3 at `~/.claude-mem/claude-mem.db` with FTS5 full-text search
|
||||
|
||||
3. **PostToolUse Hook** (`save-hook`)
|
||||
- Captures tool execution observations
|
||||
- Sends observations to worker service for processing
|
||||
**Search Skill** (`plugin/skills/mem-search/SKILL.md`) - HTTP API for searching past work, auto-invoked when users ask about history
|
||||
|
||||
4. **Summary Hook**
|
||||
- Generates AI-powered session summaries
|
||||
- Processes accumulated observations
|
||||
**Chroma** (`src/services/sync/ChromaSync.ts`) - Vector embeddings for semantic search
|
||||
|
||||
5. **SessionEnd Hook** (`cleanup-hook`)
|
||||
- Marks sessions as completed (graceful cleanup as of v4.1.0)
|
||||
- Skips cleanup on `/clear` commands to preserve ongoing sessions
|
||||
- Previously sent DELETE requests; now allows workers to finish naturally
|
||||
**Viewer UI** (`src/ui/viewer/`) - React interface at http://localhost:37777, built to `plugin/ui/viewer.html`
|
||||
|
||||
### Worker Service Architecture
|
||||
## Privacy Tags
|
||||
|
||||
- **Technology**: HTTP REST API built with Express.js, managed by PM2
|
||||
- **Port**: Fixed port 37777 (configurable via CLAUDE_MEM_WORKER_PORT)
|
||||
- **Location**: `src/services/worker-service.ts`
|
||||
- **Configurable Model**: Uses `CLAUDE_MEM_MODEL` environment variable (default: claude-sonnet-4-5)
|
||||
**Dual-Tag System** for meta-observation control:
|
||||
- `<private>content</private>` - User-level privacy control (manual, prevents storage)
|
||||
- `<claude-mem-context>content</claude-mem-context>` - System-level tag (auto-injected observations, prevents recursive storage)
|
||||
|
||||
**REST API Endpoints** (6 total):
|
||||
- Session management endpoints
|
||||
- Observation processing endpoints
|
||||
- Worker port tracking
|
||||
**Implementation**: Tag stripping happens at hook layer (edge processing) before data reaches worker/database. See `src/utils/tag-stripping.ts` for shared utilities.
|
||||
|
||||
The worker service runs as a PM2-managed background process that handles AI processing separately from the hook execution, preventing hook timeout issues.
|
||||
|
||||
### Database Layer
|
||||
|
||||
**Technology**: SQLite 3 with better-sqlite3 native module
|
||||
**Location**: `~/.claude-mem/claude-mem.db`
|
||||
|
||||
**Note**: SessionStore and SessionSearch use better-sqlite3 as the primary database implementation. Database.ts (which uses bun:sqlite) is legacy code.
|
||||
|
||||
**Core Tables**:
|
||||
- `sdk_sessions` - Session tracking with prompt counters
|
||||
- `session_summaries` - AI-generated session summaries (multiple per session)
|
||||
- `observations` - Captured tool usage with structured fields
|
||||
- `user_prompts` - Raw user prompts with FTS5 search (as of v4.2.0)
|
||||
|
||||
**Schema Features**:
|
||||
- FTS5 (Full-Text Search) virtual tables for fast searching
|
||||
- Automatic sync triggers between main tables and FTS5 tables
|
||||
- Support for multi-prompt sessions (prompt_counter, prompt_number)
|
||||
- Hierarchical observations (title, subtitle, facts, narrative, concepts, files_read, files_modified)
|
||||
- Observation types: decision, bugfix, feature, refactor, discovery, change
|
||||
|
||||
**Database Classes**:
|
||||
- `SessionStore` - CRUD operations for sessions, observations, summaries, user prompts
|
||||
- `SessionSearch` - FTS5 full-text search with 8 search methods
|
||||
|
||||
### MCP Search Server
|
||||
|
||||
**Location**: `src/servers/search-server.ts`
|
||||
**Configuration**: `plugin/.mcp.json`
|
||||
|
||||
Exposes 8 specialized search tools to Claude:
|
||||
|
||||
1. **search_observations** - Full-text search across observations
|
||||
2. **search_sessions** - Full-text search across session summaries
|
||||
3. **search_user_prompts** - Full-text search across raw user prompts (as of v4.2.0)
|
||||
4. **find_by_concept** - Find observations tagged with specific concepts
|
||||
5. **find_by_file** - Find observations referencing specific file paths
|
||||
6. **find_by_type** - Find observations by type (decision/bugfix/feature/etc.)
|
||||
7. **get_recent_context** - Get recent session context including summaries and observations for a project
|
||||
8. **advanced_search** - Combine multiple filters with full-text search
|
||||
|
||||
**Search Pipeline**:
|
||||
```
|
||||
Claude Request → MCP Server → SessionSearch Service → FTS5 Database → Results → Claude
|
||||
```
|
||||
|
||||
**Citations**: All search results use the `claude-mem://` URI scheme for referencing specific observations and sessions.
|
||||
|
||||
## Installation
|
||||
|
||||
### Requirements
|
||||
- Node.js 18+
|
||||
- Claude Code plugin system
|
||||
|
||||
### Installation Method
|
||||
|
||||
**Local Marketplace Installation** (recommended as of v4.0.4+):
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# 1. Clone the repository
|
||||
git clone https://github.com/thedotmack/claude-mem.git
|
||||
cd claude-mem
|
||||
|
||||
# 2. Add to Claude Code marketplace
|
||||
/plugin marketplace add .claude-plugin/marketplace.json
|
||||
|
||||
# 3. Install the plugin
|
||||
/plugin install claude-mem
|
||||
npm run build-and-sync # Build, sync to marketplace, restart worker
|
||||
```
|
||||
|
||||
**Viewer UI**: http://localhost:37777
|
||||
|
||||
## Configuration
|
||||
|
||||
### Model Selection
|
||||
Settings are managed in `~/.claude-mem/settings.json`. The file is auto-created with defaults on first run.
|
||||
|
||||
Configure which AI model processes your observations:
|
||||
**Core Settings:**
|
||||
- `CLAUDE_MEM_MODEL` - Model for observations/summaries (default: claude-sonnet-4-5)
|
||||
- `CLAUDE_MEM_CONTEXT_OBSERVATIONS` - Observations injected at SessionStart
|
||||
- `CLAUDE_MEM_WORKER_PORT` - Worker service port (default: 37777)
|
||||
- `CLAUDE_MEM_WORKER_HOST` - Worker bind address (default: 127.0.0.1, use 0.0.0.0 for remote access)
|
||||
|
||||
**Using the interactive script**:
|
||||
```bash
|
||||
./claude-mem-settings.sh
|
||||
```
|
||||
**System Configuration:**
|
||||
- `CLAUDE_MEM_DATA_DIR` - Data directory location (default: ~/.claude-mem)
|
||||
- `CLAUDE_MEM_LOG_LEVEL` - Log verbosity: DEBUG, INFO, WARN, ERROR, SILENT (default: INFO)
|
||||
|
||||
**Available models**:
|
||||
- `claude-haiku-4-5` - Fast, cost-efficient
|
||||
- `claude-sonnet-4-5` - Balanced (default)
|
||||
- `claude-opus-4` - Most capable
|
||||
- `claude-3-7-sonnet` - Alternative version
|
||||
## File Locations
|
||||
|
||||
The script manages `CLAUDE_MEM_MODEL` in `~/.claude/settings.json`.
|
||||
TODO: also have script create and manage `CLAUDE_MEM_MODEL` in `~/.claude/plugins/marketplaces/thedotmack/.env` so our worker script has access to the value (we may not even need it in our settings but only in our plugin folder since hooks shouldn't be calling queries, not sure).
|
||||
- **Source**: `<project-root>/src/`
|
||||
- **Built Plugin**: `<project-root>/plugin/`
|
||||
- **Installed Plugin**: `~/.claude/plugins/marketplaces/thedotmack/`
|
||||
- **Database**: `~/.claude-mem/claude-mem.db`
|
||||
- **Chroma**: `~/.claude-mem/chroma/`
|
||||
|
||||
## Data Flow
|
||||
## Requirements
|
||||
|
||||
### Memory Pipeline
|
||||
```
|
||||
Tool Execution → Hook Capture → Worker Processing → AI Compression → Database Storage → Future Context Injection
|
||||
```
|
||||
- **Bun** (all platforms - auto-installed if missing)
|
||||
- **uv** (all platforms - auto-installed if missing, provides Python for Chroma)
|
||||
- Node.js (build tools only)
|
||||
|
||||
### Search Pipeline
|
||||
```
|
||||
Search Query → MCP Server → SessionSearch → FTS5 Query → Results with Citations
|
||||
```
|
||||
## Documentation
|
||||
|
||||
## Development
|
||||
**Public Docs**: https://docs.claude-mem.ai (Mintlify)
|
||||
**Source**: `docs/public/` - MDX files, edit `docs.json` for navigation
|
||||
**Deploy**: Auto-deploys from GitHub on push to main
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
claude-mem/
|
||||
├── src/
|
||||
│ ├── bin/hooks/ # Hook entry points
|
||||
│ ├── hooks/ # Hook implementations
|
||||
│ ├── services/ # Worker service
|
||||
│ ├── services/sqlite/ # Database layer
|
||||
│ ├── servers/ # MCP search server
|
||||
│ ├── sdk/ # Claude Agent SDK integration
|
||||
│ ├── shared/ # Shared utilities
|
||||
│ └── utils/ # General utilities
|
||||
├── plugin/ # Built plugin files
|
||||
│ ├── scripts/ # Built hook executables
|
||||
│ └── .mcp.json # MCP server configuration
|
||||
└── .claude-plugin/ # Plugin metadata
|
||||
└── marketplace.json # Marketplace definition
|
||||
```
|
||||
## Pro Features Architecture
|
||||
|
||||
### Technology Stack
|
||||
- **Language**: TypeScript
|
||||
- **Database**: SQLite 3 with better-sqlite3
|
||||
- **HTTP**: Express.js
|
||||
- **Process Management**: PM2
|
||||
- **AI SDK**: @anthropic-ai/claude-agent-sdk (v0.1.23)
|
||||
- **MCP SDK**: @modelcontextprotocol/sdk (v1.20.1)
|
||||
- **Schema Validation**: zod-to-json-schema (v3.24.6)
|
||||
Claude-mem is designed with a clean separation between open-source core functionality and optional Pro features.
|
||||
|
||||
### Build Process
|
||||
```bash
|
||||
npm run build && git commit -a -m "Build and update" && git push && cd ~/.claude/plugins/marketplaces/thedotmack/ && git pull && pm2 flush claude-mem-worker && pm2 restart claude-mem-worker && pm2 logs claude-mem-worker --nostream
|
||||
```
|
||||
**Open-Source Core** (this repository):
|
||||
|
||||
1) Compiles TypeScript and outputs hook executables to `plugin/scripts/`
|
||||
2) Does all the things needed to update and test since plugin-based installs are out of the .claude/ folder
|
||||
- All worker API endpoints on localhost:37777 remain fully open and accessible
|
||||
- Pro features are headless - no proprietary UI elements in this codebase
|
||||
- Pro integration points are minimal: settings for license keys, tunnel provisioning logic
|
||||
- The architecture ensures Pro features extend rather than replace core functionality
|
||||
|
||||
**Build Outputs**:
|
||||
- Hook executables: `*-hook.js` (ESM format)
|
||||
- Worker service: `worker-service.cjs` (CJS format)
|
||||
- Search server: `search-server.js` (ESM format)
|
||||
**Pro Features** (coming soon, external):
|
||||
|
||||
## Version History
|
||||
- Enhanced UI (Memory Stream) connects to the same localhost:37777 endpoints as the open viewer
|
||||
- Additional features like advanced filtering, timeline scrubbing, and search tools
|
||||
- Access gated by license validation, not by modifying core endpoints
|
||||
- Users without Pro licenses continue using the full open-source viewer UI without limitation
|
||||
|
||||
### v4.2.4 (Current)
|
||||
**Breaking Changes**: None (patch version)
|
||||
This architecture preserves the open-source nature of the project while enabling sustainable development through optional paid features.
|
||||
|
||||
**Improvements**:
|
||||
- Enhanced summary prompt clarity and reliability
|
||||
- Removed optional skip_summary functionality (summaries now always generated)
|
||||
- Clarified that summaries are mid-session checkpoints, not session endings
|
||||
- Improved request field instructions to better form descriptive titles
|
||||
- Changed wording from "discovered" to "learned" for consistency
|
||||
# Important
|
||||
|
||||
**Technical Details**:
|
||||
- Updated `src/sdk/prompts.ts` to remove `WHEN NOT TO SUMMARIZE` section
|
||||
- Added footer text clarifying summaries track progress within ongoing sessions
|
||||
- Changed request field prompt from "Use their original sentiment" to "Form a title that reflects the actual request"
|
||||
- Affects both observation and summary prompt generation
|
||||
|
||||
### v4.2.3
|
||||
**Breaking Changes**: None (patch version)
|
||||
|
||||
**Security**:
|
||||
- Fixed FTS5 injection vulnerability in search functions
|
||||
- Implemented proper double-quote escaping for FTS5 queries
|
||||
- Added comprehensive test suite with 332 injection attack tests
|
||||
- Affects: `search_observations`, `search_sessions`, `search_user_prompts` MCP tools
|
||||
|
||||
**Fixes**:
|
||||
- Fixed ESM/CJS compatibility for getDirname function in src/shared/paths.ts
|
||||
- Detects context using `typeof __dirname !== 'undefined'`
|
||||
- Falls back to `fileURLToPath(import.meta.url)` for ESM modules
|
||||
- Resolves path resolution issues across hook (ESM) and worker (CJS) contexts
|
||||
- Fixed Windows PowerShell compatibility issue with SessionStart hook
|
||||
- Replaced bash-specific test command `[` with cross-platform npm install command
|
||||
- Hook now runs `npm install` with quiet flags (fast and idempotent when dependencies exist)
|
||||
|
||||
**Technical Details**:
|
||||
- SessionSearch.ts now escapes double quotes in FTS5 queries: `query.replace(/"/g, '""')`
|
||||
- Updated `plugin/hooks/hooks.json` SessionStart command to use standard shell syntax
|
||||
- Changed from: `[ ! -d ... ] && cd ... && npm install && node ... || node ...`
|
||||
- Changed to: `cd ... && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ...`
|
||||
- Dependencies are installed in marketplace folder (parent of CLAUDE_PLUGIN_ROOT) where root package.json exists
|
||||
- getDirname function now properly handles both CommonJS (__dirname) and ES modules (import.meta.url)
|
||||
|
||||
### v4.2.0
|
||||
**Breaking Changes**: None (minor version)
|
||||
|
||||
**Features**:
|
||||
- User prompt storage with FTS5 full-text search
|
||||
- New `user_prompts` table stores raw user input for every prompt
|
||||
- New `search_user_prompts` MCP tool enables searching actual user requests
|
||||
- Automatic FTS5 indexing of all user prompts for fast retrieval
|
||||
|
||||
**Benefits**:
|
||||
- Full context reconstruction from user intent → Claude actions → outcomes
|
||||
- Pattern detection for repeated requests (identify when Claude isn't listening)
|
||||
- Improved debugging by tracing from original user words to final implementation
|
||||
- Historical search: "How many times did user ask for X feature?"
|
||||
|
||||
**Implementation**:
|
||||
- Migration 10: Creates user_prompts table with FTS5 virtual table and sync triggers
|
||||
- UserPromptSubmit hook now saves prompts using claude_session_id (available immediately)
|
||||
- Citations use `claude-mem://user-prompt/{id}` URI scheme
|
||||
|
||||
### v4.1.0
|
||||
**Breaking Changes**: None (minor version)
|
||||
|
||||
**Features**:
|
||||
- Graceful session cleanup (marks complete instead of DELETE)
|
||||
- Restored MCP search server from backup
|
||||
- Updated dependencies (claude-agent-sdk 0.1.23, MCP SDK 1.20.1)
|
||||
|
||||
**Fixes**:
|
||||
- `/clear` command now skips cleanup to prevent session interruption
|
||||
- Session workers can finish pending operations naturally
|
||||
|
||||
### v4.0.0
|
||||
**Breaking Changes**:
|
||||
- Data directory relocated to `${CLAUDE_PLUGIN_ROOT}/data/`
|
||||
- Fresh start required (no migration from v3.x)
|
||||
- Worker auto-starts in SessionStart hook
|
||||
|
||||
**Features**:
|
||||
- MCP Search Server with 8 specialized search tools
|
||||
- FTS5 full-text search across observations, sessions, and user prompts
|
||||
- Citation support with `claude-mem://` URIs
|
||||
- HTTP REST API architecture with PM2 management
|
||||
- Plugin data directory integration
|
||||
|
||||
**Changes**:
|
||||
- Improved session continuity
|
||||
- Enhanced error handling
|
||||
- Better process cleanup
|
||||
|
||||
### Earlier Versions (v3.x)
|
||||
- v3.9.17: MCP integration, hookSpecificOutput JSON format
|
||||
- v3.7.1: SQLite storage backend
|
||||
- Earlier: Mintlify documentation, statusline support
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### Graceful Cleanup (v4.1.0)
|
||||
Changed from aggressive session deletion (HTTP DELETE to workers) to graceful completion (marking sessions complete and allowing workers to finish). This prevents interruption of important operations like summary generation.
|
||||
|
||||
### FTS5 for Search Performance
|
||||
Implements SQLite FTS5 (Full-Text Search) virtual tables with automatic synchronization triggers, enabling fast full-text search across thousands of observations without performance degradation.
|
||||
|
||||
### Multi-Prompt Session Support
|
||||
Tracks `prompt_counter` and `prompt_number` across sessions and observations, enabling context preservation across conversation restarts within the same coding session.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Worker Service Issues
|
||||
- Check PM2 status: `pm2 list`
|
||||
- View logs: `npm run worker:logs`
|
||||
- Restart worker: `npm run worker:restart`
|
||||
|
||||
### Database Issues
|
||||
- Database location: `~/.claude-mem/claude-mem.db`
|
||||
- Check schema: `sqlite3 <db-path> ".schema"`
|
||||
- FTS5 tables are automatically synchronized via triggers
|
||||
|
||||
### Hook Issues
|
||||
- Hooks output to Claude Code's hook execution log
|
||||
- Check `plugin/scripts/` for built executables
|
||||
|
||||
### Model Configuration Issues
|
||||
- Use `./claude-mem-settings.sh` to manage model settings
|
||||
- Settings stored in `~/.claude/settings.json`
|
||||
- Default fallback: `claude-sonnet-4-5`
|
||||
|
||||
## Citations & References
|
||||
|
||||
This project uses the `claude-mem://` URI scheme for citations:
|
||||
- `claude-mem://observation/{id}` - References specific observations
|
||||
- `claude-mem://session/{id}` - References specific sessions
|
||||
|
||||
All MCP search results include citations, enabling Claude to reference specific historical context.
|
||||
|
||||
## License
|
||||
|
||||
AGPL-3.0
|
||||
|
||||
## Repository
|
||||
|
||||
https://github.com/thedotmack/claude-mem
|
||||
No need to edit the changelog ever, it's generated automatically.
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<br>
|
||||
<a href="https://github.com/thedotmack/claude-mem">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/claude-mem-logo-for-dark-mode.webp">
|
||||
<source media="(prefers-color-scheme: light)" srcset="docs/claude-mem-logo-for-light-mode.webp">
|
||||
<img src="docs/claude-mem-logo-for-light-mode.webp" alt="Claude-Mem" width="400">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/claude-mem-logo-for-dark-mode.webp">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/claude-mem-logo-for-light-mode.webp">
|
||||
<img src="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/claude-mem-logo-for-light-mode.webp" alt="Claude-Mem" width="400">
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
@@ -17,11 +17,34 @@
|
||||
<img src="https://img.shields.io/badge/License-AGPL%203.0-blue.svg" alt="License">
|
||||
</a>
|
||||
<a href="package.json">
|
||||
<img src="https://img.shields.io/badge/version-4.2.3-green.svg" alt="Version">
|
||||
<img src="https://img.shields.io/badge/version-6.5.0-green.svg" alt="Version">
|
||||
</a>
|
||||
<a href="package.json">
|
||||
<img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg" alt="Node">
|
||||
</a>
|
||||
<a href="https://github.com/thedotmack/awesome-claude-code">
|
||||
<img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Claude Code">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/15496" target="_blank">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/trendshift-badge-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/trendshift-badge.svg">
|
||||
<img src="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/trendshift-badge.svg" alt="thedotmack/claude-mem | Trendshift" width="250" height="55"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/thedotmack/claude-mem">
|
||||
<picture>
|
||||
<img src="https://raw.githubusercontent.com/thedotmack/claude-mem/main/docs/public/cm-preview.gif" alt="Claude-Mem Preview" width="800">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -53,11 +76,17 @@ Start a new Claude Code session in the terminal and enter the following commands
|
||||
Restart Claude Code. Context from previous sessions will automatically appear in new sessions.
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- 🧠 **Persistent Memory** - Context survives across sessions
|
||||
- 🔍 **7 Search Tools** - Query your project history via MCP
|
||||
- 📊 **Progressive Disclosure** - Layered memory retrieval with token cost visibility
|
||||
- 🔍 **Skill-Based Search** - Query your project history with mem-search skill
|
||||
- 🖥️ **Web Viewer UI** - Real-time memory stream at http://localhost:37777
|
||||
- 💻 **Claude Desktop Skill** - Search memory from Claude Desktop conversations
|
||||
- 🔒 **Privacy Control** - Use `<private>` tags to exclude sensitive content from storage
|
||||
- ⚙️ **Context Configuration** - Fine-grained control over what context gets injected
|
||||
- 🤖 **Automatic Operation** - No manual intervention required
|
||||
- 📊 **FTS5 Search** - Fast full-text search across observations
|
||||
- 🔗 **Citations** - Reference past decisions with `claude-mem://` URIs
|
||||
- 🔗 **Citations** - Reference past observations with IDs (access via http://localhost:37777/api/observation/{id} or view all in the web viewer at http://localhost:37777)
|
||||
- 🧪 **Beta Channel** - Try experimental features like Endless Mode via version switching
|
||||
|
||||
---
|
||||
|
||||
@@ -66,27 +95,39 @@ Restart Claude Code. Context from previous sessions will automatically appear in
|
||||
📚 **[View Full Documentation](docs/)** - Browse markdown docs on GitHub
|
||||
|
||||
💻 **Local Preview**: Run Mintlify docs locally:
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
cd docs/public
|
||||
npx mintlify dev
|
||||
```
|
||||
|
||||
### Getting Started
|
||||
- **[Installation Guide](docs/installation.mdx)** - Quick start & advanced installation
|
||||
- **[Usage Guide](docs/usage/getting-started.mdx)** - How Claude-Mem works automatically
|
||||
- **[MCP Search Tools](docs/usage/search-tools.mdx)** - Query your project history
|
||||
|
||||
- **[Installation Guide](https://docs.claude-mem.ai/installation)** - Quick start & advanced installation
|
||||
- **[Usage Guide](https://docs.claude-mem.ai/usage/getting-started)** - How Claude-Mem works automatically
|
||||
- **[Search Tools](https://docs.claude-mem.ai/usage/search-tools)** - Query your project history with natural language
|
||||
- **[Beta Features](https://docs.claude-mem.ai/beta-features)** - Try experimental features like Endless Mode
|
||||
|
||||
### Best Practices
|
||||
|
||||
- **[Context Engineering](https://docs.claude-mem.ai/context-engineering)** - AI agent context optimization principles
|
||||
- **[Progressive Disclosure](https://docs.claude-mem.ai/progressive-disclosure)** - Philosophy behind Claude-Mem's context priming strategy
|
||||
|
||||
### Architecture
|
||||
- **[Overview](docs/architecture/overview.mdx)** - System components & data flow
|
||||
- **[Hooks](docs/architecture/hooks.mdx)** - 5 lifecycle hooks explained
|
||||
- **[Worker Service](docs/architecture/worker-service.mdx)** - HTTP API & PM2 management
|
||||
- **[Database](docs/architecture/database.mdx)** - SQLite schema & FTS5 search
|
||||
- **[MCP Search](docs/architecture/mcp-search.mdx)** - 7 search tools & examples
|
||||
|
||||
- **[Overview](https://docs.claude-mem.ai/architecture/overview)** - System components & data flow
|
||||
- **[Architecture Evolution](https://docs.claude-mem.ai/architecture-evolution)** - The journey from v3 to v5
|
||||
- **[Hooks Architecture](https://docs.claude-mem.ai/hooks-architecture)** - How Claude-Mem uses lifecycle hooks
|
||||
- **[Hooks Reference](https://docs.claude-mem.ai/architecture/hooks)** - 7 hook scripts explained
|
||||
- **[Worker Service](https://docs.claude-mem.ai/architecture/worker-service)** - HTTP API & Bun management
|
||||
- **[Database](https://docs.claude-mem.ai/architecture/database)** - SQLite schema & FTS5 search
|
||||
- **[Search Architecture](https://docs.claude-mem.ai/architecture/search-architecture)** - Hybrid search with Chroma vector database
|
||||
|
||||
### Configuration & Development
|
||||
- **[Configuration](docs/configuration.mdx)** - Environment variables & settings
|
||||
- **[Development](docs/development.mdx)** - Building, testing, contributing
|
||||
- **[Troubleshooting](docs/troubleshooting.mdx)** - Common issues & solutions
|
||||
|
||||
- **[Configuration](https://docs.claude-mem.ai/configuration)** - Environment variables & settings
|
||||
- **[Development](https://docs.claude-mem.ai/development)** - Building, testing, contributing
|
||||
- **[Troubleshooting](https://docs.claude-mem.ai/troubleshooting)** - Common issues & solutions
|
||||
|
||||
---
|
||||
|
||||
@@ -94,7 +135,7 @@ npx mintlify dev
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Session Start → Inject context from last 10 sessions │
|
||||
│ Session Start → Inject recent observations as context │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
@@ -115,49 +156,119 @@ npx mintlify dev
|
||||
```
|
||||
|
||||
**Core Components:**
|
||||
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd
|
||||
2. **Worker Service** - HTTP API on port 37777 managed by PM2
|
||||
3. **SQLite Database** - Stores sessions, observations, summaries with FTS5 search
|
||||
4. **7 MCP Search Tools** - Query historical context with citations
|
||||
|
||||
See [Architecture Overview](docs/architecture/overview.mdx) for details.
|
||||
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts)
|
||||
2. **Smart Install** - Cached dependency checker (pre-hook script, not a lifecycle hook)
|
||||
3. **Worker Service** - HTTP API on port 37777 with web viewer UI and 10 search endpoints, managed by Bun
|
||||
4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 full-text search
|
||||
5. **mem-search Skill** - Natural language queries with progressive disclosure
|
||||
6. **Chroma Vector Database** - Hybrid semantic + keyword search for intelligent context retrieval
|
||||
|
||||
See [Architecture Overview](https://docs.claude-mem.ai/architecture/overview) for details.
|
||||
|
||||
---
|
||||
|
||||
## MCP Search Tools
|
||||
## mem-search Skill
|
||||
|
||||
Claude-Mem provides 7 specialized search tools:
|
||||
Claude-Mem provides intelligent search through the mem-search skill that auto-invokes when you ask about past work:
|
||||
|
||||
1. **search_observations** - Full-text search across observations
|
||||
2. **search_sessions** - Full-text search across session summaries
|
||||
3. **search_user_prompts** - Search raw user requests
|
||||
4. **find_by_concept** - Find by concept tags
|
||||
5. **find_by_file** - Find by file references
|
||||
6. **find_by_type** - Find by type (decision, bugfix, feature, etc.)
|
||||
7. **get_recent_context** - Get recent session context
|
||||
**How It Works:**
|
||||
- Just ask naturally: *"What did we do last session?"* or *"Did we fix this bug before?"*
|
||||
- Claude automatically invokes the mem-search skill to find relevant context
|
||||
|
||||
**Available Search Operations:**
|
||||
|
||||
1. **Search Observations** - Full-text search across observations
|
||||
2. **Search Sessions** - Full-text search across session summaries
|
||||
3. **Search Prompts** - Search raw user requests
|
||||
4. **By Concept** - Find by concept tags (discovery, problem-solution, pattern, etc.)
|
||||
5. **By File** - Find observations referencing specific files
|
||||
6. **By Type** - Find by type (decision, bugfix, feature, refactor, discovery, change)
|
||||
7. **Recent Context** - Get recent session context for a project
|
||||
8. **Timeline** - Get unified timeline of context around a specific point in time
|
||||
9. **Timeline by Query** - Search for observations and get timeline context around best match
|
||||
10. **API Help** - Get search API documentation
|
||||
|
||||
**Example Natural Language Queries:**
|
||||
|
||||
**Example Queries:**
|
||||
```
|
||||
search_observations with query="authentication" and type="decision"
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
search_user_prompts with query="add dark mode"
|
||||
get_recent_context with limit=5
|
||||
"What bugs did we fix last session?"
|
||||
"How did we implement authentication?"
|
||||
"What changes were made to worker-service.ts?"
|
||||
"Show me recent work on this project"
|
||||
"What was happening when we added the viewer UI?"
|
||||
```
|
||||
|
||||
See [MCP Search Tools Guide](docs/usage/search-tools.mdx) for detailed examples.
|
||||
See [Search Tools Guide](https://docs.claude-mem.ai/usage/search-tools) for detailed examples.
|
||||
|
||||
---
|
||||
|
||||
## What's New in v4.2.3
|
||||
## Beta Features & Endless Mode
|
||||
|
||||
**Security:**
|
||||
- Fixed FTS5 injection vulnerability in search functions
|
||||
- Added comprehensive test suite with 332 injection attack tests
|
||||
> **Note**: Endless Mode is an **experimental feature in the beta branch only**. It is not included in the stable release you install via the marketplace. You must manually switch to the beta channel to try it, and it comes with significant caveats (see below).
|
||||
|
||||
**Fixes:**
|
||||
- Fixed ESM/CJS compatibility for getDirname function
|
||||
- Fixed Windows PowerShell compatibility in SessionStart hook
|
||||
- Cross-platform dependency installation now works on Windows, macOS, and Linux
|
||||
Claude-Mem offers a **beta channel** with experimental features. Switch between stable and beta versions directly from the web viewer UI.
|
||||
|
||||
### How to Try Beta
|
||||
|
||||
1. Open http://localhost:37777
|
||||
2. Click Settings (gear icon)
|
||||
3. In **Version Channel**, click "Try Beta (Endless Mode)"
|
||||
4. Wait for the worker to restart
|
||||
|
||||
Your memory data is preserved when switching versions.
|
||||
|
||||
### Endless Mode (Beta)
|
||||
|
||||
The flagship beta feature is **Endless Mode** - a biomimetic memory architecture that dramatically extends session length:
|
||||
|
||||
**The Problem**: Standard Claude Code sessions hit context limits after ~50 tool uses. Each tool adds 1-10k+ tokens, and Claude re-synthesizes all previous outputs on every response (O(N²) complexity).
|
||||
|
||||
**The Solution**: Endless Mode compresses tool outputs into ~500-token observations and transforms the transcript in real-time:
|
||||
|
||||
```
|
||||
Working Memory (Context): Compressed observations (~500 tokens each)
|
||||
Archive Memory (Disk): Full tool outputs preserved for recall
|
||||
```
|
||||
|
||||
**Projected Results** (based on theoretical modeling, not production measurements):
|
||||
- Significant token reduction in context window
|
||||
- More tool uses before context exhaustion
|
||||
- Linear O(N) scaling instead of quadratic O(N²)
|
||||
- Full transcripts preserved for perfect recall
|
||||
|
||||
**Important Caveats**:
|
||||
- **Not in stable release** - You must switch to beta branch to use this feature
|
||||
- **Still in development** - May have bugs, breaking changes, or incomplete functionality
|
||||
- **Slower than standard mode** - Blocking observation generation adds latency to each tool use
|
||||
- **Theoretical projections** - The efficiency claims above are based on simulations, not real-world production data
|
||||
|
||||
See [Beta Features Documentation](https://docs.claude-mem.ai/beta-features) for details.
|
||||
|
||||
---
|
||||
|
||||
## What's New
|
||||
|
||||
**v6.4.9 - Context Configuration Settings:**
|
||||
- 11 new settings for fine-grained control over context injection
|
||||
- Configure token economics display, observation filtering by type/concept
|
||||
- Control number of observations and which fields to display
|
||||
|
||||
**v6.4.0 - Dual-Tag Privacy System:**
|
||||
- `<private>` tags for user-controlled privacy - wrap sensitive content to exclude from storage
|
||||
- System-level `<claude-mem-context>` tags prevent recursive observation storage
|
||||
- Edge processing ensures private content never reaches database
|
||||
|
||||
**v6.3.0 - Version Channel:**
|
||||
- Switch between stable and beta versions from the web viewer UI
|
||||
- Try experimental features like Endless Mode without manual git operations
|
||||
|
||||
**Previous Highlights:**
|
||||
- **v6.0.0**: Major session management & transcript processing improvements
|
||||
- **v5.5.0**: mem-search skill enhancement with 100% effectiveness rate
|
||||
- **v5.4.0**: Skill-based search architecture (~2,250 tokens saved per session)
|
||||
- **v5.1.0**: Web-based viewer UI with real-time updates
|
||||
- **v5.0.0**: Hybrid search with Chroma vector database
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md) for complete version history.
|
||||
|
||||
@@ -167,29 +278,43 @@ See [CHANGELOG.md](CHANGELOG.md) for complete version history.
|
||||
|
||||
- **Node.js**: 18.0.0 or higher
|
||||
- **Claude Code**: Latest version with plugin support
|
||||
- **PM2**: Process manager (bundled - no global install required)
|
||||
- **Bun**: JavaScript runtime and process manager (auto-installed if missing)
|
||||
- **uv**: Python package manager for vector search (auto-installed if missing)
|
||||
- **SQLite 3**: For persistent storage (bundled)
|
||||
|
||||
---
|
||||
|
||||
## Key Benefits
|
||||
|
||||
### Progressive Disclosure Context
|
||||
|
||||
- **Layered memory retrieval** mirrors human memory patterns
|
||||
- **Layer 1 (Index)**: See what observations exist with token costs at session start
|
||||
- **Layer 2 (Details)**: Fetch full narratives on-demand via MCP search
|
||||
- **Layer 3 (Perfect Recall)**: Access source code and original transcripts
|
||||
- **Smart decision-making**: Token counts help Claude choose between fetching details or reading code
|
||||
- **Type indicators**: Visual cues (🔴 critical, 🟤 decision, 🔵 informational) highlight observation importance
|
||||
|
||||
### Automatic Memory
|
||||
|
||||
- Context automatically injected when Claude starts
|
||||
- No manual commands or configuration needed
|
||||
- Works transparently in the background
|
||||
|
||||
### Full History Search
|
||||
|
||||
- Search across all sessions and observations
|
||||
- FTS5 full-text search for fast queries
|
||||
- Citations link back to specific observations
|
||||
|
||||
### Structured Observations
|
||||
|
||||
- AI-powered extraction of learnings
|
||||
- Categorized by type (decision, bugfix, feature, etc.)
|
||||
- Tagged with concepts and file references
|
||||
|
||||
### Multi-Prompt Sessions
|
||||
|
||||
- Sessions span multiple user prompts
|
||||
- Context preserved across `/clear` commands
|
||||
- Track entire conversation threads
|
||||
@@ -198,17 +323,45 @@ See [CHANGELOG.md](CHANGELOG.md) for complete version history.
|
||||
|
||||
## Configuration
|
||||
|
||||
**Model Selection:**
|
||||
Settings are managed in `~/.claude-mem/settings.json`. The file is auto-created with defaults on first run.
|
||||
|
||||
**Available Settings:**
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `CLAUDE_MEM_MODEL` | `claude-sonnet-4-5` | AI model for observations |
|
||||
| `CLAUDE_MEM_WORKER_PORT` | `37777` | Worker service port |
|
||||
| `CLAUDE_MEM_WORKER_HOST` | `127.0.0.1` | Worker bind address (use `0.0.0.0` for remote access) |
|
||||
| `CLAUDE_MEM_DATA_DIR` | `~/.claude-mem` | Data directory location |
|
||||
| `CLAUDE_MEM_LOG_LEVEL` | `INFO` | Log verbosity (DEBUG, INFO, WARN, ERROR, SILENT) |
|
||||
| `CLAUDE_MEM_PYTHON_VERSION` | `3.13` | Python version for chroma-mcp |
|
||||
| `CLAUDE_CODE_PATH` | _(auto-detect)_ | Path to Claude executable |
|
||||
| `CLAUDE_MEM_CONTEXT_OBSERVATIONS` | `50` | Number of observations to inject at SessionStart |
|
||||
|
||||
**Settings Management:**
|
||||
|
||||
```bash
|
||||
# Edit settings via CLI helper
|
||||
./claude-mem-settings.sh
|
||||
|
||||
# Or edit directly
|
||||
nano ~/.claude-mem/settings.json
|
||||
|
||||
# View current settings
|
||||
curl http://localhost:37777/api/settings
|
||||
```
|
||||
|
||||
**Environment Variables:**
|
||||
- `CLAUDE_MEM_MODEL` - AI model for processing (default: claude-sonnet-4-5)
|
||||
- `CLAUDE_MEM_WORKER_PORT` - Worker port (default: 37777)
|
||||
- `CLAUDE_MEM_DATA_DIR` - Data directory override (dev only)
|
||||
**Settings File Format:**
|
||||
|
||||
See [Configuration Guide](docs/configuration.mdx) for details.
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_MODEL": "claude-sonnet-4-5",
|
||||
"CLAUDE_MEM_WORKER_PORT": "37777",
|
||||
"CLAUDE_MEM_CONTEXT_OBSERVATIONS": "50"
|
||||
}
|
||||
```
|
||||
|
||||
See [Configuration Guide](https://docs.claude-mem.ai/configuration) for details.
|
||||
|
||||
---
|
||||
|
||||
@@ -231,19 +384,59 @@ npm run worker:start
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
See [Development Guide](docs/development.mdx) for detailed instructions.
|
||||
See [Development Guide](https://docs.claude-mem.ai/development) for detailed instructions.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Quick Diagnostic:**
|
||||
|
||||
If you're experiencing issues, describe the problem to Claude and the troubleshoot skill will automatically activate to diagnose and provide fixes.
|
||||
|
||||
**Common Issues:**
|
||||
- Worker not starting → `npm run worker:restart`
|
||||
|
||||
- Worker not starting → `claude-mem restart`
|
||||
- No context appearing → `npm run test:context`
|
||||
- Database issues → `sqlite3 ~/.claude-mem/claude-mem.db "PRAGMA integrity_check;"`
|
||||
- Search not working → Check FTS5 tables exist
|
||||
|
||||
See [Troubleshooting Guide](docs/troubleshooting.mdx) for complete solutions.
|
||||
See [Troubleshooting Guide](https://docs.claude-mem.ai/troubleshooting) for complete solutions.
|
||||
|
||||
### Windows Known Issues
|
||||
|
||||
**Console Window Visibility**: On Windows, a console window may briefly appear when the worker service starts. This is a cosmetic issue that we're working to resolve. We've prioritized stability by removing a workaround that was causing libuv crashes. The window does not affect functionality and will be addressed in a future release when the MCP SDK provides proper window hiding support.
|
||||
|
||||
---
|
||||
|
||||
## Bug Reports
|
||||
|
||||
**Automated Bug Report Generator** - Create comprehensive bug reports with one command:
|
||||
|
||||
```bash
|
||||
# From the plugin directory
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack
|
||||
npm run bug-report
|
||||
```
|
||||
|
||||
The bug report tool will:
|
||||
- 🌎 **Auto-translate** - Write in ANY language, automatically translates to English
|
||||
- 📊 **Collect diagnostics** - Gathers versions, platform info, worker status, logs, and configuration
|
||||
- 📝 **Interactive prompts** - Guides you through describing the issue with multiline support
|
||||
- 🤖 **AI formatting** - Uses Claude Agent SDK to generate professional GitHub issues
|
||||
- 🔒 **Privacy-safe** - Auto-sanitizes paths, optional `--no-logs` flag
|
||||
- 🌐 **Auto-submit** - Opens GitHub with pre-filled title and body
|
||||
|
||||
**Plugin Directory Paths:**
|
||||
- **macOS/Linux**: `~/.claude/plugins/marketplaces/thedotmack`
|
||||
- **Windows**: `%USERPROFILE%\.claude\plugins\marketplaces\thedotmack`
|
||||
|
||||
**Options:**
|
||||
```bash
|
||||
npm run bug-report --no-logs # Skip logs for privacy
|
||||
npm run bug-report --verbose # Show all diagnostics
|
||||
npm run bug-report --help # Show help
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -257,7 +450,7 @@ Contributions are welcome! Please:
|
||||
4. Update documentation
|
||||
5. Submit a Pull Request
|
||||
|
||||
See [Development Guide](docs/development.mdx) for contribution workflow.
|
||||
See [Development Guide](https://docs.claude-mem.ai/development) for contribution workflow.
|
||||
|
||||
---
|
||||
|
||||
@@ -270,6 +463,7 @@ Copyright (C) 2025 Alex Newman (@thedotmack). All rights reserved.
|
||||
See the [LICENSE](LICENSE) file for full details.
|
||||
|
||||
**What This Means:**
|
||||
|
||||
- You can use, modify, and distribute this software freely
|
||||
- If you modify and deploy on a network server, you must make your source code available
|
||||
- Derivative works must also be licensed under AGPL-3.0
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "claude-mem",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.1.0",
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"boxen": "^8.0.1",
|
||||
"chalk": "^5.6.0",
|
||||
"commander": "^14.0.0",
|
||||
"glob": "^11.0.3",
|
||||
"gradient-string": "^3.0.0",
|
||||
"handlebars": "^4.7.8",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.1.15", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "peerDependencies": { "zod": "^3.24.1" } }, "sha512-x0UR/YW87lRel3wYVimWjAkUOEGapg/nXx2GYNLbUD1ORsetRHeXZGFdJMuhRkk1Jt9sbn5m/RpT42b5R0pgYg=="],
|
||||
|
||||
"@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
|
||||
|
||||
"@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||
|
||||
"@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
|
||||
|
||||
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
|
||||
|
||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"@types/tinycolor2": ["@types/tinycolor2@1.4.6", "", {}, "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw=="],
|
||||
|
||||
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"better-sqlite3": ["better-sqlite3@11.10.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ=="],
|
||||
|
||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||
|
||||
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
||||
|
||||
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
|
||||
|
||||
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||
|
||||
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
|
||||
|
||||
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
|
||||
"chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
||||
|
||||
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"commander": ["commander@14.0.1", "", {}, "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
||||
|
||||
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
||||
|
||||
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
||||
|
||||
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
|
||||
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
|
||||
|
||||
"github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
|
||||
|
||||
"glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="],
|
||||
|
||||
"gradient-string": ["gradient-string@3.0.0", "", { "dependencies": { "chalk": "^5.3.0", "tinygradient": "^1.1.5" } }, "sha512-frdKI4Qi8Ihp4C6wZNB565de/THpIaw3DjP5ku87M+N9rNSGmPTjfkq61SdRXB7eCaL8O1hkKDvf6CDMtOzIAg=="],
|
||||
|
||||
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="],
|
||||
|
||||
"lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="],
|
||||
|
||||
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
||||
|
||||
"minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||
|
||||
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
||||
|
||||
"napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
|
||||
|
||||
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||
|
||||
"node-abi": ["node-abi@3.78.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
|
||||
|
||||
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
||||
|
||||
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
||||
|
||||
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
||||
|
||||
"simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
|
||||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
|
||||
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
||||
|
||||
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
||||
|
||||
"tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
|
||||
|
||||
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
||||
|
||||
"tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="],
|
||||
|
||||
"tinygradient": ["tinygradient@1.1.5", "", { "dependencies": { "@types/tinycolor2": "^1.4.0", "tinycolor2": "^1.0.0" } }, "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw=="],
|
||||
|
||||
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
||||
|
||||
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
||||
|
||||
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
||||
|
||||
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||
|
||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
|
||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
}
|
||||
}
|
||||
@@ -1,987 +0,0 @@
|
||||
# Claude-Mem Architecture v3 to v4 Plan (✅ Completed)
|
||||
|
||||
This file exists as a reference to explain the path forward from v3 to v4.
|
||||
|
||||
## Core Purpose
|
||||
|
||||
Create a lightweight, hook-driven memory system that captures important context during Claude Code sessions and makes it available in future sessions.
|
||||
|
||||
**Principles:**
|
||||
- Hooks should be fast and non-blocking
|
||||
- SDK agent synthesizes observations, not just stores raw data
|
||||
- Storage should be simple and queryable
|
||||
- Users should never notice the memory system working
|
||||
|
||||
---
|
||||
|
||||
## Understanding the Foundation
|
||||
|
||||
### What Claude Code Hooks Actually Do
|
||||
|
||||
**SessionStart Hook:**
|
||||
- Runs when Claude Code starts or resumes
|
||||
- Can inject context via stdout (plain text) OR JSON `additionalContext`
|
||||
- This is how we show "What's new" to Claude
|
||||
|
||||
**UserPromptSubmit Hook:**
|
||||
- Runs BEFORE Claude processes the user's message
|
||||
- Can inject context via stdout OR JSON `additionalContext`
|
||||
- This is where we initialize per-session tracking
|
||||
|
||||
**PostToolUse Hook:**
|
||||
- Runs AFTER each tool completes successfully
|
||||
- Gets both tool input and output
|
||||
- Runs in PARALLEL with other matching hooks
|
||||
- This is where we observe what Claude is doing
|
||||
|
||||
**Stop Hook:**
|
||||
- Runs when main agent finishes (NOT on user interrupt)
|
||||
- This is where we finalize the session
|
||||
- Summary should be structured responses that answer the following:
|
||||
- What did user request?
|
||||
- What did you investigate?
|
||||
- What did you learn?
|
||||
- What did you do?
|
||||
- What's next?
|
||||
- Files read
|
||||
- Files edited
|
||||
- Notes
|
||||
|
||||
### How SDK Streaming Actually Works
|
||||
|
||||
**Streaming Input Mode (what we need):**
|
||||
- Persistent session with AsyncGenerator
|
||||
- Can queue multiple messages
|
||||
- Supports interruption via `interrupt()` method
|
||||
- Natural multi-turn conversations
|
||||
- The SDK maintains conversation state
|
||||
|
||||
**Critical insight:** We use "Streaming Input Mode" which creates ONE long-running SDK session per Claude Code session, not multiple short sessions.
|
||||
|
||||
**Session ID Management:**
|
||||
- Session IDs change with each turn of the conversation
|
||||
- Must capture session ID from the initial system message
|
||||
- SDK worker needs to track session ID updates continuously, not just capture once
|
||||
- The first message in the response stream is a system init message with the session_id
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Visual Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CLAUDE CODE SESSION │
|
||||
│ (Main session - user interacting with Claude Code) │
|
||||
│ │
|
||||
│ User → Claude → Tools (Read, Edit, Write, Bash, etc.) │
|
||||
│ │ │
|
||||
│ │ PostToolUse Hook │
|
||||
│ ↓ │
|
||||
│ claude-mem save │
|
||||
│ (queues observation) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ SQLite observation_queue
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ SDK WORKER PROCESS │
|
||||
│ (Background process - detached from main session) │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ Message Generator (AsyncIterable) │ │
|
||||
│ │ - Yields initial prompt │ │
|
||||
│ │ - Polls observation_queue │ │
|
||||
│ │ - Yields observation prompts │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ SDK query() → Claude API │ │
|
||||
│ │ Model: claude-sonnet-4-5 │ │
|
||||
│ │ No tools needed (text-only synthesis) │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ Response Handler │ │
|
||||
│ │ - Parses XML <observation> blocks │ │
|
||||
│ │ - Parses XML <summary> blocks │ │
|
||||
│ │ - Writes to SQLite tables │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ SQLite: observations, session_summaries
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ NEXT CLAUDE CODE SESSION │
|
||||
│ │
|
||||
│ SessionStart Hook → claude-mem context │
|
||||
│ (Reads from SQLite and injects context) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### What is the SDK agent's job?
|
||||
|
||||
The SDK agent is a **synthesis engine**, not a data collector.
|
||||
|
||||
It should:
|
||||
- Receive tool observations as they happen
|
||||
- Extract meaningful patterns and insights
|
||||
- Store atomic, searchable observations in SQLite
|
||||
- Synthesize a human-readable summary at the end
|
||||
|
||||
It should NOT:
|
||||
- Store raw tool outputs
|
||||
- Try to capture everything
|
||||
- Make decisions about what Claude Code should do
|
||||
- Block or slow down the main session
|
||||
|
||||
### Session Management Strategy
|
||||
|
||||
**Built-in SDK Session Resumption:**
|
||||
|
||||
The Agent SDK provides native session resumption capabilities. Instead of manually tracking and rebuilding session state, we can leverage the SDK's built-in features:
|
||||
|
||||
```typescript
|
||||
// Resume a previous SDK session
|
||||
const resumedResponse = query({
|
||||
prompt: "Continue where we left off",
|
||||
options: {
|
||||
resume: sdkSessionId // Use the session ID captured from init message
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**When to use session resumption:**
|
||||
- User interrupts Claude Code and resumes later
|
||||
- SDK worker crashes and needs to restart
|
||||
- Long-running observations that span multiple Claude Code sessions
|
||||
|
||||
**Session state tracking:**
|
||||
- Store SDK session ID in database when captured from init message
|
||||
- Mark sessions as 'active', 'completed', 'interrupted', or 'failed'
|
||||
- Use session status to determine whether to resume or start fresh
|
||||
|
||||
### How hooks run in parallel
|
||||
|
||||
PostToolUse hooks run in parallel. Handle this by:
|
||||
- Make SDK agent calls async and fire-and-forget
|
||||
- Use the observation_queue SQLite table to serialize observations
|
||||
- SDK worker polls this queue and processes observations sequentially
|
||||
|
||||
### What if the user interrupts Claude Code?
|
||||
|
||||
Stop hook doesn't run on interrupts. So:
|
||||
- Observations stay in queue
|
||||
- Next session continues where left off
|
||||
- Mark session as 'interrupted' after 24h of inactivity
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
```sql
|
||||
-- Tracks SDK streaming sessions
|
||||
CREATE TABLE sdk_sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
claude_session_id TEXT UNIQUE NOT NULL,
|
||||
sdk_session_id TEXT UNIQUE NOT NULL,
|
||||
project TEXT NOT NULL,
|
||||
user_prompt TEXT,
|
||||
started_at TEXT NOT NULL,
|
||||
started_at_epoch INTEGER NOT NULL,
|
||||
completed_at TEXT,
|
||||
completed_at_epoch INTEGER,
|
||||
status TEXT CHECK(status IN ('active', 'completed', 'failed'))
|
||||
);
|
||||
|
||||
-- Tracks pending observations (message queue)
|
||||
CREATE TABLE observation_queue (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
tool_name TEXT NOT NULL,
|
||||
tool_input TEXT NOT NULL, -- JSON
|
||||
tool_output TEXT NOT NULL, -- JSON
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
processed_at_epoch INTEGER,
|
||||
FOREIGN KEY(sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
|
||||
-- Stores extracted observations (what SDK decides is important)
|
||||
CREATE TABLE observations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
project TEXT NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
type TEXT NOT NULL, -- 'decision' | 'bugfix' | 'feature' | 'refactor' | 'discovery'
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
FOREIGN KEY(sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_observations_project ON observations(project);
|
||||
CREATE INDEX idx_observations_created ON observations(created_at_epoch DESC);
|
||||
|
||||
-- Stores session summaries
|
||||
CREATE TABLE session_summaries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT UNIQUE NOT NULL,
|
||||
project TEXT NOT NULL,
|
||||
summary TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
FOREIGN KEY(sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_summaries_project ON session_summaries(project);
|
||||
CREATE INDEX idx_summaries_created ON session_summaries(created_at_epoch DESC);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hook Implementation
|
||||
|
||||
**IMPORTANT DISTINCTION:**
|
||||
|
||||
There are TWO separate hook systems at play here:
|
||||
|
||||
1. **Claude Code Hooks** - External command hooks configured in `~/.config/claude-code/settings.json`
|
||||
- These hooks observe the MAIN Claude Code session
|
||||
- They run as external commands (like `claude-mem save`)
|
||||
- This is what we use to capture observations from the user's session
|
||||
|
||||
2. **SDK Hooks** - Programmatic hooks configured in TypeScript code via `HookMatcher`
|
||||
- These hooks would observe the MEMORY SDK agent's own tool usage
|
||||
- They run as TypeScript callbacks within the SDK worker process
|
||||
- We're NOT using these (yet) - they're a future enhancement
|
||||
|
||||
**Our architecture:** Use Claude Code hooks (external commands) to observe the main session, and run a separate SDK worker process that doesn't need its own hooks.
|
||||
|
||||
### 1. SessionStart Hook
|
||||
|
||||
**Purpose:** Show user what happened in recent sessions
|
||||
|
||||
**Claude Code Hook Config (in settings.json):**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"matcher": "startup",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "claude-mem context"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Command: `claude-mem context`**
|
||||
|
||||
Flow:
|
||||
1. Read stdin JSON (session_id, cwd, source, etc.)
|
||||
2. If source !== "startup", exit immediately
|
||||
3. Extract project from cwd basename
|
||||
4. Query SQLite for recent summaries:
|
||||
```sql
|
||||
SELECT summary, created_at
|
||||
FROM session_summaries
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT 10
|
||||
```
|
||||
5. Format results as human-readable text
|
||||
6. Output to stdout (Claude Code automatically injects this)
|
||||
7. Exit with code 0
|
||||
|
||||
### 2. UserPromptSubmit Hook
|
||||
|
||||
**Purpose:** Initialize SDK memory session in background
|
||||
|
||||
**Hook config:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "claude-mem new"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Command: `claude-mem new`**
|
||||
|
||||
Flow:
|
||||
1. Read stdin JSON (session_id, prompt, cwd, etc.)
|
||||
2. Extract project from cwd
|
||||
3. Create SDK session record in database
|
||||
4. Start SDK session with initialization prompt in background process
|
||||
5. Save SDK session ID to database
|
||||
6. Output: `{"continue": true, "suppressOutput": true}`
|
||||
7. Exit immediately (SDK runs in background daemon/process)
|
||||
|
||||
**The Background SDK Process:**
|
||||
|
||||
The SDK session should run as a detached background process:
|
||||
```typescript
|
||||
// In claude-mem new
|
||||
const child = spawn('claude-mem', ['sdk-worker', session_id], {
|
||||
detached: true,
|
||||
stdio: 'ignore'
|
||||
});
|
||||
child.unref();
|
||||
```
|
||||
|
||||
The SDK worker:
|
||||
```typescript
|
||||
// claude-mem sdk-worker <session_id>
|
||||
import { query } from '@anthropic-ai/agent-sdk';
|
||||
import type { Query, UserMessage } from '@anthropic-ai/agent-sdk';
|
||||
|
||||
async function runSDKWorker(sessionId: string) {
|
||||
const session = await loadSessionFromDB(sessionId);
|
||||
|
||||
// Track the SDK session ID from the init message
|
||||
let sdkSessionId: string | undefined;
|
||||
const abortController = new AbortController();
|
||||
|
||||
// Message generator yields UserMessage objects (role + content)
|
||||
// This matches the SDK's expected format for streaming input mode
|
||||
async function* messageGenerator(): AsyncIterable<UserMessage> {
|
||||
// Initial prompt
|
||||
yield {
|
||||
role: "user",
|
||||
content: buildInitPrompt(session)
|
||||
};
|
||||
|
||||
// Then listen for queued observations
|
||||
while (session.status === 'active' && !abortController.signal.aborted) {
|
||||
const observations = await pollObservationQueue(session.sdk_session_id);
|
||||
|
||||
for (const obs of observations) {
|
||||
yield {
|
||||
role: "user",
|
||||
content: buildObservationPrompt(obs)
|
||||
};
|
||||
markObservationProcessed(obs.id);
|
||||
}
|
||||
|
||||
await sleep(1000); // Poll every second
|
||||
}
|
||||
}
|
||||
|
||||
// Run SDK session with proper streaming interface
|
||||
// The query function signature: query({ prompt, options }): Query
|
||||
const response: Query = query({
|
||||
prompt: messageGenerator(), // AsyncIterable<UserMessage>
|
||||
options: {
|
||||
model: 'claude-sonnet-4-5', // Use documented model name
|
||||
disallowedTools: ['Glob', 'Grep', 'ListMcpResourcesTool', 'WebSearch'], // More efficient than filtering in hooks
|
||||
maxTurns: 1000,
|
||||
cwd: session.cwd,
|
||||
abortController: abortController
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// Consume responses from the Query AsyncGenerator
|
||||
for await (const msg of response) {
|
||||
// Capture session ID from system init message
|
||||
if (msg.type === 'system' && msg.subtype === 'init') {
|
||||
sdkSessionId = msg.session_id;
|
||||
console.log(`SDK session started with ID: ${sdkSessionId}`);
|
||||
// Store SDK session ID in database for potential resumption
|
||||
await updateSDKSessionId(session.id, sdkSessionId);
|
||||
}
|
||||
|
||||
if (msg.type === 'text') {
|
||||
// Use an XML parser library (e.g., fast-xml-parser or similar) to parse observations and summaries
|
||||
// Parse <observation> blocks and call storeObservation(session_id, project, type, text)
|
||||
// Parse <summary> blocks, extract all 8 fields, format and call storeSummary(session_id, project, text)
|
||||
|
||||
parseAndStoreObservations(msg.content, session);
|
||||
parseAndStoreSummary(msg.content, session);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (abortController.signal.aborted) {
|
||||
console.log('SDK worker interrupted gracefully');
|
||||
} else {
|
||||
console.error('SDK worker error:', error);
|
||||
await markSessionFailed(session.id, error);
|
||||
}
|
||||
} finally {
|
||||
await cleanupSession(session.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Query and UserMessage types are imported from '@anthropic-ai/agent-sdk'
|
||||
// Query extends AsyncGenerator and provides interrupt() and setPermissionMode() methods
|
||||
// UserMessage has the shape: { role: "user", content: string }
|
||||
```
|
||||
|
||||
### 3. PostToolUse Hook
|
||||
|
||||
**Purpose:** Queue tool observations for SDK processing
|
||||
|
||||
**Hook config:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "claude-mem save"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Command: `claude-mem save`**
|
||||
|
||||
Flow:
|
||||
1. Read stdin JSON (tool_name, tool_input, tool_output, etc.)
|
||||
2. Find active SDK session for this project
|
||||
3. Insert observation into queue:
|
||||
```sql
|
||||
INSERT INTO observation_queue
|
||||
(sdk_session_id, tool_name, tool_input, tool_output, created_at_epoch)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
```
|
||||
4. Output: `{"continue": true, "suppressOutput": true}`
|
||||
5. Exit immediately
|
||||
|
||||
**Observation Filtering:**
|
||||
|
||||
Tool filtering is now handled at the SDK level (see SDK Worker section) using `disallowedTools` option. The hook no longer needs to filter tools manually - all tool observations that reach the hook are already relevant.
|
||||
|
||||
However, you may still want to skip certain tools for performance reasons:
|
||||
```typescript
|
||||
// Optional: Skip very frequent or low-value tools
|
||||
const SKIP_TOOLS = new Set(['TodoWrite', 'ListMcpResourcesTool']);
|
||||
|
||||
if (SKIP_TOOLS.has(tool_name)) {
|
||||
console.log('{"continue": true, "suppressOutput": true}');
|
||||
process.exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** The SDK worker uses `disallowedTools: ['Glob', 'Grep', 'ListMcpResourcesTool', 'WebSearch']` which is more efficient than hook-level filtering because it prevents the SDK agent from using these tools entirely.
|
||||
|
||||
### 4. Stop Hook
|
||||
|
||||
**Purpose:** Signal SDK to finalize and generate summary
|
||||
|
||||
**Hook config:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "claude-mem summary"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Command: `claude-mem summary`**
|
||||
|
||||
Flow:
|
||||
1. Read stdin JSON (session_id, cwd, etc.)
|
||||
2. Find active SDK session
|
||||
3. Insert special "FINALIZE" message into observation queue:
|
||||
```sql
|
||||
INSERT INTO observation_queue
|
||||
(sdk_session_id, tool_name, tool_input, tool_output, created_at_epoch)
|
||||
VALUES (?, 'FINALIZE', '{}', '{}', ?)
|
||||
```
|
||||
4. Output: `{"continue": true, "suppressOutput": true}`
|
||||
5. Exit immediately
|
||||
|
||||
**SDK Worker Handling:**
|
||||
|
||||
When SDK worker sees FINALIZE message:
|
||||
```typescript
|
||||
if (obs.tool_name === 'FINALIZE') {
|
||||
yield {
|
||||
type: "user",
|
||||
message: {
|
||||
role: "user",
|
||||
content: buildFinalizePrompt(session)
|
||||
}
|
||||
};
|
||||
|
||||
// Wait for SDK to finish processing
|
||||
await waitForSDKCompletion();
|
||||
|
||||
// Update session status
|
||||
await markSessionCompleted(session.id);
|
||||
|
||||
// Exit worker
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SDK Agent Prompts
|
||||
|
||||
### Initialization Prompt
|
||||
|
||||
```typescript
|
||||
function buildInitPrompt(project: string, sessionId: string, userPrompt: string): string {
|
||||
return `You are a memory assistant for the "${project}" project.
|
||||
|
||||
SESSION CONTEXT
|
||||
---------------
|
||||
Session ID: ${sessionId}
|
||||
User's Goal: ${userPrompt}
|
||||
Date: ${new Date().toISOString().split('T')[0]}
|
||||
|
||||
YOUR ROLE
|
||||
---------
|
||||
You will observe tool executions during this Claude Code session. Your job is to:
|
||||
|
||||
1. Extract meaningful insights (not just raw data)
|
||||
2. Store atomic observations in SQLite
|
||||
3. Focus on: key decisions, patterns discovered, problems solved, technical insights
|
||||
|
||||
WHAT TO CAPTURE
|
||||
----------------
|
||||
✓ Architecture decisions (e.g., "chose PostgreSQL over MongoDB for ACID guarantees")
|
||||
✓ Bug fixes (e.g., "fixed race condition in auth middleware by adding mutex")
|
||||
✓ New features (e.g., "implemented JWT refresh token flow")
|
||||
✓ Refactorings (e.g., "extracted validation logic into separate service")
|
||||
✓ Discoveries (e.g., "found that API rate limit is 100 req/min")
|
||||
|
||||
✗ NOT routine operations (reading files, listing directories)
|
||||
✗ NOT work-in-progress (only completed work)
|
||||
✗ NOT obvious facts (e.g., "TypeScript file has types")
|
||||
|
||||
HOW TO STORE OBSERVATIONS
|
||||
--------------------------
|
||||
When you identify something worth remembering, output your observation in this EXACT XML format:
|
||||
|
||||
\`\`\`xml
|
||||
<observation>
|
||||
<type>feature</type>
|
||||
<text>Implemented JWT token refresh flow with 7-day expiry</text>
|
||||
</observation>
|
||||
\`\`\`
|
||||
|
||||
Valid types: decision, bugfix, feature, refactor, discovery
|
||||
|
||||
Structure requirements:
|
||||
- <observation> is the root element
|
||||
- <type> must be one of the 5 valid types (single word)
|
||||
- <text> contains your concise observation (one sentence preferred)
|
||||
- No additional fields or nesting
|
||||
|
||||
The SDK worker will parse all <observation> blocks from your response using regex and store them in SQLite.
|
||||
|
||||
You can include your reasoning before or after the observation block, or just output the observation by itself.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
Bad: "Read src/auth.ts file"
|
||||
Good: "Implemented JWT token refresh flow with 7-day expiry"
|
||||
|
||||
Wait for tool observations. Acknowledge this message briefly.`;
|
||||
}
|
||||
```
|
||||
|
||||
### Observation Prompt
|
||||
|
||||
```typescript
|
||||
function buildObservationPrompt(obs: Observation): string {
|
||||
return `TOOL OBSERVATION
|
||||
================
|
||||
Tool: ${obs.tool_name}
|
||||
Time: ${new Date(obs.created_at_epoch).toISOString()}
|
||||
|
||||
Input:
|
||||
${JSON.stringify(JSON.parse(obs.tool_input), null, 2)}
|
||||
|
||||
Output:
|
||||
${JSON.stringify(JSON.parse(obs.tool_output), null, 2)}
|
||||
|
||||
ANALYSIS TASK
|
||||
-------------
|
||||
1. Does this observation contain something worth remembering?
|
||||
2. If YES: Output the observation in this EXACT XML format:
|
||||
|
||||
\`\`\`xml
|
||||
<observation>
|
||||
<type>feature</type>
|
||||
<text>Your concise observation here</text>
|
||||
</observation>
|
||||
\`\`\`
|
||||
|
||||
Requirements:
|
||||
- Use one of these types: decision, bugfix, feature, refactor, discovery
|
||||
- Keep text concise (one sentence preferred)
|
||||
- No markdown formatting inside <text>
|
||||
- No additional XML fields
|
||||
|
||||
3. If NO: Just acknowledge and wait for next observation
|
||||
|
||||
Remember: Quality over quantity. Only store meaningful insights.`;
|
||||
}
|
||||
```
|
||||
|
||||
### Finalization Prompt
|
||||
|
||||
```typescript
|
||||
function buildFinalizePrompt(session: SDKSession): string {
|
||||
return `SESSION ENDING
|
||||
==============
|
||||
The Claude Code session is finishing.
|
||||
|
||||
FINAL TASK
|
||||
----------
|
||||
1. Review the observations you've stored this session
|
||||
2. Generate a structured summary that answers these questions:
|
||||
- What did user request?
|
||||
- What did you investigate?
|
||||
- What did you learn?
|
||||
- What did you do?
|
||||
- What's next?
|
||||
- Files read
|
||||
- Files edited
|
||||
- Notes
|
||||
|
||||
3. Generate the structured summary and output it in this EXACT XML format:
|
||||
|
||||
\`\`\`xml
|
||||
<summary>
|
||||
<request>Implement JWT authentication system</request>
|
||||
<investigated>Existing auth middleware, session management, token storage patterns</investigated>
|
||||
<learned>Current system uses session cookies; no JWT support; race condition in middleware</learned>
|
||||
<completed>Implemented JWT token + refresh flow with 7-day expiry; fixed race condition with mutex; added token validation middleware</completed>
|
||||
<next_steps>Add token revocation API endpoint; write integration tests</next_steps>
|
||||
<files_read>
|
||||
<file>src/auth.ts</file>
|
||||
<file>src/middleware/session.ts</file>
|
||||
<file>src/types/user.ts</file>
|
||||
</files_read>
|
||||
<files_edited>
|
||||
<file>src/auth.ts</file>
|
||||
<file>src/middleware/auth.ts</file>
|
||||
<file>src/routes/auth.ts</file>
|
||||
</files_edited>
|
||||
<notes>Token secret stored in .env; refresh tokens use rotation strategy</notes>
|
||||
</summary>
|
||||
\`\`\`
|
||||
|
||||
Structure requirements:
|
||||
- <summary> is the root element
|
||||
- All 8 child elements are REQUIRED: request, investigated, learned, completed, next_steps, files_read, files_edited, notes
|
||||
- <files_read> and <files_edited> must contain <file> child elements (one per file)
|
||||
- If no files were read/edited, use empty tags: <files_read></files_read>
|
||||
- Text fields can be multiple sentences but avoid markdown formatting
|
||||
- Use underscores in element names: next_steps, files_read, files_edited
|
||||
|
||||
The SDK worker will parse the <summary> block and extract all fields to store in SQLite.
|
||||
|
||||
Generate the summary now in the required XML format.`;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hook Commands Architecture
|
||||
|
||||
All four hook commands (`claude-mem context`, `claude-mem new`, `claude-mem save`, `claude-mem summary`) are implemented as standalone TypeScript functions that:
|
||||
|
||||
1. **Use bun:sqlite directly** - No spawning child processes or CLI subcommands
|
||||
2. **Are self-contained** - Each hook has all the logic it needs
|
||||
3. **Share a common database layer** - Import from shared `db.ts` module
|
||||
4. **Never call other claude-mem commands** - All functionality via direct library calls
|
||||
|
||||
```typescript
|
||||
// Example structure
|
||||
import { Database } from 'bun:sqlite';
|
||||
|
||||
export function contextHook(stdin: HookInput) {
|
||||
const db = new Database('~/.claude-mem/db.sqlite');
|
||||
// Query and return context directly
|
||||
const summaries = db.query('SELECT ...').all();
|
||||
console.log(formatContext(summaries));
|
||||
db.close();
|
||||
}
|
||||
|
||||
export function saveHook(stdin: HookInput) {
|
||||
const db = new Database('~/.claude-mem/db.sqlite');
|
||||
// Insert observation directly
|
||||
db.run('INSERT INTO observation_queue ...', params);
|
||||
db.close();
|
||||
console.log('{"continue": true, "suppressOutput": true}');
|
||||
}
|
||||
```
|
||||
|
||||
**Key principle:** Hooks are fast, synchronous database operations. The SDK worker process is where async/complex logic happens.
|
||||
|
||||
---
|
||||
|
||||
## Background Process Management
|
||||
|
||||
The `claude-mem save` hook just queues observations - processing happens in the background SDK worker process that polls the queue continuously.
|
||||
|
||||
The SDK worker is spawned by `claude-mem new` as a detached process and runs for the duration of the Claude Code session.
|
||||
|
||||
Benefits:
|
||||
- Works on all platforms (no systemd/launchd needed)
|
||||
- Self-contained (spawned and managed by claude-mem itself)
|
||||
- Simple state management (all state in SQLite)
|
||||
|
||||
---
|
||||
|
||||
## Advanced SDK Features
|
||||
|
||||
### Permission Integration (Future Enhancement)
|
||||
|
||||
The SDK provides a permission system that could be integrated with memory for context-aware decisions:
|
||||
|
||||
```typescript
|
||||
canUseTool: async (toolName, input) => {
|
||||
// Check memory for previous decisions about this tool/context
|
||||
const previousDecisions = await queryMemoryForTool(toolName, input);
|
||||
|
||||
if (previousDecisions.shouldAllow) {
|
||||
return {
|
||||
behavior: "allow",
|
||||
updatedInput: input
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
behavior: "ask_user",
|
||||
message: `This tool was previously flagged. Allow anyway?`
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This could enable:
|
||||
- Learning from previous tool use patterns
|
||||
- Automatically allowing/denying based on historical context
|
||||
- Providing smart defaults based on project-specific patterns
|
||||
|
||||
**Implementation priority:** Low (add after core functionality is stable)
|
||||
|
||||
### SDK Hook Configuration (Alternative to Claude Code Hooks)
|
||||
|
||||
Instead of using external command hooks via Claude Code settings.json, the SDK supports native hook configuration:
|
||||
|
||||
```typescript
|
||||
import { HookMatcher } from '@anthropic-ai/agent-sdk';
|
||||
|
||||
const response = query({
|
||||
prompt: messageGenerator(),
|
||||
options: {
|
||||
hooks: {
|
||||
'PreToolUse': [
|
||||
HookMatcher(matcher='Bash', hooks=[validateBashCommand]),
|
||||
HookMatcher(hooks=[logToolUse]) // Applies to all tools
|
||||
],
|
||||
'PostToolUse': [
|
||||
HookMatcher(hooks=[captureObservation])
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
type HookCallback = (
|
||||
input: HookInput,
|
||||
toolUseID: string | undefined,
|
||||
options: { signal: AbortSignal }
|
||||
) => Promise<HookJSONOutput>;
|
||||
```
|
||||
|
||||
**When to use SDK hooks vs Claude Code hooks:**
|
||||
- **Claude Code hooks**: For integrating with the main Claude Code session (our current approach)
|
||||
- **SDK hooks**: For controlling the memory agent's own tool usage (future enhancement)
|
||||
|
||||
**Implementation priority:** Medium (could simplify architecture, but adds complexity to migration)
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
**SDK worker failures:**
|
||||
- Each observation processing is atomic
|
||||
- Failed observations stay in queue
|
||||
- Next worker run retries
|
||||
- After 3 failures, mark observation as skipped
|
||||
- Use AbortController for graceful cancellation
|
||||
|
||||
**Abort signal handling:**
|
||||
```typescript
|
||||
try {
|
||||
for await (const msg of response) {
|
||||
if (abortController.signal.aborted) {
|
||||
throw new Error('Aborted');
|
||||
}
|
||||
// Process message
|
||||
}
|
||||
} catch (error) {
|
||||
if (abortController.signal.aborted) {
|
||||
// Clean shutdown
|
||||
await response.interrupt();
|
||||
} else {
|
||||
// Actual error
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Database corruption:**
|
||||
- SQLite with WAL mode (write-ahead logging)
|
||||
- Regular backups to ~/.claude-mem/backups/
|
||||
- Automatic recovery from backups
|
||||
|
||||
**SDK API failures:**
|
||||
- Retry with exponential backoff
|
||||
- Don't block main Claude Code session
|
||||
- Log errors for debugging
|
||||
- Mark session as 'failed' after max retries
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. **Database setup** - Create tables and migration scripts
|
||||
2. **Hook commands** - Implement the 4 hook commands (context, new, save, summary)
|
||||
3. **SDK worker** - Implement the background worker process with response parsing
|
||||
4. **SDK prompts** - Wire up the prompts and message generator
|
||||
5. **Test end-to-end** - Run a real Claude Code session and verify it works
|
||||
|
||||
Start simple. Get one hook working before moving to the next. Don't try to build everything at once.
|
||||
|
||||
**Note:** MCP is only used for retrieval (when Claude Code needs to access stored memories), not for storage. The SDK agent stores data by outputting specially formatted text that the SDK worker parses and writes to SQLite.
|
||||
|
||||
### SDK Import Verification
|
||||
|
||||
Before implementing, verify the SDK exports match your usage:
|
||||
|
||||
```typescript
|
||||
// Required imports from @anthropic-ai/agent-sdk
|
||||
import { query } from '@anthropic-ai/agent-sdk';
|
||||
import type { Query, UserMessage, Options } from '@anthropic-ai/agent-sdk';
|
||||
|
||||
// Verify the query function signature:
|
||||
// function query(options: { prompt: string | AsyncIterable<UserMessage>; options?: Options }): Query
|
||||
|
||||
// Verify Query type:
|
||||
// interface Query extends AsyncGenerator<SDKMessage, void> {
|
||||
// interrupt(): Promise<void>;
|
||||
// setPermissionMode(mode: PermissionMode): Promise<void>;
|
||||
// }
|
||||
|
||||
// Verify UserMessage type:
|
||||
// type UserMessage = { role: "user"; content: string }
|
||||
```
|
||||
|
||||
If the SDK exports differ from this structure, adjust the implementation accordingly. The SDK documentation should be the source of truth.
|
||||
|
||||
---
|
||||
|
||||
## Key Corrections from Agent SDK Documentation
|
||||
|
||||
This refactor plan has been updated to align with the official Agent SDK documentation. Key corrections include:
|
||||
|
||||
### 1. Session ID Management
|
||||
- **Before:** Captured session ID once in UserPromptSubmit hook
|
||||
- **After:** Capture from system init message and track updates continuously
|
||||
- **Why:** Session IDs change with each conversation turn
|
||||
|
||||
### 2. Hook Configuration
|
||||
- **Before:** Mixed up SDK hook format with Claude Code hook format
|
||||
- **After:** Clarified that Claude Code uses settings.json format (external commands); SDK uses TypeScript HookMatcher (programmatic callbacks)
|
||||
- **Why:** Two separate hook systems with different purposes and configuration methods
|
||||
- **Our approach:** Use Claude Code hooks to observe the main session; SDK hooks are future enhancement
|
||||
|
||||
### 3. Message Generator and Query Interface
|
||||
- **Before:** Custom SDKMessage type with nested message structure
|
||||
- **After:** Simple UserMessage type `{ role: "user", content: string }` yielded from AsyncIterable
|
||||
- **Why:** SDK expects AsyncIterable<UserMessage>, not a custom wrapper format
|
||||
- **Query type:** Properly typed as `Query` which extends AsyncGenerator with interrupt() and setPermissionMode()
|
||||
|
||||
### 4. Tool Filtering
|
||||
- **Before:** Filter "boring tools" in PostToolUse hook
|
||||
- **After:** Use SDK's `disallowedTools` option in query configuration
|
||||
- **Why:** More efficient to prevent SDK from using tools entirely
|
||||
|
||||
### 5. Model Identifier
|
||||
- **Before:** Used `claude-haiku-4-5-20251001` (undocumented)
|
||||
- **After:** Use `claude-sonnet-4-5` (documented model name)
|
||||
- **Why:** Stick to documented model identifiers for stability
|
||||
|
||||
### 6. Error Handling
|
||||
- **Before:** Custom error handling without SDK features
|
||||
- **After:** Use AbortController and response.interrupt() for graceful cancellation
|
||||
- **Why:** SDK provides built-in cancellation mechanisms
|
||||
|
||||
### 7. Session Resumption
|
||||
- **Before:** Manual session state reconstruction
|
||||
- **After:** Leverage SDK's built-in `resume: sessionId` option
|
||||
- **Why:** SDK already handles session resumption
|
||||
|
||||
### Future Enhancements to Consider
|
||||
|
||||
1. **Permission integration** - Use canUseTool callback to make memory-aware decisions
|
||||
2. **SDK native hooks** - Replace external command hooks with SDK HookMatcher
|
||||
3. **Better session recovery** - Use SDK resumption for interrupted sessions
|
||||
|
||||
These corrections ensure our implementation follows Agent SDK best practices and avoids reinventing functionality the SDK already provides.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Validation Summary
|
||||
|
||||
This plan has been validated against the official Agent SDK documentation and confirmed to be architecturally sound.
|
||||
|
||||
### ✅ Validated Design Decisions
|
||||
|
||||
1. **Hook System Usage** - Correctly uses Claude Code external command hooks for observation; SDK programmatic hooks reserved for future enhancement
|
||||
2. **Query Function Interface** - Properly implements AsyncIterable<UserMessage> for streaming input mode
|
||||
3. **Session Management** - Leverages SDK's built-in session resumption instead of manual state reconstruction
|
||||
4. **Tool Filtering** - Uses SDK's `disallowedTools` option for efficiency
|
||||
5. **Error Handling** - Implements AbortController and interrupt() for graceful cancellation
|
||||
6. **Separation of Concerns** - Clean isolation between main Claude Code session and background SDK worker
|
||||
|
||||
### 🎯 Architecture Strengths
|
||||
|
||||
- **Non-blocking** - Hooks are fast database operations; complex logic happens in background
|
||||
- **Queue-based** - Handles parallel hook execution correctly via observation_queue table
|
||||
- **Fault-tolerant** - Failed observations stay in queue for retry; graceful degradation
|
||||
- **Platform-agnostic** - No dependency on systemd/launchd; works everywhere
|
||||
- **Type-safe** - Uses official SDK TypeScript types throughout
|
||||
|
||||
### 📋 Pre-Implementation Checklist
|
||||
|
||||
Before starting implementation, verify:
|
||||
|
||||
1. [ ] Agent SDK installed and accessible: `@anthropic-ai/agent-sdk`
|
||||
2. [ ] Verify SDK exports match expected structure (query, Query, UserMessage types)
|
||||
3. [ ] SQLite database location decided: `~/.claude-mem/db.sqlite`
|
||||
4. [ ] Claude Code settings.json hook configuration tested
|
||||
5. [ ] Background process spawning works on target platform (test detached process)
|
||||
|
||||
### 🚀 Ready for Implementation
|
||||
|
||||
The architecture is validated and ready for implementation. Follow the phased approach:
|
||||
|
||||
1. Database setup first (get schema working with bun:sqlite)
|
||||
2. Implement hooks one at a time (start with `context`, then `save`)
|
||||
3. Build SDK worker with simple message generator
|
||||
4. Test end-to-end with a real Claude Code session
|
||||
5. Iterate and refine based on real-world usage
|
||||
|
||||
**Remember:** Start simple, get one piece working, then build on it. Don't try to implement everything at once.
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
|
||||
# Claude Code Hooks Exit Code Cheat Sheet
|
||||
|
||||
## Exit Code Behavior [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
- **Exit code 0**: Success. `stdout` is shown to the user in transcript mode, except for `UserPromptSubmit` hook where stdout is injected as context [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
- **Exit code 2**: Blocking error. `stderr` is fed back to Claude to process automatically [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
- **Other exit codes**: Non-blocking error. `stderr` is shown to the user and execution continues [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
## Per-Hook Event Behavior [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
| Hook Event | Exit Code 2 Behavior |
|
||||
|------------|---------------------|
|
||||
| `PreToolUse` | Blocks the tool call, shows stderr to Claude [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `PostToolUse` | Shows stderr to Claude (tool already ran) [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `Notification` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `UserPromptSubmit` | Blocks prompt processing, erases prompt, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `Stop` | Blocks stoppage, shows stderr to Claude [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SubagentStop` | Blocks stoppage, shows stderr to Claude subagent [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `PreCompact` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SessionStart` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SessionEnd` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
|
||||
## Quick Reference
|
||||
|
||||
- **Success**: `process.exit(0)` - Operation completed successfully
|
||||
- **Block & feedback**: `process.exit(2)` - Block operation and give Claude feedback via stderr
|
||||
- **Non-blocking error**: `process.exit(1)` - Show error to user but continue execution
|
||||
|
||||
**Important**: Claude Code does not see stdout if the exit code is 0, except for the `UserPromptSubmit` hook where stdout is injected as context [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
@@ -1,837 +0,0 @@
|
||||
# Hooks reference
|
||||
|
||||
> This page provides reference documentation for implementing hooks in Claude Code.
|
||||
|
||||
<Tip>
|
||||
For a quickstart guide with examples, see [Get started with Claude Code hooks](/en/docs/claude-code/hooks-guide).
|
||||
</Tip>
|
||||
|
||||
## Configuration
|
||||
|
||||
Claude Code hooks are configured in your [settings files](/en/docs/claude-code/settings):
|
||||
|
||||
* `~/.claude/settings.json` - User settings
|
||||
* `.claude/settings.json` - Project settings
|
||||
* `.claude/settings.local.json` - Local project settings (not committed)
|
||||
* Enterprise managed policy settings
|
||||
|
||||
### Structure
|
||||
|
||||
Hooks are organized by matchers, where each matcher can have multiple hooks:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"EventName": [
|
||||
{
|
||||
"matcher": "ToolPattern",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "your-command-here"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **matcher**: Pattern to match tool names, case-sensitive (only applicable for
|
||||
`PreToolUse` and `PostToolUse`)
|
||||
* Simple strings match exactly: `Write` matches only the Write tool
|
||||
* Supports regex: `Edit|Write` or `Notebook.*`
|
||||
* Use `*` to match all tools. You can also use empty string (`""`) or leave
|
||||
`matcher` blank.
|
||||
* **hooks**: Array of commands to execute when the pattern matches
|
||||
* `type`: Currently only `"command"` is supported
|
||||
* `command`: The bash command to execute (can use `$CLAUDE_PROJECT_DIR`
|
||||
environment variable)
|
||||
* `timeout`: (Optional) How long a command should run, in seconds, before
|
||||
canceling that specific command.
|
||||
|
||||
For events like `UserPromptSubmit`, `Notification`, `Stop`, and `SubagentStop`
|
||||
that don't use matchers, you can omit the matcher field:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/path/to/prompt-validator.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Project-Specific Hook Scripts
|
||||
|
||||
You can use the environment variable `CLAUDE_PROJECT_DIR` (only available when
|
||||
Claude Code spawns the hook command) to reference scripts stored in your project,
|
||||
ensuring they work regardless of Claude's current directory:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin hooks
|
||||
|
||||
[Plugins](/en/docs/claude-code/plugins) can provide hooks that integrate seamlessly with your user and project hooks. Plugin hooks are automatically merged with your configuration when plugins are enabled.
|
||||
|
||||
**How plugin hooks work**:
|
||||
|
||||
* Plugin hooks are defined in the plugin's `hooks/hooks.json` file or in a file given by a custom path to the `hooks` field.
|
||||
* When a plugin is enabled, its hooks are merged with user and project hooks
|
||||
* Multiple hooks from different sources can respond to the same event
|
||||
* Plugin hooks use the `${CLAUDE_PLUGIN_ROOT}` environment variable to reference plugin files
|
||||
|
||||
**Example plugin hook configuration**:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"description": "Automatic code formatting",
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Plugin hooks use the same format as regular hooks with an optional `description` field to explain the hook's purpose.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Plugin hooks run alongside your custom hooks. If multiple hooks match an event, they all execute in parallel.
|
||||
</Note>
|
||||
|
||||
**Environment variables for plugins**:
|
||||
|
||||
* `${CLAUDE_PLUGIN_ROOT}`: Absolute path to the plugin directory
|
||||
* `${CLAUDE_PROJECT_DIR}`: Project root directory (same as for project hooks)
|
||||
* All standard environment variables are available
|
||||
|
||||
See the [plugin components reference](/en/docs/claude-code/plugins-reference#hooks) for details on creating plugin hooks.
|
||||
|
||||
## Hook Events
|
||||
|
||||
### PreToolUse
|
||||
|
||||
Runs after Claude creates tool parameters and before processing the tool call.
|
||||
|
||||
**Common matchers:**
|
||||
|
||||
* `Task` - Subagent tasks (see [subagents documentation](/en/docs/claude-code/sub-agents))
|
||||
* `Bash` - Shell commands
|
||||
* `Glob` - File pattern matching
|
||||
* `Grep` - Content search
|
||||
* `Read` - File reading
|
||||
* `Edit` - File editing
|
||||
* `Write` - File writing
|
||||
* `WebFetch`, `WebSearch` - Web operations
|
||||
|
||||
### PostToolUse
|
||||
|
||||
Runs immediately after a tool completes successfully.
|
||||
|
||||
Recognizes the same matcher values as PreToolUse.
|
||||
|
||||
### Notification
|
||||
|
||||
Runs when Claude Code sends notifications. Notifications are sent when:
|
||||
|
||||
1. Claude needs your permission to use a tool. Example: "Claude needs your
|
||||
permission to use Bash"
|
||||
2. The prompt input has been idle for at least 60 seconds. "Claude is waiting
|
||||
for your input"
|
||||
|
||||
### UserPromptSubmit
|
||||
|
||||
Runs when the user submits a prompt, before Claude processes it. This allows you
|
||||
to add additional context based on the prompt/conversation, validate prompts, or
|
||||
block certain types of prompts.
|
||||
|
||||
### Stop
|
||||
|
||||
Runs when the main Claude Code agent has finished responding. Does not run if
|
||||
the stoppage occurred due to a user interrupt.
|
||||
|
||||
### SubagentStop
|
||||
|
||||
Runs when a Claude Code subagent (Task tool call) has finished responding.
|
||||
|
||||
### PreCompact
|
||||
|
||||
Runs before Claude Code is about to run a compact operation.
|
||||
|
||||
**Matchers:**
|
||||
|
||||
* `manual` - Invoked from `/compact`
|
||||
* `auto` - Invoked from auto-compact (due to full context window)
|
||||
|
||||
### SessionStart
|
||||
|
||||
Runs when Claude Code starts a new session or resumes an existing session (which
|
||||
currently does start a new session under the hood). Useful for loading in
|
||||
development context like existing issues or recent changes to your codebase.
|
||||
|
||||
**Matchers:**
|
||||
|
||||
* `startup` - Invoked from startup
|
||||
* `resume` - Invoked from `--resume`, `--continue`, or `/resume`
|
||||
* `clear` - Invoked from `/clear`
|
||||
* `compact` - Invoked from auto or manual compact.
|
||||
|
||||
### SessionEnd
|
||||
|
||||
Runs when a Claude Code session ends. Useful for cleanup tasks, logging session
|
||||
statistics, or saving session state.
|
||||
|
||||
The `reason` field in the hook input will be one of:
|
||||
|
||||
* `clear` - Session cleared with /clear command
|
||||
* `logout` - User logged out
|
||||
* `prompt_input_exit` - User exited while prompt input was visible
|
||||
* `other` - Other exit reasons
|
||||
|
||||
## Hook Input
|
||||
|
||||
Hooks receive JSON data via stdin containing session information and
|
||||
event-specific data:
|
||||
|
||||
```typescript theme={null}
|
||||
{
|
||||
// Common fields
|
||||
session_id: string
|
||||
transcript_path: string // Path to conversation JSON
|
||||
cwd: string // The current working directory when the hook is invoked
|
||||
|
||||
// Event-specific fields
|
||||
hook_event_name: string
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### PreToolUse Input
|
||||
|
||||
The exact schema for `tool_input` depends on the tool.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"cwd": "/Users/...",
|
||||
"hook_event_name": "PreToolUse",
|
||||
"tool_name": "Write",
|
||||
"tool_input": {
|
||||
"file_path": "/path/to/file.txt",
|
||||
"content": "file content"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PostToolUse Input
|
||||
|
||||
The exact schema for `tool_input` and `tool_response` depends on the tool.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"cwd": "/Users/...",
|
||||
"hook_event_name": "PostToolUse",
|
||||
"tool_name": "Write",
|
||||
"tool_input": {
|
||||
"file_path": "/path/to/file.txt",
|
||||
"content": "file content"
|
||||
},
|
||||
"tool_response": {
|
||||
"filePath": "/path/to/file.txt",
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Notification Input
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"cwd": "/Users/...",
|
||||
"hook_event_name": "Notification",
|
||||
"message": "Task completed successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### UserPromptSubmit Input
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"cwd": "/Users/...",
|
||||
"hook_event_name": "UserPromptSubmit",
|
||||
"prompt": "Write a function to calculate the factorial of a number"
|
||||
}
|
||||
```
|
||||
|
||||
### Stop and SubagentStop Input
|
||||
|
||||
`stop_hook_active` is true when Claude Code is already continuing as a result of
|
||||
a stop hook. Check this value or process the transcript to prevent Claude Code
|
||||
from running indefinitely.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"hook_event_name": "Stop",
|
||||
"stop_hook_active": true
|
||||
}
|
||||
```
|
||||
|
||||
### PreCompact Input
|
||||
|
||||
For `manual`, `custom_instructions` comes from what the user passes into
|
||||
`/compact`. For `auto`, `custom_instructions` is empty.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"hook_event_name": "PreCompact",
|
||||
"trigger": "manual",
|
||||
"custom_instructions": ""
|
||||
}
|
||||
```
|
||||
|
||||
### SessionStart Input
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"hook_event_name": "SessionStart",
|
||||
"source": "startup"
|
||||
}
|
||||
```
|
||||
|
||||
### SessionEnd Input
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
|
||||
"cwd": "/Users/...",
|
||||
"hook_event_name": "SessionEnd",
|
||||
"reason": "exit"
|
||||
}
|
||||
```
|
||||
|
||||
## Hook Output
|
||||
|
||||
There are two ways for hooks to return output back to Claude Code. The output
|
||||
communicates whether to block and any feedback that should be shown to Claude
|
||||
and the user.
|
||||
|
||||
### Simple: Exit Code
|
||||
|
||||
Hooks communicate status through exit codes, stdout, and stderr:
|
||||
|
||||
* **Exit code 0**: Success. `stdout` is shown to the user in transcript mode
|
||||
(CTRL-R), except for `UserPromptSubmit` and `SessionStart`, where stdout is
|
||||
added to the context.
|
||||
* **Exit code 2**: Blocking error. `stderr` is fed back to Claude to process
|
||||
automatically. See per-hook-event behavior below.
|
||||
* **Other exit codes**: Non-blocking error. `stderr` is shown to the user and
|
||||
execution continues.
|
||||
|
||||
<Warning>
|
||||
Reminder: Claude Code does not see stdout if the exit code is 0, except for
|
||||
the `UserPromptSubmit` hook where stdout is injected as context.
|
||||
</Warning>
|
||||
|
||||
#### Exit Code 2 Behavior
|
||||
|
||||
| Hook Event | Behavior |
|
||||
| ------------------ | ------------------------------------------------------------------ |
|
||||
| `PreToolUse` | Blocks the tool call, shows stderr to Claude |
|
||||
| `PostToolUse` | Shows stderr to Claude (tool already ran) |
|
||||
| `Notification` | N/A, shows stderr to user only |
|
||||
| `UserPromptSubmit` | Blocks prompt processing, erases prompt, shows stderr to user only |
|
||||
| `Stop` | Blocks stoppage, shows stderr to Claude |
|
||||
| `SubagentStop` | Blocks stoppage, shows stderr to Claude subagent |
|
||||
| `PreCompact` | N/A, shows stderr to user only |
|
||||
| `SessionStart` | N/A, shows stderr to user only |
|
||||
| `SessionEnd` | N/A, shows stderr to user only |
|
||||
|
||||
### Advanced: JSON Output
|
||||
|
||||
Hooks can return structured JSON in `stdout` for more sophisticated control:
|
||||
|
||||
#### Common JSON Fields
|
||||
|
||||
All hook types can include these optional fields:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"continue": true, // Whether Claude should continue after hook execution (default: true)
|
||||
"stopReason": "string", // Message shown when continue is false
|
||||
|
||||
"suppressOutput": true, // Hide stdout from transcript mode (default: false)
|
||||
"systemMessage": "string" // Optional warning message shown to the user
|
||||
}
|
||||
```
|
||||
|
||||
If `continue` is false, Claude stops processing after the hooks run.
|
||||
|
||||
* For `PreToolUse`, this is different from `"permissionDecision": "deny"`, which
|
||||
only blocks a specific tool call and provides automatic feedback to Claude.
|
||||
* For `PostToolUse`, this is different from `"decision": "block"`, which
|
||||
provides automated feedback to Claude.
|
||||
* For `UserPromptSubmit`, this prevents the prompt from being processed.
|
||||
* For `Stop` and `SubagentStop`, this takes precedence over any
|
||||
`"decision": "block"` output.
|
||||
* In all cases, `"continue" = false` takes precedence over any
|
||||
`"decision": "block"` output.
|
||||
|
||||
`stopReason` accompanies `continue` with a reason shown to the user, not shown
|
||||
to Claude.
|
||||
|
||||
#### `PreToolUse` Decision Control
|
||||
|
||||
`PreToolUse` hooks can control whether a tool call proceeds.
|
||||
|
||||
* `"allow"` bypasses the permission system. `permissionDecisionReason` is shown
|
||||
to the user but not to Claude.
|
||||
* `"deny"` prevents the tool call from executing. `permissionDecisionReason` is
|
||||
shown to Claude.
|
||||
* `"ask"` asks the user to confirm the tool call in the UI.
|
||||
`permissionDecisionReason` is shown to the user but not to Claude.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "allow" | "deny" | "ask",
|
||||
"permissionDecisionReason": "My reason here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
The `decision` and `reason` fields are deprecated for PreToolUse hooks.
|
||||
Use `hookSpecificOutput.permissionDecision` and
|
||||
`hookSpecificOutput.permissionDecisionReason` instead. The deprecated fields
|
||||
`"approve"` and `"block"` map to `"allow"` and `"deny"` respectively.
|
||||
</Note>
|
||||
|
||||
#### `PostToolUse` Decision Control
|
||||
|
||||
`PostToolUse` hooks can provide feedback to Claude after tool execution.
|
||||
|
||||
* `"block"` automatically prompts Claude with `reason`.
|
||||
* `undefined` does nothing. `reason` is ignored.
|
||||
* `"hookSpecificOutput.additionalContext"` adds context for Claude to consider.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"decision": "block" | undefined,
|
||||
"reason": "Explanation for decision",
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "Additional information for Claude"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `UserPromptSubmit` Decision Control
|
||||
|
||||
`UserPromptSubmit` hooks can control whether a user prompt is processed.
|
||||
|
||||
* `"block"` prevents the prompt from being processed. The submitted prompt is
|
||||
erased from context. `"reason"` is shown to the user but not added to context.
|
||||
* `undefined` allows the prompt to proceed normally. `"reason"` is ignored.
|
||||
* `"hookSpecificOutput.additionalContext"` adds the string to the context if not
|
||||
blocked.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"decision": "block" | undefined,
|
||||
"reason": "Explanation for decision",
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "UserPromptSubmit",
|
||||
"additionalContext": "My additional context here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `Stop`/`SubagentStop` Decision Control
|
||||
|
||||
`Stop` and `SubagentStop` hooks can control whether Claude must continue.
|
||||
|
||||
* `"block"` prevents Claude from stopping. You must populate `reason` for Claude
|
||||
to know how to proceed.
|
||||
* `undefined` allows Claude to stop. `reason` is ignored.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"decision": "block" | undefined,
|
||||
"reason": "Must be provided when Claude is blocked from stopping"
|
||||
}
|
||||
```
|
||||
|
||||
#### `SessionStart` Decision Control
|
||||
|
||||
`SessionStart` hooks allow you to load in context at the start of a session.
|
||||
|
||||
* `"hookSpecificOutput.additionalContext"` adds the string to the context.
|
||||
* Multiple hooks' `additionalContext` values are concatenated.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": "My additional context here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `SessionEnd` Decision Control
|
||||
|
||||
`SessionEnd` hooks run when a session ends. They cannot block session termination
|
||||
but can perform cleanup tasks.
|
||||
|
||||
#### Exit Code Example: Bash Command Validation
|
||||
|
||||
```python theme={null}
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Define validation rules as a list of (regex pattern, message) tuples
|
||||
VALIDATION_RULES = [
|
||||
(
|
||||
r"\bgrep\b(?!.*\|)",
|
||||
"Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
|
||||
),
|
||||
(
|
||||
r"\bfind\s+\S+\s+-name\b",
|
||||
"Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def validate_command(command: str) -> list[str]:
|
||||
issues = []
|
||||
for pattern, message in VALIDATION_RULES:
|
||||
if re.search(pattern, command):
|
||||
issues.append(message)
|
||||
return issues
|
||||
|
||||
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
command = tool_input.get("command", "")
|
||||
|
||||
if tool_name != "Bash" or not command:
|
||||
sys.exit(1)
|
||||
|
||||
# Validate the command
|
||||
issues = validate_command(command)
|
||||
|
||||
if issues:
|
||||
for message in issues:
|
||||
print(f"• {message}", file=sys.stderr)
|
||||
# Exit code 2 blocks tool call and shows stderr to Claude
|
||||
sys.exit(2)
|
||||
```
|
||||
|
||||
#### JSON Output Example: UserPromptSubmit to Add Context and Validation
|
||||
|
||||
<Note>
|
||||
For `UserPromptSubmit` hooks, you can inject context using either method:
|
||||
|
||||
* Exit code 0 with stdout: Claude sees the context (special case for `UserPromptSubmit`)
|
||||
* JSON output: Provides more control over the behavior
|
||||
</Note>
|
||||
|
||||
```python theme={null}
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
import datetime
|
||||
|
||||
# Load input from stdin
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
prompt = input_data.get("prompt", "")
|
||||
|
||||
# Check for sensitive patterns
|
||||
sensitive_patterns = [
|
||||
(r"(?i)\b(password|secret|key|token)\s*[:=]", "Prompt contains potential secrets"),
|
||||
]
|
||||
|
||||
for pattern, message in sensitive_patterns:
|
||||
if re.search(pattern, prompt):
|
||||
# Use JSON output to block with a specific reason
|
||||
output = {
|
||||
"decision": "block",
|
||||
"reason": f"Security policy violation: {message}. Please rephrase your request without sensitive information."
|
||||
}
|
||||
print(json.dumps(output))
|
||||
sys.exit(0)
|
||||
|
||||
# Add current time to context
|
||||
context = f"Current time: {datetime.datetime.now()}"
|
||||
print(context)
|
||||
|
||||
"""
|
||||
The following is also equivalent:
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "UserPromptSubmit",
|
||||
"additionalContext": context,
|
||||
},
|
||||
}))
|
||||
"""
|
||||
|
||||
# Allow the prompt to proceed with the additional context
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
#### JSON Output Example: PreToolUse with Approval
|
||||
|
||||
```python theme={null}
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Load input from stdin
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
|
||||
# Example: Auto-approve file reads for documentation files
|
||||
if tool_name == "Read":
|
||||
file_path = tool_input.get("file_path", "")
|
||||
if file_path.endswith((".md", ".mdx", ".txt", ".json")):
|
||||
# Use JSON output to auto-approve the tool call
|
||||
output = {
|
||||
"decision": "approve",
|
||||
"reason": "Documentation file auto-approved",
|
||||
"suppressOutput": True # Don't show in transcript mode
|
||||
}
|
||||
print(json.dumps(output))
|
||||
sys.exit(0)
|
||||
|
||||
# For other cases, let the normal permission flow proceed
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
## Working with MCP Tools
|
||||
|
||||
Claude Code hooks work seamlessly with
|
||||
[Model Context Protocol (MCP) tools](/en/docs/claude-code/mcp). When MCP servers
|
||||
provide tools, they appear with a special naming pattern that you can match in
|
||||
your hooks.
|
||||
|
||||
### MCP Tool Naming
|
||||
|
||||
MCP tools follow the pattern `mcp__<server>__<tool>`, for example:
|
||||
|
||||
* `mcp__memory__create_entities` - Memory server's create entities tool
|
||||
* `mcp__filesystem__read_file` - Filesystem server's read file tool
|
||||
* `mcp__github__search_repositories` - GitHub server's search tool
|
||||
|
||||
### Configuring Hooks for MCP Tools
|
||||
|
||||
You can target specific MCP tools or entire MCP servers:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "mcp__memory__.*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "mcp__.*__write.*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/home/user/scripts/validate-mcp-write.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
<Tip>
|
||||
For practical examples including code formatting, notifications, and file protection, see [More Examples](/en/docs/claude-code/hooks-guide#more-examples) in the get started guide.
|
||||
</Tip>
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Disclaimer
|
||||
|
||||
**USE AT YOUR OWN RISK**: Claude Code hooks execute arbitrary shell commands on
|
||||
your system automatically. By using hooks, you acknowledge that:
|
||||
|
||||
* You are solely responsible for the commands you configure
|
||||
* Hooks can modify, delete, or access any files your user account can access
|
||||
* Malicious or poorly written hooks can cause data loss or system damage
|
||||
* Anthropic provides no warranty and assumes no liability for any damages
|
||||
resulting from hook usage
|
||||
* You should thoroughly test hooks in a safe environment before production use
|
||||
|
||||
Always review and understand any hook commands before adding them to your
|
||||
configuration.
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
Here are some key practices for writing more secure hooks:
|
||||
|
||||
1. **Validate and sanitize inputs** - Never trust input data blindly
|
||||
2. **Always quote shell variables** - Use `"$VAR"` not `$VAR`
|
||||
3. **Block path traversal** - Check for `..` in file paths
|
||||
4. **Use absolute paths** - Specify full paths for scripts (use
|
||||
"\$CLAUDE\_PROJECT\_DIR" for the project path)
|
||||
5. **Skip sensitive files** - Avoid `.env`, `.git/`, keys, etc.
|
||||
|
||||
### Configuration Safety
|
||||
|
||||
Direct edits to hooks in settings files don't take effect immediately. Claude
|
||||
Code:
|
||||
|
||||
1. Captures a snapshot of hooks at startup
|
||||
2. Uses this snapshot throughout the session
|
||||
3. Warns if hooks are modified externally
|
||||
4. Requires review in `/hooks` menu for changes to apply
|
||||
|
||||
This prevents malicious hook modifications from affecting your current session.
|
||||
|
||||
## Hook Execution Details
|
||||
|
||||
* **Timeout**: 60-second execution limit by default, configurable per command.
|
||||
* A timeout for an individual command does not affect the other commands.
|
||||
* **Parallelization**: All matching hooks run in parallel
|
||||
* **Deduplication**: Multiple identical hook commands are deduplicated automatically
|
||||
* **Environment**: Runs in current directory with Claude Code's environment
|
||||
* The `CLAUDE_PROJECT_DIR` environment variable is available and contains the
|
||||
absolute path to the project root directory (where Claude Code was started)
|
||||
* **Input**: JSON via stdin
|
||||
* **Output**:
|
||||
* PreToolUse/PostToolUse/Stop/SubagentStop: Progress shown in transcript (Ctrl-R)
|
||||
* Notification/SessionEnd: Logged to debug only (`--debug`)
|
||||
* UserPromptSubmit/SessionStart: stdout added as context for Claude
|
||||
|
||||
## Debugging
|
||||
|
||||
### Basic Troubleshooting
|
||||
|
||||
If your hooks aren't working:
|
||||
|
||||
1. **Check configuration** - Run `/hooks` to see if your hook is registered
|
||||
2. **Verify syntax** - Ensure your JSON settings are valid
|
||||
3. **Test commands** - Run hook commands manually first
|
||||
4. **Check permissions** - Make sure scripts are executable
|
||||
5. **Review logs** - Use `claude --debug` to see hook execution details
|
||||
|
||||
Common issues:
|
||||
|
||||
* **Quotes not escaped** - Use `\"` inside JSON strings
|
||||
* **Wrong matcher** - Check tool names match exactly (case-sensitive)
|
||||
* **Command not found** - Use full paths for scripts
|
||||
|
||||
### Advanced Debugging
|
||||
|
||||
For complex hook issues:
|
||||
|
||||
1. **Inspect hook execution** - Use `claude --debug` to see detailed hook
|
||||
execution
|
||||
2. **Validate JSON schemas** - Test hook input/output with external tools
|
||||
3. **Check environment variables** - Verify Claude Code's environment is correct
|
||||
4. **Test edge cases** - Try hooks with unusual file paths or inputs
|
||||
5. **Monitor system resources** - Check for resource exhaustion during hook
|
||||
execution
|
||||
6. **Use structured logging** - Implement logging in your hook scripts
|
||||
|
||||
### Debug Output Example
|
||||
|
||||
Use `claude --debug` to see hook execution details:
|
||||
|
||||
```
|
||||
[DEBUG] Executing hooks for PostToolUse:Write
|
||||
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
|
||||
[DEBUG] Found 1 hook matchers in settings
|
||||
[DEBUG] Matched 1 hooks for query "Write"
|
||||
[DEBUG] Found 1 hook commands to execute
|
||||
[DEBUG] Executing hook command: <Your command> with timeout 60000ms
|
||||
[DEBUG] Hook command completed with status 0: <Your stdout>
|
||||
```
|
||||
|
||||
Progress messages appear in transcript mode (Ctrl-R) showing:
|
||||
|
||||
* Which hook is running
|
||||
* Command being executed
|
||||
* Success/failure status
|
||||
* Output or error messages
|
||||
@@ -1,391 +0,0 @@
|
||||
# Plugins
|
||||
|
||||
> Extend Claude Code with custom commands, agents, hooks, and MCP servers through the plugin system.
|
||||
|
||||
<Tip>
|
||||
For complete technical specifications and schemas, see [Plugins reference](/en/docs/claude-code/plugins-reference). For marketplace management, see [Plugin marketplaces](/en/docs/claude-code/plugin-marketplaces).
|
||||
</Tip>
|
||||
|
||||
Plugins let you extend Claude Code with custom functionality that can be shared across projects and teams. Install plugins from [marketplaces](/en/docs/claude-code/plugin-marketplaces) to add pre-built commands, agents, hooks, and MCP servers, or create your own to automate your workflows.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Let's create a simple greeting plugin to get you familiar with the plugin system. We'll build a working plugin that adds a custom command, test it locally, and understand the core concepts.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* Claude Code installed on your machine
|
||||
* Basic familiarity with command-line tools
|
||||
|
||||
### Create your first plugin
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the marketplace structure">
|
||||
```bash theme={null}
|
||||
mkdir test-marketplace
|
||||
cd test-marketplace
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create the plugin directory">
|
||||
```bash theme={null}
|
||||
mkdir my-first-plugin
|
||||
cd my-first-plugin
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create the plugin manifest">
|
||||
```bash Create .claude-plugin/plugin.json theme={null}
|
||||
mkdir .claude-plugin
|
||||
cat > .claude-plugin/plugin.json << 'EOF'
|
||||
{
|
||||
"name": "my-first-plugin",
|
||||
"description": "A simple greeting plugin to learn the basics",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Your Name"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Add a custom command">
|
||||
```bash Create commands/hello.md theme={null}
|
||||
mkdir commands
|
||||
cat > commands/hello.md << 'EOF'
|
||||
---
|
||||
description: Greet the user with a personalized message
|
||||
---
|
||||
|
||||
# Hello Command
|
||||
|
||||
Greet the user warmly and ask how you can help them today. Make the greeting personal and encouraging.
|
||||
EOF
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create the marketplace manifest">
|
||||
```bash Create marketplace.json theme={null}
|
||||
cd ..
|
||||
mkdir .claude-plugin
|
||||
cat > .claude-plugin/marketplace.json << 'EOF'
|
||||
{
|
||||
"name": "test-marketplace",
|
||||
"owner": {
|
||||
"name": "Test User"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "my-first-plugin",
|
||||
"source": "./my-first-plugin",
|
||||
"description": "My first test plugin"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install and test your plugin">
|
||||
```bash Start Claude Code from parent directory theme={null}
|
||||
cd ..
|
||||
claude
|
||||
```
|
||||
|
||||
```shell Add the test marketplace theme={null}
|
||||
/plugin marketplace add ./test-marketplace
|
||||
```
|
||||
|
||||
```shell Install your plugin theme={null}
|
||||
/plugin install my-first-plugin@test-marketplace
|
||||
```
|
||||
|
||||
Select "Install now". You'll then need to restart Claude Code in order to use the new plugin.
|
||||
|
||||
```shell Try your new command theme={null}
|
||||
/hello
|
||||
```
|
||||
|
||||
You'll see Claude use your greeting command! Check `/help` to see your new command listed.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
You've successfully created and tested a plugin with these key components:
|
||||
|
||||
* **Plugin manifest** (`.claude-plugin/plugin.json`) - Describes your plugin's metadata
|
||||
* **Commands directory** (`commands/`) - Contains your custom slash commands
|
||||
* **Test marketplace** - Allows you to test your plugin locally
|
||||
|
||||
### Plugin structure overview
|
||||
|
||||
Your plugin follows this basic structure:
|
||||
|
||||
```
|
||||
my-first-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin metadata
|
||||
├── commands/ # Custom slash commands (optional)
|
||||
│ └── hello.md
|
||||
├── agents/ # Custom agents (optional)
|
||||
│ └── helper.md
|
||||
├── skills/ # Agent Skills (optional)
|
||||
│ └── my-skill/
|
||||
│ └── SKILL.md
|
||||
└── hooks/ # Event handlers (optional)
|
||||
└── hooks.json
|
||||
```
|
||||
|
||||
**Additional components you can add:**
|
||||
|
||||
* **Commands**: Create markdown files in `commands/` directory
|
||||
* **Agents**: Create agent definitions in `agents/` directory
|
||||
* **Skills**: Create `SKILL.md` files in `skills/` directory
|
||||
* **Hooks**: Create `hooks/hooks.json` for event handling
|
||||
* **MCP servers**: Create `.mcp.json` for external tool integration
|
||||
|
||||
<Note>
|
||||
**Next steps**: Ready to add more features? Jump to [Develop more complex plugins](#develop-more-complex-plugins) to add agents, hooks, and MCP servers. For complete technical specifications of all plugin components, see [Plugins reference](/en/docs/claude-code/plugins-reference).
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Install and manage plugins
|
||||
|
||||
Learn how to discover, install, and manage plugins to extend your Claude Code capabilities.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* Claude Code installed and running
|
||||
* Basic familiarity with command-line interfaces
|
||||
|
||||
### Add marketplaces
|
||||
|
||||
Marketplaces are catalogs of available plugins. Add them to discover and install plugins:
|
||||
|
||||
```shell Add a marketplace theme={null}
|
||||
/plugin marketplace add your-org/claude-plugins
|
||||
```
|
||||
|
||||
```shell Browse available plugins theme={null}
|
||||
/plugin
|
||||
```
|
||||
|
||||
For detailed marketplace management including Git repositories, local development, and team distribution, see [Plugin marketplaces](/en/docs/claude-code/plugin-marketplaces).
|
||||
|
||||
### Install plugins
|
||||
|
||||
#### Via interactive menu (recommended for discovery)
|
||||
|
||||
```shell Open the plugin management interface theme={null}
|
||||
/plugin
|
||||
```
|
||||
|
||||
Select "Browse Plugins" to see available options with descriptions, features, and installation options.
|
||||
|
||||
#### Via direct commands (for quick installation)
|
||||
|
||||
```shell Install a specific plugin theme={null}
|
||||
/plugin install formatter@your-org
|
||||
```
|
||||
|
||||
```shell Enable a disabled plugin theme={null}
|
||||
/plugin enable plugin-name@marketplace-name
|
||||
```
|
||||
|
||||
```shell Disable without uninstalling theme={null}
|
||||
/plugin disable plugin-name@marketplace-name
|
||||
```
|
||||
|
||||
```shell Completely remove a plugin theme={null}
|
||||
/plugin uninstall plugin-name@marketplace-name
|
||||
```
|
||||
|
||||
### Verify installation
|
||||
|
||||
After installing a plugin:
|
||||
|
||||
1. **Check available commands**: Run `/help` to see new commands
|
||||
2. **Test plugin features**: Try the plugin's commands and features
|
||||
3. **Review plugin details**: Use `/plugin` → "Manage Plugins" to see what the plugin provides
|
||||
|
||||
## Set up team plugin workflows
|
||||
|
||||
Configure plugins at the repository level to ensure consistent tooling across your team. When team members trust your repository folder, Claude Code automatically installs specified marketplaces and plugins.
|
||||
|
||||
**To set up team plugins:**
|
||||
|
||||
1. Add marketplace and plugin configuration to your repository's `.claude/settings.json`
|
||||
2. Team members trust the repository folder
|
||||
3. Plugins install automatically for all team members
|
||||
|
||||
For complete instructions including configuration examples, marketplace setup, and rollout best practices, see [Configure team marketplaces](/en/docs/claude-code/plugin-marketplaces#how-to-configure-team-marketplaces).
|
||||
|
||||
***
|
||||
|
||||
## Develop more complex plugins
|
||||
|
||||
Once you're comfortable with basic plugins, you can create more sophisticated extensions.
|
||||
|
||||
### Add Skills to your plugin
|
||||
|
||||
Plugins can include [Agent Skills](/en/docs/claude-code/skills) to extend Claude's capabilities. Skills are model-invoked—Claude autonomously uses them based on the task context.
|
||||
|
||||
To add Skills to your plugin, create a `skills/` directory at your plugin root and add Skill folders with `SKILL.md` files. Plugin Skills are automatically available when the plugin is installed.
|
||||
|
||||
For complete Skill authoring guidance, see [Agent Skills](/en/docs/claude-code/skills).
|
||||
|
||||
### Organize complex plugins
|
||||
|
||||
For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see [Plugin directory structure](/en/docs/claude-code/plugins-reference#plugin-directory-structure).
|
||||
|
||||
### Test your plugins locally
|
||||
|
||||
When developing plugins, use a local marketplace to test changes iteratively. This workflow builds on the quickstart pattern and works for plugins of any complexity.
|
||||
|
||||
<Steps>
|
||||
<Step title="Set up your development structure">
|
||||
Organize your plugin and marketplace for testing:
|
||||
|
||||
```bash Create directory structure theme={null}
|
||||
mkdir dev-marketplace
|
||||
cd dev-marketplace
|
||||
mkdir my-plugin
|
||||
```
|
||||
|
||||
This creates:
|
||||
|
||||
```
|
||||
dev-marketplace/
|
||||
├── .claude-plugin/marketplace.json (you'll create this)
|
||||
└── my-plugin/ (your plugin under development)
|
||||
├── .claude-plugin/plugin.json
|
||||
├── commands/
|
||||
├── agents/
|
||||
└── hooks/
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create the marketplace manifest">
|
||||
```bash Create marketplace.json theme={null}
|
||||
mkdir .claude-plugin
|
||||
cat > .claude-plugin/marketplace.json << 'EOF'
|
||||
{
|
||||
"name": "dev-marketplace",
|
||||
"owner": {
|
||||
"name": "Developer"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"source": "./my-plugin",
|
||||
"description": "Plugin under development"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install and test">
|
||||
```bash Start Claude Code from parent directory theme={null}
|
||||
cd ..
|
||||
claude
|
||||
```
|
||||
|
||||
```shell Add your development marketplace theme={null}
|
||||
/plugin marketplace add ./dev-marketplace
|
||||
```
|
||||
|
||||
```shell Install your plugin theme={null}
|
||||
/plugin install my-plugin@dev-marketplace
|
||||
```
|
||||
|
||||
Test your plugin components:
|
||||
|
||||
* Try your commands with `/command-name`
|
||||
* Check that agents appear in `/agents`
|
||||
* Verify hooks work as expected
|
||||
</Step>
|
||||
|
||||
<Step title="Iterate on your plugin">
|
||||
After making changes to your plugin code:
|
||||
|
||||
```shell Uninstall the current version theme={null}
|
||||
/plugin uninstall my-plugin@dev-marketplace
|
||||
```
|
||||
|
||||
```shell Reinstall to test changes theme={null}
|
||||
/plugin install my-plugin@dev-marketplace
|
||||
```
|
||||
|
||||
Repeat this cycle as you develop and refine your plugin.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
**For multiple plugins**: Organize plugins in subdirectories like `./plugins/plugin-name` and update your marketplace.json accordingly. See [Plugin sources](/en/docs/claude-code/plugin-marketplaces#plugin-sources) for organization patterns.
|
||||
</Note>
|
||||
|
||||
### Debug plugin issues
|
||||
|
||||
If your plugin isn't working as expected:
|
||||
|
||||
1. **Check the structure**: Ensure your directories are at the plugin root, not inside `.claude-plugin/`
|
||||
2. **Test components individually**: Check each command, agent, and hook separately
|
||||
3. **Use validation and debugging tools**: See [Debugging and development tools](/en/docs/claude-code/plugins-reference#debugging-and-development-tools) for CLI commands and troubleshooting techniques
|
||||
|
||||
### Share your plugins
|
||||
|
||||
When your plugin is ready to share:
|
||||
|
||||
1. **Add documentation**: Include a README.md with installation and usage instructions
|
||||
2. **Version your plugin**: Use semantic versioning in your `plugin.json`
|
||||
3. **Create or use a marketplace**: Distribute through plugin marketplaces for easy installation
|
||||
4. **Test with others**: Have team members test the plugin before wider distribution
|
||||
|
||||
<Note>
|
||||
For complete technical specifications, debugging techniques, and distribution strategies, see [Plugins reference](/en/docs/claude-code/plugins-reference).
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that you understand Claude Code's plugin system, here are suggested paths for different goals:
|
||||
|
||||
### For plugin users
|
||||
|
||||
* **Discover plugins**: Browse community marketplaces for useful tools
|
||||
* **Team adoption**: Set up repository-level plugins for your projects
|
||||
* **Marketplace management**: Learn to manage multiple plugin sources
|
||||
* **Advanced usage**: Explore plugin combinations and workflows
|
||||
|
||||
### For plugin developers
|
||||
|
||||
* **Create your first marketplace**: [Plugin marketplaces guide](/en/docs/claude-code/plugin-marketplaces)
|
||||
* **Advanced components**: Dive deeper into specific plugin components:
|
||||
* [Slash commands](/en/docs/claude-code/slash-commands) - Command development details
|
||||
* [Subagents](/en/docs/claude-code/sub-agents) - Agent configuration and capabilities
|
||||
* [Agent Skills](/en/docs/claude-code/skills) - Extend Claude's capabilities
|
||||
* [Hooks](/en/docs/claude-code/hooks) - Event handling and automation
|
||||
* [MCP](/en/docs/claude-code/mcp) - External tool integration
|
||||
* **Distribution strategies**: Package and share your plugins effectively
|
||||
* **Community contribution**: Consider contributing to community plugin collections
|
||||
|
||||
### For team leads and administrators
|
||||
|
||||
* **Repository configuration**: Set up automatic plugin installation for team projects
|
||||
* **Plugin governance**: Establish guidelines for plugin approval and security review
|
||||
* **Marketplace maintenance**: Create and maintain organization-specific plugin catalogs
|
||||
* **Training and documentation**: Help team members adopt plugin workflows effectively
|
||||
|
||||
## See also
|
||||
|
||||
* [Plugin marketplaces](/en/docs/claude-code/plugin-marketplaces) - Creating and managing plugin catalogs
|
||||
* [Slash commands](/en/docs/claude-code/slash-commands) - Understanding custom commands
|
||||
* [Subagents](/en/docs/claude-code/sub-agents) - Creating and using specialized agents
|
||||
* [Agent Skills](/en/docs/claude-code/skills) - Extend Claude's capabilities
|
||||
* [Hooks](/en/docs/claude-code/hooks) - Automating workflows with event handlers
|
||||
* [MCP](/en/docs/claude-code/mcp) - Connecting to external tools and services
|
||||
* [Settings](/en/docs/claude-code/settings) - Configuration options for plugins
|
||||
@@ -1,218 +0,0 @@
|
||||
# Models overview
|
||||
|
||||
> Claude is a family of state-of-the-art large language models developed by Anthropic. This guide introduces our models and compares their performance with legacy models.
|
||||
|
||||
export const ModelId = ({children, style = {}}) => {
|
||||
const copiedNotice = 'Copied!';
|
||||
const handleClick = e => {
|
||||
const element = e.currentTarget;
|
||||
const originalText = element.textContent;
|
||||
navigator.clipboard.writeText(children).then(() => {
|
||||
element.textContent = copiedNotice;
|
||||
element.style.backgroundColor = '#d4edda';
|
||||
element.style.color = '#155724';
|
||||
element.style.borderColor = '#c3e6cb';
|
||||
setTimeout(() => {
|
||||
element.textContent = originalText;
|
||||
element.style.backgroundColor = '#f5f5f5';
|
||||
element.style.color = '';
|
||||
element.style.borderColor = 'transparent';
|
||||
}, 2000);
|
||||
}).catch(error => {
|
||||
console.error('Failed to copy:', error);
|
||||
});
|
||||
};
|
||||
const handleMouseEnter = e => {
|
||||
const element = e.currentTarget;
|
||||
const tooltip = element.querySelector('.copy-tooltip');
|
||||
if (tooltip && element.textContent !== copiedNotice) {
|
||||
tooltip.style.opacity = '1';
|
||||
}
|
||||
element.style.backgroundColor = '#e8e8e8';
|
||||
element.style.borderColor = '#d0d0d0';
|
||||
};
|
||||
const handleMouseLeave = e => {
|
||||
const element = e.currentTarget;
|
||||
const tooltip = element.querySelector('.copy-tooltip');
|
||||
if (tooltip) {
|
||||
tooltip.style.opacity = '0';
|
||||
}
|
||||
if (element.textContent !== copiedNotice) {
|
||||
element.style.backgroundColor = '#f5f5f5';
|
||||
element.style.borderColor = 'transparent';
|
||||
}
|
||||
};
|
||||
const defaultStyle = {
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
transition: 'all 0.2s ease',
|
||||
display: 'inline-block',
|
||||
userSelect: 'none',
|
||||
backgroundColor: '#f5f5f5',
|
||||
padding: '2px 4px',
|
||||
borderRadius: '4px',
|
||||
fontFamily: 'Monaco, Consolas, "Courier New", monospace',
|
||||
fontSize: '0.9em',
|
||||
border: '1px solid transparent',
|
||||
...style
|
||||
};
|
||||
return <span onClick={handleClick} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} style={defaultStyle}>
|
||||
{children}
|
||||
</span>;
|
||||
};
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Claude Sonnet 4.5" icon="star" href="/en/docs/about-claude/models/overview#model-comparison-table">
|
||||
Our best model for complex agents and coding
|
||||
|
||||
* <Icon icon="inbox-in" iconType="thin" /> Text and image input
|
||||
* <Icon icon="inbox-out" iconType="thin" /> Text output
|
||||
* <Icon icon="book" iconType="thin" /> 200k context window (1M context beta available)
|
||||
* <Icon icon="brain" iconType="thin" /> Highest intelligence across most tasks
|
||||
</Card>
|
||||
|
||||
<Card title="Claude Haiku 4.5" icon="rocket-launch" href="/en/docs/about-claude/models/overview#model-comparison-table">
|
||||
Our fastest and most intelligent Haiku model
|
||||
|
||||
* <Icon icon="inbox-in" iconType="thin" /> Text and image input
|
||||
* <Icon icon="inbox-out" iconType="thin" /> Text output
|
||||
* <Icon icon="book" iconType="thin" /> 200k context window
|
||||
* <Icon icon="zap" iconType="thin" /> Lightning-fast speed with extended thinking
|
||||
</Card>
|
||||
|
||||
<Card title="Claude Opus 4.1" icon="trophy" href="/en/docs/about-claude/models/overview#model-comparison-table">
|
||||
Exceptional model for specialized complex tasks
|
||||
|
||||
* <Icon icon="inbox-in" iconType="thin" /> Text and image input
|
||||
* <Icon icon="inbox-out" iconType="thin" /> Text output
|
||||
* <Icon icon="book" iconType="thin" /> 200k context window
|
||||
* <Icon icon="brain" iconType="thin" /> Superior reasoning capabilities
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## Model names
|
||||
|
||||
| Model | Claude API | AWS Bedrock | GCP Vertex AI |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------- |
|
||||
| Claude Sonnet 4.5 | <ModelId>claude-sonnet-4-5-20250929</ModelId> | <ModelId>anthropic.claude-sonnet-4-5-20250929-v1:0</ModelId> | <ModelId>claude-sonnet-4-5\@20250929</ModelId> |
|
||||
| Claude Sonnet 4 | <ModelId>claude-sonnet-4-20250514</ModelId> | <ModelId>anthropic.claude-sonnet-4-20250514-v1:0</ModelId> | <ModelId>claude-sonnet-4\@20250514</ModelId> |
|
||||
| Claude Sonnet 3.7 | <ModelId>claude-3-7-sonnet-20250219</ModelId> (<ModelId>claude-3-7-sonnet-latest</ModelId>) | <ModelId>anthropic.claude-3-7-sonnet-20250219-v1:0</ModelId> | <ModelId>claude-3-7-sonnet\@20250219</ModelId> |
|
||||
| Claude Haiku 4.5 | <ModelId>claude-haiku-4-5-20251001</ModelId> | <ModelId>anthropic.claude-haiku-4-5-20251001-v1:0</ModelId> | <ModelId>claude-haiku-4-5\@20251001</ModelId> |
|
||||
| Claude Haiku 3.5 | <ModelId>claude-3-5-haiku-20241022</ModelId> (<ModelId>claude-3-5-haiku-latest</ModelId>) | <ModelId>anthropic.claude-3-5-haiku-20241022-v1:0</ModelId> | <ModelId>claude-3-5-haiku\@20241022</ModelId> |
|
||||
| Claude Haiku 3 | <ModelId>claude-3-haiku-20240307</ModelId> | <ModelId>anthropic.claude-3-haiku-20240307-v1:0</ModelId> | <ModelId>claude-3-haiku\@20240307</ModelId> |
|
||||
| Claude Opus 4.1 | <ModelId>claude-opus-4-1-20250805</ModelId> | <ModelId>anthropic.claude-opus-4-1-20250805-v1:0</ModelId> | <ModelId>claude-opus-4-1\@20250805</ModelId> |
|
||||
| Claude Opus 4 | <ModelId>claude-opus-4-20250514</ModelId> | <ModelId>anthropic.claude-opus-4-20250514-v1:0</ModelId> | <ModelId>claude-opus-4\@20250514</ModelId> |
|
||||
|
||||
<Note>Models with the same snapshot date (e.g., 20240620) are identical across all platforms and do not change. The snapshot date in the model name ensures consistency and allows developers to rely on stable performance across different environments.</Note>
|
||||
|
||||
<Note>Starting with **Claude Sonnet 4.5 and all future models**, AWS Bedrock and Google Vertex AI offer two endpoint types: **global endpoints** (dynamic routing for maximum availability) and **regional endpoints** (guaranteed data routing through specific geographic regions). For more information, see the [third-party platform pricing section](/en/docs/about-claude/pricing#third-party-platform-pricing).</Note>
|
||||
|
||||
### Model aliases
|
||||
|
||||
For convenience during development and testing, we offer aliases for our model ids. These aliases automatically point to the most recent snapshot of a given model. When we release new model snapshots, we migrate aliases to point to the newest version of a model, typically within a week of the new release.
|
||||
|
||||
<Tip>
|
||||
While aliases are useful for experimentation, we recommend using specific model versions (e.g., `claude-sonnet-4-5-20250929`) in production applications to ensure consistent behavior.
|
||||
</Tip>
|
||||
|
||||
| Model | Alias | Model ID |
|
||||
| ----------------- | ------------------------------------------- | --------------------------------------------- |
|
||||
| Claude Sonnet 4.5 | <ModelId>claude-sonnet-4-5</ModelId> | <ModelId>claude-sonnet-4-5-20250929</ModelId> |
|
||||
| Claude Sonnet 4 | <ModelId>claude-sonnet-4-0</ModelId> | <ModelId>claude-sonnet-4-20250514</ModelId> |
|
||||
| Claude Sonnet 3.7 | <ModelId>claude-3-7-sonnet-latest</ModelId> | <ModelId>claude-3-7-sonnet-20250219</ModelId> |
|
||||
| Claude Haiku 4.5 | <ModelId>claude-haiku-4-5</ModelId> | <ModelId>claude-haiku-4-5-20251001</ModelId> |
|
||||
| Claude Haiku 3.5 | <ModelId>claude-3-5-haiku-latest</ModelId> | <ModelId>claude-3-5-haiku-20241022</ModelId> |
|
||||
| Claude Opus 4.1 | <ModelId>claude-opus-4-1</ModelId> | <ModelId>claude-opus-4-1-20250805</ModelId> |
|
||||
| Claude Opus 4 | <ModelId>claude-opus-4-0</ModelId> | <ModelId>claude-opus-4-20250514</ModelId> |
|
||||
|
||||
<Note>
|
||||
Aliases are subject to the same rate limits and pricing as the underlying model version they reference.
|
||||
</Note>
|
||||
|
||||
### Model comparison table
|
||||
|
||||
To help you choose the right model for your needs, we've compiled a table comparing the key features and capabilities of each model in the Claude family:
|
||||
|
||||
| Feature | Claude Sonnet 4.5 | Claude Sonnet 4 | Claude Sonnet 3.7 | Claude Opus 4.1 | Claude Opus 4 | Claude Haiku 4.5 | Claude Haiku 3.5 | Claude Haiku 3 |
|
||||
| :-------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- |
|
||||
| **Description** | Our best model for complex agents and coding | High-performance model | High-performance model with early extended thinking | Exceptional model for specialized complex tasks | Our previous flagship model | Our fastest and most intelligent Haiku model | Our fastest model | Fast and compact model for near-instant responsiveness |
|
||||
| **Strengths** | Highest intelligence across most tasks with exceptional agent and coding capabilities | High intelligence and balanced performance | High intelligence with toggleable extended thinking | Very high intelligence and capability for specialized tasks | Very high intelligence and capability | Near-frontier intelligence at blazing speeds with extended thinking and exceptional cost-efficiency | Intelligence at blazing speeds | Quick and accurate targeted performance |
|
||||
| **Multilingual** | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| **Vision** | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| **[Extended thinking](/en/docs/build-with-claude/extended-thinking)** | Yes | Yes | Yes | Yes | Yes | Yes | No | No |
|
||||
| **[Priority Tier](/en/api/service-tiers)** | Yes | Yes | Yes | Yes | Yes | Yes | Yes | No |
|
||||
| **API model name** | <ModelId>claude-sonnet-4-5-20250929</ModelId> | <ModelId>claude-sonnet-4-20250514</ModelId> | <ModelId>claude-3-7-sonnet-20250219</ModelId> | <ModelId>claude-opus-4-1-20250805</ModelId> | <ModelId>claude-opus-4-20250514</ModelId> | <ModelId>claude-haiku-4-5-20251001</ModelId> | <ModelId>claude-3-5-haiku-20241022</ModelId> | <ModelId>claude-3-haiku-20240307</ModelId> |
|
||||
| **Comparative latency** | Fast | Fast | Fast | Moderately Fast | Moderately Fast | Fastest | Fastest | Fast |
|
||||
| **Context window** | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> / <br /> 1M (beta)<sup>1</sup> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> / <br /> 1M (beta)<sup>1</sup> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> | <Tooltip tip="~150K words \ ~215K unicode characters">200K</Tooltip> | <Tooltip tip="~150K words \ ~680K unicode characters">200K</Tooltip> |
|
||||
| **Max output** | <Tooltip tip="~48K words \ 218K unicode characters \ ~100 single spaced pages">64000 tokens</Tooltip> | <Tooltip tip="~48K words \ 218K unicode characters \ ~100 single spaced pages">64000 tokens</Tooltip> | <Tooltip tip="~48K words \ 218K unicode characters \ ~100 single spaced pages">64000 tokens</Tooltip> | <Tooltip tip="~24K words \ 109K unicode characters \ ~50 single spaced pages">32000 tokens</Tooltip> | <Tooltip tip="~24K words \ 109K unicode characters \ ~50 single spaced pages">32000 tokens</Tooltip> | <Tooltip tip="~48K words \ 218K unicode characters \ ~100 single spaced pages">64000 tokens</Tooltip> | <Tooltip tip="~6.2K words \ 28K unicode characters \ ~12-13 single spaced pages">8192 tokens</Tooltip> | <Tooltip tip="~3.1K words \ 14K unicode characters \ ~6-7 single spaced pages">4096 tokens</Tooltip> |
|
||||
| **Reliable knowledge cutoff** | Jan 2025<sup>2</sup> | Jan 2025<sup>2</sup> | Oct 2024<sup>2</sup> | Jan 2025<sup>2</sup> | Jan 2025<sup>2</sup> | Feb 2025 | <sup>3</sup> | <sup>3</sup> |
|
||||
| **Training data cutoff** | Jul 2025 | Mar 2025 | Nov 2024 | Mar 2025 | Mar 2025 | Jul 2025 | Jul 2024 | Aug 2023 |
|
||||
|
||||
*<sup>1 - Claude Sonnet 4.5 and Claude Sonnet 4 support a [1M token context window](/en/docs/build-with-claude/context-windows#1m-token-context-window) when using the `context-1m-2025-08-07` beta header. [Long context pricing](/en/docs/about-claude/pricing#long-context-pricing) applies to requests exceeding 200K tokens.</sup>*
|
||||
|
||||
*<sup>2 - **Reliable knowledge cutoff** indicates the date through which a model's knowledge is most extensive and reliable. **Training data cutoff** is the broader date range of training data used. For example, Claude Sonnet 4.5 was trained on publicly available information through July 2025, but its knowledge is most extensive and reliable through January 2025. For more information, see [Anthropic's Transparency Hub](https://www.anthropic.com/transparency).</sup>*
|
||||
|
||||
*<sup>3 - Some Haiku models have a single training data cutoff date.</sup>*
|
||||
|
||||
<Note>
|
||||
Include the beta header `output-128k-2025-02-19` in your API request to increase the maximum output token length to 128k tokens for Claude Sonnet 3.7.
|
||||
|
||||
We strongly suggest using our [streaming Messages API](/en/docs/build-with-claude/streaming) to avoid timeouts when generating longer outputs.
|
||||
See our guidance on [long requests](/en/api/errors#long-requests) for more details.
|
||||
</Note>
|
||||
|
||||
### Model pricing
|
||||
|
||||
The table below shows the price per million tokens for each model:
|
||||
|
||||
| Model | Base Input Tokens | 5m Cache Writes | 1h Cache Writes | Cache Hits & Refreshes | Output Tokens |
|
||||
| -------------------------------------------------------------------------- | ----------------- | --------------- | --------------- | ---------------------- | ------------- |
|
||||
| Claude Opus 4.1 | \$15 / MTok | \$18.75 / MTok | \$30 / MTok | \$1.50 / MTok | \$75 / MTok |
|
||||
| Claude Opus 4 | \$15 / MTok | \$18.75 / MTok | \$30 / MTok | \$1.50 / MTok | \$75 / MTok |
|
||||
| Claude Sonnet 4.5 | \$3 / MTok | \$3.75 / MTok | \$6 / MTok | \$0.30 / MTok | \$15 / MTok |
|
||||
| Claude Sonnet 4 | \$3 / MTok | \$3.75 / MTok | \$6 / MTok | \$0.30 / MTok | \$15 / MTok |
|
||||
| Claude Sonnet 3.7 | \$3 / MTok | \$3.75 / MTok | \$6 / MTok | \$0.30 / MTok | \$15 / MTok |
|
||||
| Claude Sonnet 3.5 ([deprecated](/en/docs/about-claude/model-deprecations)) | \$3 / MTok | \$3.75 / MTok | \$6 / MTok | \$0.30 / MTok | \$15 / MTok |
|
||||
| Claude Haiku 4.5 | \$1 / MTok | \$1.25 / MTok | \$2 / MTok | \$0.10 / MTok | \$5 / MTok |
|
||||
| Claude Haiku 3.5 | \$0.80 / MTok | \$1 / MTok | \$1.6 / MTok | \$0.08 / MTok | \$4 / MTok |
|
||||
| Claude Opus 3 ([deprecated](/en/docs/about-claude/model-deprecations)) | \$15 / MTok | \$18.75 / MTok | \$30 / MTok | \$1.50 / MTok | \$75 / MTok |
|
||||
| Claude Haiku 3 | \$0.25 / MTok | \$0.30 / MTok | \$0.50 / MTok | \$0.03 / MTok | \$1.25 / MTok |
|
||||
|
||||
## Prompt and output performance
|
||||
|
||||
Claude 4 models excel in:
|
||||
|
||||
* **Performance**: Top-tier results in reasoning, coding, multilingual tasks, long-context handling, honesty, and image processing. See the [Claude 4 blog post](http://www.anthropic.com/news/claude-4) for more information.
|
||||
* **Engaging responses**: Claude models are ideal for applications that require rich, human-like interactions.
|
||||
|
||||
* If you prefer more concise responses, you can adjust your prompts to guide the model toward the desired output length. Refer to our [prompt engineering guides](/en/docs/build-with-claude/prompt-engineering) for details.
|
||||
* For specific Claude 4 prompting best practices, see our [Claude 4 best practices guide](/en/docs/build-with-claude/prompt-engineering/claude-4-best-practices).
|
||||
* **Output quality**: When migrating from previous model generations to Claude 4, you may notice larger improvements in overall performance.
|
||||
|
||||
## Migrating to Claude 4.5
|
||||
|
||||
If you're currently using Claude 3 models, we recommend migrating to Claude 4.5 to take advantage of improved intelligence and enhanced capabilities. For detailed migration instructions, see [Migrating to Claude 4.5](/en/docs/about-claude/models/migrating-to-claude-4).
|
||||
|
||||
## Get started with Claude
|
||||
|
||||
If you're ready to start exploring what Claude can do for you, let's dive in! Whether you're a developer looking to integrate Claude into your applications or a user wanting to experience the power of AI firsthand, we've got you covered.
|
||||
|
||||
<Note>Looking to chat with Claude? Visit [claude.ai](http://www.claude.ai)!</Note>
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Intro to Claude" icon="check" href="/en/docs/intro-to-claude">
|
||||
Explore Claude’s capabilities and development flow.
|
||||
</Card>
|
||||
|
||||
<Card title="Quickstart" icon="bolt-lightning" href="/en/resources/quickstarts">
|
||||
Learn how to make your first API call in minutes.
|
||||
</Card>
|
||||
|
||||
<Card title="Claude Console" icon="code" href="https://console.anthropic.com">
|
||||
Craft and test powerful prompts directly in your browser.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
If you have any questions or need assistance, don't hesitate to reach out to our [support team](https://support.claude.com/) or consult the [Discord community](https://www.anthropic.com/discord).
|
||||
@@ -1,376 +0,0 @@
|
||||
# Plugins reference
|
||||
|
||||
> Complete technical reference for Claude Code plugin system, including schemas, CLI commands, and component specifications.
|
||||
|
||||
<Tip>
|
||||
For hands-on tutorials and practical usage, see [Plugins](/en/docs/claude-code/plugins). For plugin management across teams and communities, see [Plugin marketplaces](/en/docs/claude-code/plugin-marketplaces).
|
||||
</Tip>
|
||||
|
||||
This reference provides complete technical specifications for the Claude Code plugin system, including component schemas, CLI commands, and development tools.
|
||||
|
||||
## Plugin components reference
|
||||
|
||||
This section documents the five types of components that plugins can provide.
|
||||
|
||||
### Commands
|
||||
|
||||
Plugins add custom slash commands that integrate seamlessly with Claude Code's command system.
|
||||
|
||||
**Location**: `commands/` directory in plugin root
|
||||
|
||||
**File format**: Markdown files with frontmatter
|
||||
|
||||
For complete details on plugin command structure, invocation patterns, and features, see [Plugin commands](/en/docs/claude-code/slash-commands#plugin-commands).
|
||||
|
||||
### Agents
|
||||
|
||||
Plugins can provide specialized subagents for specific tasks that Claude can invoke automatically when appropriate.
|
||||
|
||||
**Location**: `agents/` directory in plugin root
|
||||
|
||||
**File format**: Markdown files describing agent capabilities
|
||||
|
||||
**Agent structure**:
|
||||
|
||||
```markdown theme={null}
|
||||
---
|
||||
description: What this agent specializes in
|
||||
capabilities: ["task1", "task2", "task3"]
|
||||
---
|
||||
|
||||
# Agent Name
|
||||
|
||||
Detailed description of the agent's role, expertise, and when Claude should invoke it.
|
||||
|
||||
## Capabilities
|
||||
- Specific task the agent excels at
|
||||
- Another specialized capability
|
||||
- When to use this agent vs others
|
||||
|
||||
## Context and examples
|
||||
Provide examples of when this agent should be used and what kinds of problems it solves.
|
||||
```
|
||||
|
||||
**Integration points**:
|
||||
|
||||
* Agents appear in the `/agents` interface
|
||||
* Claude can invoke agents automatically based on task context
|
||||
* Agents can be invoked manually by users
|
||||
* Plugin agents work alongside built-in Claude agents
|
||||
|
||||
### Skills
|
||||
|
||||
Plugins can provide Agent Skills that extend Claude's capabilities. Skills are model-invoked—Claude autonomously decides when to use them based on the task context.
|
||||
|
||||
**Location**: `skills/` directory in plugin root
|
||||
|
||||
**File format**: Directories containing `SKILL.md` files with frontmatter
|
||||
|
||||
**Skill structure**:
|
||||
|
||||
```
|
||||
skills/
|
||||
├── pdf-processor/
|
||||
│ ├── SKILL.md
|
||||
│ ├── reference.md (optional)
|
||||
│ └── scripts/ (optional)
|
||||
└── code-reviewer/
|
||||
└── SKILL.md
|
||||
```
|
||||
|
||||
**Integration behavior**:
|
||||
|
||||
* Plugin Skills are automatically discovered when the plugin is installed
|
||||
* Claude autonomously invokes Skills based on matching task context
|
||||
* Skills can include supporting files alongside SKILL.md
|
||||
|
||||
For SKILL.md format and complete Skill authoring guidance, see:
|
||||
|
||||
* [Use Skills in Claude Code](/en/docs/claude-code/skills)
|
||||
* [Agent Skills overview](/en/docs/agents-and-tools/agent-skills/overview#skill-structure)
|
||||
|
||||
### Hooks
|
||||
|
||||
Plugins can provide event handlers that respond to Claude Code events automatically.
|
||||
|
||||
**Location**: `hooks/hooks.json` in plugin root, or inline in plugin.json
|
||||
|
||||
**Format**: JSON configuration with event matchers and actions
|
||||
|
||||
**Hook configuration**:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format-code.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Available events**:
|
||||
|
||||
* `PreToolUse`: Before Claude uses any tool
|
||||
* `PostToolUse`: After Claude uses any tool
|
||||
* `UserPromptSubmit`: When user submits a prompt
|
||||
* `Notification`: When Claude Code sends notifications
|
||||
* `Stop`: When Claude attempts to stop
|
||||
* `SubagentStop`: When a subagent attempts to stop
|
||||
* `SessionStart`: At the beginning of sessions
|
||||
* `SessionEnd`: At the end of sessions
|
||||
* `PreCompact`: Before conversation history is compacted
|
||||
|
||||
**Hook types**:
|
||||
|
||||
* `command`: Execute shell commands or scripts
|
||||
* `validation`: Validate file contents or project state
|
||||
* `notification`: Send alerts or status updates
|
||||
|
||||
### MCP servers
|
||||
|
||||
Plugins can bundle Model Context Protocol (MCP) servers to connect Claude Code with external tools and services.
|
||||
|
||||
**Location**: `.mcp.json` in plugin root, or inline in plugin.json
|
||||
|
||||
**Format**: Standard MCP server configuration
|
||||
|
||||
**MCP server configuration**:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"mcpServers": {
|
||||
"plugin-database": {
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
|
||||
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
|
||||
"env": {
|
||||
"DB_PATH": "${CLAUDE_PLUGIN_ROOT}/data"
|
||||
}
|
||||
},
|
||||
"plugin-api-client": {
|
||||
"command": "npx",
|
||||
"args": ["@company/mcp-server", "--plugin-mode"],
|
||||
"cwd": "${CLAUDE_PLUGIN_ROOT}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Integration behavior**:
|
||||
|
||||
* Plugin MCP servers start automatically when the plugin is enabled
|
||||
* Servers appear as standard MCP tools in Claude's toolkit
|
||||
* Server capabilities integrate seamlessly with Claude's existing tools
|
||||
* Plugin servers can be configured independently of user MCP servers
|
||||
|
||||
***
|
||||
|
||||
## Plugin manifest schema
|
||||
|
||||
The `plugin.json` file defines your plugin's metadata and configuration. This section documents all supported fields and options.
|
||||
|
||||
### Complete schema
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"name": "plugin-name",
|
||||
"version": "1.2.0",
|
||||
"description": "Brief plugin description",
|
||||
"author": {
|
||||
"name": "Author Name",
|
||||
"email": "author@example.com",
|
||||
"url": "https://github.com/author"
|
||||
},
|
||||
"homepage": "https://docs.example.com/plugin",
|
||||
"repository": "https://github.com/author/plugin",
|
||||
"license": "MIT",
|
||||
"keywords": ["keyword1", "keyword2"],
|
||||
"commands": ["./custom/commands/special.md"],
|
||||
"agents": "./custom/agents/",
|
||||
"hooks": "./config/hooks.json",
|
||||
"mcpServers": "./mcp-config.json"
|
||||
}
|
||||
```
|
||||
|
||||
### Required fields
|
||||
|
||||
| Field | Type | Description | Example |
|
||||
| :----- | :----- | :---------------------------------------- | :------------------- |
|
||||
| `name` | string | Unique identifier (kebab-case, no spaces) | `"deployment-tools"` |
|
||||
|
||||
### Metadata fields
|
||||
|
||||
| Field | Type | Description | Example |
|
||||
| :------------ | :----- | :---------------------------------- | :------------------------------------------------- |
|
||||
| `version` | string | Semantic version | `"2.1.0"` |
|
||||
| `description` | string | Brief explanation of plugin purpose | `"Deployment automation tools"` |
|
||||
| `author` | object | Author information | `{"name": "Dev Team", "email": "dev@company.com"}` |
|
||||
| `homepage` | string | Documentation URL | `"https://docs.example.com"` |
|
||||
| `repository` | string | Source code URL | `"https://github.com/user/plugin"` |
|
||||
| `license` | string | License identifier | `"MIT"`, `"Apache-2.0"` |
|
||||
| `keywords` | array | Discovery tags | `["deployment", "ci-cd"]` |
|
||||
|
||||
### Component path fields
|
||||
|
||||
| Field | Type | Description | Example |
|
||||
| :----------- | :------------- | :----------------------------------- | :------------------------------------- |
|
||||
| `commands` | string\|array | Additional command files/directories | `"./custom/cmd.md"` or `["./cmd1.md"]` |
|
||||
| `agents` | string\|array | Additional agent files | `"./custom/agents/"` |
|
||||
| `hooks` | string\|object | Hook config path or inline config | `"./hooks.json"` |
|
||||
| `mcpServers` | string\|object | MCP config path or inline config | `"./mcp.json"` |
|
||||
|
||||
### Path behavior rules
|
||||
|
||||
**Important**: Custom paths supplement default directories - they don't replace them.
|
||||
|
||||
* If `commands/` exists, it's loaded in addition to custom command paths
|
||||
* All paths must be relative to plugin root and start with `./`
|
||||
* Commands from custom paths use the same naming and namespacing rules
|
||||
* Multiple paths can be specified as arrays for flexibility
|
||||
|
||||
**Path examples**:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"commands": [
|
||||
"./specialized/deploy.md",
|
||||
"./utilities/batch-process.md"
|
||||
],
|
||||
"agents": [
|
||||
"./custom-agents/reviewer.md",
|
||||
"./custom-agents/tester.md"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Environment variables
|
||||
|
||||
**`${CLAUDE_PLUGIN_ROOT}`**: Contains the absolute path to your plugin directory. Use this in hooks, MCP servers, and scripts to ensure correct paths regardless of installation location.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/process.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Plugin directory structure
|
||||
|
||||
### Standard plugin layout
|
||||
|
||||
A complete plugin follows this structure:
|
||||
|
||||
```
|
||||
enterprise-plugin/
|
||||
├── .claude-plugin/ # Metadata directory
|
||||
│ └── plugin.json # Required: plugin manifest
|
||||
├── commands/ # Default command location
|
||||
│ ├── status.md
|
||||
│ └── logs.md
|
||||
├── agents/ # Default agent location
|
||||
│ ├── security-reviewer.md
|
||||
│ ├── performance-tester.md
|
||||
│ └── compliance-checker.md
|
||||
├── skills/ # Agent Skills
|
||||
│ ├── code-reviewer/
|
||||
│ │ └── SKILL.md
|
||||
│ └── pdf-processor/
|
||||
│ ├── SKILL.md
|
||||
│ └── scripts/
|
||||
├── hooks/ # Hook configurations
|
||||
│ ├── hooks.json # Main hook config
|
||||
│ └── security-hooks.json # Additional hooks
|
||||
├── .mcp.json # MCP server definitions
|
||||
├── scripts/ # Hook and utility scripts
|
||||
│ ├── security-scan.sh
|
||||
│ ├── format-code.py
|
||||
│ └── deploy.js
|
||||
├── LICENSE # License file
|
||||
└── CHANGELOG.md # Version history
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The `.claude-plugin/` directory contains the `plugin.json` file. All other directories (commands/, agents/, skills/, hooks/) must be at the plugin root, not inside `.claude-plugin/`.
|
||||
</Warning>
|
||||
|
||||
### File locations reference
|
||||
|
||||
| Component | Default Location | Purpose |
|
||||
| :-------------- | :--------------------------- | :------------------------------- |
|
||||
| **Manifest** | `.claude-plugin/plugin.json` | Required metadata file |
|
||||
| **Commands** | `commands/` | Slash command markdown files |
|
||||
| **Agents** | `agents/` | Subagent markdown files |
|
||||
| **Skills** | `skills/` | Agent Skills with SKILL.md files |
|
||||
| **Hooks** | `hooks/hooks.json` | Hook configuration |
|
||||
| **MCP servers** | `.mcp.json` | MCP server definitions |
|
||||
|
||||
***
|
||||
|
||||
## Debugging and development tools
|
||||
|
||||
### Debugging commands
|
||||
|
||||
Use `claude --debug` to see plugin loading details:
|
||||
|
||||
```bash theme={null}
|
||||
claude --debug
|
||||
```
|
||||
|
||||
This shows:
|
||||
|
||||
* Which plugins are being loaded
|
||||
* Any errors in plugin manifests
|
||||
* Command, agent, and hook registration
|
||||
* MCP server initialization
|
||||
|
||||
### Common issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
| :--------------------- | :------------------------------ | :--------------------------------------------------- |
|
||||
| Plugin not loading | Invalid `plugin.json` | Validate JSON syntax |
|
||||
| Commands not appearing | Wrong directory structure | Ensure `commands/` at root, not in `.claude-plugin/` |
|
||||
| Hooks not firing | Script not executable | Run `chmod +x script.sh` |
|
||||
| MCP server fails | Missing `${CLAUDE_PLUGIN_ROOT}` | Use variable for all plugin paths |
|
||||
| Path errors | Absolute paths used | All paths must be relative and start with `./` |
|
||||
|
||||
***
|
||||
|
||||
## Distribution and versioning reference
|
||||
|
||||
### Version management
|
||||
|
||||
Follow semantic versioning for plugin releases:
|
||||
|
||||
```json theme={null}
|
||||
|
||||
## See also
|
||||
|
||||
- [Plugins](/en/docs/claude-code/plugins) - Tutorials and practical usage
|
||||
- [Plugin marketplaces](/en/docs/claude-code/plugin-marketplaces) - Creating and managing marketplaces
|
||||
- [Slash commands](/en/docs/claude-code/slash-commands) - Command development details
|
||||
- [Subagents](/en/docs/claude-code/sub-agents) - Agent configuration and capabilities
|
||||
- [Agent Skills](/en/docs/claude-code/skills) - Extend Claude's capabilities
|
||||
- [Hooks](/en/docs/claude-code/hooks) - Event handling and automation
|
||||
- [MCP](/en/docs/claude-code/mcp) - External tool integration
|
||||
- [Settings](/en/docs/claude-code/settings) - Configuration options for plugins
|
||||
```
|
||||
@@ -1,295 +0,0 @@
|
||||
# Streaming Input
|
||||
|
||||
> Understanding the two input modes for Claude Agent SDK and when to use each
|
||||
|
||||
## Overview
|
||||
|
||||
The Claude Agent SDK supports two distinct input modes for interacting with agents:
|
||||
|
||||
* **Streaming Input Mode** (Default & Recommended) - A persistent, interactive session
|
||||
* **Single Message Input** - One-shot queries that use session state and resuming
|
||||
|
||||
This guide explains the differences, benefits, and use cases for each mode to help you choose the right approach for your application.
|
||||
|
||||
## Streaming Input Mode (Recommended)
|
||||
|
||||
Streaming input mode is the **preferred** way to use the Claude Agent SDK. It provides full access to the agent's capabilities and enables rich, interactive experiences.
|
||||
|
||||
It allows the agent to operate as a long lived process that takes in user input, handles interruptions, surfaces permission requests, and handles session management.
|
||||
|
||||
### How It Works
|
||||
|
||||
```mermaid theme={null}
|
||||
%%{init: {"theme": "base", "themeVariables": {"edgeLabelBackground": "#F0F0EB", "lineColor": "#91918D", "primaryColor": "#F0F0EB", "primaryTextColor": "#191919", "primaryBorderColor": "#D9D8D5", "secondaryColor": "#F5E6D8", "tertiaryColor": "#CC785C", "noteBkgColor": "#FAF0E6", "noteBorderColor": "#91918D"}, "sequence": {"actorMargin": 50, "width": 150, "height": 65, "boxMargin": 10, "boxTextMargin": 5, "noteMargin": 10, "messageMargin": 35}}}%%
|
||||
sequenceDiagram
|
||||
participant App as Your Application
|
||||
participant Agent as Claude Agent
|
||||
participant Tools as Tools/Hooks
|
||||
participant FS as Environment/<br/>File System
|
||||
|
||||
App->>Agent: Initialize with AsyncGenerator
|
||||
activate Agent
|
||||
|
||||
App->>Agent: Yield Message 1
|
||||
Agent->>Tools: Execute tools
|
||||
Tools->>FS: Read files
|
||||
FS-->>Tools: File contents
|
||||
Tools->>FS: Write/Edit files
|
||||
FS-->>Tools: Success/Error
|
||||
Agent-->>App: Stream partial response
|
||||
Agent-->>App: Stream more content...
|
||||
Agent->>App: Complete Message 1
|
||||
|
||||
App->>Agent: Yield Message 2 + Image
|
||||
Agent->>Tools: Process image & execute
|
||||
Tools->>FS: Access filesystem
|
||||
FS-->>Tools: Operation results
|
||||
Agent-->>App: Stream response 2
|
||||
|
||||
App->>Agent: Queue Message 3
|
||||
App->>Agent: Interrupt/Cancel
|
||||
Agent->>App: Handle interruption
|
||||
|
||||
Note over App,Agent: Session stays alive
|
||||
Note over Tools,FS: Persistent file system<br/>state maintained
|
||||
|
||||
deactivate Agent
|
||||
```
|
||||
|
||||
### Benefits
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Image Uploads" icon="image">
|
||||
Attach images directly to messages for visual analysis and understanding
|
||||
</Card>
|
||||
|
||||
<Card title="Queued Messages" icon="layer-group">
|
||||
Send multiple messages that process sequentially, with ability to interrupt
|
||||
</Card>
|
||||
|
||||
<Card title="Tool Integration" icon="wrench">
|
||||
Full access to all tools and custom MCP servers during the session
|
||||
</Card>
|
||||
|
||||
<Card title="Hooks Support" icon="link">
|
||||
Use lifecycle hooks to customize behavior at various points
|
||||
</Card>
|
||||
|
||||
<Card title="Real-time Feedback" icon="bolt">
|
||||
See responses as they're generated, not just final results
|
||||
</Card>
|
||||
|
||||
<Card title="Context Persistence" icon="database">
|
||||
Maintain conversation context across multiple turns naturally
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Implementation Example
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
async function* generateMessages() {
|
||||
// First message
|
||||
yield {
|
||||
type: "user" as const,
|
||||
message: {
|
||||
role: "user" as const,
|
||||
content: "Analyze this codebase for security issues"
|
||||
}
|
||||
};
|
||||
|
||||
// Wait for conditions or user input
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// Follow-up with image
|
||||
yield {
|
||||
type: "user" as const,
|
||||
message: {
|
||||
role: "user" as const,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "Review this architecture diagram"
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
source: {
|
||||
type: "base64",
|
||||
media_type: "image/png",
|
||||
data: readFileSync("diagram.png", "base64")
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Process streaming responses
|
||||
for await (const message of query({
|
||||
prompt: generateMessages(),
|
||||
options: {
|
||||
maxTurns: 10,
|
||||
allowedTools: ["Read", "Grep"]
|
||||
}
|
||||
})) {
|
||||
if (message.type === "result") {
|
||||
console.log(message.result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, TextBlock
|
||||
import asyncio
|
||||
import base64
|
||||
|
||||
async def streaming_analysis():
|
||||
async def message_generator():
|
||||
# First message
|
||||
yield {
|
||||
"type": "user",
|
||||
"message": {
|
||||
"role": "user",
|
||||
"content": "Analyze this codebase for security issues"
|
||||
}
|
||||
}
|
||||
|
||||
# Wait for conditions
|
||||
await asyncio.sleep(2)
|
||||
|
||||
# Follow-up with image
|
||||
with open("diagram.png", "rb") as f:
|
||||
image_data = base64.b64encode(f.read()).decode()
|
||||
|
||||
yield {
|
||||
"type": "user",
|
||||
"message": {
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Review this architecture diagram"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": "image/png",
|
||||
"data": image_data
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Use ClaudeSDKClient for streaming input
|
||||
options = ClaudeAgentOptions(
|
||||
max_turns=10,
|
||||
allowed_tools=["Read", "Grep"]
|
||||
)
|
||||
|
||||
async with ClaudeSDKClient(options) as client:
|
||||
# Send streaming input
|
||||
await client.query(message_generator())
|
||||
|
||||
# Process responses
|
||||
async for message in client.receive_response():
|
||||
if isinstance(message, AssistantMessage):
|
||||
for block in message.content:
|
||||
if isinstance(block, TextBlock):
|
||||
print(block.text)
|
||||
|
||||
asyncio.run(streaming_analysis())
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Single Message Input
|
||||
|
||||
Single message input is simpler but more limited.
|
||||
|
||||
### When to Use Single Message Input
|
||||
|
||||
Use single message input when:
|
||||
|
||||
* You need a one-shot response
|
||||
* You do not need image attachments, hooks, etc.
|
||||
* You need to operate in a stateless environment, such as a lambda function
|
||||
|
||||
### Limitations
|
||||
|
||||
<Warning>
|
||||
Single message input mode does **not** support:
|
||||
|
||||
* Direct image attachments in messages
|
||||
* Dynamic message queueing
|
||||
* Real-time interruption
|
||||
* Hook integration
|
||||
* Natural multi-turn conversations
|
||||
</Warning>
|
||||
|
||||
### Implementation Example
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||
|
||||
// Simple one-shot query
|
||||
for await (const message of query({
|
||||
prompt: "Explain the authentication flow",
|
||||
options: {
|
||||
maxTurns: 1,
|
||||
allowedTools: ["Read", "Grep"]
|
||||
}
|
||||
})) {
|
||||
if (message.type === "result") {
|
||||
console.log(message.result);
|
||||
}
|
||||
}
|
||||
|
||||
// Continue conversation with session management
|
||||
for await (const message of query({
|
||||
prompt: "Now explain the authorization process",
|
||||
options: {
|
||||
continue: true,
|
||||
maxTurns: 1
|
||||
}
|
||||
})) {
|
||||
if (message.type === "result") {
|
||||
console.log(message.result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
|
||||
import asyncio
|
||||
|
||||
async def single_message_example():
|
||||
# Simple one-shot query using query() function
|
||||
async for message in query(
|
||||
prompt="Explain the authentication flow",
|
||||
options=ClaudeAgentOptions(
|
||||
max_turns=1,
|
||||
allowed_tools=["Read", "Grep"]
|
||||
)
|
||||
):
|
||||
if isinstance(message, ResultMessage):
|
||||
print(message.result)
|
||||
|
||||
# Continue conversation with session management
|
||||
async for message in query(
|
||||
prompt="Now explain the authorization process",
|
||||
options=ClaudeAgentOptions(
|
||||
continue_conversation=True,
|
||||
max_turns=1
|
||||
)
|
||||
):
|
||||
if isinstance(message, ResultMessage):
|
||||
print(message.result)
|
||||
|
||||
asyncio.run(single_message_example())
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -1,201 +0,0 @@
|
||||
---
|
||||
title: "Plugin Hooks"
|
||||
description: "5 lifecycle hooks that power Claude-Mem"
|
||||
---
|
||||
|
||||
# Plugin Hooks
|
||||
|
||||
Claude-Mem integrates with Claude Code through 5 lifecycle hooks that capture events and inject context.
|
||||
|
||||
## Hook Overview
|
||||
|
||||
| Hook Name | Purpose | Timeout | Script |
|
||||
|---------------------|--------------------------------------|---------|-------------------------|
|
||||
| SessionStart | Inject context from previous sessions| 120s | context-hook.js |
|
||||
| UserPromptSubmit | Create/track new sessions | 120s | new-hook.js |
|
||||
| PostToolUse | Capture tool execution observations | 120s | save-hook.js |
|
||||
| Stop | Generate session summaries | 120s | summary-hook.js |
|
||||
| SessionEnd | Mark sessions complete | 120s | cleanup-hook.js |
|
||||
|
||||
## Hook Configuration
|
||||
|
||||
Hooks are configured in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Claude-mem memory system hooks",
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "cd \"${CLAUDE_PLUGIN_ROOT}/..\" && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 1. SessionStart Hook (`context-hook.js`)
|
||||
|
||||
**Purpose**: Inject context from previous sessions into Claude's initial context.
|
||||
|
||||
**Behavior**:
|
||||
- Ensures dependencies are installed (runs fast idempotent npm install)
|
||||
- Auto-starts PM2 worker service if not running
|
||||
- Retrieves last 10 session summaries with three-tier verbosity (v4.2.0)
|
||||
- Returns context via `hookSpecificOutput` in JSON format (fixed in v4.1.0)
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "startup"
|
||||
}
|
||||
```
|
||||
|
||||
**Output** (via stdout):
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": "# Recent Sessions\n\n## Session 1...\n"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/context.ts` and `src/bin/hooks/context-hook.ts`
|
||||
|
||||
## 2. UserPromptSubmit Hook (`new-hook.js`)
|
||||
|
||||
**Purpose**: Create new session records and initialize session tracking.
|
||||
|
||||
**Behavior**:
|
||||
- Creates new session in database
|
||||
- Initializes session tracking
|
||||
- Saves raw user prompts for full-text search (as of v4.2.0)
|
||||
- Sends init signal to worker service
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"prompt": "User's actual prompt text"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/new.ts` and `src/bin/hooks/new-hook.ts`
|
||||
|
||||
## 3. PostToolUse Hook (`save-hook.js`)
|
||||
|
||||
**Purpose**: Capture tool execution observations.
|
||||
|
||||
**Behavior**:
|
||||
- Fires after EVERY tool execution (Read, Write, Edit, Bash, etc.)
|
||||
- Sends observations to worker service for processing
|
||||
- Includes correlation IDs for tracing
|
||||
- Filters low-value observations
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"tool_name": "Read",
|
||||
"tool_input": {...},
|
||||
"tool_result": "...",
|
||||
"correlation_id": "abc-123"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/save.ts` and `src/bin/hooks/save-hook.ts`
|
||||
|
||||
## 4. Stop Hook (`summary-hook.js`)
|
||||
|
||||
**Purpose**: Generate session summaries when Claude stops.
|
||||
|
||||
**Behavior**:
|
||||
- Triggers final summary generation
|
||||
- Sends summarize request to worker service
|
||||
- Summary includes: request, completed, learned, next_steps
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "user_stop"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/summary.ts` and `src/bin/hooks/summary-hook.ts`
|
||||
|
||||
## 5. SessionEnd Hook (`cleanup-hook.js`)
|
||||
|
||||
**Purpose**: Mark sessions as completed (graceful cleanup as of v4.1.0).
|
||||
|
||||
**Behavior**:
|
||||
- Marks sessions as completed
|
||||
- Skips cleanup on `/clear` commands to preserve ongoing sessions
|
||||
- Allows workers to finish pending operations naturally
|
||||
- Previously sent DELETE requests; now uses graceful completion
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "normal"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/cleanup.ts` and `src/bin/hooks/cleanup-hook.ts`
|
||||
|
||||
## Hook Development
|
||||
|
||||
### Adding a New Hook
|
||||
|
||||
1. Create hook implementation in `src/hooks/your-hook.ts`
|
||||
2. Create entry point in `src/bin/hooks/your-hook.ts`
|
||||
3. Add to `plugin/hooks/hooks.json`
|
||||
4. Rebuild with `npm run build`
|
||||
|
||||
### Hook Best Practices
|
||||
|
||||
- **Fast execution**: Hooks should complete quickly (< 1s ideal)
|
||||
- **Graceful degradation**: Don't block Claude if worker is down
|
||||
- **Structured logging**: Use logger for debugging
|
||||
- **Error handling**: Catch and log errors, don't crash
|
||||
- **JSON output**: Use `hookSpecificOutput` for context injection
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Hook Issues](../troubleshooting.md#hook-issues) for common problems and solutions.
|
||||
@@ -1,313 +0,0 @@
|
||||
---
|
||||
title: "MCP Search Server"
|
||||
description: "7 search tools with examples and usage patterns"
|
||||
---
|
||||
|
||||
# MCP Search Server
|
||||
|
||||
Claude-Mem includes a Model Context Protocol (MCP) server that exposes 7 specialized search tools for querying stored observations and sessions.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Location**: `src/servers/search-server.ts`
|
||||
- **Configuration**: `plugin/.mcp.json`
|
||||
- **Transport**: stdio
|
||||
- **Tools**: 7 specialized search functions
|
||||
- **Citations**: All results use `claude-mem://` URI scheme
|
||||
|
||||
## Configuration
|
||||
|
||||
The MCP server is automatically registered via `plugin/.mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"claude-mem-search": {
|
||||
"type": "stdio",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/search-server.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This registers the `claude-mem-search` server with Claude Code, making the 7 search tools available in all sessions. The server is automatically started when Claude Code launches and communicates via stdio transport.
|
||||
|
||||
## Search Tools
|
||||
|
||||
### 1. search_observations
|
||||
|
||||
Full-text search across observation titles, narratives, facts, and concepts.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `type`: Filter by observation type(s) (decision, bugfix, feature, refactor, discovery, change)
|
||||
- `concepts`: Filter by concept tags
|
||||
- `files`: Filter by file paths (partial match)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range (`{start, end}`)
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" for titles/dates only, "full" for complete details)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_observations with query="build system" and type="decision"
|
||||
```
|
||||
|
||||
### 2. search_sessions
|
||||
|
||||
Full-text search across session summaries, requests, and learnings.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_sessions with query="hooks implementation"
|
||||
```
|
||||
|
||||
### 3. search_user_prompts
|
||||
|
||||
Search raw user prompts with full-text search. Use this to find what the user actually said/requested across all sessions.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" for truncated prompts/dates, "full" for complete prompt text)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_user_prompts with query="authentication feature"
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Full context reconstruction from user intent → Claude actions → outcomes
|
||||
- Pattern detection for repeated requests
|
||||
- Improved debugging by tracing from original user words to final implementation
|
||||
|
||||
### 4. find_by_concept
|
||||
|
||||
Find observations tagged with specific concepts.
|
||||
|
||||
**Parameters**:
|
||||
- `concept` (required): Concept tag to search for
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_concept with concept="architecture"
|
||||
```
|
||||
|
||||
### 5. find_by_file
|
||||
|
||||
Find observations and sessions that reference specific file paths.
|
||||
|
||||
**Parameters**:
|
||||
- `filePath` (required): File path to search for (supports partial matching)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
```
|
||||
|
||||
### 6. find_by_type
|
||||
|
||||
Find observations by type (decision, bugfix, feature, refactor, discovery, change).
|
||||
|
||||
**Parameters**:
|
||||
- `type` (required): Observation type(s) to filter by (single type or array)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_type with type=["decision", "feature"]
|
||||
```
|
||||
|
||||
### 7. get_recent_context
|
||||
|
||||
Get recent session context including summaries and observations for a project.
|
||||
|
||||
**Parameters**:
|
||||
- `project`: Project name (defaults to current working directory basename)
|
||||
- `limit`: Number of recent sessions to retrieve (default: 3, max: 10)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
get_recent_context with limit=5
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
All search tools support two output formats:
|
||||
|
||||
### Index Format (Default)
|
||||
|
||||
Returns titles, dates, and source URIs only. Uses ~10x fewer tokens than full format.
|
||||
|
||||
**Always use index format first** to get an overview and identify relevant results.
|
||||
|
||||
**Example Output**:
|
||||
```
|
||||
1. [decision] Implement graceful session cleanup
|
||||
Date: 2025-10-21 14:23:45
|
||||
Source: claude-mem://observation/123
|
||||
|
||||
2. [feature] Add FTS5 full-text search
|
||||
Date: 2025-10-21 13:15:22
|
||||
Source: claude-mem://observation/124
|
||||
```
|
||||
|
||||
### Full Format
|
||||
|
||||
Returns complete observation/summary details including narrative, facts, concepts, files, etc.
|
||||
|
||||
**Only use after reviewing index results** to dive deep into specific items of interest.
|
||||
|
||||
## Search Strategy
|
||||
|
||||
**Recommended Workflow**:
|
||||
|
||||
1. **Initial search**: Use default (index) format to see titles, dates, and sources
|
||||
2. **Review results**: Identify which items are most relevant to your needs
|
||||
3. **Deep dive**: Only then use `format: "full"` on specific items of interest
|
||||
4. **Narrow down**: Use filters (type, dateRange, concepts, files) to refine results
|
||||
|
||||
**Token Efficiency**:
|
||||
- Index format: ~50-100 tokens per result
|
||||
- Full format: ~500-1000 tokens per result
|
||||
- Start with 3-5 results to avoid MCP token limits
|
||||
|
||||
## Citations
|
||||
|
||||
All search results use the `claude-mem://` URI scheme for citations:
|
||||
|
||||
- `claude-mem://observation/{id}` - References specific observations
|
||||
- `claude-mem://session/{id}` - References specific sessions
|
||||
- `claude-mem://user-prompt/{id}` - References specific user prompts
|
||||
|
||||
These citations allow Claude to reference specific historical context in responses.
|
||||
|
||||
## FTS5 Query Syntax
|
||||
|
||||
The `query` parameter supports SQLite FTS5 full-text search syntax:
|
||||
|
||||
- **Simple**: `"error handling"`
|
||||
- **AND**: `"error" AND "handling"`
|
||||
- **OR**: `"bug" OR "fix"`
|
||||
- **NOT**: `"bug" NOT "feature"`
|
||||
- **Phrase**: `"'exact phrase'"`
|
||||
- **Column**: `title:"authentication"`
|
||||
|
||||
## Security
|
||||
|
||||
As of v4.2.3, all FTS5 queries are properly escaped to prevent SQL injection attacks:
|
||||
- Double quotes are escaped: `query.replace(/"/g, '""')`
|
||||
- Comprehensive test suite with 332 injection attack tests
|
||||
- Affects: `search_observations`, `search_sessions`, `search_user_prompts`
|
||||
|
||||
## Example Queries
|
||||
|
||||
```
|
||||
# Find all decisions about build system
|
||||
search_observations with query="build system" and type="decision"
|
||||
|
||||
# Show everything related to worker-service.ts
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
|
||||
# Search what we learned about hooks
|
||||
search_sessions with query="hooks"
|
||||
|
||||
# Show observations tagged with 'architecture'
|
||||
find_by_concept with concept="architecture"
|
||||
|
||||
# Find what user asked about authentication
|
||||
search_user_prompts with query="authentication"
|
||||
|
||||
# Get recent context for debugging
|
||||
get_recent_context with limit=5
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
The MCP search server is implemented using:
|
||||
- `@modelcontextprotocol/sdk` (v1.20.1)
|
||||
- `SessionSearch` service for FTS5 queries
|
||||
- `SessionStore` for database access
|
||||
- `zod-to-json-schema` for parameter validation
|
||||
|
||||
**Source Code**: `src/servers/search-server.ts`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tool Not Available
|
||||
|
||||
If search tools are not available in Claude Code sessions:
|
||||
|
||||
1. Check MCP configuration:
|
||||
```bash
|
||||
cat plugin/.mcp.json
|
||||
```
|
||||
|
||||
2. Verify search server is built:
|
||||
```bash
|
||||
ls -l plugin/scripts/search-server.js
|
||||
```
|
||||
|
||||
3. Rebuild if needed:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Search Returns No Results
|
||||
|
||||
1. Check database has data:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations;"
|
||||
```
|
||||
|
||||
2. Verify FTS5 tables exist:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%_fts';"
|
||||
```
|
||||
|
||||
3. Test query syntax:
|
||||
```bash
|
||||
# Simple query should work
|
||||
search_observations with query="test"
|
||||
```
|
||||
|
||||
### Token Limit Errors
|
||||
|
||||
If you hit MCP token limits:
|
||||
|
||||
1. Use `format: "index"` instead of `format: "full"`
|
||||
2. Reduce `limit` parameter (try 3-5 instead of 20)
|
||||
3. Use more specific filters to narrow results
|
||||
4. Use `offset` to paginate through results
|
||||
@@ -1,165 +0,0 @@
|
||||
---
|
||||
title: "Architecture Overview"
|
||||
description: "System components and data flow in Claude-Mem"
|
||||
---
|
||||
|
||||
# Architecture Overview
|
||||
|
||||
## System Components
|
||||
|
||||
Claude-Mem operates as a Claude Code plugin with four core components:
|
||||
|
||||
1. **Plugin Hooks** - Capture lifecycle events
|
||||
2. **Worker Service** - Process observations via Claude Agent SDK
|
||||
3. **Database Layer** - Store sessions and observations (SQLite + FTS5)
|
||||
4. **MCP Search Server** - Query historical context
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|------------------------|-------------------------------------------|
|
||||
| **Language** | TypeScript (ES2022, ESNext modules) |
|
||||
| **Runtime** | Node.js 18+ |
|
||||
| **Database** | SQLite 3 with better-sqlite3 driver |
|
||||
| **HTTP Server** | Express.js 4.18 |
|
||||
| **AI SDK** | @anthropic-ai/claude-agent-sdk |
|
||||
| **Build Tool** | esbuild (bundles TypeScript) |
|
||||
| **Process Manager** | PM2 |
|
||||
| **Testing** | Node.js built-in test runner |
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Memory Pipeline
|
||||
```
|
||||
Hook (stdin) → Database → Worker Service → SDK Processor → Database → Next Session Hook
|
||||
```
|
||||
|
||||
1. **Input**: Claude Code sends tool execution data via stdin to hooks
|
||||
2. **Storage**: Hooks write observations to SQLite database
|
||||
3. **Processing**: Worker service reads observations, processes via SDK
|
||||
4. **Output**: Processed summaries written back to database
|
||||
5. **Retrieval**: Next session's context hook reads summaries from database
|
||||
|
||||
### Search Pipeline
|
||||
```
|
||||
Claude Request → MCP Server → SessionSearch Service → FTS5 Database → Search Results → Claude
|
||||
```
|
||||
|
||||
1. **Query**: Claude uses MCP search tools (e.g., `search_observations`)
|
||||
2. **Search**: MCP server calls SessionSearch service with query parameters
|
||||
3. **FTS5**: Full-text search executes against FTS5 virtual tables
|
||||
4. **Format**: Results formatted as `search_result` blocks with citations
|
||||
5. **Return**: Claude receives citable search results for analysis
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Session Starts → Context Hook Fires │
|
||||
│ Injects summaries from last 3 sessions into Claude's context │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. User Types Prompt → UserPromptSubmit Hook Fires │
|
||||
│ Creates SDK session in database, notifies worker service │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Claude Uses Tools → PostToolUse Hook Fires (100+ times) │
|
||||
│ Sends observations to worker service for processing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Worker Processes → Claude Agent SDK Analyzes │
|
||||
│ Extracts structured learnings via iterative AI processing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 5. Claude Stops → Stop Hook Fires │
|
||||
│ Generates final summary with request, status, next steps │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 6. Session Ends → Cleanup Hook Fires │
|
||||
│ Marks session complete, ready for next session context │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
claude-mem/
|
||||
├── src/
|
||||
│ ├── bin/hooks/ # Entry point scripts for 5 hooks
|
||||
│ │ ├── context-hook.ts # SessionStart
|
||||
│ │ ├── new-hook.ts # UserPromptSubmit
|
||||
│ │ ├── save-hook.ts # PostToolUse
|
||||
│ │ ├── summary-hook.ts # Stop
|
||||
│ │ └── cleanup-hook.ts # SessionEnd
|
||||
│ │
|
||||
│ ├── hooks/ # Hook implementation logic
|
||||
│ │ ├── context.ts
|
||||
│ │ ├── new.ts
|
||||
│ │ ├── save.ts
|
||||
│ │ ├── summary.ts
|
||||
│ │ └── cleanup.ts
|
||||
│ │
|
||||
│ ├── servers/ # MCP servers
|
||||
│ │ └── search-server.ts # MCP search tools server
|
||||
│ │
|
||||
│ ├── sdk/ # Claude Agent SDK integration
|
||||
│ │ ├── prompts.ts # XML prompt builders
|
||||
│ │ ├── parser.ts # XML response parser
|
||||
│ │ └── worker.ts # Main SDK agent loop
|
||||
│ │
|
||||
│ ├── services/
|
||||
│ │ ├── worker-service.ts # Express HTTP service
|
||||
│ │ └── sqlite/ # Database layer
|
||||
│ │ ├── SessionStore.ts # CRUD operations
|
||||
│ │ ├── SessionSearch.ts # FTS5 search service
|
||||
│ │ ├── migrations.ts
|
||||
│ │ └── types.ts
|
||||
│ │
|
||||
│ ├── shared/ # Shared utilities
|
||||
│ │ ├── config.ts
|
||||
│ │ ├── paths.ts
|
||||
│ │ └── storage.ts
|
||||
│ │
|
||||
│ └── utils/
|
||||
│ ├── logger.ts
|
||||
│ ├── platform.ts
|
||||
│ └── port-allocator.ts
|
||||
│
|
||||
├── plugin/ # Plugin distribution
|
||||
│ ├── .claude-plugin/
|
||||
│ │ └── plugin.json
|
||||
│ ├── .mcp.json # MCP server configuration
|
||||
│ ├── hooks/
|
||||
│ │ └── hooks.json
|
||||
│ └── scripts/ # Built executables
|
||||
│ ├── context-hook.js
|
||||
│ ├── new-hook.js
|
||||
│ ├── save-hook.js
|
||||
│ ├── summary-hook.js
|
||||
│ ├── cleanup-hook.js
|
||||
│ ├── worker-service.cjs # Background worker
|
||||
│ └── search-server.js # MCP search server
|
||||
│
|
||||
├── tests/ # Test suite
|
||||
├── docs/ # Documentation
|
||||
└── ecosystem.config.cjs # PM2 configuration
|
||||
```
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. Plugin Hooks
|
||||
See [Plugin Hooks](/architecture/hooks) for detailed hook documentation.
|
||||
|
||||
### 2. Worker Service
|
||||
See [Worker Service](/architecture/worker-service) for HTTP API and endpoints.
|
||||
|
||||
### 3. Database Layer
|
||||
See [Database Architecture](/architecture/database) for schema and FTS5 search.
|
||||
|
||||
### 4. MCP Search Server
|
||||
See [MCP Search Server](/architecture/mcp-search) for search tools and examples.
|
||||
@@ -1,248 +0,0 @@
|
||||
---
|
||||
title: "Worker Service"
|
||||
description: "HTTP API and PM2 process management"
|
||||
---
|
||||
|
||||
# Worker Service
|
||||
|
||||
The worker service is a long-running HTTP API built with Express.js and managed by PM2. It processes observations through the Claude Agent SDK separately from hook execution to prevent timeout issues.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Technology**: Express.js HTTP server
|
||||
- **Process Manager**: PM2
|
||||
- **Port**: Fixed port 37777 (configurable via `CLAUDE_MEM_WORKER_PORT`)
|
||||
- **Location**: `src/services/worker-service.ts`
|
||||
- **Built Output**: `plugin/scripts/worker-service.cjs`
|
||||
- **Model**: Configurable via `CLAUDE_MEM_MODEL` environment variable (default: claude-sonnet-4-5)
|
||||
|
||||
## REST API Endpoints
|
||||
|
||||
The worker service exposes 6 HTTP endpoints:
|
||||
|
||||
### 1. Health Check
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 12345,
|
||||
"port": 37777
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Initialize Session
|
||||
```
|
||||
POST /sessions/:sessionDbId/init
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"sdk_session_id": "abc-123",
|
||||
"project": "my-project"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"session_id": "abc-123"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Add Observation
|
||||
```
|
||||
POST /sessions/:sessionDbId/observations
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"tool_name": "Read",
|
||||
"tool_input": {...},
|
||||
"tool_result": "...",
|
||||
"correlation_id": "xyz-789"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"observation_id": 123
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Generate Summary
|
||||
```
|
||||
POST /sessions/:sessionDbId/summarize
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"trigger": "stop"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"summary_id": 456
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Session Status
|
||||
```
|
||||
GET /sessions/:sessionDbId/status
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"session_id": "abc-123",
|
||||
"status": "active",
|
||||
"observation_count": 42,
|
||||
"summary_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Delete Session
|
||||
```
|
||||
DELETE /sessions/:sessionDbId
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: As of v4.1.0, the cleanup hook no longer calls this endpoint. Sessions are marked complete instead of deleted to allow graceful worker shutdown.
|
||||
|
||||
## PM2 Management
|
||||
|
||||
### Configuration
|
||||
|
||||
The worker is configured via `ecosystem.config.cjs`:
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'claude-mem-worker',
|
||||
script: './plugin/scripts/worker-service.cjs',
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '1G',
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
FORCE_COLOR: '1'
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
# Start worker (auto-starts on first session)
|
||||
npm run worker:start
|
||||
|
||||
# Stop worker
|
||||
npm run worker:stop
|
||||
|
||||
# Restart worker
|
||||
npm run worker:restart
|
||||
|
||||
# View logs
|
||||
npm run worker:logs
|
||||
|
||||
# Check status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
### Auto-Start Behavior
|
||||
|
||||
As of v4.0.0, the worker service auto-starts when the SessionStart hook fires. Manual start is optional.
|
||||
|
||||
## Claude Agent SDK Integration
|
||||
|
||||
The worker service routes observations to the Claude Agent SDK for AI-powered processing:
|
||||
|
||||
### Processing Flow
|
||||
|
||||
1. **Observation Queue**: Observations accumulate in memory
|
||||
2. **SDK Processing**: Observations sent to Claude via Agent SDK
|
||||
3. **XML Parsing**: Responses parsed for structured data
|
||||
4. **Database Storage**: Processed observations stored in SQLite
|
||||
|
||||
### SDK Components
|
||||
|
||||
- **Prompts** (`src/sdk/prompts.ts`): Builds XML-structured prompts
|
||||
- **Parser** (`src/sdk/parser.ts`): Parses Claude's XML responses
|
||||
- **Worker** (`src/sdk/worker.ts`): Main SDK agent loop
|
||||
|
||||
### Model Configuration
|
||||
|
||||
Set the AI model used for processing via environment variable:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_MODEL=claude-sonnet-4-5
|
||||
```
|
||||
|
||||
Available models:
|
||||
- `claude-haiku-4-5` - Fast, cost-efficient
|
||||
- `claude-sonnet-4-5` - Balanced (default)
|
||||
- `claude-opus-4` - Most capable
|
||||
- `claude-3-7-sonnet` - Alternative version
|
||||
|
||||
## Port Allocation
|
||||
|
||||
The worker uses a fixed port (37777 by default) for consistent communication:
|
||||
|
||||
- **Default**: Port 37777
|
||||
- **Override**: Set `CLAUDE_MEM_WORKER_PORT` environment variable
|
||||
- **Port File**: `${CLAUDE_PLUGIN_ROOT}/data/worker.port` tracks current port
|
||||
|
||||
If port 37777 is in use, the worker will fail to start. Set a custom port via environment variable.
|
||||
|
||||
## Data Storage
|
||||
|
||||
The worker service stores data in the plugin data directory:
|
||||
|
||||
```
|
||||
${CLAUDE_PLUGIN_ROOT}/data/
|
||||
├── claude-mem.db # SQLite database
|
||||
├── worker.port # Current worker port file
|
||||
└── logs/
|
||||
├── worker-out.log # Worker stdout logs
|
||||
└── worker-error.log # Worker stderr logs
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The worker implements graceful degradation:
|
||||
|
||||
- **Database Errors**: Logged but don't crash the service
|
||||
- **SDK Errors**: Retried with exponential backoff
|
||||
- **Network Errors**: Logged and skipped
|
||||
- **Invalid Input**: Validated and rejected with error response
|
||||
|
||||
## Performance
|
||||
|
||||
- **Async Processing**: Observations processed asynchronously
|
||||
- **In-Memory Queue**: Fast observation accumulation
|
||||
- **Batch Processing**: Multiple observations processed together
|
||||
- **Connection Pooling**: SQLite connections reused
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Worker Issues](../troubleshooting.md#worker-service-issues) for common problems and solutions.
|
||||
@@ -1,303 +0,0 @@
|
||||
---
|
||||
title: "Configuration"
|
||||
description: "Environment variables and settings for Claude-Mem"
|
||||
---
|
||||
|
||||
# Configuration
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|-------------------------|---------------------------------|---------------------------------------|
|
||||
| `CLAUDE_PLUGIN_ROOT` | Set by Claude Code | Plugin installation directory |
|
||||
| `CLAUDE_MEM_DATA_DIR` | `~/.claude-mem/` | Data directory (dev override) |
|
||||
| `CLAUDE_MEM_WORKER_PORT`| `37777` | Worker service port |
|
||||
| `CLAUDE_MEM_MODEL` | `claude-sonnet-4-5` | AI model for processing observations |
|
||||
| `NODE_ENV` | `production` | Environment mode |
|
||||
| `FORCE_COLOR` | `1` | Enable colored logs |
|
||||
|
||||
## Model Configuration
|
||||
|
||||
Configure which AI model processes your observations.
|
||||
|
||||
### Available Models
|
||||
|
||||
- `claude-haiku-4-5` - Fast, cost-efficient
|
||||
- `claude-sonnet-4-5` - Balanced (default)
|
||||
- `claude-opus-4` - Most capable
|
||||
- `claude-3-7-sonnet` - Alternative version
|
||||
|
||||
### Using the Interactive Script
|
||||
|
||||
```bash
|
||||
./claude-mem-settings.sh
|
||||
```
|
||||
|
||||
This script manages `CLAUDE_MEM_MODEL` in `~/.claude/settings.json`.
|
||||
|
||||
### Manual Configuration
|
||||
|
||||
Edit `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_MODEL": "claude-sonnet-4-5"
|
||||
}
|
||||
```
|
||||
|
||||
## Files and Directories
|
||||
|
||||
### Data Directory Structure
|
||||
|
||||
```
|
||||
~/.claude-mem/
|
||||
├── claude-mem.db # SQLite database
|
||||
├── worker.port # Current worker port file
|
||||
└── logs/
|
||||
├── worker-out.log # Worker stdout logs
|
||||
└── worker-error.log # Worker stderr logs
|
||||
```
|
||||
|
||||
### Plugin Directory Structure
|
||||
|
||||
```
|
||||
${CLAUDE_PLUGIN_ROOT}/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin metadata
|
||||
├── .mcp.json # MCP server configuration
|
||||
├── hooks/
|
||||
│ └── hooks.json # Hook configuration
|
||||
└── scripts/ # Built executables
|
||||
├── context-hook.js
|
||||
├── new-hook.js
|
||||
├── save-hook.js
|
||||
├── summary-hook.js
|
||||
├── cleanup-hook.js
|
||||
├── worker-service.cjs
|
||||
└── search-server.js
|
||||
```
|
||||
|
||||
## Plugin Configuration
|
||||
|
||||
### Hooks Configuration
|
||||
|
||||
Hooks are configured in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Claude-mem memory system hooks",
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "cd \"${CLAUDE_PLUGIN_ROOT}/..\" && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### MCP Server Configuration
|
||||
|
||||
The MCP search server is configured in `plugin/.mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"claude-mem-search": {
|
||||
"type": "stdio",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/search-server.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This registers the `claude-mem-search` server with Claude Code, making the 7 search tools available in all sessions.
|
||||
|
||||
## PM2 Configuration
|
||||
|
||||
Worker service is managed by PM2 via `ecosystem.config.cjs`:
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'claude-mem-worker',
|
||||
script: './plugin/scripts/worker-service.cjs',
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '1G',
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
FORCE_COLOR: '1'
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
### PM2 Settings
|
||||
|
||||
- **instances**: 1 (single instance)
|
||||
- **autorestart**: true (auto-restart on crash)
|
||||
- **watch**: false (no file watching)
|
||||
- **max_memory_restart**: 1G (restart if memory exceeds 1GB)
|
||||
|
||||
## Customization
|
||||
|
||||
### Custom Data Directory
|
||||
|
||||
For development or testing, override the data directory:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_DATA_DIR=/custom/path
|
||||
```
|
||||
|
||||
### Custom Worker Port
|
||||
|
||||
If port 37777 is in use:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_WORKER_PORT=38000
|
||||
npm run worker:restart
|
||||
```
|
||||
|
||||
### Custom Model
|
||||
|
||||
Use a different AI model:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_MODEL=claude-opus-4
|
||||
npm run worker:restart
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Hook Timeouts
|
||||
|
||||
Modify timeouts in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"timeout": 120 // Default: 120 seconds
|
||||
}
|
||||
```
|
||||
|
||||
Recommended values:
|
||||
- SessionStart: 120s (needs time for npm install and context retrieval)
|
||||
- UserPromptSubmit: 60s
|
||||
- PostToolUse: 120s (can process many observations)
|
||||
- Stop: 60s
|
||||
- SessionEnd: 60s
|
||||
|
||||
### Worker Memory Limit
|
||||
|
||||
Modify PM2 memory limit in `ecosystem.config.cjs`:
|
||||
|
||||
```javascript
|
||||
{
|
||||
max_memory_restart: '2G' // Increase if needed
|
||||
}
|
||||
```
|
||||
|
||||
### Logging Verbosity
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
export DEBUG=claude-mem:*
|
||||
npm run worker:restart
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
## Configuration Best Practices
|
||||
|
||||
1. **Use defaults**: Default configuration works for most use cases
|
||||
2. **Override selectively**: Only change what you need
|
||||
3. **Document changes**: Keep track of custom configurations
|
||||
4. **Test after changes**: Verify worker restarts successfully
|
||||
5. **Monitor logs**: Check worker logs after configuration changes
|
||||
|
||||
## Troubleshooting Configuration
|
||||
|
||||
### Configuration Not Applied
|
||||
|
||||
1. Restart worker after changes:
|
||||
```bash
|
||||
npm run worker:restart
|
||||
```
|
||||
|
||||
2. Verify environment variables:
|
||||
```bash
|
||||
echo $CLAUDE_MEM_MODEL
|
||||
echo $CLAUDE_MEM_WORKER_PORT
|
||||
```
|
||||
|
||||
3. Check worker logs:
|
||||
```bash
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
### Invalid Model Name
|
||||
|
||||
If you specify an invalid model name, the worker will fall back to `claude-sonnet-4-5` and log a warning.
|
||||
|
||||
Valid models:
|
||||
- claude-haiku-4-5
|
||||
- claude-sonnet-4-5
|
||||
- claude-opus-4
|
||||
- claude-3-7-sonnet
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
If port 37777 is already in use:
|
||||
|
||||
1. Set custom port:
|
||||
```bash
|
||||
export CLAUDE_MEM_WORKER_PORT=38000
|
||||
```
|
||||
|
||||
2. Restart worker:
|
||||
```bash
|
||||
npm run worker:restart
|
||||
```
|
||||
|
||||
3. Verify new port:
|
||||
```bash
|
||||
cat ~/.claude-mem/worker.port
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Architecture Overview](architecture/overview) - Understand the system
|
||||
- [Troubleshooting](troubleshooting) - Common issues
|
||||
- [Development](development) - Building from source
|
||||
@@ -0,0 +1,390 @@
|
||||
# TypeScript SDK V2 interface (preview)
|
||||
|
||||
Preview of the simplified V2 TypeScript Agent SDK, with session-based send/receive patterns for multi-turn conversations.
|
||||
|
||||
---
|
||||
|
||||
<Warning>
|
||||
The V2 interface is an **unstable preview**. APIs may change based on feedback before becoming stable. Some features like session forking are only available in the [V1 SDK](/docs/en/agent-sdk/typescript).
|
||||
</Warning>
|
||||
|
||||
The V2 Claude Agent TypeScript SDK removes the need for async generators and yield coordination. This makes multi-turn conversations simpler—instead of managing generator state across turns, each turn is a separate `send()`/`receive()` cycle. The API surface reduces to three concepts:
|
||||
|
||||
- `createSession()` / `resumeSession()`: Start or continue a conversation
|
||||
- `session.send()`: Send a message
|
||||
- `session.receive()`: Get the response
|
||||
|
||||
## Installation
|
||||
|
||||
The V2 interface is included in the existing SDK package:
|
||||
|
||||
```bash
|
||||
npm install @anthropic-ai/claude-agent-sdk
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
### One-shot prompt
|
||||
|
||||
For simple single-turn queries where you don't need to maintain a session, use `unstable_v2_prompt()`. This example sends a math question and logs the answer:
|
||||
|
||||
```typescript
|
||||
import { unstable_v2_prompt } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
const result = await unstable_v2_prompt('What is 2 + 2?', {
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
console.log(result.result)
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>See the same operation in V1</summary>
|
||||
|
||||
```typescript
|
||||
import { query } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
const q = query({
|
||||
prompt: 'What is 2 + 2?',
|
||||
options: { model: 'claude-sonnet-4-5-20250929' }
|
||||
})
|
||||
|
||||
for await (const msg of q) {
|
||||
if (msg.type === 'result') {
|
||||
console.log(msg.result)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Basic session
|
||||
|
||||
For interactions beyond a single prompt, create a session. V2 separates sending and receiving into distinct steps:
|
||||
- `send()` dispatches your message
|
||||
- `receive()` streams back the response
|
||||
|
||||
This explicit separation makes it easier to add logic between turns (like processing responses before sending follow-ups).
|
||||
|
||||
The example below creates a session, sends "Hello!" to Claude, and prints the text response. It uses [`await using`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management) (TypeScript 5.2+) to automatically close the session when the block exits. You can also call `session.close()` manually.
|
||||
|
||||
```typescript
|
||||
import { unstable_v2_createSession } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
await using session = unstable_v2_createSession({
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
|
||||
await session.send('Hello!')
|
||||
for await (const msg of session.receive()) {
|
||||
// Filter for assistant messages to get human-readable output
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log(text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>See the same operation in V1</summary>
|
||||
|
||||
In V1, both input and output flow through a single async generator. For a basic prompt this looks similar, but adding multi-turn logic requires restructuring to use an input generator.
|
||||
|
||||
```typescript
|
||||
import { query } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
const q = query({
|
||||
prompt: 'Hello!',
|
||||
options: { model: 'claude-sonnet-4-5-20250929' }
|
||||
})
|
||||
|
||||
for await (const msg of q) {
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log(text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Multi-turn conversation
|
||||
|
||||
Sessions persist context across multiple exchanges. To continue a conversation, call `send()` again on the same session. Claude remembers the previous turns.
|
||||
|
||||
This example asks a math question, then asks a follow-up that references the previous answer:
|
||||
|
||||
```typescript
|
||||
import { unstable_v2_createSession } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
await using session = unstable_v2_createSession({
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
|
||||
// Turn 1
|
||||
await session.send('What is 5 + 3?')
|
||||
for await (const msg of session.receive()) {
|
||||
// Filter for assistant messages to get human-readable output
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log(text)
|
||||
}
|
||||
}
|
||||
|
||||
// Turn 2
|
||||
await session.send('Multiply that by 2')
|
||||
for await (const msg of session.receive()) {
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log(text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>See the same operation in V1</summary>
|
||||
|
||||
```typescript
|
||||
import { query } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
// Must create an async iterable to feed messages
|
||||
async function* createInputStream() {
|
||||
yield {
|
||||
type: 'user',
|
||||
session_id: '',
|
||||
message: { role: 'user', content: [{ type: 'text', text: 'What is 5 + 3?' }] },
|
||||
parent_tool_use_id: null
|
||||
}
|
||||
// Must coordinate when to yield next message
|
||||
yield {
|
||||
type: 'user',
|
||||
session_id: '',
|
||||
message: { role: 'user', content: [{ type: 'text', text: 'Multiply by 2' }] },
|
||||
parent_tool_use_id: null
|
||||
}
|
||||
}
|
||||
|
||||
const q = query({
|
||||
prompt: createInputStream(),
|
||||
options: { model: 'claude-sonnet-4-5-20250929' }
|
||||
})
|
||||
|
||||
for await (const msg of q) {
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log(text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Session resume
|
||||
|
||||
If you have a session ID from a previous interaction, you can resume it later. This is useful for long-running workflows or when you need to persist conversations across application restarts.
|
||||
|
||||
This example creates a session, stores its ID, closes it, then resumes the conversation:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
unstable_v2_createSession,
|
||||
unstable_v2_resumeSession,
|
||||
type SDKMessage
|
||||
} from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
// Helper to extract text from assistant messages
|
||||
function getAssistantText(msg: SDKMessage): string | null {
|
||||
if (msg.type !== 'assistant') return null
|
||||
return msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
}
|
||||
|
||||
// Create initial session and have a conversation
|
||||
const session = unstable_v2_createSession({
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
|
||||
await session.send('Remember this number: 42')
|
||||
|
||||
// Get the session ID from any received message
|
||||
let sessionId: string | undefined
|
||||
for await (const msg of session.receive()) {
|
||||
sessionId = msg.session_id
|
||||
const text = getAssistantText(msg)
|
||||
if (text) console.log('Initial response:', text)
|
||||
}
|
||||
|
||||
console.log('Session ID:', sessionId)
|
||||
session.close()
|
||||
|
||||
// Later: resume the session using the stored ID
|
||||
await using resumedSession = unstable_v2_resumeSession(sessionId!, {
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
|
||||
await resumedSession.send('What number did I ask you to remember?')
|
||||
for await (const msg of resumedSession.receive()) {
|
||||
const text = getAssistantText(msg)
|
||||
if (text) console.log('Resumed response:', text)
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>See the same operation in V1</summary>
|
||||
|
||||
```typescript
|
||||
import { query } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
// Create initial session
|
||||
const initialQuery = query({
|
||||
prompt: 'Remember this number: 42',
|
||||
options: { model: 'claude-sonnet-4-5-20250929' }
|
||||
})
|
||||
|
||||
// Get session ID from any message
|
||||
let sessionId: string | undefined
|
||||
for await (const msg of initialQuery) {
|
||||
sessionId = msg.session_id
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log('Initial response:', text)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Session ID:', sessionId)
|
||||
|
||||
// Later: resume the session
|
||||
const resumedQuery = query({
|
||||
prompt: 'What number did I ask you to remember?',
|
||||
options: {
|
||||
model: 'claude-sonnet-4-5-20250929',
|
||||
resume: sessionId
|
||||
}
|
||||
})
|
||||
|
||||
for await (const msg of resumedQuery) {
|
||||
if (msg.type === 'assistant') {
|
||||
const text = msg.message.content
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.join('')
|
||||
console.log('Resumed response:', text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Cleanup
|
||||
|
||||
Sessions can be closed manually or automatically using [`await using`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management), a TypeScript 5.2+ feature for automatic resource cleanup. If you're using an older TypeScript version or encounter compatibility issues, use manual cleanup instead.
|
||||
|
||||
**Automatic cleanup (TypeScript 5.2+):**
|
||||
|
||||
```typescript
|
||||
import { unstable_v2_createSession } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
await using session = unstable_v2_createSession({
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
// Session closes automatically when the block exits
|
||||
```
|
||||
|
||||
**Manual cleanup:**
|
||||
|
||||
```typescript
|
||||
import { unstable_v2_createSession } from '@anthropic-ai/claude-agent-sdk'
|
||||
|
||||
const session = unstable_v2_createSession({
|
||||
model: 'claude-sonnet-4-5-20250929'
|
||||
})
|
||||
// ... use the session ...
|
||||
session.close()
|
||||
```
|
||||
|
||||
## API reference
|
||||
|
||||
### `unstable_v2_createSession()`
|
||||
|
||||
Creates a new session for multi-turn conversations.
|
||||
|
||||
```typescript
|
||||
function unstable_v2_createSession(options: {
|
||||
model: string;
|
||||
// Additional options supported
|
||||
}): Session
|
||||
```
|
||||
|
||||
### `unstable_v2_resumeSession()`
|
||||
|
||||
Resumes an existing session by ID.
|
||||
|
||||
```typescript
|
||||
function unstable_v2_resumeSession(
|
||||
sessionId: string,
|
||||
options: {
|
||||
model: string;
|
||||
// Additional options supported
|
||||
}
|
||||
): Session
|
||||
```
|
||||
|
||||
### `unstable_v2_prompt()`
|
||||
|
||||
One-shot convenience function for single-turn queries.
|
||||
|
||||
```typescript
|
||||
function unstable_v2_prompt(
|
||||
prompt: string,
|
||||
options: {
|
||||
model: string;
|
||||
// Additional options supported
|
||||
}
|
||||
): Promise<Result>
|
||||
```
|
||||
|
||||
### Session interface
|
||||
|
||||
```typescript
|
||||
interface Session {
|
||||
send(message: string): Promise<void>;
|
||||
receive(): AsyncGenerator<SDKMessage>;
|
||||
close(): void;
|
||||
}
|
||||
```
|
||||
|
||||
## Feature availability
|
||||
|
||||
Not all V1 features are available in V2 yet. The following require using the [V1 SDK](/docs/en/agent-sdk/typescript):
|
||||
|
||||
- Session forking (`forkSession` option)
|
||||
- Some advanced streaming input patterns
|
||||
|
||||
## Feedback
|
||||
|
||||
Share your feedback on the V2 interface before it becomes stable. Report issues and suggestions through [GitHub Issues](https://github.com/anthropics/claude-code/issues).
|
||||
|
||||
## See also
|
||||
|
||||
- [TypeScript SDK reference (V1)](/docs/en/agent-sdk/typescript) - Full V1 SDK documentation
|
||||
- [SDK overview](/docs/en/agent-sdk/overview) - General SDK concepts
|
||||
- [V2 examples on GitHub](https://github.com/anthropics/claude-agent-sdk-demos/tree/main/hello-world-v2) - Working code examples
|
||||
@@ -0,0 +1,88 @@
|
||||
# Claude-Mem Public Documentation
|
||||
|
||||
## What This Folder Is
|
||||
|
||||
This `docs/public/` folder contains the **Mintlify documentation site** - the official user-facing documentation for claude-mem. It's a structured documentation platform with a specific file format and organization.
|
||||
|
||||
## Folder Structure
|
||||
|
||||
```
|
||||
docs/
|
||||
├── public/ ← You are here (Mintlify MDX files)
|
||||
│ ├── *.mdx - User-facing documentation pages
|
||||
│ ├── docs.json - Mintlify configuration and navigation
|
||||
│ ├── architecture/ - Technical architecture docs
|
||||
│ ├── usage/ - User guides and workflows
|
||||
│ └── *.webp, *.gif - Assets (logos, screenshots)
|
||||
└── context/ ← Internal documentation (DO NOT put here)
|
||||
└── *.md - Planning docs, audits, references
|
||||
```
|
||||
|
||||
## File Requirements
|
||||
|
||||
### Mintlify Documentation Files (.mdx)
|
||||
All official documentation files must be:
|
||||
- Written in `.mdx` format (Markdown with JSX support)
|
||||
- Listed in `docs.json` navigation structure
|
||||
- Follow Mintlify's schema and conventions
|
||||
|
||||
The documentation is organized into these sections:
|
||||
- **Get Started**: Introduction, installation, usage guides
|
||||
- **Best Practices**: Context engineering, progressive disclosure
|
||||
- **Configuration & Development**: Settings, dev workflow, troubleshooting
|
||||
- **Architecture**: System design, components, technical details
|
||||
|
||||
### Configuration File
|
||||
`docs.json` defines:
|
||||
- Site metadata (name, description, theme)
|
||||
- Navigation structure
|
||||
- Branding (logos, colors)
|
||||
- Footer links and social media
|
||||
|
||||
## What Does NOT Belong Here
|
||||
|
||||
**Planning documents, design docs, and reference materials go in `/docs/context/` instead:**
|
||||
|
||||
Files that belong in `/docs/context/` (NOT here):
|
||||
- Planning documents (`*-plan.md`, `*-outline.md`)
|
||||
- Implementation analysis (`*-audit.md`, `*-code-reference.md`)
|
||||
- Error tracking (`typescript-errors.md`)
|
||||
- Internal design documents
|
||||
- PR review responses
|
||||
- Reference materials (like `agent-sdk-ref.md`)
|
||||
- Work-in-progress documentation
|
||||
|
||||
## How to Add Official Documentation
|
||||
|
||||
1. Create a new `.mdx` file in the appropriate subdirectory
|
||||
2. Add the file path to `docs.json` navigation
|
||||
3. Use Mintlify's frontmatter and components
|
||||
4. Follow the existing documentation style
|
||||
5. Test locally: `npx mintlify dev`
|
||||
|
||||
## Development Workflow
|
||||
|
||||
**For contributors working on claude-mem:**
|
||||
- Read `/CLAUDE.md` in the project root for development instructions
|
||||
- Place planning/design docs in `/docs/context/`
|
||||
- Only add user-facing documentation to `/docs/public/`
|
||||
- Test documentation locally with Mintlify CLI before committing
|
||||
|
||||
## Testing Documentation
|
||||
|
||||
```bash
|
||||
# Validate docs structure
|
||||
npx mintlify validate
|
||||
|
||||
# Check for broken links
|
||||
npx mintlify broken-links
|
||||
|
||||
# Run local dev server
|
||||
npx mintlify dev
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
**Simple Rule**:
|
||||
- `/docs/public/` = Official user documentation (Mintlify .mdx files) ← YOU ARE HERE
|
||||
- `/docs/context/` = Internal docs, plans, references, audits
|
||||
@@ -5,17 +5,17 @@ description: "SQLite schema, FTS5 search, and data storage"
|
||||
|
||||
# Database Architecture
|
||||
|
||||
Claude-Mem uses SQLite 3 with the better-sqlite3 native module for persistent storage and FTS5 for full-text search.
|
||||
Claude-Mem uses SQLite 3 with the bun:sqlite native module for persistent storage and FTS5 for full-text search.
|
||||
|
||||
## Database Location
|
||||
|
||||
- **Current**: `~/.claude-mem/claude-mem.db`
|
||||
**Path**: `~/.claude-mem/claude-mem.db`
|
||||
|
||||
**Note**: Despite the README claiming v4.0.0+ moved the database to `${CLAUDE_PLUGIN_ROOT}/data/`, the actual implementation still uses `~/.claude-mem/`.
|
||||
The database uses SQLite's WAL (Write-Ahead Logging) mode for concurrent reads/writes.
|
||||
|
||||
## Database Implementation
|
||||
|
||||
**Primary Implementation**: better-sqlite3 (native SQLite module)
|
||||
**Primary Implementation**: bun:sqlite (native SQLite module)
|
||||
- Used by: SessionStore and SessionSearch
|
||||
- Format: Synchronous API with better performance
|
||||
- **Note**: Database.ts (using bun:sqlite) is legacy code
|
||||
@@ -301,8 +301,8 @@ Database schema is managed via migrations in `src/services/sqlite/migrations.ts`
|
||||
- **Indexes**: All foreign keys and frequently queried columns are indexed
|
||||
- **FTS5**: Full-text search is significantly faster than LIKE queries
|
||||
- **Triggers**: Automatic synchronization has minimal overhead
|
||||
- **Connection Pooling**: better-sqlite3 reuses connections efficiently
|
||||
- **Synchronous API**: better-sqlite3 uses synchronous API for better performance
|
||||
- **Connection Pooling**: bun:sqlite reuses connections efficiently
|
||||
- **Synchronous API**: bun:sqlite uses synchronous API for better performance
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -0,0 +1,959 @@
|
||||
---
|
||||
title: "Hook Lifecycle"
|
||||
description: "Complete guide to the 5-stage memory agent lifecycle for platform implementers"
|
||||
---
|
||||
|
||||
# Hook Lifecycle
|
||||
|
||||
Claude-Mem implements a **5-stage hook system** that captures development work across Claude Code sessions. This document provides a complete technical reference for developers implementing this pattern on other platforms.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### System Architecture
|
||||
|
||||
This two-process architecture works in both Claude Code and VS Code:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph EXT["Extension Process (runs in IDE)"]
|
||||
direction TB
|
||||
ACT[Extension Activation]
|
||||
HOOKS[Hook Event Handlers]
|
||||
ACT --> HOOKS
|
||||
|
||||
subgraph HOOK_HANDLERS["5 Lifecycle Hooks"]
|
||||
H1[SessionStart<br/>activate function]
|
||||
H2[UserPromptSubmit<br/>command handler]
|
||||
H3[PostToolUse<br/>middleware]
|
||||
H4[Stop<br/>idle timeout]
|
||||
H5[SessionEnd<br/>deactivate function]
|
||||
end
|
||||
|
||||
HOOKS --> HOOK_HANDLERS
|
||||
end
|
||||
|
||||
HOOK_HANDLERS -->|"HTTP<br/>(fire-and-forget<br/>2s timeout)"| HTTP[Worker HTTP API<br/>Port 37777]
|
||||
|
||||
subgraph WORKER["Worker Process (separate Node.js)"]
|
||||
direction TB
|
||||
HTTP --> API[Express Server]
|
||||
API --> SESS[Session Manager]
|
||||
API --> AGENT[SDK Agent]
|
||||
API --> DB[Database Manager]
|
||||
|
||||
AGENT -->|Event-Driven| CLAUDE[Claude Agent SDK]
|
||||
CLAUDE --> SQLITE[(SQLite + FTS5)]
|
||||
CLAUDE --> CHROMA[(Chroma Vectors)]
|
||||
end
|
||||
|
||||
style EXT fill:#e1f5ff
|
||||
style WORKER fill:#fff4e1
|
||||
style HOOK_HANDLERS fill:#f0f0f0
|
||||
```
|
||||
|
||||
**Key Principles:**
|
||||
- Extension process never blocks (fire-and-forget HTTP)
|
||||
- Worker processes observations asynchronously
|
||||
- Session state persists across IDE restarts
|
||||
|
||||
### VS Code Extension API Integration Points
|
||||
|
||||
For developers porting to VS Code, here's where to hook into the VS Code Extension API:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph VSCODE["VS Code Extension API"]
|
||||
direction TB
|
||||
A["activate(context)"]
|
||||
B["commands.registerCommand()"]
|
||||
C["chat.createChatParticipant()"]
|
||||
D["workspace.onDidSaveTextDocument()"]
|
||||
E["window.onDidChangeActiveTextEditor()"]
|
||||
F["deactivate()"]
|
||||
end
|
||||
|
||||
subgraph HOOKS["Hook Equivalents"]
|
||||
direction TB
|
||||
G[SessionStart]
|
||||
H[UserPromptSubmit]
|
||||
I[PostToolUse]
|
||||
J[Stop/Summary]
|
||||
K[SessionEnd]
|
||||
end
|
||||
|
||||
subgraph WORKER_API["Worker HTTP Endpoints"]
|
||||
direction TB
|
||||
L[GET /api/context/inject]
|
||||
M[POST /sessions/init]
|
||||
N[POST /sessions/observations]
|
||||
O[POST /sessions/summarize]
|
||||
P[POST /sessions/complete]
|
||||
end
|
||||
|
||||
A --> G
|
||||
B --> H
|
||||
C --> H
|
||||
D --> I
|
||||
E --> I
|
||||
F --> K
|
||||
|
||||
G --> L
|
||||
H --> M
|
||||
I --> N
|
||||
J --> O
|
||||
K --> P
|
||||
|
||||
style VSCODE fill:#007acc,color:#fff
|
||||
style HOOKS fill:#f0f0f0
|
||||
style WORKER_API fill:#4caf50,color:#fff
|
||||
```
|
||||
|
||||
**Implementation Examples:**
|
||||
|
||||
```typescript
|
||||
// VS Code Extension - SessionStart Hook
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
const sessionId = generateSessionId()
|
||||
const project = workspace.name || 'default'
|
||||
|
||||
// Fetch context from worker
|
||||
const response = await fetch(`http://localhost:37777/api/context/inject?project=${project}`)
|
||||
const context = await response.text()
|
||||
|
||||
// Inject into chat or UI panel
|
||||
injectContextToChat(context)
|
||||
}
|
||||
|
||||
// VS Code Extension - UserPromptSubmit Hook
|
||||
const command = vscode.commands.registerCommand('extension.command', async (prompt) => {
|
||||
await fetch('http://localhost:37777/sessions/init', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ sessionId, project, userPrompt: prompt })
|
||||
})
|
||||
})
|
||||
|
||||
// VS Code Extension - PostToolUse Hook (middleware pattern)
|
||||
workspace.onDidSaveTextDocument(async (document) => {
|
||||
await fetch('http://localhost:37777/api/sessions/observations', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
claudeSessionId: sessionId,
|
||||
tool_name: 'FileSave',
|
||||
tool_input: { path: document.uri.path },
|
||||
tool_response: 'File saved successfully'
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Async Processing Pipeline
|
||||
|
||||
How observations flow from extension to database without blocking the IDE:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A["Extension: Tool Use Event"] --> B{"Skip List?<br/>(TodoWrite, AskUserQuestion, etc.)"}
|
||||
B -->|"Skip"| X["Discard"]
|
||||
B -->|"Keep"| C["Strip Privacy Tags<br/><private>...</private>"]
|
||||
C --> D["HTTP POST to Worker<br/>Port 37777"]
|
||||
D --> E["2s timeout<br/>fire-and-forget"]
|
||||
E --> F["Extension continues<br/>(non-blocking)"]
|
||||
|
||||
D -.Async Path.-> G["Worker: Queue Observation"]
|
||||
G --> H["SDK Agent picks up<br/>(event-driven)"]
|
||||
H --> I["Call Claude API<br/>(compress observation)"]
|
||||
I --> J["Parse XML response"]
|
||||
J --> K["Save to SQLite<br/>(sdk_sessions table)"]
|
||||
K --> L["Sync to Chroma<br/>(vector embeddings)"]
|
||||
|
||||
style F fill:#90EE90,stroke:#2d6b2d,stroke-width:3px
|
||||
style L fill:#87CEEB,stroke:#2d5f8d,stroke-width:3px
|
||||
style E fill:#ffeb3b,stroke:#c6a700,stroke-width:2px
|
||||
```
|
||||
|
||||
**Critical Pattern:** The extension's HTTP call has a 2-second timeout and doesn't wait for AI processing. The worker handles compression asynchronously using an event-driven queue.
|
||||
|
||||
## The 5 Lifecycle Stages
|
||||
|
||||
| Stage | Hook | Trigger | Purpose |
|
||||
|-------|------|---------|---------|
|
||||
| **1. SessionStart** | `context-hook.js` + `user-message-hook.js` | User opens Claude Code | Inject prior context, show UI messages |
|
||||
| **2. UserPromptSubmit** | `new-hook.js` | User submits a prompt | Create/get session, save prompt, init worker |
|
||||
| **3. PostToolUse** | `save-hook.js` | Claude uses any tool | Queue observation for AI compression |
|
||||
| **4. Stop** | `summary-hook.js` | User stops asking questions | Generate session summary |
|
||||
| **5. SessionEnd** | `cleanup-hook.js` | Session closes | Mark session completed |
|
||||
|
||||
## Hook Configuration
|
||||
|
||||
Hooks are configured in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 300
|
||||
}, {
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/user-message-hook.js",
|
||||
"timeout": 10
|
||||
}]
|
||||
}],
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Stage 1: SessionStart
|
||||
|
||||
**Timing**: When user opens Claude Code or resumes session
|
||||
|
||||
**Hooks Triggered** (in order):
|
||||
1. `context-hook.js` - Fetches and injects prior session context
|
||||
2. `user-message-hook.js` - Displays context info to user via stderr
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant IDE as IDE/Extension
|
||||
participant ContextHook as context-hook.js
|
||||
participant Worker as Worker Service
|
||||
participant DB as SQLite Database
|
||||
|
||||
User->>IDE: Opens workspace / resumes session
|
||||
IDE->>ContextHook: Trigger SessionStart hook
|
||||
ContextHook->>ContextHook: Generate/reuse session_id
|
||||
ContextHook->>Worker: Health check (max 10s retry)
|
||||
|
||||
alt Worker Ready
|
||||
ContextHook->>Worker: GET /api/context/inject?project=X
|
||||
Worker->>DB: SELECT * FROM observations<br/>WHERE project=X<br/>ORDER BY created_at DESC<br/>LIMIT 50
|
||||
DB-->>Worker: Last 50 observations
|
||||
Worker-->>ContextHook: Context markdown
|
||||
ContextHook-->>IDE: hookSpecificOutput.additionalContext
|
||||
IDE->>IDE: Inject context to Claude's prompt
|
||||
IDE-->>User: Session ready with context
|
||||
else Worker Not Ready
|
||||
ContextHook-->>IDE: Empty context (graceful degradation)
|
||||
IDE-->>User: Session ready without context
|
||||
end
|
||||
|
||||
Note over User,DB: Total time: <300ms (with health check)
|
||||
```
|
||||
|
||||
### Context Hook (`context-hook.js`)
|
||||
|
||||
**Purpose**: Inject context from previous sessions into Claude's initial context.
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "startup"
|
||||
}
|
||||
```
|
||||
|
||||
**Processing**:
|
||||
1. Wait for worker to be available (health check, max 10 seconds)
|
||||
2. Call: `GET http://127.0.0.1:37777/api/context/inject?project={project}`
|
||||
3. Return formatted context as `additionalContext` in `hookSpecificOutput`
|
||||
|
||||
**Output** (via stdout):
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": "<<formatted context markdown>>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/context-hook.ts`
|
||||
|
||||
### User Message Hook (`user-message-hook.js`)
|
||||
|
||||
**Purpose**: Display helpful user messages during first-time setup or when viewing context.
|
||||
|
||||
**Behavior**:
|
||||
- Shows first-time setup message when `node_modules` is missing
|
||||
- Displays formatted context information with colors
|
||||
- Provides tips for using claude-mem effectively
|
||||
- Shows link to viewer UI (`http://localhost:37777`)
|
||||
- Uses stderr as communication channel (only output available in Claude Code UI)
|
||||
|
||||
**Implementation**: `src/hooks/user-message-hook.ts`
|
||||
|
||||
---
|
||||
|
||||
## Stage 2: UserPromptSubmit
|
||||
|
||||
**Timing**: When user submits any prompt in a session
|
||||
|
||||
**Hook**: `new-hook.js`
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant IDE as IDE/Extension
|
||||
participant NewHook as new-hook.js
|
||||
participant DB as Direct SQLite Access
|
||||
participant Worker as Worker Service
|
||||
|
||||
User->>IDE: Submits prompt: "Add login feature"
|
||||
IDE->>NewHook: Trigger UserPromptSubmit<br/>{ session_id, cwd, prompt }
|
||||
|
||||
NewHook->>NewHook: Extract project = basename(cwd)
|
||||
NewHook->>NewHook: Strip privacy tags<br/><private>...</private>
|
||||
|
||||
alt Prompt fully private (empty after stripping)
|
||||
NewHook-->>IDE: Skip (don't save)
|
||||
else Prompt has content
|
||||
NewHook->>DB: INSERT OR IGNORE INTO sdk_sessions<br/>(claude_session_id, project, first_user_prompt)
|
||||
DB-->>NewHook: sessionDbId (new or existing)
|
||||
|
||||
NewHook->>DB: UPDATE sdk_sessions<br/>SET prompt_counter = prompt_counter + 1<br/>WHERE id = sessionDbId
|
||||
DB-->>NewHook: promptNumber (e.g., 1 for first, 2 for continuation)
|
||||
|
||||
NewHook->>DB: INSERT INTO user_prompts<br/>(session_id, prompt_number, prompt)
|
||||
|
||||
NewHook->>Worker: POST /sessions/{sessionDbId}/init<br/>{ project, userPrompt, promptNumber }<br/>(fire-and-forget, 2s timeout)
|
||||
Worker-->>NewHook: 200 OK (or timeout)
|
||||
|
||||
NewHook-->>IDE: { continue: true, suppressOutput: true }
|
||||
IDE-->>User: Prompt accepted
|
||||
end
|
||||
|
||||
Note over NewHook,DB: Idempotent: Same session_id → same sessionDbId
|
||||
```
|
||||
|
||||
**Key Pattern:** The `INSERT OR IGNORE` ensures the same `session_id` always maps to the same `sessionDbId`, enabling conversation continuations.
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"prompt": "User's actual prompt text"
|
||||
}
|
||||
```
|
||||
|
||||
**Processing Steps**:
|
||||
|
||||
```typescript
|
||||
// 1. Extract project name from working directory
|
||||
project = path.basename(cwd)
|
||||
|
||||
// 2. Create or get database session (IDEMPOTENT)
|
||||
sessionDbId = db.createSDKSession(session_id, project, prompt)
|
||||
// INSERT OR IGNORE: Creates new row if first prompt, returns existing if continuation
|
||||
|
||||
// 3. Increment prompt counter
|
||||
promptNumber = db.incrementPromptCounter(sessionDbId)
|
||||
// Returns 1 for first prompt, 2 for continuation, etc.
|
||||
|
||||
// 4. Strip privacy tags
|
||||
cleanedPrompt = stripMemoryTagsFromPrompt(prompt)
|
||||
// Removes <private>...</private> and <claude-mem-context>...</claude-mem-context>
|
||||
|
||||
// 5. Skip if fully private
|
||||
if (!cleanedPrompt || cleanedPrompt.trim() === '') {
|
||||
return // Don't save, don't call worker
|
||||
}
|
||||
|
||||
// 6. Save user prompt to database
|
||||
db.saveUserPrompt(session_id, promptNumber, cleanedPrompt)
|
||||
|
||||
// 7. Initialize session via worker HTTP
|
||||
POST http://127.0.0.1:37777/sessions/{sessionDbId}/init
|
||||
Body: { project, userPrompt, promptNumber }
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```json
|
||||
{ "continue": true, "suppressOutput": true }
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/new-hook.ts`
|
||||
|
||||
<Note>
|
||||
The same `session_id` flows through ALL hooks in a conversation. The `createSDKSession` call is idempotent - it returns the existing session for continuation prompts.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Stage 3: PostToolUse
|
||||
|
||||
**Timing**: After Claude uses any tool (Read, Bash, Grep, Write, etc.)
|
||||
|
||||
**Hook**: `save-hook.js`
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Claude as Claude AI
|
||||
participant IDE as IDE/Extension
|
||||
participant SaveHook as save-hook.js
|
||||
participant Worker as Worker Service
|
||||
participant Agent as SDK Agent
|
||||
participant DB as SQLite + Chroma
|
||||
|
||||
Claude->>IDE: Uses tool: Read("/src/auth.ts")
|
||||
IDE->>SaveHook: PostToolUse hook triggered<br/>{ session_id, tool_name, tool_input, tool_response }
|
||||
|
||||
SaveHook->>SaveHook: Check skip list<br/>(TodoWrite, AskUserQuestion, etc.)
|
||||
|
||||
alt Tool in skip list
|
||||
SaveHook-->>IDE: Discard (low-value tool)
|
||||
else Tool allowed
|
||||
SaveHook->>SaveHook: Strip privacy tags from input/response
|
||||
|
||||
SaveHook->>SaveHook: Ensure worker running<br/>(health check)
|
||||
|
||||
SaveHook->>Worker: POST /api/sessions/observations<br/>{ claudeSessionId, tool_name, tool_input, tool_response, cwd }<br/>(fire-and-forget, 2s timeout)
|
||||
|
||||
SaveHook-->>IDE: { continue: true, suppressOutput: true }
|
||||
IDE-->>Claude: Tool execution complete
|
||||
|
||||
Note over Worker,DB: Async path (doesn't block IDE)
|
||||
|
||||
Worker->>Worker: createSDKSession(claudeSessionId)<br/>→ returns sessionDbId
|
||||
Worker->>Worker: Check if prompt was private<br/>(skip if fully private)
|
||||
Worker->>Agent: Queue observation for processing
|
||||
Agent->>Agent: Call Claude SDK to compress<br/>observation into structured format
|
||||
Agent->>DB: Save compressed observation<br/>to sdk_sessions table
|
||||
Agent->>DB: Sync to Chroma vector DB
|
||||
end
|
||||
|
||||
Note over SaveHook,DB: Total sync time: ~2ms<br/>AI processing: 1-3s (async)
|
||||
```
|
||||
|
||||
**Key Pattern:** The hook returns immediately after HTTP POST. AI compression happens asynchronously in the worker without blocking Claude's tool execution.
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"tool_name": "Read",
|
||||
"tool_input": { "file_path": "/src/index.ts" },
|
||||
"tool_response": "file contents..."
|
||||
}
|
||||
```
|
||||
|
||||
**Processing Steps**:
|
||||
|
||||
```typescript
|
||||
// 1. Check blocklist - skip low-value tools
|
||||
const SKIP_TOOLS = {
|
||||
'ListMcpResourcesTool', // MCP infrastructure noise
|
||||
'SlashCommand', // Command invocation
|
||||
'Skill', // Skill invocation
|
||||
'TodoWrite', // Task management meta-tool
|
||||
'AskUserQuestion' // User interaction
|
||||
}
|
||||
|
||||
if (SKIP_TOOLS[tool_name]) return
|
||||
|
||||
// 2. Ensure worker is running
|
||||
await ensureWorkerRunning()
|
||||
|
||||
// 3. Send to worker (fire-and-forget HTTP)
|
||||
POST http://127.0.0.1:37777/api/sessions/observations
|
||||
Body: {
|
||||
claudeSessionId: session_id,
|
||||
tool_name,
|
||||
tool_input,
|
||||
tool_response,
|
||||
cwd
|
||||
}
|
||||
Timeout: 2000ms
|
||||
```
|
||||
|
||||
**Worker Processing**:
|
||||
1. Looks up or creates session: `createSDKSession(claudeSessionId, '', '')`
|
||||
2. Gets prompt counter
|
||||
3. Checks privacy (skips if user prompt was entirely private)
|
||||
4. Strips memory tags from `tool_input` and `tool_response`
|
||||
5. Queues observation for SDK agent processing
|
||||
6. SDK agent calls Claude to compress into structured observation
|
||||
7. Stores observation in database and syncs to Chroma
|
||||
|
||||
**Output**:
|
||||
```json
|
||||
{ "continue": true, "suppressOutput": true }
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/save-hook.ts`
|
||||
|
||||
---
|
||||
|
||||
## Stage 4: Stop
|
||||
|
||||
**Timing**: When user stops or pauses asking questions
|
||||
|
||||
**Hook**: `summary-hook.js`
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant IDE as IDE/Extension
|
||||
participant SummaryHook as summary-hook.js
|
||||
participant Worker as Worker Service
|
||||
participant Agent as SDK Agent
|
||||
participant DB as SQLite Database
|
||||
|
||||
User->>IDE: Stops asking questions<br/>(pause, idle, or explicit stop)
|
||||
IDE->>SummaryHook: Stop hook triggered<br/>{ session_id, cwd, transcript_path }
|
||||
|
||||
SummaryHook->>SummaryHook: Read transcript JSONL file
|
||||
SummaryHook->>SummaryHook: Extract last user message<br/>(type: "user")
|
||||
SummaryHook->>SummaryHook: Extract last assistant message<br/>(type: "assistant", filter <system-reminder>)
|
||||
|
||||
SummaryHook->>Worker: POST /api/sessions/summarize<br/>{ claudeSessionId, last_user_message, last_assistant_message }<br/>(fire-and-forget, 2s timeout)
|
||||
|
||||
SummaryHook->>Worker: POST /api/processing<br/>{ isProcessing: false }<br/>(stop spinner)
|
||||
|
||||
SummaryHook-->>IDE: { continue: true, suppressOutput: true }
|
||||
IDE-->>User: Session paused/stopped
|
||||
|
||||
Note over Worker,DB: Async path
|
||||
|
||||
Worker->>Worker: Lookup sessionDbId from claudeSessionId
|
||||
Worker->>Agent: Queue summarization request
|
||||
Agent->>Agent: Call Claude SDK with prompt:<br/>"Summarize: request, investigated, learned, completed, next_steps"
|
||||
Agent->>Agent: Parse XML response
|
||||
Agent->>DB: INSERT INTO session_summaries<br/>{ session_id, request, investigated, learned, completed, next_steps }
|
||||
Agent->>DB: Sync to Chroma (for semantic search)
|
||||
|
||||
Note over SummaryHook,DB: Total sync time: ~2ms<br/>AI summarization: 2-5s (async)
|
||||
```
|
||||
|
||||
**Key Pattern:** The summary is generated asynchronously and doesn't block the user from resuming work or closing the session.
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"transcript_path": "/path/to/transcript.jsonl"
|
||||
}
|
||||
```
|
||||
|
||||
**Processing Steps**:
|
||||
|
||||
```typescript
|
||||
// 1. Extract last messages from transcript JSONL
|
||||
const lines = fs.readFileSync(transcript_path, 'utf-8').split('\n')
|
||||
// Find last user message (type: "user")
|
||||
// Find last assistant message (type: "assistant", filter <system-reminder> tags)
|
||||
|
||||
// 2. Ensure worker is running
|
||||
await ensureWorkerRunning()
|
||||
|
||||
// 3. Send summarization request (fire-and-forget HTTP)
|
||||
POST http://127.0.0.1:37777/api/sessions/summarize
|
||||
Body: {
|
||||
claudeSessionId: session_id,
|
||||
last_user_message: string,
|
||||
last_assistant_message: string
|
||||
}
|
||||
Timeout: 2000ms
|
||||
|
||||
// 4. Stop processing spinner
|
||||
POST http://127.0.0.1:37777/api/processing
|
||||
Body: { isProcessing: false }
|
||||
```
|
||||
|
||||
**Worker Processing**:
|
||||
1. Queues summarization for SDK agent
|
||||
2. Agent calls Claude to generate structured summary
|
||||
3. Summary stored in database with fields: `request`, `investigated`, `learned`, `completed`, `next_steps`
|
||||
|
||||
**Output**:
|
||||
```json
|
||||
{ "continue": true, "suppressOutput": true }
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/summary-hook.ts`
|
||||
|
||||
---
|
||||
|
||||
## Stage 5: SessionEnd
|
||||
|
||||
**Timing**: When Claude Code session closes (exit, clear, logout, etc.)
|
||||
|
||||
**Hook**: `cleanup-hook.js`
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant IDE as IDE/Extension
|
||||
participant CleanupHook as cleanup-hook.js
|
||||
participant Worker as Worker Service
|
||||
participant DB as SQLite Database
|
||||
participant SSE as SSE Clients (Viewer UI)
|
||||
|
||||
User->>IDE: Closes session<br/>(exit, clear, logout)
|
||||
IDE->>CleanupHook: SessionEnd hook triggered<br/>{ session_id, cwd, transcript_path, reason }
|
||||
|
||||
CleanupHook->>Worker: POST /api/sessions/complete<br/>{ claudeSessionId, reason }<br/>(fire-and-forget, 2s timeout)
|
||||
|
||||
CleanupHook-->>IDE: { continue: true, suppressOutput: true }
|
||||
IDE-->>User: Session closed
|
||||
|
||||
Note over Worker,SSE: Async path
|
||||
|
||||
Worker->>Worker: Lookup sessionDbId from claudeSessionId
|
||||
Worker->>DB: UPDATE sdk_sessions<br/>SET status = 'completed', completed_at = NOW()<br/>WHERE claude_session_id = claudeSessionId
|
||||
Worker->>SSE: Broadcast session completion event<br/>(for live viewer UI updates)
|
||||
|
||||
SSE-->>SSE: Update UI to show session as completed
|
||||
|
||||
Note over CleanupHook,SSE: Total sync time: ~2ms
|
||||
```
|
||||
|
||||
**Key Pattern:** Session completion is tracked for analytics and UI updates, but doesn't prevent the user from closing the IDE.
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"transcript_path": "/path/to/transcript.jsonl",
|
||||
"reason": "exit"
|
||||
}
|
||||
```
|
||||
|
||||
**Processing Steps**:
|
||||
|
||||
```typescript
|
||||
// Send session complete (fire-and-forget HTTP)
|
||||
POST http://127.0.0.1:37777/api/sessions/complete
|
||||
Body: {
|
||||
claudeSessionId: session_id,
|
||||
reason: string // 'exit' | 'clear' | 'logout' | 'prompt_input_exit' | 'other'
|
||||
}
|
||||
Timeout: 2000ms
|
||||
```
|
||||
|
||||
**Worker Processing**:
|
||||
1. Finds session by `claudeSessionId`
|
||||
2. Marks session as 'completed' in database
|
||||
3. Broadcasts session completion event to SSE clients
|
||||
|
||||
**Output**:
|
||||
```json
|
||||
{ "continue": true, "suppressOutput": true }
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/cleanup-hook.ts`
|
||||
|
||||
---
|
||||
|
||||
## Session State Machine
|
||||
|
||||
Understanding session lifecycle and state transitions:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Initialized: SessionStart hook<br/>(generate session_id)
|
||||
|
||||
Initialized --> Active: UserPromptSubmit<br/>(first prompt)
|
||||
|
||||
Active --> Active: UserPromptSubmit<br/>(continuation prompts)<br/>promptNumber++
|
||||
|
||||
Active --> ObservationQueued: PostToolUse hook<br/>(tool execution captured)
|
||||
|
||||
ObservationQueued --> Active: Observation processed<br/>(async, non-blocking)
|
||||
|
||||
Active --> Summarizing: Stop hook<br/>(user pauses/stops)
|
||||
|
||||
Summarizing --> Active: User resumes<br/>(new prompt submitted)
|
||||
|
||||
Summarizing --> Completed: SessionEnd hook<br/>(session closes)
|
||||
|
||||
Active --> Completed: SessionEnd hook<br/>(session closes)
|
||||
|
||||
Completed --> [*]
|
||||
|
||||
note right of Active
|
||||
session_id: constant (e.g., "claude-session-abc123")
|
||||
sessionDbId: constant (e.g., 42)
|
||||
promptNumber: increments (1, 2, 3, ...)
|
||||
All operations use same sessionDbId
|
||||
end note
|
||||
|
||||
note right of ObservationQueued
|
||||
Fire-and-forget HTTP
|
||||
AI compression happens async
|
||||
IDE never blocks
|
||||
end note
|
||||
```
|
||||
|
||||
**Key Insights:**
|
||||
- `session_id` never changes during a conversation
|
||||
- `sessionDbId` is the database primary key for the session
|
||||
- `promptNumber` increments with each user prompt
|
||||
- State transitions are non-blocking (fire-and-forget pattern)
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
The session-centric data model that enables cross-session memory:
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
SDK_SESSIONS ||--o{ USER_PROMPTS : "has many"
|
||||
SDK_SESSIONS ||--o{ OBSERVATIONS : "has many"
|
||||
SDK_SESSIONS ||--o{ SESSION_SUMMARIES : "has many"
|
||||
|
||||
SDK_SESSIONS {
|
||||
integer id PK "Auto-increment primary key"
|
||||
text claude_session_id UK "From IDE (e.g., 'claude-session-123')"
|
||||
text project "Project name from cwd basename"
|
||||
text first_user_prompt "Initial prompt that started session"
|
||||
integer prompt_counter "Increments with each UserPromptSubmit"
|
||||
text status "initialized | active | completed"
|
||||
datetime created_at
|
||||
datetime completed_at
|
||||
}
|
||||
|
||||
USER_PROMPTS {
|
||||
integer id PK
|
||||
integer session_id FK "References SDK_SESSIONS.id"
|
||||
integer prompt_number "1, 2, 3, ... matches prompt_counter"
|
||||
text prompt "User's actual prompt (tags stripped)"
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
OBSERVATIONS {
|
||||
integer id PK
|
||||
integer session_id FK "References SDK_SESSIONS.id"
|
||||
integer prompt_number "Which prompt this observation belongs to"
|
||||
text tool_name "Read, Bash, Grep, Write, etc."
|
||||
text tool_input_json "Stripped of privacy tags"
|
||||
text tool_response_text "Stripped of privacy tags"
|
||||
text compressed_observation "AI-generated structured observation"
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
SESSION_SUMMARIES {
|
||||
integer id PK
|
||||
integer session_id FK "References SDK_SESSIONS.id"
|
||||
text request "What user requested"
|
||||
text investigated "What was explored"
|
||||
text learned "What was discovered"
|
||||
text completed "What was accomplished"
|
||||
text next_steps "What remains to be done"
|
||||
datetime created_at
|
||||
}
|
||||
```
|
||||
|
||||
**Idempotency Pattern:**
|
||||
|
||||
```sql
|
||||
-- This ensures same session_id always maps to same sessionDbId
|
||||
INSERT OR IGNORE INTO sdk_sessions (claude_session_id, project, first_user_prompt)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING id;
|
||||
|
||||
-- If already exists, returns existing row
|
||||
-- If new, creates and returns new row
|
||||
```
|
||||
|
||||
**Foreign Key Cascade:**
|
||||
|
||||
All child tables (user_prompts, observations, session_summaries) use `session_id` foreign key referencing `SDK_SESSIONS.id`. This ensures:
|
||||
- All data for a session is queryable by sessionDbId
|
||||
- Session deletions cascade to child tables
|
||||
- Efficient joins for context injection
|
||||
|
||||
<Warning>
|
||||
Never generate your own session IDs. Always use the `session_id` provided by the IDE - this is the source of truth for linking all data together.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Privacy & Tag Stripping
|
||||
|
||||
### Dual-Tag System
|
||||
|
||||
```typescript
|
||||
// User-Level Privacy Control (manual)
|
||||
<private>sensitive data</private>
|
||||
|
||||
// System-Level Recursion Prevention (auto-injected)
|
||||
<claude-mem-context>...</claude-mem-context>
|
||||
```
|
||||
|
||||
### Processing Pipeline
|
||||
|
||||
**Location**: `src/utils/tag-stripping.ts`
|
||||
|
||||
```typescript
|
||||
// Called by: new-hook.js (user prompts)
|
||||
stripMemoryTagsFromPrompt(prompt: string): string
|
||||
|
||||
// Called by: save-hook.js (tool_input, tool_response)
|
||||
stripMemoryTagsFromJson(jsonString: string): string
|
||||
```
|
||||
|
||||
**Execution Order** (Edge Processing):
|
||||
1. `new-hook.js` strips tags from user prompt before saving
|
||||
2. `save-hook.js` strips tags from tool data before sending to worker
|
||||
3. Worker strips tags again (defense in depth) before storing
|
||||
|
||||
---
|
||||
|
||||
## SDK Agent Processing
|
||||
|
||||
### Query Loop (Event-Driven)
|
||||
|
||||
**Location**: `src/services/worker/SDKAgent.ts`
|
||||
|
||||
```typescript
|
||||
async startSession(session: ActiveSession, worker?: any) {
|
||||
// 1. Create event-driven message generator
|
||||
const messageGenerator = this.createMessageGenerator(session)
|
||||
|
||||
// 2. Run Agent SDK query loop
|
||||
const queryResult = query({
|
||||
prompt: messageGenerator,
|
||||
options: {
|
||||
model: 'claude-sonnet-4-5',
|
||||
disallowedTools: ['Bash', 'Read', 'Write', ...], // Observer-only
|
||||
abortController: session.abortController
|
||||
}
|
||||
})
|
||||
|
||||
// 3. Process responses
|
||||
for await (const message of queryResult) {
|
||||
if (message.type === 'assistant') {
|
||||
await this.processSDKResponse(session, text, worker)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Message Types
|
||||
|
||||
The message generator yields three types of prompts:
|
||||
|
||||
1. **Initial Prompt** (prompt #1): Full instructions for starting observation
|
||||
2. **Continuation Prompt** (prompt #2+): Context-only for continuing work
|
||||
3. **Observation Prompts**: Tool use data to compress into observations
|
||||
4. **Summary Prompts**: Session data to summarize
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
For developers implementing this pattern on other platforms:
|
||||
|
||||
### Hook Registration
|
||||
- [ ] Define hook entry points in platform config
|
||||
- [ ] 5 hook types: SessionStart (2 hooks), UserPromptSubmit, PostToolUse, Stop, SessionEnd
|
||||
- [ ] Pass `session_id`, `cwd`, and context-specific data
|
||||
|
||||
### Database Schema
|
||||
- [ ] SQLite with WAL mode
|
||||
- [ ] 4 main tables: `sdk_sessions`, `user_prompts`, `observations`, `session_summaries`
|
||||
- [ ] Indices for common queries
|
||||
|
||||
### Worker Service
|
||||
- [ ] HTTP server on configurable port (default 37777)
|
||||
- [ ] Bun runtime for process management
|
||||
- [ ] 3 core services: SessionManager, SDKAgent, DatabaseManager
|
||||
|
||||
### Hook Implementation
|
||||
- [ ] context-hook: `GET /api/context/inject` (with health check)
|
||||
- [ ] new-hook: createSDKSession, saveUserPrompt, `POST /sessions/{id}/init`
|
||||
- [ ] save-hook: Skip low-value tools, `POST /api/sessions/observations`
|
||||
- [ ] summary-hook: Parse transcript, `POST /api/sessions/summarize`
|
||||
- [ ] cleanup-hook: `POST /api/sessions/complete`
|
||||
|
||||
### Privacy & Tags
|
||||
- [ ] Implement `stripMemoryTagsFromPrompt()` and `stripMemoryTagsFromJson()`
|
||||
- [ ] Process tags at hook layer (edge processing)
|
||||
- [ ] Max tag count = 100 (ReDoS protection)
|
||||
|
||||
### SDK Integration
|
||||
- [ ] Call Claude Agent SDK to process observations/summaries
|
||||
- [ ] Parse XML responses for structured data
|
||||
- [ ] Store to database + sync to vector DB
|
||||
|
||||
---
|
||||
|
||||
## Key Design Principles
|
||||
|
||||
1. **Session ID is Source of Truth**: Never generate your own session IDs
|
||||
2. **Idempotent Database Operations**: Use `INSERT OR IGNORE` for session creation
|
||||
3. **Edge Processing for Privacy**: Strip tags at hook layer before data reaches worker
|
||||
4. **Fire-and-Forget for Non-Blocking**: HTTP timeouts prevent IDE blocking
|
||||
5. **Event-Driven, Not Polling**: Zero-latency queue notification to SDK agent
|
||||
6. **Everything Saves Always**: No "orphaned" sessions
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
| Problem | Root Cause | Solution |
|
||||
|---------|-----------|----------|
|
||||
| Session ID mismatch | Different `session_id` used in different hooks | Always use ID from hook input |
|
||||
| Duplicate sessions | Creating new session instead of using existing | Use `INSERT OR IGNORE` with `session_id` as key |
|
||||
| Blocking IDE | Waiting for full response | Use fire-and-forget with short timeouts |
|
||||
| Memory tags in DB | Stripping tags in wrong layer | Strip at hook layer, before HTTP send |
|
||||
| Worker not found | Health check too fast | Add retry loop with exponential backoff |
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Worker Service](/architecture/worker-service) - HTTP API and async processing
|
||||
- [Database Schema](/architecture/database) - SQLite tables and FTS5 search
|
||||
- [Privacy Tags](/usage/private-tags) - Using `<private>` tags
|
||||
- [Troubleshooting](/troubleshooting) - Common hook issues
|
||||
@@ -0,0 +1,240 @@
|
||||
---
|
||||
title: "Architecture Overview"
|
||||
description: "System components and data flow in Claude-Mem"
|
||||
---
|
||||
|
||||
# Architecture Overview
|
||||
|
||||
## System Components
|
||||
|
||||
Claude-Mem operates as a Claude Code plugin with five core components:
|
||||
|
||||
1. **Plugin Hooks** - Capture lifecycle events (6 hook files)
|
||||
2. **Smart Install** - Cached dependency checker (pre-hook script, runs before context-hook)
|
||||
3. **Worker Service** - Process observations via Claude Agent SDK + HTTP API (10 search endpoints)
|
||||
4. **Database Layer** - Store sessions and observations (SQLite + FTS5 + ChromaDB)
|
||||
5. **mem-search Skill** - Skill-based search with progressive disclosure (v5.4.0+)
|
||||
6. **Viewer UI** - Web-based real-time memory stream visualization
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|------------------------|-------------------------------------------|
|
||||
| **Language** | TypeScript (ES2022, ESNext modules) |
|
||||
| **Runtime** | Node.js 18+ |
|
||||
| **Database** | SQLite 3 with bun:sqlite driver |
|
||||
| **Vector Store** | ChromaDB (optional, for semantic search) |
|
||||
| **HTTP Server** | Express.js 4.18 |
|
||||
| **Real-time** | Server-Sent Events (SSE) |
|
||||
| **UI Framework** | React + TypeScript |
|
||||
| **AI SDK** | @anthropic-ai/claude-agent-sdk |
|
||||
| **Build Tool** | esbuild (bundles TypeScript) |
|
||||
| **Process Manager** | Bun |
|
||||
| **Testing** | Node.js built-in test runner |
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Memory Pipeline
|
||||
```
|
||||
Hook (stdin) → Database → Worker Service → SDK Processor → Database → Next Session Hook
|
||||
```
|
||||
|
||||
1. **Input**: Claude Code sends tool execution data via stdin to hooks
|
||||
2. **Storage**: Hooks write observations to SQLite database
|
||||
3. **Processing**: Worker service reads observations, processes via SDK
|
||||
4. **Output**: Processed summaries written back to database
|
||||
5. **Retrieval**: Next session's context hook reads summaries from database
|
||||
|
||||
### Search Pipeline (v5.4.0+)
|
||||
```
|
||||
User Query → mem-search Skill Invoked → HTTP API → SessionSearch Service → FTS5 Database → Search Results → Claude
|
||||
```
|
||||
|
||||
1. **User Query**: User asks naturally: "What bugs did we fix?"
|
||||
2. **Skill Invoked**: Claude recognizes intent and invokes mem-search skill
|
||||
3. **HTTP API**: Skill uses curl to call HTTP endpoint (e.g., `/api/search/observations`)
|
||||
4. **SessionSearch**: Worker service queries FTS5 virtual tables
|
||||
5. **Format**: Results formatted and returned to skill
|
||||
6. **Return**: Claude presents formatted results to user
|
||||
|
||||
**Token Savings**: ~2,250 tokens per session vs MCP approach through progressive disclosure
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 0. Smart Install Pre-Hook Fires │
|
||||
│ Checks dependencies (cached), only runs on version changes │
|
||||
│ Not a lifecycle hook - runs before context-hook starts │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Session Starts → Context Hook Fires │
|
||||
│ Starts Bun worker if needed, injects context from previous │
|
||||
│ sessions (configurable observation count) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. User Types Prompt → UserPromptSubmit Hook Fires │
|
||||
│ Creates session in database, saves raw user prompt for FTS5 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Claude Uses Tools → PostToolUse Hook Fires (100+ times) │
|
||||
│ Captures tool executions, sends to worker for AI compression │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Worker Processes → Claude Agent SDK Analyzes │
|
||||
│ Extracts structured learnings via iterative AI processing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 5. Claude Stops → Summary Hook Fires │
|
||||
│ Generates final summary with request, completions, learnings │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 6. Session Ends → Cleanup Hook Fires │
|
||||
│ Marks session complete (graceful, not DELETE), ready for │
|
||||
│ next session context. Skips on /clear to preserve ongoing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
claude-mem/
|
||||
├── src/
|
||||
│ ├── hooks/ # Hook implementations (6 hooks)
|
||||
│ │ ├── context-hook.ts # SessionStart
|
||||
│ │ ├── user-message-hook.ts # UserMessage (for debugging)
|
||||
│ │ ├── new-hook.ts # UserPromptSubmit
|
||||
│ │ ├── save-hook.ts # PostToolUse
|
||||
│ │ ├── summary-hook.ts # Stop
|
||||
│ │ ├── cleanup-hook.ts # SessionEnd
|
||||
│ │ └── hook-response.ts # Hook response utilities
|
||||
│ │
|
||||
│ ├── sdk/ # Claude Agent SDK integration
|
||||
│ │ ├── prompts.ts # XML prompt builders
|
||||
│ │ ├── parser.ts # XML response parser
|
||||
│ │ └── worker.ts # Main SDK agent loop
|
||||
│ │
|
||||
│ ├── services/
|
||||
│ │ ├── worker-service.ts # Express HTTP + SSE service
|
||||
│ │ └── sqlite/ # Database layer
|
||||
│ │ ├── SessionStore.ts # CRUD operations
|
||||
│ │ ├── SessionSearch.ts # FTS5 search service
|
||||
│ │ ├── migrations.ts
|
||||
│ │ └── types.ts
|
||||
│ │
|
||||
│ ├── ui/ # Viewer UI
|
||||
│ │ └── viewer/ # React + TypeScript web interface
|
||||
│ │ ├── components/ # UI components
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── utils/ # Utilities
|
||||
│ │ └── assets/ # Fonts, logos
|
||||
│ │
|
||||
│ ├── shared/ # Shared utilities
|
||||
│ │ ├── config.ts
|
||||
│ │ ├── paths.ts
|
||||
│ │ └── storage.ts
|
||||
│ │
|
||||
│ └── utils/
|
||||
│ ├── logger.ts
|
||||
│ ├── platform.ts
|
||||
│ └── port-allocator.ts
|
||||
│
|
||||
├── scripts/ # Build and utility scripts
|
||||
│ └── smart-install.js # Cached dependency checker (pre-hook)
|
||||
│
|
||||
├── plugin/ # Plugin distribution
|
||||
│ ├── .claude-plugin/
|
||||
│ │ └── plugin.json
|
||||
│ ├── hooks/
|
||||
│ │ └── hooks.json
|
||||
│ ├── scripts/ # Built executables
|
||||
│ │ ├── context-hook.js
|
||||
│ │ ├── user-message-hook.js
|
||||
│ │ ├── new-hook.js
|
||||
│ │ ├── save-hook.js
|
||||
│ │ ├── summary-hook.js
|
||||
│ │ ├── cleanup-hook.js
|
||||
│ │ └── worker-service.cjs # Background worker + HTTP API
|
||||
│ │
|
||||
│ ├── skills/ # Agent skills (v5.4.0+)
|
||||
│ │ ├── mem-search/ # Search skill with progressive disclosure (v5.5.0)
|
||||
│ │ │ ├── SKILL.md # Skill frontmatter (~250 tokens)
|
||||
│ │ │ ├── operations/ # 12 detailed operation docs
|
||||
│ │ │ └── principles/ # 2 principle guides
|
||||
│ │ ├── troubleshoot/ # Troubleshooting skill
|
||||
│ │ │ ├── SKILL.md
|
||||
│ │ │ └── operations/ # 6 operation docs
|
||||
│ │ └── version-bump/ # Version management skill (deprecated)
|
||||
│ │
|
||||
│ └── ui/ # Built viewer UI
|
||||
│ └── viewer.html # Self-contained bundle
|
||||
│
|
||||
├── tests/ # Test suite
|
||||
├── docs/ # Documentation
|
||||
└── ecosystem.config.cjs # Process configuration (deprecated)
|
||||
```
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. Plugin Hooks (6 Hooks)
|
||||
- **context-hook.js** - SessionStart: Starts Bun worker, injects context
|
||||
- **user-message-hook.js** - UserMessage: Debugging hook
|
||||
- **new-hook.js** - UserPromptSubmit: Creates session, saves prompt
|
||||
- **save-hook.js** - PostToolUse: Captures tool executions
|
||||
- **summary-hook.js** - Stop: Generates session summary
|
||||
- **cleanup-hook.js** - SessionEnd: Marks session complete
|
||||
|
||||
**Note**: smart-install.js is a pre-hook dependency checker (not a lifecycle hook). It's called before context-hook via command chaining in hooks.json and only runs when dependencies need updating.
|
||||
|
||||
See [Plugin Hooks](/architecture/hooks) for detailed hook documentation.
|
||||
|
||||
### 2. Worker Service
|
||||
Express.js HTTP server on port 37777 (configurable) with:
|
||||
- 10 search HTTP API endpoints (v5.4.0+)
|
||||
- 8 viewer UI HTTP/SSE endpoints
|
||||
- Async observation processing via Claude Agent SDK
|
||||
- Real-time updates via Server-Sent Events
|
||||
- Auto-managed by Bun
|
||||
|
||||
See [Worker Service](/architecture/worker-service) for HTTP API and endpoints.
|
||||
|
||||
### 3. Database Layer
|
||||
SQLite3 with bun:sqlite driver featuring:
|
||||
- FTS5 virtual tables for full-text search
|
||||
- SessionStore for CRUD operations
|
||||
- SessionSearch for FTS5 queries
|
||||
- Location: `~/.claude-mem/claude-mem.db`
|
||||
|
||||
See [Database Architecture](/architecture/database) for schema and FTS5 search.
|
||||
|
||||
### 4. mem-search Skill (v5.4.0+)
|
||||
Skill-based search with progressive disclosure providing 10 search operations:
|
||||
- Search observations, sessions, prompts (full-text FTS5)
|
||||
- Filter by type, concept, file
|
||||
- Get recent context, timeline, timeline by query
|
||||
- API help documentation
|
||||
|
||||
**Token Savings**: ~2,250 tokens per session vs MCP approach
|
||||
- Skill frontmatter: ~250 tokens (loaded at session start)
|
||||
- Full instructions: ~2,500 tokens (loaded on-demand when invoked)
|
||||
- HTTP API endpoints instead of MCP tools
|
||||
|
||||
**Skill Enhancement (v5.5.0)**: Renamed from "search" to "mem-search" for better scope differentiation. Effectiveness increased from 67% to 100% with enhanced triggers and comprehensive documentation.
|
||||
|
||||
See [Search Architecture](/architecture/search-architecture) for technical details and examples.
|
||||
|
||||
### 5. Viewer UI
|
||||
React + TypeScript web interface at http://localhost:37777 featuring:
|
||||
- Real-time memory stream via Server-Sent Events
|
||||
- Infinite scroll pagination with automatic deduplication
|
||||
- Project filtering and settings persistence
|
||||
- GPU-accelerated animations
|
||||
- Self-contained HTML bundle (viewer.html)
|
||||
|
||||
Built with esbuild into a single file deployment.
|
||||
@@ -0,0 +1,559 @@
|
||||
---
|
||||
title: "PM2 to Bun Migration"
|
||||
description: "Complete technical documentation for the process management and database driver migration in v7.1.0"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Historical Migration Documentation**
|
||||
|
||||
This document describes the PM2 to Bun migration that occurred in v7.1.0 (December 2025). If you're installing claude-mem for the first time, this migration has already been completed and you can use the current Bun-based system documented in the main guides.
|
||||
|
||||
This documentation is preserved for users upgrading from versions older than v7.1.0.
|
||||
</Note>
|
||||
|
||||
# PM2 to Bun Migration: Complete Technical Documentation
|
||||
|
||||
**Version**: 7.1.0
|
||||
**Date**: December 2025
|
||||
**Migration Type**: Process Management (PM2 → Bun) + Database Driver (better-sqlite3 → bun:sqlite)
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Claude-mem version 7.1.0 introduces two major architectural migrations:
|
||||
|
||||
1. **Process Management**: PM2 → Custom Bun-based ProcessManager
|
||||
2. **Database Driver**: better-sqlite3 npm package → bun:sqlite runtime module
|
||||
|
||||
Both migrations are **automatic** and **transparent** to end users. The first time a hook fires after updating to 7.1.0+, the system performs a one-time cleanup of legacy PM2 processes and transitions to the new architecture.
|
||||
|
||||
### Key Benefits
|
||||
|
||||
- **Simplified Dependencies**: Removes PM2 and better-sqlite3 npm packages
|
||||
- **Improved Cross-Platform Support**: Better Windows compatibility
|
||||
- **Faster Installation**: No native module compilation required
|
||||
- **Built-in Runtime**: Leverages Bun's built-in process management and SQLite
|
||||
- **Reduced Complexity**: Custom ProcessManager is simpler than PM2 integration
|
||||
|
||||
### Migration Impact
|
||||
|
||||
- **Data Preservation**: User data, settings, and database remain unchanged
|
||||
- **Automatic Cleanup**: Old PM2 processes automatically terminated (all platforms)
|
||||
- **No User Action Required**: Migration happens automatically on first hook trigger
|
||||
- **Backward Compatible**: SQLite database format unchanged (only driver changed)
|
||||
|
||||
## Architecture Comparison
|
||||
|
||||
### Old System (PM2-based)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Process Management (PM2)">
|
||||
**Component**: PM2 (Process Manager 2)
|
||||
- **Package**: `pm2` npm dependency
|
||||
- **Process Name**: `claude-mem-worker`
|
||||
- **Management**: External PM2 daemon manages lifecycle
|
||||
- **Discovery**: `pm2 list`, `pm2 describe` commands
|
||||
- **Auto-restart**: PM2 automatically restarts on crash
|
||||
- **Logs**: `~/.pm2/logs/claude-mem-worker-*.log`
|
||||
- **PID File**: `~/.pm2/pids/claude-mem-worker.pid`
|
||||
|
||||
**Lifecycle Commands**:
|
||||
```bash
|
||||
pm2 start <script> # Start worker
|
||||
pm2 stop claude-mem-worker # Stop worker
|
||||
pm2 restart claude-mem-worker # Restart worker
|
||||
pm2 delete claude-mem-worker # Remove from PM2
|
||||
pm2 logs claude-mem-worker # View logs
|
||||
```
|
||||
|
||||
**Pain Points**:
|
||||
- Additional npm dependency required
|
||||
- PM2 daemon must be running
|
||||
- Potential conflicts with other PM2 processes
|
||||
- Windows compatibility issues
|
||||
- Complex configuration for simple use case
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Database Driver (better-sqlite3)">
|
||||
**Component**: better-sqlite3
|
||||
- **Package**: `better-sqlite3` npm package (native module)
|
||||
- **Installation**: Requires native compilation (node-gyp)
|
||||
- **Windows**: Requires Visual Studio build tools + Python
|
||||
- **Import**: `import Database from 'better-sqlite3'`
|
||||
|
||||
**Installation Requirements**:
|
||||
- Node.js development headers
|
||||
- C++ compiler (gcc/clang on Mac/Linux, MSVC on Windows)
|
||||
- Python (for node-gyp)
|
||||
- Windows: Visual Studio Build Tools
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### New System (Bun-based)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Process Management (Custom ProcessManager)">
|
||||
**Component**: Custom ProcessManager (`src/services/process/ProcessManager.ts`)
|
||||
- **Package**: Built-in Bun APIs (no external dependency)
|
||||
- **Process Spawn**: `Bun.spawn()` with detached mode
|
||||
- **Management**: Direct process control via PID file
|
||||
- **Discovery**: PID file + process existence check + HTTP health check
|
||||
- **Auto-restart**: Hook-triggered restart on failure detection
|
||||
- **Logs**: `~/.claude-mem/logs/worker-YYYY-MM-DD.log`
|
||||
- **PID File**: `~/.claude-mem/.worker.pid`
|
||||
- **Port File**: `~/.claude-mem/.worker.port` (new)
|
||||
|
||||
**Lifecycle Commands**:
|
||||
```bash
|
||||
npm run worker:start # Start worker
|
||||
npm run worker:stop # Stop worker
|
||||
claude-mem restart # Restart worker
|
||||
npm run worker:status # Check status
|
||||
npm run worker:logs # View logs
|
||||
```
|
||||
|
||||
**Core Mechanisms**:
|
||||
|
||||
1. **PID File Management**:
|
||||
- File: `~/.claude-mem/.worker.pid`
|
||||
- Content: Process ID (e.g., "35557")
|
||||
- Validation: Process existence via `kill(pid, 0)` signal
|
||||
|
||||
2. **Port File Management**:
|
||||
- File: `~/.claude-mem/.worker.port`
|
||||
- Content: Two lines (port number, PID)
|
||||
- Purpose: Track port binding and validate PID match
|
||||
|
||||
3. **Health Checking**:
|
||||
- Layer 1: PID file exists?
|
||||
- Layer 2: Process alive? (`kill(pid, 0)`)
|
||||
- Layer 3: HTTP health check (`GET /health`)
|
||||
- All three must pass for "healthy" status
|
||||
|
||||
**Advantages**:
|
||||
- No external dependencies
|
||||
- Simpler codebase (direct control)
|
||||
- Better error handling and validation
|
||||
- Platform-agnostic (Bun handles platform differences)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Database Driver (bun:sqlite)">
|
||||
**Component**: bun:sqlite
|
||||
- **Package**: Built into Bun runtime (no npm package)
|
||||
- **Installation**: None required (comes with Bun ≥1.0)
|
||||
- **Platform**: Works anywhere Bun works
|
||||
- **Import**: `import { Database } from 'bun:sqlite'`
|
||||
- **API**: Similar to better-sqlite3 (synchronous)
|
||||
|
||||
**Installation Requirements**:
|
||||
- Bun ≥1.0 (automatically installed if missing)
|
||||
- No native compilation required
|
||||
- No platform-specific build tools needed
|
||||
|
||||
**Compatibility**:
|
||||
- SQLite database format: **Unchanged**
|
||||
- Database file: `~/.claude-mem/claude-mem.db` (same location)
|
||||
- Query syntax: **Identical** (both use SQLite SQL)
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Migration Mechanics
|
||||
|
||||
### One-Time PM2 Cleanup
|
||||
|
||||
The migration system uses a marker-based approach to perform PM2 cleanup exactly once.
|
||||
|
||||
**Implementation**: `src/shared/worker-utils.ts:73-86`
|
||||
|
||||
```typescript
|
||||
// Clean up legacy PM2 (one-time migration)
|
||||
const pm2MigratedMarker = join(DATA_DIR, '.pm2-migrated');
|
||||
|
||||
if (!existsSync(pm2MigratedMarker)) {
|
||||
try {
|
||||
spawnSync('pm2', ['delete', 'claude-mem-worker'], { stdio: 'ignore' });
|
||||
// Mark migration as complete
|
||||
writeFileSync(pm2MigratedMarker, new Date().toISOString(), 'utf-8');
|
||||
logger.debug('SYSTEM', 'PM2 cleanup completed and marked');
|
||||
} catch {
|
||||
// PM2 not installed or process doesn't exist - still mark as migrated
|
||||
writeFileSync(pm2MigratedMarker, new Date().toISOString(), 'utf-8');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Migration Trigger Points
|
||||
|
||||
<Steps>
|
||||
<Step title="Hook Execution">
|
||||
SessionStart, UserPromptSubmit, or PostToolUse hooks execute using new 7.1.0 code
|
||||
</Step>
|
||||
<Step title="Worker Status Check">
|
||||
`ensureWorkerRunning()` checks if `~/.claude-mem/.worker.pid` exists (it doesn't for first run after update)
|
||||
</Step>
|
||||
<Step title="Start Worker Decision">
|
||||
Worker not running → Call `startWorker()`
|
||||
</Step>
|
||||
<Step title="Migration Check">
|
||||
Check if `~/.claude-mem/.pm2-migrated` exists
|
||||
</Step>
|
||||
<Step title="PM2 Cleanup">
|
||||
Execute `pm2 delete claude-mem-worker` (errors ignored), create marker file
|
||||
</Step>
|
||||
<Step title="New Worker Start">
|
||||
Spawn new Bun-managed worker process with PID and port files
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Marker File
|
||||
|
||||
**Location**: `~/.claude-mem/.pm2-migrated`
|
||||
|
||||
**Content**: ISO 8601 timestamp
|
||||
```
|
||||
2025-12-13T00:18:39.673Z
|
||||
```
|
||||
|
||||
**Purpose**:
|
||||
- One-time migration flag
|
||||
- Prevents repeated PM2 cleanup on every start
|
||||
- Persists across restarts and reboots
|
||||
|
||||
**Lifecycle**:
|
||||
- Created: First hook trigger after update to 7.1.0+ (all platforms)
|
||||
- Updated: Never
|
||||
- Deleted: Never (user could manually delete to force re-migration)
|
||||
|
||||
## User Experience Timeline
|
||||
|
||||
### First Session After Update
|
||||
|
||||
<Note>
|
||||
This is the critical migration moment. The process takes approximately 2-5 seconds.
|
||||
</Note>
|
||||
|
||||
**Step-by-Step Execution**:
|
||||
|
||||
1. **Hook fires** (SessionStart most common)
|
||||
2. **Worker status check**: No PID file → worker not running
|
||||
3. **Migration check**: No marker file → run PM2 cleanup
|
||||
4. **PM2 cleanup**: `pm2 delete claude-mem-worker` (old worker terminated)
|
||||
5. **Marker creation**: `~/.claude-mem/.pm2-migrated` with timestamp
|
||||
6. **New worker start**: Bun process spawned, PID/port files created
|
||||
7. **Verification**: Process check + HTTP health check
|
||||
8. **Hook completes**: Claude Code session starts normally
|
||||
|
||||
**User Observable Behavior**:
|
||||
- Slight delay on first startup (PM2 cleanup + new worker spawn)
|
||||
- No error messages (cleanup failures silently handled)
|
||||
- Worker appears running via `npm run worker:status`
|
||||
- Old PM2 worker no longer in `pm2 list`
|
||||
|
||||
### Subsequent Sessions
|
||||
|
||||
After migration completes, every hook trigger follows the fast path:
|
||||
|
||||
1. PID file exists? **YES**
|
||||
2. Process alive? **YES**
|
||||
3. HTTP health check? **SUCCESS**
|
||||
4. Result: Worker already running, done (~50ms)
|
||||
|
||||
No migration logic runs on subsequent sessions.
|
||||
|
||||
## Platform-Specific Behavior
|
||||
|
||||
### Platform Comparison
|
||||
|
||||
| Feature | macOS | Linux | Windows |
|
||||
|---------|-------|-------|---------|
|
||||
| PM2 Cleanup | Attempted | Attempted | Attempted |
|
||||
| Marker File | Created | Created | Created |
|
||||
| Process Signals | POSIX (native) | POSIX (native) | Bun abstraction |
|
||||
| Bun Support | Full | Full | Full |
|
||||
| PID File | Yes | Yes | Yes |
|
||||
| Port File | Yes | Yes | Yes |
|
||||
| Health Check | HTTP | HTTP | HTTP |
|
||||
| Migration Delay | ~2-5s first time | ~2-5s first time | ~2-5s first time |
|
||||
|
||||
### Platform Notes
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS">
|
||||
- POSIX signal handling works natively
|
||||
- Bun fully supported
|
||||
- No platform-specific workarounds needed
|
||||
</Tab>
|
||||
<Tab title="Linux">
|
||||
- Identical behavior to macOS
|
||||
- POSIX signal handling
|
||||
- Works on Ubuntu, Debian, RHEL, CentOS, Arch
|
||||
- Alpine may require glibc (not musl)
|
||||
</Tab>
|
||||
<Tab title="Windows">
|
||||
- PM2 cleanup now runs (safe due to try/catch)
|
||||
- Bun abstracts signal handling differences
|
||||
- Path module handles Windows separators
|
||||
- File locking handled by SQLite
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Observable Changes
|
||||
|
||||
### Command Changes
|
||||
|
||||
| Old (PM2) | New (Bun) | Notes |
|
||||
|-----------|-----------|-------|
|
||||
| `pm2 list` | `npm run worker:status` | Shows worker status |
|
||||
| `pm2 start <script>` | `npm run worker:start` | Start worker |
|
||||
| `pm2 stop claude-mem-worker` | `npm run worker:stop` | Stop worker |
|
||||
| `pm2 restart claude-mem-worker` | `claude-mem restart` | Restart worker |
|
||||
| `pm2 delete claude-mem-worker` | `npm run worker:stop` | Remove worker |
|
||||
| `pm2 logs claude-mem-worker` | `npm run worker:logs` | View logs |
|
||||
| `pm2 describe claude-mem-worker` | `npm run worker:status` | Detailed status |
|
||||
| `pm2 monit` | No equivalent | PM2-specific monitoring |
|
||||
|
||||
### File Location Changes
|
||||
|
||||
**Logs**:
|
||||
```
|
||||
Old: ~/.pm2/logs/claude-mem-worker-out.log
|
||||
~/.pm2/logs/claude-mem-worker-error.log
|
||||
|
||||
New: ~/.claude-mem/logs/worker-YYYY-MM-DD.log
|
||||
```
|
||||
|
||||
**PID Files**:
|
||||
```
|
||||
Old: ~/.pm2/pids/claude-mem-worker.pid
|
||||
|
||||
New: ~/.claude-mem/.worker.pid
|
||||
```
|
||||
|
||||
**Process State**:
|
||||
```
|
||||
Old: PM2 daemon memory (pm2 save)
|
||||
|
||||
New: ~/.claude-mem/.worker.pid
|
||||
~/.claude-mem/.worker.port
|
||||
~/.claude-mem/.pm2-migrated (all platforms)
|
||||
```
|
||||
|
||||
**Database** (unchanged):
|
||||
```
|
||||
Same: ~/.claude-mem/claude-mem.db
|
||||
```
|
||||
|
||||
### User-Visible Changes
|
||||
|
||||
**Before Update**:
|
||||
```bash
|
||||
$ pm2 list
|
||||
┌────┬────────────────────┬─────────┬─────────┬──────────┐
|
||||
│ id │ name │ status │ restart │ uptime │
|
||||
├────┼────────────────────┼─────────┼─────────┼──────────┤
|
||||
│ 0 │ claude-mem-worker │ online │ 0 │ 2d 5h │
|
||||
└────┴────────────────────┴─────────┴─────────┴──────────┘
|
||||
```
|
||||
|
||||
**After Update**:
|
||||
```bash
|
||||
$ pm2 list
|
||||
# Empty - worker no longer managed by PM2
|
||||
|
||||
$ npm run worker:status
|
||||
Worker is running
|
||||
PID: 35557
|
||||
Port: 37777
|
||||
Uptime: 2h 15m
|
||||
```
|
||||
|
||||
### Orphaned Files
|
||||
|
||||
After migration, these PM2 files may remain (safe to delete):
|
||||
|
||||
```
|
||||
~/.pm2/ # Entire PM2 directory
|
||||
~/.pm2/logs/ # Old logs
|
||||
~/.pm2/pids/ # Old PID files
|
||||
~/.pm2/pm2.log # PM2 daemon log
|
||||
~/.pm2/dump.pm2 # PM2 process dump
|
||||
```
|
||||
|
||||
**Cleanup (optional)**:
|
||||
```bash
|
||||
# Remove PM2 entirely (if not used for other processes)
|
||||
pm2 kill
|
||||
rm -rf ~/.pm2
|
||||
|
||||
# Or just remove claude-mem logs
|
||||
rm -f ~/.pm2/logs/claude-mem-worker-*.log
|
||||
rm -f ~/.pm2/pids/claude-mem-worker.pid
|
||||
```
|
||||
|
||||
## File System State
|
||||
|
||||
### State Directory Structure
|
||||
|
||||
**Before Migration** (PM2 system):
|
||||
```
|
||||
~/.claude-mem/
|
||||
├── claude-mem.db # Database (unchanged)
|
||||
├── chroma/ # Vector embeddings (unchanged)
|
||||
├── logs/ # Application logs (unchanged)
|
||||
└── settings.json # User settings (unchanged)
|
||||
|
||||
~/.pm2/
|
||||
├── logs/
|
||||
│ ├── claude-mem-worker-out.log
|
||||
│ └── claude-mem-worker-error.log
|
||||
├── pids/
|
||||
│ └── claude-mem-worker.pid
|
||||
└── pm2.log
|
||||
```
|
||||
|
||||
**After Migration** (Bun system):
|
||||
```
|
||||
~/.claude-mem/
|
||||
├── claude-mem.db # Database (same file)
|
||||
├── chroma/ # Vector embeddings (unchanged)
|
||||
├── logs/
|
||||
│ └── worker-2025-12-13.log # New log format
|
||||
├── settings.json # User settings (unchanged)
|
||||
├── .worker.pid # NEW: Process ID
|
||||
├── .worker.port # NEW: Port + PID
|
||||
└── .pm2-migrated # NEW: Migration marker (all platforms)
|
||||
|
||||
~/.pm2/ # Orphaned (safe to delete)
|
||||
├── logs/ # Old logs (no longer written)
|
||||
├── pids/ # Old PID (no longer updated)
|
||||
└── pm2.log # PM2 daemon log (not used)
|
||||
```
|
||||
|
||||
## Edge Cases and Troubleshooting
|
||||
|
||||
### Scenario 1: Migration Fails (PM2 Still Running)
|
||||
|
||||
<Warning>
|
||||
This is rare but can happen if PM2 has watch mode enabled or the process is manually restarted.
|
||||
</Warning>
|
||||
|
||||
**Symptoms**:
|
||||
- `pm2 list` still shows `claude-mem-worker`
|
||||
- Port conflict errors in logs
|
||||
- Worker fails to start
|
||||
|
||||
**Resolution**:
|
||||
```bash
|
||||
# Manual cleanup
|
||||
pm2 delete claude-mem-worker
|
||||
pm2 save # Persist the deletion
|
||||
|
||||
# Force re-migration (optional)
|
||||
rm ~/.claude-mem/.pm2-migrated
|
||||
|
||||
# Restart worker
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Scenario 2: Stale PID File (Process Dead)
|
||||
|
||||
**Symptoms**:
|
||||
- `npm run worker:status` shows "not running"
|
||||
- `.worker.pid` file exists
|
||||
- Process ID doesn't exist
|
||||
|
||||
**Automatic Recovery**: Next hook trigger detects dead process and starts a fresh worker.
|
||||
|
||||
**Manual Resolution**:
|
||||
```bash
|
||||
rm ~/.claude-mem/.worker.pid
|
||||
rm ~/.claude-mem/.worker.port
|
||||
npm run worker:start
|
||||
```
|
||||
|
||||
### Scenario 3: Port Already in Use
|
||||
|
||||
**Error**: `EADDRINUSE: address already in use`
|
||||
|
||||
**Resolution**:
|
||||
```bash
|
||||
# Check what's using the port
|
||||
lsof -i :37777
|
||||
|
||||
# Kill the process
|
||||
kill -9 <PID>
|
||||
|
||||
# Restart worker
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Common Error Messages
|
||||
|
||||
| Error | Cause | Resolution |
|
||||
|-------|-------|------------|
|
||||
| `EADDRINUSE` | Port already in use | `lsof -i :37777` then kill conflicting process |
|
||||
| `No such process` | Stale PID file | Automatic cleanup on next hook trigger |
|
||||
| `pm2: command not found` | PM2 not installed | None needed (error is caught and ignored) |
|
||||
| `Invalid port X` | Port validation failed | Update `CLAUDE_MEM_WORKER_PORT` in settings |
|
||||
|
||||
## Developer Notes
|
||||
|
||||
### Testing the Migration
|
||||
|
||||
```bash
|
||||
# 1. Install old version (with PM2)
|
||||
git checkout <pre-7.1.0-tag>
|
||||
npm install && npm run build && npm run sync-marketplace
|
||||
|
||||
# 2. Start PM2 worker
|
||||
pm2 start plugin/scripts/worker-cli.js --name claude-mem-worker
|
||||
|
||||
# 3. Update to new version
|
||||
git checkout main
|
||||
npm install && npm run build && npm run sync-marketplace
|
||||
|
||||
# 4. Trigger hook
|
||||
node plugin/scripts/session-start-hook.js
|
||||
|
||||
# 5. Verify migration
|
||||
pm2 list # Should NOT show claude-mem-worker
|
||||
cat ~/.claude-mem/.pm2-migrated # Should exist
|
||||
npm run worker:status # Should show Bun worker running
|
||||
```
|
||||
|
||||
### Architecture Decisions
|
||||
|
||||
**Why Custom ProcessManager Instead of PM2?**
|
||||
1. **Simplicity**: Direct control, no external daemon
|
||||
2. **Dependencies**: Remove npm dependency
|
||||
3. **Cross-platform**: Bun handles platform differences
|
||||
4. **Bundle Size**: Reduce plugin package size
|
||||
5. **Control**: Fine-grained error handling and validation
|
||||
|
||||
**Why One-Time Marker Instead of Always Running PM2 Delete?**
|
||||
1. **Performance**: Avoid unnecessary process spawning
|
||||
2. **Idempotency**: Migration runs exactly once
|
||||
3. **Debugging**: Timestamp shows when migration occurred
|
||||
4. **Simplicity**: Clear migration state
|
||||
|
||||
**Why Run PM2 Cleanup on All Platforms?**
|
||||
1. **Quality Migration**: Clean up orphaned processes
|
||||
2. **Consistency**: Same behavior across all platforms
|
||||
3. **Safety**: Error handling already in place (try/catch)
|
||||
4. **No Downside**: If PM2 not installed, error is caught and ignored
|
||||
|
||||
## Summary
|
||||
|
||||
The migration from PM2 to Bun-based ProcessManager is a **one-time, automatic, transparent** transition that:
|
||||
|
||||
1. **Removes external dependencies** (PM2, better-sqlite3)
|
||||
2. **Simplifies architecture** (direct process control)
|
||||
3. **Improves cross-platform support** (especially Windows)
|
||||
4. **Preserves user data** (database, settings, logs unchanged)
|
||||
5. **Requires no user action** (automatic on first hook trigger)
|
||||
|
||||
**Key Migration Moment**: First hook trigger after update to 7.1.0+
|
||||
**Duration**: ~2-5 seconds (one-time delay)
|
||||
**Impact**: Seamless transition, user-invisible
|
||||
**Rollback**: Not needed (migration is forward-only, safe)
|
||||
|
||||
For most users, the migration will be completely transparent - they'll see no errors, no data loss, and experience improved reliability and simpler troubleshooting going forward.
|
||||
@@ -0,0 +1,448 @@
|
||||
---
|
||||
title: "Search Architecture"
|
||||
description: "mem-search skill with HTTP API and progressive disclosure"
|
||||
---
|
||||
|
||||
# Search Architecture
|
||||
|
||||
Claude-Mem uses a skill-based search architecture that provides intelligent memory retrieval through natural language queries. This replaced the MCP-based approach in v5.4.0 with a more efficient implementation. The skill was enhanced and renamed to "mem-search" in v5.5.0 for better scope differentiation.
|
||||
|
||||
## Overview
|
||||
|
||||
**Architecture**: Skill-Based Search + HTTP API + Progressive Disclosure
|
||||
|
||||
**Key Components**:
|
||||
1. **mem-search Skill** (`plugin/skills/mem-search/SKILL.md`) - Auto-invoked when users ask about past work
|
||||
2. **HTTP API Endpoints** (10 routes) - Fast, efficient search operations on port 37777
|
||||
3. **Worker Service** - Express.js server with FTS5 full-text search
|
||||
4. **SQLite Database** - Persistent storage with FTS5 virtual tables
|
||||
5. **Chroma Vector DB** - Semantic search with hybrid retrieval
|
||||
|
||||
**v5.5.0 Enhancement**: Renamed from "search" to "mem-search" with:
|
||||
- Effectiveness increased from 67% to 100%
|
||||
- Concrete triggers increased from 44% to 85%
|
||||
- 5+ unique identifiers for better scope differentiation
|
||||
- Comprehensive documentation (17 files, 12 operation guides)
|
||||
|
||||
## How It Works
|
||||
|
||||
### 1. User Query (Natural Language)
|
||||
|
||||
```
|
||||
User: "What bugs did we fix last session?"
|
||||
```
|
||||
|
||||
### 2. Skill Invocation
|
||||
|
||||
Claude recognizes the intent and invokes the mem-search skill:
|
||||
- Skill frontmatter (~250 tokens) loaded at session start
|
||||
- Full skill instructions loaded on-demand when skill is invoked
|
||||
- Progressive disclosure pattern minimizes context overhead
|
||||
- "mem-search" naming provides clear scope differentiation from native memory
|
||||
|
||||
### 3. HTTP API Call
|
||||
|
||||
The skill uses `curl` to call the HTTP API:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:37777/api/search/observations?query=bugs&type=bugfix&limit=5"
|
||||
```
|
||||
|
||||
### 4. FTS5 Search
|
||||
|
||||
Worker service queries SQLite FTS5 virtual tables:
|
||||
|
||||
```sql
|
||||
SELECT * FROM observations_fts
|
||||
WHERE observations_fts MATCH ?
|
||||
AND type = 'bugfix'
|
||||
ORDER BY rank
|
||||
LIMIT 5
|
||||
```
|
||||
|
||||
### 5. Results Formatted
|
||||
|
||||
Skill formats results and returns to Claude:
|
||||
|
||||
```
|
||||
## Recent Bugfixes
|
||||
|
||||
1. [bugfix] Fixed authentication token expiry
|
||||
Date: 2025-11-08 14:23:45
|
||||
Files: src/auth/jwt.ts
|
||||
|
||||
2. [bugfix] Resolved database connection leak
|
||||
Date: 2025-11-08 13:15:22
|
||||
Files: src/services/database.ts
|
||||
```
|
||||
|
||||
### 6. User Sees Answer
|
||||
|
||||
Claude presents the formatted results naturally in conversation.
|
||||
|
||||
## Architecture Change (v5.4.0)
|
||||
|
||||
### Before: MCP-Based Search
|
||||
|
||||
**Approach**: 9 MCP tools registered at session start
|
||||
|
||||
**Token Cost**: ~2,500 tokens in tool definitions per session
|
||||
- Each tool's schema, parameters, descriptions loaded
|
||||
- All 9 tools available whether needed or not
|
||||
- No progressive disclosure
|
||||
|
||||
**Example MCP Tool**:
|
||||
```json
|
||||
{
|
||||
"name": "search_observations",
|
||||
"description": "Full-text search across observations...",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": { "type": "string", "description": "..." },
|
||||
"type": { "type": "array", "items": { "enum": [...] } },
|
||||
"format": { "enum": ["index", "full"] },
|
||||
// ... many more parameters
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### After: Skill-Based Search
|
||||
|
||||
**Approach**: 1 mem-search skill with progressive disclosure
|
||||
|
||||
**Token Cost**: ~250 tokens in skill frontmatter per session
|
||||
- Only skill description loaded at session start
|
||||
- Full instructions loaded on-demand when skill is invoked
|
||||
- HTTP API endpoints instead of MCP protocol
|
||||
|
||||
**Example Skill Frontmatter**:
|
||||
```markdown
|
||||
# Claude-Mem mem-search Skill
|
||||
|
||||
Access claude-mem's persistent memory through a comprehensive HTTP API.
|
||||
Search for past work, understand context, and learn from previous decisions.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Invoke this skill when users ask about:
|
||||
- Past work: "What did we do last session?"
|
||||
- Bug fixes: "Did we fix this before?"
|
||||
- Features: "How did we implement authentication?"
|
||||
...
|
||||
```
|
||||
|
||||
**Token Efficiency**: Minimal frontmatter at session start with progressive disclosure
|
||||
|
||||
## HTTP API Endpoints
|
||||
|
||||
The worker service exposes 10 search endpoints:
|
||||
|
||||
### Full-Text Search
|
||||
|
||||
```
|
||||
GET /api/search/observations
|
||||
GET /api/search/sessions
|
||||
GET /api/search/prompts
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `query` - FTS5 search query (required)
|
||||
- `type` - Filter by type (bugfix, feature, refactor, etc.)
|
||||
- `project` - Filter by project name
|
||||
- `limit` - Maximum results (default: 20)
|
||||
- `offset` - Pagination offset
|
||||
- `format` - Response format (index or full)
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
curl "http://localhost:37777/api/search/observations?query=authentication&type=decision&limit=5"
|
||||
```
|
||||
|
||||
### Filtered Search
|
||||
|
||||
```
|
||||
GET /api/search/by-type
|
||||
GET /api/search/by-concept
|
||||
GET /api/search/by-file
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `type` / `concept` / `filePath` - Filter criteria (required)
|
||||
- `project` - Filter by project
|
||||
- `limit` - Maximum results
|
||||
- `format` - Response format
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
curl "http://localhost:37777/api/search/by-file?filePath=worker-service.ts&limit=10"
|
||||
```
|
||||
|
||||
### Context Retrieval
|
||||
|
||||
```
|
||||
GET /api/context/recent
|
||||
GET /api/context/timeline
|
||||
GET /api/timeline/by-query
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `project` - Filter by project
|
||||
- `limit` - Number of sessions/records
|
||||
- `anchor` - Timeline anchor point (ID or timestamp)
|
||||
- `depth_before` - Records before anchor
|
||||
- `depth_after` - Records after anchor
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
curl "http://localhost:37777/api/context/recent?project=claude-mem&limit=5"
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
```
|
||||
GET /api/search/help
|
||||
```
|
||||
|
||||
Returns API documentation in JSON format.
|
||||
|
||||
## Progressive Disclosure Pattern
|
||||
|
||||
The mem-search skill uses progressive disclosure to minimize token usage:
|
||||
|
||||
### Layer 1: Skill Frontmatter (Session Start)
|
||||
|
||||
**What's Loaded**: Skill description and when to use it (~250 tokens)
|
||||
|
||||
**Purpose**: Claude can recognize when to invoke the skill
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
# Claude-Mem mem-search Skill
|
||||
|
||||
Access claude-mem's persistent memory through a comprehensive HTTP API.
|
||||
|
||||
## When to Use This Skill
|
||||
Invoke this skill when users ask about:
|
||||
- Past work: "What did we do last session?"
|
||||
- Bug fixes: "Did we fix this before?"
|
||||
...
|
||||
```
|
||||
|
||||
### Layer 2: Full Skill Instructions (On-Demand)
|
||||
|
||||
**What's Loaded**: Complete operation documentation (~2,500 tokens)
|
||||
|
||||
**Purpose**: Detailed instructions for each search operation
|
||||
|
||||
**When Loaded**: Only when Claude invokes the skill
|
||||
|
||||
**Example Structure**:
|
||||
```
|
||||
/skills/search/
|
||||
├── SKILL.md (main frontmatter)
|
||||
├── operations/
|
||||
│ ├── observations.md (detailed instructions)
|
||||
│ ├── sessions.md
|
||||
│ ├── prompts.md
|
||||
│ ├── by-type.md
|
||||
│ ├── by-concept.md
|
||||
│ ├── by-file.md
|
||||
│ ├── recent-context.md
|
||||
│ ├── timeline.md
|
||||
│ ├── timeline-by-query.md
|
||||
│ ├── help.md
|
||||
│ ├── formatting.md
|
||||
│ └── common-workflows.md
|
||||
```
|
||||
|
||||
### Layer 3: API Response
|
||||
|
||||
**What's Returned**: Search results in requested format
|
||||
|
||||
**Format Options**:
|
||||
- `index` - Titles, dates, IDs only (~50-100 tokens per result)
|
||||
- `full` - Complete details (~500-1000 tokens per result)
|
||||
|
||||
**Progressive Usage**: Start with `index`, drill down with `full` as needed
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### mem-search Skill Structure
|
||||
|
||||
```
|
||||
plugin/skills/mem-search/
|
||||
├── SKILL.md # Main frontmatter (~250 tokens)
|
||||
├── operations/
|
||||
│ ├── observations.md # Search observations
|
||||
│ ├── sessions.md # Search sessions
|
||||
│ ├── prompts.md # Search prompts
|
||||
│ ├── by-type.md # Filter by type
|
||||
│ ├── by-concept.md # Filter by concept
|
||||
│ ├── by-file.md # Filter by file
|
||||
│ ├── recent-context.md # Get recent context
|
||||
│ ├── timeline.md # Timeline around point
|
||||
│ ├── timeline-by-query.md # Search + timeline
|
||||
│ ├── help.md # API documentation
|
||||
│ ├── formatting.md # Result formatting guide
|
||||
│ └── common-workflows.md # Usage patterns
|
||||
```
|
||||
|
||||
### Worker Service Integration
|
||||
|
||||
**File**: `src/services/worker-service.ts`
|
||||
|
||||
**Search Routes**:
|
||||
```typescript
|
||||
// Full-text search
|
||||
app.get('/api/search/observations', handleSearchObservations);
|
||||
app.get('/api/search/sessions', handleSearchSessions);
|
||||
app.get('/api/search/prompts', handleSearchPrompts);
|
||||
|
||||
// Filtered search
|
||||
app.get('/api/search/by-type', handleSearchByType);
|
||||
app.get('/api/search/by-concept', handleSearchByConcept);
|
||||
app.get('/api/search/by-file', handleSearchByFile);
|
||||
|
||||
// Context retrieval
|
||||
app.get('/api/context/recent', handleRecentContext);
|
||||
app.get('/api/context/timeline', handleTimeline);
|
||||
app.get('/api/timeline/by-query', handleTimelineByQuery);
|
||||
|
||||
// Documentation
|
||||
app.get('/api/search/help', handleHelp);
|
||||
```
|
||||
|
||||
**Database Access**:
|
||||
- Uses `SessionSearch` service for FTS5 queries
|
||||
- Uses `SessionStore` for structured queries
|
||||
- Hybrid search with ChromaDB for semantic similarity
|
||||
|
||||
### Security
|
||||
|
||||
**FTS5 Injection Prevention** (v4.2.3):
|
||||
```typescript
|
||||
function escapeFTS5Query(query: string): string {
|
||||
return query.replace(/"/g, '""');
|
||||
}
|
||||
```
|
||||
|
||||
All user-provided search queries are properly escaped to prevent SQL injection.
|
||||
|
||||
**Comprehensive Testing**: 332 injection attack tests covering:
|
||||
- Special characters
|
||||
- SQL keywords
|
||||
- Quote escaping
|
||||
- Boolean operators
|
||||
|
||||
## Benefits
|
||||
|
||||
### 1. Token Efficiency
|
||||
|
||||
**Before (MCP)**:
|
||||
- Session start: All tool definitions loaded upfront
|
||||
- Every session pays this cost
|
||||
- No progressive disclosure
|
||||
|
||||
**After (Skill)**:
|
||||
- Session start: Minimal token cost for skill frontmatter
|
||||
- Full instructions loaded only when invoked (progressive disclosure)
|
||||
- More efficient than loading all tool definitions upfront
|
||||
|
||||
### 2. Natural Language Interface
|
||||
|
||||
**Before**: Users needed to learn MCP tool syntax
|
||||
```
|
||||
search_observations with query="authentication" and type="decision"
|
||||
```
|
||||
|
||||
**After**: Users ask naturally
|
||||
```
|
||||
"What decisions did we make about authentication?"
|
||||
```
|
||||
|
||||
Claude translates to appropriate API call.
|
||||
|
||||
### 3. Flexibility
|
||||
|
||||
**HTTP API Benefits**:
|
||||
- Can be called from skills, MCP tools, or other clients
|
||||
- Easy to test with curl
|
||||
- Standard REST conventions
|
||||
- JSON responses
|
||||
|
||||
**Progressive Disclosure**:
|
||||
- Loads only what's needed
|
||||
- Can add more operations without increasing base cost
|
||||
- Documentation co-located with operations
|
||||
|
||||
### 4. Performance
|
||||
|
||||
**Fast Queries**: FTS5 full-text search under 10ms for typical queries
|
||||
|
||||
**Caching**: HTTP layer allows response caching
|
||||
|
||||
**Pagination**: Efficient result pagination with offset/limit
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### For Users
|
||||
|
||||
**No Action Required**: The migration from MCP to skill-based search is transparent.
|
||||
|
||||
**Same Questions Work**: Natural language queries work exactly the same way.
|
||||
|
||||
**Invisible Change**: Users won't notice any difference except better performance.
|
||||
|
||||
### For Developers
|
||||
|
||||
**Renamed**: MCP server (formerly `search-server.ts`, now `src/servers/mcp-server.ts`)
|
||||
- Source file kept for reference
|
||||
- No longer built or registered
|
||||
- MCP configuration removed from `plugin/.mcp.json`
|
||||
|
||||
**New Implementation**: Skill-based search
|
||||
- Skill files: `plugin/skills/mem-search/`
|
||||
- HTTP endpoints: `src/services/worker-service.ts` (lines 200-400)
|
||||
- Build script: `npm run build` includes skill files
|
||||
- Sync script: `npm run sync-marketplace` copies to plugin directory
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Worker Service Not Running
|
||||
|
||||
If searches fail, check worker service:
|
||||
|
||||
```bash
|
||||
npm run worker:status # Check status
|
||||
claude-mem restart # Restart worker
|
||||
npm run worker:logs # View logs
|
||||
```
|
||||
|
||||
### HTTP Endpoints Not Responding
|
||||
|
||||
Test endpoints directly:
|
||||
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:37777/health
|
||||
|
||||
# Search test
|
||||
curl "http://localhost:37777/api/search/observations?query=test&limit=1"
|
||||
```
|
||||
|
||||
### Skill Not Invoking
|
||||
|
||||
If Claude doesn't invoke the mem-search skill automatically:
|
||||
|
||||
1. Check skill files exist: `ls ~/.claude/plugins/marketplaces/thedotmack/plugin/skills/mem-search/`
|
||||
2. Restart Claude Code session to reload skill definitions
|
||||
3. Try more explicit phrasing: "Search past sessions for bug fixes" or "What did we do in yesterday's session?"
|
||||
4. Ensure your question is about previous sessions (not current conversation context)
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Search Tools Usage](/usage/search-tools) - User guide with examples
|
||||
- [Worker Service Architecture](/architecture/worker-service) - HTTP API details
|
||||
- [Database Schema](/architecture/database) - FTS5 tables and indexes
|
||||
@@ -0,0 +1,598 @@
|
||||
---
|
||||
title: "Worker Service"
|
||||
description: "HTTP API and Bun process management"
|
||||
---
|
||||
|
||||
# Worker Service
|
||||
|
||||
The worker service is a long-running HTTP API built with Express.js and managed natively by Bun. It processes observations through the Claude Agent SDK separately from hook execution to prevent timeout issues.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Technology**: Express.js HTTP server
|
||||
- **Runtime**: Bun (auto-installed if missing)
|
||||
- **Process Manager**: Native Bun process management via ProcessManager
|
||||
- **Port**: Fixed port 37777 (configurable via `CLAUDE_MEM_WORKER_PORT`)
|
||||
- **Location**: `src/services/worker-service.ts`
|
||||
- **Built Output**: `plugin/scripts/worker-service.cjs`
|
||||
- **Model**: Configurable via `CLAUDE_MEM_MODEL` environment variable (default: sonnet)
|
||||
|
||||
## REST API Endpoints
|
||||
|
||||
The worker service exposes 20 HTTP endpoints organized into five categories:
|
||||
|
||||
### Viewer & Health Endpoints
|
||||
|
||||
#### 1. Viewer UI
|
||||
```
|
||||
GET /
|
||||
```
|
||||
|
||||
**Purpose**: Serves the web-based viewer UI (v5.1.0+)
|
||||
|
||||
**Response**: HTML page with embedded React application
|
||||
|
||||
**Features**:
|
||||
- Real-time memory stream visualization
|
||||
- Infinite scroll pagination
|
||||
- Project filtering
|
||||
- SSE-based live updates
|
||||
- Theme toggle (light/dark mode) as of v5.1.2
|
||||
|
||||
#### 2. Health Check
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**Purpose**: Worker health status check
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 12345,
|
||||
"port": 37777
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Server-Sent Events Stream
|
||||
```
|
||||
GET /stream
|
||||
```
|
||||
|
||||
**Purpose**: Real-time updates for viewer UI
|
||||
|
||||
**Response**: SSE stream with events:
|
||||
- `observation-created`: New observation added
|
||||
- `session-summary-created`: New summary generated
|
||||
- `user-prompt-created`: New prompt recorded
|
||||
|
||||
**Event Format**:
|
||||
```
|
||||
event: observation-created
|
||||
data: {"id": 123, "title": "...", ...}
|
||||
```
|
||||
|
||||
### Data Retrieval Endpoints
|
||||
|
||||
#### 4. Get Prompts
|
||||
```
|
||||
GET /api/prompts?project=my-project&limit=20&offset=0
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve paginated user prompts
|
||||
|
||||
**Query Parameters**:
|
||||
- `project` (optional): Filter by project name
|
||||
- `limit` (default: 20): Number of results
|
||||
- `offset` (default: 0): Pagination offset
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"prompts": [{
|
||||
"id": 1,
|
||||
"session_id": "abc123",
|
||||
"prompt": "User's prompt text",
|
||||
"prompt_number": 1,
|
||||
"created_at": "2025-11-06T10:30:00Z"
|
||||
}],
|
||||
"total": 150,
|
||||
"hasMore": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 5. Get Observations
|
||||
```
|
||||
GET /api/observations?project=my-project&limit=20&offset=0
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve paginated observations
|
||||
|
||||
**Query Parameters**:
|
||||
- `project` (optional): Filter by project name
|
||||
- `limit` (default: 20): Number of results
|
||||
- `offset` (default: 0): Pagination offset
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"observations": [{
|
||||
"id": 123,
|
||||
"title": "Fix authentication bug",
|
||||
"type": "bugfix",
|
||||
"narrative": "...",
|
||||
"created_at": "2025-11-06T10:30:00Z"
|
||||
}],
|
||||
"total": 500,
|
||||
"hasMore": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 6. Get Summaries
|
||||
```
|
||||
GET /api/summaries?project=my-project&limit=20&offset=0
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve paginated session summaries
|
||||
|
||||
**Query Parameters**:
|
||||
- `project` (optional): Filter by project name
|
||||
- `limit` (default: 20): Number of results
|
||||
- `offset` (default: 0): Pagination offset
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"summaries": [{
|
||||
"id": 456,
|
||||
"session_id": "abc123",
|
||||
"request": "User's original request",
|
||||
"completed": "Work finished",
|
||||
"created_at": "2025-11-06T10:30:00Z"
|
||||
}],
|
||||
"total": 100,
|
||||
"hasMore": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 7. Get Observation by ID
|
||||
```
|
||||
GET /api/observation/:id
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve a single observation by its ID
|
||||
|
||||
**Path Parameters**:
|
||||
- `id` (required): Observation ID
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"id": 123,
|
||||
"sdk_session_id": "abc123",
|
||||
"project": "my-project",
|
||||
"type": "bugfix",
|
||||
"title": "Fix authentication bug",
|
||||
"narrative": "...",
|
||||
"created_at": "2025-11-06T10:30:00Z",
|
||||
"created_at_epoch": 1730886600000
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response** (404):
|
||||
```json
|
||||
{
|
||||
"error": "Observation #123 not found"
|
||||
}
|
||||
```
|
||||
|
||||
#### 8. Get Observations by IDs (Batch)
|
||||
```
|
||||
POST /api/observations/batch
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve multiple observations by their IDs in a single request
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"ids": [123, 456, 789],
|
||||
"orderBy": "date_desc",
|
||||
"limit": 10,
|
||||
"project": "my-project"
|
||||
}
|
||||
```
|
||||
|
||||
**Body Parameters**:
|
||||
- `ids` (required): Array of observation IDs
|
||||
- `orderBy` (optional): Sort order - `date_desc` or `date_asc` (default: `date_desc`)
|
||||
- `limit` (optional): Maximum number of results to return
|
||||
- `project` (optional): Filter by project name
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 789,
|
||||
"sdk_session_id": "abc123",
|
||||
"project": "my-project",
|
||||
"type": "feature",
|
||||
"title": "Add new feature",
|
||||
"narrative": "...",
|
||||
"created_at": "2025-11-06T12:00:00Z",
|
||||
"created_at_epoch": 1730891400000
|
||||
},
|
||||
{
|
||||
"id": 456,
|
||||
"sdk_session_id": "abc124",
|
||||
"project": "my-project",
|
||||
"type": "bugfix",
|
||||
"title": "Fix authentication bug",
|
||||
"narrative": "...",
|
||||
"created_at": "2025-11-06T10:30:00Z",
|
||||
"created_at_epoch": 1730886600000
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
- `400 Bad Request`: `{"error": "ids must be an array of numbers"}`
|
||||
- `400 Bad Request`: `{"error": "All ids must be integers"}`
|
||||
|
||||
**Use Case**: This endpoint is used by the `get_observations` MCP tool to efficiently retrieve multiple observations in a single request, avoiding the overhead of multiple individual requests.
|
||||
|
||||
#### 9. Get Session by ID
|
||||
```
|
||||
GET /api/session/:id
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve a single session by its ID
|
||||
|
||||
**Path Parameters**:
|
||||
- `id` (required): Session ID
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"id": 456,
|
||||
"sdk_session_id": "abc123",
|
||||
"project": "my-project",
|
||||
"request": "User's original request",
|
||||
"completed": "Work finished",
|
||||
"created_at": "2025-11-06T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response** (404):
|
||||
```json
|
||||
{
|
||||
"error": "Session #456 not found"
|
||||
}
|
||||
```
|
||||
|
||||
#### 10. Get Prompt by ID
|
||||
```
|
||||
GET /api/prompt/:id
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve a single user prompt by its ID
|
||||
|
||||
**Path Parameters**:
|
||||
- `id` (required): Prompt ID
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"session_id": "abc123",
|
||||
"prompt": "User's prompt text",
|
||||
"prompt_number": 1,
|
||||
"created_at": "2025-11-06T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response** (404):
|
||||
```json
|
||||
{
|
||||
"error": "Prompt #1 not found"
|
||||
}
|
||||
```
|
||||
|
||||
#### 12. Get Stats
|
||||
```
|
||||
GET /api/stats
|
||||
```
|
||||
|
||||
**Purpose**: Get database statistics by project
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"byProject": {
|
||||
"my-project": {
|
||||
"observations": 245,
|
||||
"summaries": 12,
|
||||
"prompts": 48
|
||||
},
|
||||
"other-project": {
|
||||
"observations": 156,
|
||||
"summaries": 8,
|
||||
"prompts": 32
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"observations": 401,
|
||||
"summaries": 20,
|
||||
"prompts": 80,
|
||||
"sessions": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 13. Get Projects
|
||||
```
|
||||
GET /api/projects
|
||||
```
|
||||
|
||||
**Purpose**: Get list of distinct projects from observations
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"projects": ["my-project", "other-project", "test-project"]
|
||||
}
|
||||
```
|
||||
|
||||
### Settings Endpoints
|
||||
|
||||
#### 14. Get Settings
|
||||
```
|
||||
GET /api/settings
|
||||
```
|
||||
|
||||
**Purpose**: Retrieve user settings
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"sidebarOpen": true,
|
||||
"selectedProject": "my-project",
|
||||
"theme": "dark"
|
||||
}
|
||||
```
|
||||
|
||||
#### 15. Save Settings
|
||||
```
|
||||
POST /api/settings
|
||||
```
|
||||
|
||||
**Purpose**: Persist user settings
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"sidebarOpen": false,
|
||||
"selectedProject": "other-project",
|
||||
"theme": "light"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### Session Management Endpoints
|
||||
|
||||
#### 16. Initialize Session
|
||||
```
|
||||
POST /sessions/:sessionDbId/init
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"sdk_session_id": "abc-123",
|
||||
"project": "my-project"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"session_id": "abc-123"
|
||||
}
|
||||
```
|
||||
|
||||
#### 17. Add Observation
|
||||
```
|
||||
POST /sessions/:sessionDbId/observations
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"tool_name": "Read",
|
||||
"tool_input": {...},
|
||||
"tool_result": "...",
|
||||
"correlation_id": "xyz-789"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"observation_id": 123
|
||||
}
|
||||
```
|
||||
|
||||
#### 18. Generate Summary
|
||||
```
|
||||
POST /sessions/:sessionDbId/summarize
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"trigger": "stop"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"summary_id": 456
|
||||
}
|
||||
```
|
||||
|
||||
#### 19. Session Status
|
||||
```
|
||||
GET /sessions/:sessionDbId/status
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"session_id": "abc-123",
|
||||
"status": "active",
|
||||
"observation_count": 42,
|
||||
"summary_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
#### 20. Delete Session
|
||||
```
|
||||
DELETE /sessions/:sessionDbId
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: As of v4.1.0, the cleanup hook no longer calls this endpoint. Sessions are marked complete instead of deleted to allow graceful worker shutdown.
|
||||
|
||||
## Bun Process Management
|
||||
|
||||
### Overview
|
||||
|
||||
The worker is managed by the native `ProcessManager` class which handles:
|
||||
- Process spawning with Bun runtime
|
||||
- PID file tracking at `~/.claude-mem/worker.pid`
|
||||
- Health checks with automatic retry
|
||||
- Graceful shutdown with SIGTERM/SIGKILL fallback
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
# Start worker (auto-starts on first session)
|
||||
npm run worker:start
|
||||
|
||||
# Stop worker
|
||||
npm run worker:stop
|
||||
|
||||
# Restart worker
|
||||
claude-mem restart
|
||||
|
||||
# View logs
|
||||
npm run worker:logs
|
||||
|
||||
# Check status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
### Auto-Start Behavior
|
||||
|
||||
The worker service auto-starts when the SessionStart hook fires. Manual start is optional.
|
||||
|
||||
### Bun Requirement
|
||||
|
||||
Bun is required to run the worker service. If Bun is not installed, the smart-install script will automatically install it on first run:
|
||||
|
||||
- **Windows**: `powershell -c "irm bun.sh/install.ps1 | iex"`
|
||||
- **macOS/Linux**: `curl -fsSL https://bun.sh/install | bash`
|
||||
|
||||
You can also install manually via:
|
||||
- `winget install Oven-sh.Bun` (Windows)
|
||||
- `brew install oven-sh/bun/bun` (macOS)
|
||||
|
||||
## Claude Agent SDK Integration
|
||||
|
||||
The worker service routes observations to the Claude Agent SDK for AI-powered processing:
|
||||
|
||||
### Processing Flow
|
||||
|
||||
1. **Observation Queue**: Observations accumulate in memory
|
||||
2. **SDK Processing**: Observations sent to Claude via Agent SDK
|
||||
3. **XML Parsing**: Responses parsed for structured data
|
||||
4. **Database Storage**: Processed observations stored in SQLite
|
||||
|
||||
### SDK Components
|
||||
|
||||
- **Prompts** (`src/sdk/prompts.ts`): Builds XML-structured prompts
|
||||
- **Parser** (`src/sdk/parser.ts`): Parses Claude's XML responses
|
||||
- **Worker** (`src/sdk/worker.ts`): Main SDK agent loop
|
||||
|
||||
### Model Configuration
|
||||
|
||||
Set the AI model used for processing via environment variable:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_MODEL=sonnet
|
||||
```
|
||||
|
||||
Available shorthand models (forward to latest version):
|
||||
- `haiku` - Fast, cost-efficient
|
||||
- `sonnet` - Balanced (default)
|
||||
- `opus` - Most capable
|
||||
|
||||
## Port Allocation
|
||||
|
||||
The worker uses a fixed port (37777 by default) for consistent communication:
|
||||
|
||||
- **Default**: Port 37777
|
||||
- **Override**: Set `CLAUDE_MEM_WORKER_PORT` environment variable
|
||||
- **Port File**: `${CLAUDE_PLUGIN_ROOT}/data/worker.port` tracks current port
|
||||
|
||||
If port 37777 is in use, the worker will fail to start. Set a custom port via environment variable.
|
||||
|
||||
## Data Storage
|
||||
|
||||
The worker service stores data in the user data directory:
|
||||
|
||||
```
|
||||
~/.claude-mem/
|
||||
├── claude-mem.db # SQLite database (bun:sqlite)
|
||||
├── worker.pid # PID file for process tracking
|
||||
├── settings.json # User settings
|
||||
└── logs/
|
||||
└── worker-YYYY-MM-DD.log # Daily rotating logs
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The worker implements graceful degradation:
|
||||
|
||||
- **Database Errors**: Logged but don't crash the service
|
||||
- **SDK Errors**: Retried with exponential backoff
|
||||
- **Network Errors**: Logged and skipped
|
||||
- **Invalid Input**: Validated and rejected with error response
|
||||
|
||||
## Performance
|
||||
|
||||
- **Async Processing**: Observations processed asynchronously
|
||||
- **In-Memory Queue**: Fast observation accumulation
|
||||
- **Batch Processing**: Multiple observations processed together
|
||||
- **Connection Pooling**: SQLite connections reused
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Worker Issues](../troubleshooting.md#worker-service-issues) for common problems and solutions.
|
||||
@@ -0,0 +1,151 @@
|
||||
---
|
||||
title: "Beta Features"
|
||||
description: "Try experimental features like Endless Mode before they're released"
|
||||
---
|
||||
|
||||
# Beta Features
|
||||
|
||||
<Warning>
|
||||
**Endless Mode is experimental and not included in the stable release.** You must manually switch to the beta branch to try it. The efficiency projections below are based on theoretical modeling, not production measurements. Expect slower performance than standard mode and potential bugs.
|
||||
</Warning>
|
||||
|
||||
Claude-Mem offers a beta channel for users who want to try experimental features before they're released to the stable channel.
|
||||
|
||||
## Version Channel Switching
|
||||
|
||||
You can switch between stable and beta versions directly from the web viewer UI at http://localhost:37777.
|
||||
|
||||
### How to Access
|
||||
|
||||
1. Open the Claude-Mem viewer at http://localhost:37777
|
||||
2. Click the **Settings** gear icon in the top-right
|
||||
3. Find the **Version Channel** section
|
||||
4. Click **Try Beta (Endless Mode)** to switch to beta, or **Switch to Stable** to return
|
||||
|
||||
### What Happens When You Switch
|
||||
|
||||
When switching versions:
|
||||
|
||||
1. **Local changes are discarded** - Any modifications in the plugin directory are reset
|
||||
2. **Git fetch and checkout** - The installed plugin switches to the target branch
|
||||
3. **Dependencies reinstall** - `npm install` runs to ensure correct dependencies
|
||||
4. **Worker restarts automatically** - The background service restarts with the new version
|
||||
|
||||
**Your memory data is always preserved.** The database at `~/.claude-mem/claude-mem.db` is not affected by version switching. All your observations, sessions, and summaries remain intact.
|
||||
|
||||
### Version Indicators
|
||||
|
||||
The Version Channel section shows your current status:
|
||||
|
||||
- **Stable** (green badge) - You're running the production release
|
||||
- **Beta** (orange badge) - You're running the beta with experimental features
|
||||
|
||||
You'll also see the exact branch name (e.g., `main` for stable, `beta/7.0` for beta).
|
||||
|
||||
## Endless Mode (Beta)
|
||||
|
||||
The flagship experimental feature in beta is **Endless Mode** - a biomimetic memory architecture that dramatically extends how long Claude can maintain context in a session.
|
||||
|
||||
### The Problem Endless Mode Solves
|
||||
|
||||
In standard Claude Code sessions:
|
||||
|
||||
- Tool outputs (file reads, bash output, search results) accumulate in the context window
|
||||
- Each tool can add 1-10k+ tokens to the context
|
||||
- After ~50 tool uses, the context window fills up (~200k tokens)
|
||||
- You're forced to start a new session, losing conversational continuity
|
||||
|
||||
Worse, Claude **re-synthesizes all previous tool outputs** on every response. This is O(N²) complexity - quadratically growing both in tokens and compute.
|
||||
|
||||
### How Endless Mode Works
|
||||
|
||||
Endless Mode applies a biomimetic memory architecture inspired by how human memory works:
|
||||
|
||||
**Two-Tier Memory System:**
|
||||
|
||||
```
|
||||
Working Memory (Context Window):
|
||||
→ Compressed observations only (~500 tokens each)
|
||||
→ Fast, efficient, manageable
|
||||
|
||||
Archive Memory (Transcript File):
|
||||
→ Full tool outputs preserved on disk
|
||||
→ Perfect recall, searchable
|
||||
```
|
||||
|
||||
**The Key Innovation**: After each tool use, Endless Mode:
|
||||
1. Waits for the worker to generate a compressed observation (blocking)
|
||||
2. Transforms the transcript file on disk
|
||||
3. Replaces the full tool output with the compressed observation
|
||||
4. Claude resumes with the compressed context
|
||||
|
||||
This transforms O(N²) scaling into O(N) - linear instead of quadratic.
|
||||
|
||||
### Projected Results
|
||||
|
||||
Based on theoretical modeling (not production measurements):
|
||||
|
||||
- **Token savings**: Significant reduction in context window usage
|
||||
- **Efficiency gain**: More tool uses before context exhaustion
|
||||
- **Quality preservation**: Observations cache the synthesis result, so no information is lost
|
||||
|
||||
### Important Caveats
|
||||
|
||||
Endless Mode is experimental and has significant limitations:
|
||||
|
||||
- **Not in stable release** - You must manually switch to the beta branch to use this feature
|
||||
- **Still in development** - May have bugs, breaking changes, or incomplete functionality
|
||||
- **Slower than standard mode** - Blocking observation generation adds latency to each tool use
|
||||
- **Theoretical projections** - The efficiency claims above are based on simulations, not real-world production data
|
||||
- **Requires working database** - Observations must save successfully for transformation
|
||||
- **New architecture** - Less battle-tested than standard mode
|
||||
|
||||
### When to Use Beta
|
||||
|
||||
Consider switching to beta if you:
|
||||
|
||||
- Frequently hit context window limits
|
||||
- Work on long, complex sessions with many tool uses
|
||||
- Want to help test and provide feedback on new features
|
||||
- Are comfortable with experimental software
|
||||
|
||||
### When to Stay on Stable
|
||||
|
||||
Stay on stable if you:
|
||||
|
||||
- Need maximum reliability for critical work
|
||||
- Prefer battle-tested, production-ready features
|
||||
- Don't frequently hit context limits
|
||||
- Want the smoothest, fastest experience
|
||||
|
||||
## Checking for Updates
|
||||
|
||||
While on beta (or stable), you can check for updates:
|
||||
|
||||
1. Open Settings in the viewer
|
||||
2. In the Version Channel section, click **Check for Updates**
|
||||
3. The plugin will pull the latest changes and restart
|
||||
|
||||
## Switching Back
|
||||
|
||||
If you encounter issues on beta:
|
||||
|
||||
1. Open Settings in the viewer
|
||||
2. Click **Switch to Stable**
|
||||
3. Wait for the worker to restart
|
||||
|
||||
Your memory data is preserved, and you'll be back on the stable release.
|
||||
|
||||
## Providing Feedback
|
||||
|
||||
If you encounter bugs or have feedback about beta features:
|
||||
|
||||
- Open an issue at [GitHub Issues](https://github.com/thedotmack/claude-mem/issues)
|
||||
- Include your branch (`beta/7.0` etc.) in the report
|
||||
- Describe what you expected vs. what happened
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration](configuration) - Customize other Claude-Mem settings
|
||||
- [Troubleshooting](troubleshooting) - Common issues and solutions
|
||||
- [Architecture Overview](architecture/overview) - Understand how Claude-Mem works
|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
@@ -0,0 +1,455 @@
|
||||
---
|
||||
title: "Configuration"
|
||||
description: "Environment variables and settings for Claude-Mem"
|
||||
---
|
||||
|
||||
# Configuration
|
||||
|
||||
## Settings File
|
||||
|
||||
Settings are managed in `~/.claude-mem/settings.json`. The file is auto-created with defaults on first run.
|
||||
|
||||
### Core Settings
|
||||
|
||||
| Setting | Default | Description |
|
||||
|-------------------------------|---------------------------------|---------------------------------------|
|
||||
| `CLAUDE_MEM_MODEL` | `sonnet` | AI model for processing observations |
|
||||
| `CLAUDE_MEM_CONTEXT_OBSERVATIONS` | `50` | Number of observations to inject |
|
||||
| `CLAUDE_MEM_WORKER_PORT` | `37777` | Worker service port |
|
||||
| `CLAUDE_MEM_SKIP_TOOLS` | `ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion` | Comma-separated tools to exclude from observations |
|
||||
|
||||
### System Configuration
|
||||
|
||||
| Setting | Default | Description |
|
||||
|-------------------------------|---------------------------------|---------------------------------------|
|
||||
| `CLAUDE_MEM_DATA_DIR` | `~/.claude-mem` | Data directory location |
|
||||
| `CLAUDE_MEM_LOG_LEVEL` | `INFO` | Log verbosity (DEBUG, INFO, WARN, ERROR, SILENT) |
|
||||
| `CLAUDE_MEM_PYTHON_VERSION` | `3.13` | Python version for chroma-mcp |
|
||||
| `CLAUDE_CODE_PATH` | _(auto-detect)_ | Path to Claude Code CLI (for Windows) |
|
||||
|
||||
## Model Configuration
|
||||
|
||||
Configure which AI model processes your observations.
|
||||
|
||||
### Available Models
|
||||
|
||||
Shorthand model names automatically forward to the latest version:
|
||||
|
||||
- `haiku` - Fast, cost-efficient
|
||||
- `sonnet` - Balanced (default)
|
||||
- `opus` - Most capable
|
||||
|
||||
### Using the Interactive Script
|
||||
|
||||
```bash
|
||||
./claude-mem-settings.sh
|
||||
```
|
||||
|
||||
This script manages settings in `~/.claude-mem/settings.json`.
|
||||
|
||||
### Manual Configuration
|
||||
|
||||
Edit `~/.claude-mem/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_MODEL": "sonnet"
|
||||
}
|
||||
```
|
||||
|
||||
## Files and Directories
|
||||
|
||||
### Data Directory Structure
|
||||
|
||||
The data directory location depends on the environment:
|
||||
- **Production (installed plugin)**: `~/.claude-mem/` (always, regardless of CLAUDE_PLUGIN_ROOT)
|
||||
- **Development**: Can be overridden with `CLAUDE_MEM_DATA_DIR`
|
||||
|
||||
```
|
||||
~/.claude-mem/
|
||||
├── claude-mem.db # SQLite database
|
||||
├── .install-version # Cached version for smart installer
|
||||
├── worker.port # Current worker port file
|
||||
└── logs/
|
||||
├── worker-out.log # Worker stdout logs
|
||||
└── worker-error.log # Worker stderr logs
|
||||
```
|
||||
|
||||
### Plugin Directory Structure
|
||||
|
||||
```
|
||||
${CLAUDE_PLUGIN_ROOT}/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin metadata
|
||||
├── .mcp.json # MCP server configuration
|
||||
├── hooks/
|
||||
│ └── hooks.json # Hook configuration
|
||||
├── scripts/ # Built executables
|
||||
│ ├── smart-install.js # Smart installer script
|
||||
│ ├── context-hook.js # Context injection hook
|
||||
│ ├── new-hook.js # Session creation hook
|
||||
│ ├── save-hook.js # Observation capture hook
|
||||
│ ├── summary-hook.js # Summary generation hook
|
||||
│ ├── cleanup-hook.js # Session cleanup hook
|
||||
│ ├── worker-service.cjs # Worker service (CJS)
|
||||
│ └── mcp-server.cjs # MCP search server (CJS)
|
||||
└── ui/
|
||||
└── viewer.html # Web viewer UI bundle
|
||||
```
|
||||
|
||||
## Plugin Configuration
|
||||
|
||||
### Hooks Configuration
|
||||
|
||||
Hooks are configured in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Claude-mem memory system hooks",
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/smart-install.js && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Search Configuration (v5.4.0+)
|
||||
|
||||
**Migration Note**: As of v5.4.0, Claude-Mem uses skill-based search instead of MCP tools. As of v5.5.0, the skill was renamed to "mem-search" for better scope differentiation.
|
||||
|
||||
**Previous (v5.3.x and earlier)**: MCP search server with 9 tools (~2,500 tokens per session)
|
||||
**Current (v5.4.0+)**: mem-search skill with HTTP API (~250 tokens per session)
|
||||
|
||||
**No configuration required** - the mem-search skill is automatically available in Claude Code sessions.
|
||||
|
||||
Search operations are now provided via:
|
||||
- **Skill**: `plugin/skills/mem-search/SKILL.md` (auto-invoked when users ask about past work)
|
||||
- **HTTP API**: 10 endpoints on worker service port 37777
|
||||
- **Progressive Disclosure**: Full instructions loaded on-demand only when needed
|
||||
|
||||
## Version Channel
|
||||
|
||||
Claude-Mem supports switching between stable and beta versions via the web viewer UI.
|
||||
|
||||
### Accessing Version Channel
|
||||
|
||||
1. Open the viewer at http://localhost:37777
|
||||
2. Click the Settings gear icon
|
||||
3. Find the **Version Channel** section
|
||||
|
||||
### Switching Versions
|
||||
|
||||
- **Try Beta**: Click "Try Beta (Endless Mode)" to switch to the beta branch with experimental features
|
||||
- **Switch to Stable**: Click "Switch to Stable" to return to the production release
|
||||
- **Check for Updates**: Pull the latest changes for your current branch
|
||||
|
||||
**Your memory data is preserved** when switching versions. Only the plugin code changes.
|
||||
|
||||
<Note>
|
||||
Endless Mode is experimental and slower than standard mode. See [Beta Features](beta-features) for full details and important limitations.
|
||||
</Note>
|
||||
|
||||
## Worker Service Management
|
||||
|
||||
Worker service is managed by Bun as a background process. The worker auto-starts on first session and runs continuously in the background.
|
||||
|
||||
## Context Injection Configuration
|
||||
|
||||
Claude-Mem injects past observations into each new session, giving Claude awareness of recent work. You can configure exactly what gets injected using the **Context Settings Modal**.
|
||||
|
||||
### Context Settings Modal
|
||||
|
||||
Access the settings modal from the web viewer at http://localhost:37777:
|
||||
|
||||
1. Click the **gear icon** in the header
|
||||
2. Adjust settings in the right panel
|
||||
3. See changes reflected live in the **Terminal Preview** on the left
|
||||
4. Settings auto-save as you change them
|
||||
|
||||
The Terminal Preview shows exactly what will be injected at the start of your next Claude Code session for the selected project.
|
||||
|
||||
### Loading Settings
|
||||
|
||||
Control how many observations are injected:
|
||||
|
||||
| Setting | Default | Range | Description |
|
||||
|---------|---------|-------|-------------|
|
||||
| **Observations** | 50 | 1-200 | Total number of recent observations to include |
|
||||
| **Sessions** | 10 | 1-50 | Number of recent sessions to pull observations from |
|
||||
|
||||
**Considerations**:
|
||||
- **Higher values** = More context but slower SessionStart and more tokens used
|
||||
- **Lower values** = Faster SessionStart but less historical awareness
|
||||
- Default of 50 observations from 10 sessions balances context richness with performance
|
||||
|
||||
### Filter Settings
|
||||
|
||||
Control which observation types and concepts are included:
|
||||
|
||||
**Types** (select any combination):
|
||||
- `bugfix` - Bug fixes and error resolutions
|
||||
- `feature` - New functionality additions
|
||||
- `refactor` - Code restructuring
|
||||
- `discovery` - Learnings about how code works
|
||||
- `decision` - Architectural or design decisions
|
||||
- `change` - General code changes
|
||||
|
||||
**Concepts** (select any combination):
|
||||
- `how-it-works` - System behavior explanations
|
||||
- `why-it-exists` - Rationale for code/design
|
||||
- `what-changed` - Change summaries
|
||||
- `problem-solution` - Problem/solution pairs
|
||||
- `gotcha` - Edge cases and pitfalls
|
||||
- `pattern` - Recurring patterns
|
||||
- `trade-off` - Design trade-offs
|
||||
|
||||
Use "All" or "None" buttons to quickly select/deselect all options.
|
||||
|
||||
### Display Settings
|
||||
|
||||
Control how observations appear in the context:
|
||||
|
||||
**Full Observations**:
|
||||
| Setting | Default | Options | Description |
|
||||
|---------|---------|---------|-------------|
|
||||
| **Count** | 5 | 0-20 | How many observations show expanded details |
|
||||
| **Field** | narrative | narrative, facts | Which field to expand |
|
||||
|
||||
The most recent N observations (set by Count) show their full narrative or facts. Remaining observations show only title, type, and token counts in a compact table format.
|
||||
|
||||
**Token Economics** (toggles):
|
||||
| Setting | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| **Read cost** | true | Show tokens to read each observation |
|
||||
| **Work investment** | true | Show tokens spent creating the observation |
|
||||
| **Savings** | true | Show total tokens saved by reusing context |
|
||||
|
||||
Token economics help you understand the value of cached observations vs. re-reading files.
|
||||
|
||||
### Advanced Settings
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| **Model** | sonnet | AI model for generating observations |
|
||||
| **Worker Port** | 37777 | Port for background worker service |
|
||||
| **MCP search server** | true | Enable Model Context Protocol search tools |
|
||||
| **Include last summary** | false | Add previous session's summary to context |
|
||||
| **Include last message** | false | Add previous session's final message |
|
||||
|
||||
### Manual Configuration
|
||||
|
||||
Settings are stored in `~/.claude-mem/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_CONTEXT_OBSERVATIONS": "100",
|
||||
"CLAUDE_MEM_CONTEXT_SESSION_COUNT": "20",
|
||||
"CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES": "bugfix,decision,discovery",
|
||||
"CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS": "how-it-works,gotcha",
|
||||
"CLAUDE_MEM_CONTEXT_FULL_COUNT": "10",
|
||||
"CLAUDE_MEM_CONTEXT_FULL_FIELD": "narrative",
|
||||
"CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS": "true",
|
||||
"CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS": "true",
|
||||
"CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT": "true",
|
||||
"CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY": "false",
|
||||
"CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE": "false"
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: The Context Settings Modal (at http://localhost:37777) is the recommended way to configure these settings, as it provides live preview of changes.
|
||||
|
||||
## Customization
|
||||
|
||||
Settings can be customized in `~/.claude-mem/settings.json`.
|
||||
|
||||
### Custom Data Directory
|
||||
|
||||
Edit `~/.claude-mem/settings.json`:
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_DATA_DIR": "/custom/path"
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Worker Port
|
||||
|
||||
Edit `~/.claude-mem/settings.json`:
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_WORKER_PORT": "38000"
|
||||
}
|
||||
```
|
||||
|
||||
Then restart the worker:
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Custom Model
|
||||
|
||||
Edit `~/.claude-mem/settings.json`:
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_MODEL": "opus"
|
||||
}
|
||||
```
|
||||
|
||||
Then restart the worker:
|
||||
```bash
|
||||
export CLAUDE_MEM_MODEL=opus
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Custom Skip Tools
|
||||
|
||||
Control which tools are excluded from observations. Edit `~/.claude-mem/settings.json`:
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_SKIP_TOOLS": "ListMcpResourcesTool,SlashCommand,Skill"
|
||||
}
|
||||
```
|
||||
|
||||
**Default excluded tools:**
|
||||
- `ListMcpResourcesTool`
|
||||
- `SlashCommand`
|
||||
- `Skill`
|
||||
- `TodoWrite`
|
||||
- `AskUserQuestion`
|
||||
|
||||
**Common customizations:**
|
||||
- Include TodoWrite: Remove from skip list to track task planning
|
||||
- Include AskUserQuestion: Remove to capture decision-making conversations
|
||||
- Skip additional tools: Add tool names to reduce observation noise
|
||||
|
||||
Changes take effect on the next tool execution (no worker restart needed).
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Hook Timeouts
|
||||
|
||||
Modify timeouts in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"timeout": 120 // Default: 120 seconds
|
||||
}
|
||||
```
|
||||
|
||||
Recommended values:
|
||||
- SessionStart: 120s (needs time for smart install check and context retrieval)
|
||||
- UserPromptSubmit: 60s
|
||||
- PostToolUse: 120s (can process many observations)
|
||||
- Stop: 60s
|
||||
- SessionEnd: 60s
|
||||
|
||||
**Note**: With smart install caching (v5.0.3+), SessionStart is typically very fast (10ms) unless dependencies need installation.
|
||||
|
||||
### Worker Memory Limit
|
||||
|
||||
The worker service is managed by Bun and will automatically restart if it encounters issues. Memory usage is typically low (~100-200MB).
|
||||
|
||||
### Logging Verbosity
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
export DEBUG=claude-mem:*
|
||||
claude-mem restart
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
## Configuration Best Practices
|
||||
|
||||
1. **Use defaults**: Default configuration works for most use cases
|
||||
2. **Override selectively**: Only change what you need
|
||||
3. **Document changes**: Keep track of custom configurations
|
||||
4. **Test after changes**: Verify worker restarts successfully
|
||||
5. **Monitor logs**: Check worker logs after configuration changes
|
||||
|
||||
## Troubleshooting Configuration
|
||||
|
||||
### Configuration Not Applied
|
||||
|
||||
1. Restart worker after changes:
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
2. Verify environment variables:
|
||||
```bash
|
||||
echo $CLAUDE_MEM_MODEL
|
||||
echo $CLAUDE_MEM_WORKER_PORT
|
||||
```
|
||||
|
||||
3. Check worker logs:
|
||||
```bash
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
### Invalid Model Name
|
||||
|
||||
If you specify an invalid model name, the worker will fall back to `sonnet` and log a warning.
|
||||
|
||||
Valid shorthand models (forward to latest version):
|
||||
- haiku
|
||||
- sonnet
|
||||
- opus
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
If port 37777 is already in use:
|
||||
|
||||
1. Set custom port:
|
||||
```bash
|
||||
export CLAUDE_MEM_WORKER_PORT=38000
|
||||
```
|
||||
|
||||
2. Restart worker:
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
3. Verify new port:
|
||||
```bash
|
||||
cat ~/.claude-mem/worker.port
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Architecture Overview](architecture/overview) - Understand the system
|
||||
- [Troubleshooting](troubleshooting) - Common issues
|
||||
- [Development](development) - Building from source
|
||||
@@ -1,4 +1,9 @@
|
||||
# Context Engineering for AI Agents: Best Practices Cheat Sheet
|
||||
---
|
||||
title: "Context Engineering"
|
||||
description: "Best practices for curating optimal token sets for AI agents"
|
||||
---
|
||||
|
||||
# Context Engineering for AI Agents
|
||||
|
||||
## Core Principle
|
||||
**Find the smallest possible set of high-signal tokens that maximize the likelihood of your desired outcome.**
|
||||
@@ -33,13 +33,16 @@ The build process uses esbuild to compile TypeScript:
|
||||
|
||||
1. Compiles TypeScript to JavaScript
|
||||
2. Creates standalone executables for each hook in `plugin/scripts/`
|
||||
3. Bundles MCP search server to `plugin/scripts/search-server.js`
|
||||
3. Bundles MCP search server to `plugin/scripts/mcp-server.cjs`
|
||||
4. Bundles worker service to `plugin/scripts/worker-service.cjs`
|
||||
5. Bundles web viewer UI to `plugin/ui/viewer.html`
|
||||
|
||||
**Build Output**:
|
||||
- Hook executables: `*-hook.js` (ESM format)
|
||||
- Smart installer: `smart-install.js` (ESM format)
|
||||
- Worker service: `worker-service.cjs` (CJS format)
|
||||
- Search server: `search-server.js` (ESM format)
|
||||
- MCP server: `mcp-server.cjs` (CJS format)
|
||||
- Viewer UI: `viewer.html` (self-contained HTML bundle)
|
||||
|
||||
### Build Scripts
|
||||
|
||||
@@ -61,12 +64,13 @@ Edit TypeScript source files in `src/`:
|
||||
|
||||
```
|
||||
src/
|
||||
├── bin/hooks/ # Hook entry points
|
||||
├── hooks/ # Hook implementations
|
||||
├── hooks/ # Hook implementations (entry points + logic)
|
||||
├── services/ # Worker service and database
|
||||
├── servers/ # MCP search server
|
||||
├── sdk/ # Claude Agent SDK integration
|
||||
├── shared/ # Shared utilities
|
||||
├── ui/
|
||||
│ └── viewer/ # React web viewer UI components
|
||||
└── utils/ # General utilities
|
||||
```
|
||||
|
||||
@@ -112,40 +116,138 @@ echo '{"session_id":"test-123","cwd":"'$(pwd)'","source":"startup"}' | node plug
|
||||
|
||||
Repeat steps 1-4 until your changes work as expected.
|
||||
|
||||
## Viewer UI Development
|
||||
|
||||
### Working with the React Viewer
|
||||
|
||||
The web viewer UI is a React application built into a self-contained HTML bundle.
|
||||
|
||||
**Location**: `src/ui/viewer/`
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
src/ui/viewer/
|
||||
├── index.tsx # Entry point
|
||||
├── App.tsx # Main application component
|
||||
├── components/ # React components
|
||||
│ ├── Header.tsx # Header with logo and actions
|
||||
│ ├── Sidebar.tsx # Project filter sidebar
|
||||
│ ├── Feed.tsx # Main feed with infinite scroll
|
||||
│ ├── cards/ # Card components
|
||||
│ │ ├── ObservationCard.tsx
|
||||
│ │ ├── PromptCard.tsx
|
||||
│ │ ├── SummaryCard.tsx
|
||||
│ │ └── SkeletonCard.tsx
|
||||
├── hooks/ # Custom React hooks
|
||||
│ ├── useSSE.ts # Server-Sent Events connection
|
||||
│ ├── usePagination.ts # Infinite scroll pagination
|
||||
│ ├── useSettings.ts # Settings persistence
|
||||
│ └── useStats.ts # Database statistics
|
||||
├── utils/ # Utilities
|
||||
│ ├── constants.ts # Constants (API URLs, etc.)
|
||||
│ ├── formatters.ts # Date/time formatting
|
||||
│ └── merge.ts # Data merging and deduplication
|
||||
└── assets/ # Static assets (fonts, logos)
|
||||
```
|
||||
|
||||
### Building Viewer UI
|
||||
|
||||
```bash
|
||||
# Build everything including viewer
|
||||
npm run build
|
||||
|
||||
# The viewer is built to plugin/ui/viewer.html
|
||||
# It's a self-contained HTML file with inlined JS and CSS
|
||||
```
|
||||
|
||||
### Testing Viewer Changes
|
||||
|
||||
1. Make changes to React components in `src/ui/viewer/`
|
||||
2. Build: `npm run build`
|
||||
3. Sync to installed plugin: `npm run sync-marketplace`
|
||||
4. Restart worker: `claude-mem restart`
|
||||
5. Refresh browser at http://localhost:37777
|
||||
|
||||
**Hot Reload**: Not currently supported. Full rebuild + restart required for changes.
|
||||
|
||||
### Adding New Viewer Features
|
||||
|
||||
**Example: Adding a new card type**
|
||||
|
||||
1. Create component in `src/ui/viewer/components/cards/YourCard.tsx`:
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
|
||||
export interface YourCardProps {
|
||||
// Your data structure
|
||||
}
|
||||
|
||||
export const YourCard: React.FC<YourCardProps> = ({ ... }) => {
|
||||
return (
|
||||
<div className="card">
|
||||
{/* Your UI */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
2. Import and use in `Feed.tsx`:
|
||||
|
||||
```tsx
|
||||
import { YourCard } from './cards/YourCard';
|
||||
|
||||
// In render logic:
|
||||
{item.type === 'your_type' && <YourCard {...item} />}
|
||||
```
|
||||
|
||||
3. Update types if needed in `src/ui/viewer/types.ts`
|
||||
|
||||
4. Rebuild and test
|
||||
|
||||
### Viewer UI Architecture
|
||||
|
||||
**Data Flow**:
|
||||
1. Worker service exposes HTTP + SSE endpoints
|
||||
2. React app fetches initial data via HTTP (paginated)
|
||||
3. SSE connection provides real-time updates
|
||||
4. Custom hooks handle state management and data merging
|
||||
5. Components render cards based on item type
|
||||
|
||||
**Key Patterns**:
|
||||
- **Infinite Scroll**: `usePagination` hook with Intersection Observer
|
||||
- **Real-Time Updates**: `useSSE` hook with auto-reconnection
|
||||
- **Deduplication**: `merge.ts` utilities prevent duplicate items
|
||||
- **Settings Persistence**: `useSettings` hook with localStorage
|
||||
- **Theme Support**: CSS variables with light/dark/system themes
|
||||
|
||||
## Adding New Features
|
||||
|
||||
### Adding a New Hook
|
||||
|
||||
1. Create hook implementation in `src/hooks/your-hook.ts`:
|
||||
|
||||
```typescript
|
||||
import { HookInput } from './types';
|
||||
|
||||
export async function yourHook(input: HookInput) {
|
||||
// Hook implementation
|
||||
return {
|
||||
hookSpecificOutput: 'Optional output'
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
2. Create entry point in `src/bin/hooks/your-hook.ts`:
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import { readStdin } from '../../shared/stdin';
|
||||
import { yourHook } from '../../hooks/your-hook';
|
||||
import { readStdin } from '../shared/stdin';
|
||||
|
||||
async function main() {
|
||||
const input = await readStdin();
|
||||
const result = await yourHook(input);
|
||||
|
||||
// Hook implementation
|
||||
const result = {
|
||||
hookSpecificOutput: 'Optional output'
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(result));
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
3. Add to `plugin/hooks/hooks.json`:
|
||||
**Note**: As of v4.3.1, hooks are self-contained files. The shebang will be added automatically by esbuild during the build process.
|
||||
|
||||
2. Add to `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -240,7 +342,7 @@ npm test
|
||||
|
||||
### Adding MCP Search Tools
|
||||
|
||||
1. Add tool definition in `src/servers/search-server.ts`:
|
||||
1. Add tool definition in `src/servers/mcp-server.ts`:
|
||||
|
||||
```typescript
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
@@ -354,7 +456,7 @@ export async function createObservation(
|
||||
|
||||
```bash
|
||||
export DEBUG=claude-mem:*
|
||||
npm run worker:restart
|
||||
claude-mem restart
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
@@ -424,18 +526,25 @@ The `release` script:
|
||||
6. Publish to NPM
|
||||
|
||||
```bash
|
||||
# Update version
|
||||
npm version 4.2.4
|
||||
# Manual version bump:
|
||||
# 1. Update version in package.json
|
||||
# 2. Update version in plugin/.claude-plugin/plugin.json
|
||||
# 3. Update version at top of CLAUDE.md
|
||||
# 4. Update version badge in README.md
|
||||
# 5. Run: npm run build && npm run sync-marketplace
|
||||
|
||||
# Or use npm version command:
|
||||
npm version 4.3.2
|
||||
|
||||
# Update changelog
|
||||
# Edit CHANGELOG.md manually
|
||||
|
||||
# Commit
|
||||
git add .
|
||||
git commit -m "chore: Release v4.2.4"
|
||||
git commit -m "chore: Release v4.3.2"
|
||||
|
||||
# Tag
|
||||
git tag v4.2.4
|
||||
git tag v4.3.2
|
||||
|
||||
# Push
|
||||
git push origin main --tags
|
||||
@@ -541,7 +650,7 @@ rm -rf plugin/scripts/*.js plugin/scripts/*.cjs
|
||||
|
||||
1. Kill existing process:
|
||||
```bash
|
||||
pm2 delete claude-mem-worker
|
||||
npm run worker:stop
|
||||
```
|
||||
|
||||
2. Check port:
|
||||
@@ -36,7 +36,20 @@
|
||||
"introduction",
|
||||
"installation",
|
||||
"usage/getting-started",
|
||||
"usage/search-tools"
|
||||
"usage/search-tools",
|
||||
"usage/claude-desktop",
|
||||
"usage/private-tags",
|
||||
"usage/export-import",
|
||||
"beta-features",
|
||||
"endless-mode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Best Practices",
|
||||
"icon": "lightbulb",
|
||||
"pages": [
|
||||
"context-engineering",
|
||||
"progressive-disclosure"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -45,7 +58,8 @@
|
||||
"pages": [
|
||||
"configuration",
|
||||
"development",
|
||||
"troubleshooting"
|
||||
"troubleshooting",
|
||||
"platform-integration"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -53,10 +67,13 @@
|
||||
"icon": "diagram-project",
|
||||
"pages": [
|
||||
"architecture/overview",
|
||||
"architecture-evolution",
|
||||
"hooks-architecture",
|
||||
"architecture/hooks",
|
||||
"architecture/worker-service",
|
||||
"architecture/database",
|
||||
"architecture/mcp-search"
|
||||
"architecture/search-architecture",
|
||||
"architecture/pm2-to-bun-migration"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "Endless Mode (Beta)"
|
||||
description: "Experimental biomimetic memory architecture for extended sessions"
|
||||
---
|
||||
|
||||
# Current State of Endless Mode
|
||||
|
||||
## Core Concept
|
||||
|
||||
Endless Mode is a **biomimetic memory architecture** that solves Claude's context window exhaustion problem. Instead of keeping full tool outputs in the context window (O(N²) complexity), it:
|
||||
|
||||
- Captures compressed observations after each tool use
|
||||
- Replaces transcripts with low token summaries
|
||||
- Achieves O(N) linear complexity
|
||||
- Maintains two-tier memory: working memory (compressed) + archive memory (full transcript on disk, maintained by default claude code functionality)
|
||||
|
||||
## Implementation Status
|
||||
|
||||
**Status**: FUNCTIONAL BUT EXPERIMENTAL
|
||||
|
||||
**Current Branch**: `beta/endless-mode` (ahead of main)
|
||||
|
||||
**Recent Activity**:
|
||||
- Merged main branch changes
|
||||
- Resolved merge conflicts in save-hook, SessionStore, SessionRoutes
|
||||
- Updated documentation to remove misleading token reduction claims
|
||||
- Added important caveats about beta status
|
||||
|
||||
## Key Architecture Components
|
||||
|
||||
1. **Pre-Tool-Use Hook** - Tracks tool execution start, sends tool_use_id to worker
|
||||
2. **Save Hook (PostToolUse)** - **CRITICAL**: Blocks until observation is generated (110s timeout), injects compressed observation back into context
|
||||
3. **SessionManager.waitForNextObservation()** - Event-driven wait mechanism (no polling)
|
||||
4. **SDKAgent** - Generates observations via Agent SDK, emits completion events
|
||||
5. **Database** - Added `tool_use_id` column for observation correlation
|
||||
|
||||
## Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"CLAUDE_MEM_ENDLESS_MODE": "false", // Default: disabled
|
||||
"CLAUDE_MEM_ENDLESS_WAIT_TIMEOUT_MS": "90000" // 90 second timeout
|
||||
}
|
||||
```
|
||||
|
||||
**Enable via**: Manual checkout of beta branch (see instructions below)
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
Tool Executes → Pre-Hook (track ID) → Tool Completes →
|
||||
Save-Hook (BLOCKS) → Worker processes → SDK generates observation →
|
||||
Event fired → Hook receives observation → Injects markdown →
|
||||
Clears input → Context reduced
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
From the documentation:
|
||||
- ⚠️ **Slower than standard mode** - Blocking adds latency
|
||||
- ⚠️ **Still in development** - May have bugs
|
||||
- ⚠️ **Not battle-tested** - New architecture
|
||||
- ⚠️ **Theoretical projections** - Efficiency gains not yet validated in production
|
||||
|
||||
## What's Working
|
||||
|
||||
- ✅ Synchronous observation injection
|
||||
- ✅ Event-driven wait mechanism
|
||||
- ✅ Token reduction via input clearing
|
||||
- ✅ Database schema with tool_use_id
|
||||
- ✅ Web UI for version switching
|
||||
- ✅ Graceful timeout fallbacks
|
||||
|
||||
## What's Not Ready
|
||||
|
||||
- ❌ Production validation of token savings
|
||||
- ❌ Comprehensive test coverage
|
||||
- ❌ Stable channel release
|
||||
- ❌ Performance benchmarks
|
||||
- ❌ Long-running session data
|
||||
|
||||
## How to Try Endless Mode
|
||||
|
||||
Endless Mode is currently only available on the beta branch. To try it:
|
||||
|
||||
```bash
|
||||
# Navigate to your claude-mem installation
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack/
|
||||
|
||||
# Checkout the beta branch
|
||||
git checkout beta/endless-mode
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Restart the worker
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
**To return to stable:**
|
||||
|
||||
```bash
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack/
|
||||
git checkout main
|
||||
npm install
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The implementation is architecturally complete and functional, but remains experimental pending production validation of the theoretical efficiency gains.
|
||||
@@ -0,0 +1,852 @@
|
||||
# How Claude-Mem Uses Hooks: A Lifecycle-Driven Architecture
|
||||
|
||||
## Core Principle
|
||||
**Observe the main Claude Code session from the outside, process observations in the background, inject context at the right time.**
|
||||
|
||||
---
|
||||
|
||||
## The Big Picture
|
||||
|
||||
Claude-Mem is fundamentally a **hook-driven system**. Every piece of functionality happens in response to lifecycle events:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ CLAUDE CODE SESSION │
|
||||
│ (Main session - user interacting with Claude) │
|
||||
│ │
|
||||
│ SessionStart → UserPromptSubmit → Tool Use → Stop │
|
||||
│ ↓ ↓ ↓ ↓ ↓ ↓ │
|
||||
│ [3 Hooks] [Hook] [Hook] [Hook] │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ CLAUDE-MEM SYSTEM │
|
||||
│ │
|
||||
│ Smart Context User New Obs │
|
||||
│ Install Inject Message Session Capture │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Key insight:** Claude-Mem doesn't interrupt or modify Claude Code's behavior. It observes from the outside and provides value through lifecycle hooks.
|
||||
|
||||
---
|
||||
|
||||
## Why Hooks?
|
||||
|
||||
### The Non-Invasive Requirement
|
||||
|
||||
Claude-Mem had several architectural constraints:
|
||||
|
||||
1. **Can't modify Claude Code**: It's a closed-source binary
|
||||
2. **Must be fast**: Can't slow down the main session
|
||||
3. **Must be reliable**: Can't break Claude Code if it fails
|
||||
4. **Must be portable**: Works on any project without configuration
|
||||
|
||||
**Solution:** External command hooks configured via settings.json
|
||||
|
||||
### The Hook System Advantage
|
||||
|
||||
Claude Code's hook system provides exactly what we need:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Lifecycle Events" icon="clock">
|
||||
SessionStart, UserPromptSubmit, PostToolUse, Stop
|
||||
</Card>
|
||||
|
||||
<Card title="Non-Blocking" icon="forward">
|
||||
Hooks run in parallel, don't wait for completion
|
||||
</Card>
|
||||
|
||||
<Card title="Context Injection" icon="upload">
|
||||
SessionStart and UserPromptSubmit can add context
|
||||
</Card>
|
||||
|
||||
<Card title="Tool Observation" icon="eye">
|
||||
PostToolUse sees all tool inputs and outputs
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
---
|
||||
|
||||
## The Six Hook Scripts + Pre-Hook
|
||||
|
||||
Claude-Mem uses 6 lifecycle hook scripts across 5 lifecycle events, plus 1 pre-hook script for dependency management. SessionStart runs 2 hooks in sequence (after the pre-hook script).
|
||||
|
||||
### Pre-Hook: Smart Install (Before SessionStart)
|
||||
|
||||
**Purpose:** Intelligently manage dependencies and start worker service
|
||||
|
||||
**Note:** This is NOT a lifecycle hook - it's a pre-hook script executed via command chaining before context-hook runs.
|
||||
|
||||
**When:** Claude Code starts (startup, clear, or compact)
|
||||
|
||||
**What it does:**
|
||||
1. Checks if dependencies need installation (version marker)
|
||||
2. Only runs `npm install` when necessary:
|
||||
- First-time installation
|
||||
- Version changed in package.json
|
||||
3. Provides Windows-specific error messages
|
||||
4. Starts Bun worker service
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/../scripts/smart-install.js\" && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 300
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
- ✅ Version caching (`.install-version` file)
|
||||
- ✅ Fast when already installed (~10ms vs 2-5 seconds)
|
||||
- ✅ Cross-platform compatible
|
||||
- ✅ Helpful Windows error messages for build tools
|
||||
|
||||
**v5.0.3 Enhancement:** Smart caching eliminates redundant installs
|
||||
|
||||
**Source:** `scripts/smart-install.js`
|
||||
|
||||
---
|
||||
|
||||
### Hook 1: SessionStart - Context Injection
|
||||
|
||||
**Purpose:** Inject relevant context from previous sessions
|
||||
|
||||
**When:** Claude Code starts (runs after smart-install pre-hook)
|
||||
|
||||
**What it does:**
|
||||
1. Extracts project name from current working directory
|
||||
2. Queries SQLite for recent session summaries (last 10)
|
||||
3. Queries SQLite for recent observations (configurable, default 50)
|
||||
4. Formats as progressive disclosure index
|
||||
5. Outputs to stdout (automatically injected into context)
|
||||
|
||||
**Key decisions:**
|
||||
- ✅ Runs on startup, clear, and compact
|
||||
- ✅ 300-second timeout (allows for npm install if needed)
|
||||
- ✅ Progressive disclosure format (index, not full details)
|
||||
- ✅ Configurable observation count via `CLAUDE_MEM_CONTEXT_OBSERVATIONS`
|
||||
|
||||
**Output format:**
|
||||
```markdown
|
||||
# [claude-mem] recent context
|
||||
|
||||
**Legend:** 🎯 session-request | 🔴 gotcha | 🟡 problem-solution ...
|
||||
|
||||
### Oct 26, 2025
|
||||
|
||||
**General**
|
||||
| ID | Time | T | Title | Tokens |
|
||||
|----|------|---|-------|--------|
|
||||
| #2586 | 12:58 AM | 🔵 | Context hook file empty | ~51 |
|
||||
|
||||
*Use mem-search skill to access full details*
|
||||
```
|
||||
|
||||
**Source:** `src/hooks/context-hook.ts` → `plugin/scripts/context-hook.js`
|
||||
|
||||
---
|
||||
|
||||
### Hook 2: SessionStart - User Message
|
||||
|
||||
**Purpose:** Display helpful user messages during first-time setup
|
||||
|
||||
**When:** Claude Code starts (runs after context-hook)
|
||||
|
||||
**What it does:**
|
||||
1. Checks if dependencies are installed
|
||||
2. Shows first-time setup message if needed
|
||||
3. Displays formatted context information with colors
|
||||
4. Shows link to viewer UI (http://localhost:37777)
|
||||
5. Exits with code 3 (informational, not error)
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/user-message-hook.js",
|
||||
"timeout": 10
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Output Example:**
|
||||
```
|
||||
📝 Claude-Mem Context Loaded
|
||||
ℹ️ Note: This appears as stderr but is informational only
|
||||
|
||||
[Context details with colors...]
|
||||
|
||||
📺 Watch live in browser http://localhost:37777/ (New! v5.1)
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
- ✅ User-friendly first-time experience
|
||||
- ✅ Visual context display
|
||||
- ✅ Links to viewer UI
|
||||
- ✅ Non-intrusive (exit code 3)
|
||||
|
||||
**Source:** `plugin/scripts/user-message-hook.js` (minified)
|
||||
|
||||
---
|
||||
|
||||
### Hook 3: UserPromptSubmit (New Session Hook)
|
||||
|
||||
**Purpose:** Initialize session tracking when user submits a prompt
|
||||
|
||||
**When:** Before Claude processes the user's message
|
||||
|
||||
**What it does:**
|
||||
1. Reads user prompt and session ID from stdin
|
||||
2. Creates new session record in SQLite
|
||||
3. Saves raw user prompt for full-text search (v4.2.0+)
|
||||
4. Starts Bun worker service if not running
|
||||
5. Returns immediately (non-blocking)
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key decisions:**
|
||||
- ✅ No matcher (runs for all prompts)
|
||||
- ✅ Creates session record immediately
|
||||
- ✅ Stores raw prompts for search (privacy note: local SQLite only)
|
||||
- ✅ Auto-starts worker service
|
||||
- ✅ Suppresses output (`suppressOutput: true`)
|
||||
|
||||
**Database operations:**
|
||||
```sql
|
||||
INSERT INTO sdk_sessions (claude_session_id, project, user_prompt, ...)
|
||||
VALUES (?, ?, ?, ...)
|
||||
|
||||
INSERT INTO user_prompts (session_id, prompt, prompt_number, ...)
|
||||
VALUES (?, ?, ?, ...)
|
||||
```
|
||||
|
||||
**Source:** `src/hooks/new-hook.ts` → `plugin/scripts/new-hook.js`
|
||||
|
||||
---
|
||||
|
||||
### Hook 4: PostToolUse (Save Observation Hook)
|
||||
|
||||
**Purpose:** Capture tool execution observations for later processing
|
||||
|
||||
**When:** Immediately after any tool completes successfully
|
||||
|
||||
**What it does:**
|
||||
1. Receives tool name, input, output from stdin
|
||||
2. Finds active session for current project
|
||||
3. Enqueues observation in observation_queue table
|
||||
4. Returns immediately (processing happens in worker)
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key decisions:**
|
||||
- ✅ Matcher: `*` (captures all tools)
|
||||
- ✅ Non-blocking (just enqueues, doesn't process)
|
||||
- ✅ Worker processes observations asynchronously
|
||||
- ✅ Parallel execution safe (each hook gets own stdin)
|
||||
|
||||
**Database operations:**
|
||||
```sql
|
||||
INSERT INTO observation_queue (session_id, tool_name, tool_input, tool_output, ...)
|
||||
VALUES (?, ?, ?, ?, ...)
|
||||
```
|
||||
|
||||
**What gets queued:**
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"tool_name": "Edit",
|
||||
"tool_input": {
|
||||
"file_path": "/path/to/file.ts",
|
||||
"old_string": "...",
|
||||
"new_string": "..."
|
||||
},
|
||||
"tool_output": {
|
||||
"success": true,
|
||||
"linesChanged": 5
|
||||
},
|
||||
"created_at_epoch": 1698765432
|
||||
}
|
||||
```
|
||||
|
||||
**Source:** `src/hooks/save-hook.ts` → `plugin/scripts/save-hook.js`
|
||||
|
||||
---
|
||||
|
||||
### Hook 5: Stop Hook (Summary Generation)
|
||||
|
||||
**Purpose:** Generate AI-powered session summaries during the session
|
||||
|
||||
**When:** When Claude stops (triggered by Stop lifecycle event)
|
||||
|
||||
**What it does:**
|
||||
1. Gathers session observations from database
|
||||
2. Sends to Claude Agent SDK for summarization
|
||||
3. Processes response and extracts structured summary
|
||||
4. Stores in session_summaries table
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key decisions:**
|
||||
- ✅ Triggered by Stop lifecycle event
|
||||
- ✅ Multiple summaries per session (v4.2.0+)
|
||||
- ✅ Summaries are checkpoints, not endings
|
||||
- ✅ Uses Claude Agent SDK for AI compression
|
||||
|
||||
**Summary structure:**
|
||||
```xml
|
||||
<summary>
|
||||
<request>User's original request</request>
|
||||
<investigated>What was examined</investigated>
|
||||
<learned>Key discoveries</learned>
|
||||
<completed>Work finished</completed>
|
||||
<next_steps>Remaining tasks</next_steps>
|
||||
<files_read>
|
||||
<file>path/to/file1.ts</file>
|
||||
<file>path/to/file2.ts</file>
|
||||
</files_read>
|
||||
<files_modified>
|
||||
<file>path/to/file3.ts</file>
|
||||
</files_modified>
|
||||
<notes>Additional context</notes>
|
||||
</summary>
|
||||
```
|
||||
|
||||
**Source:** `src/hooks/summary-hook.ts` → `plugin/scripts/summary-hook.js`
|
||||
|
||||
---
|
||||
|
||||
### Hook 6: SessionEnd (Cleanup Hook)
|
||||
|
||||
**Purpose:** Mark sessions as completed when they end
|
||||
|
||||
**When:** Claude Code session ends (not on `/clear`)
|
||||
|
||||
**What it does:**
|
||||
1. Marks session as completed in database
|
||||
2. Allows worker to finish processing
|
||||
3. Performs graceful cleanup
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key decisions:**
|
||||
- ✅ Graceful completion (v4.1.0+)
|
||||
- ✅ No longer sends DELETE to workers
|
||||
- ✅ Skips cleanup on `/clear` commands
|
||||
- ✅ Preserves ongoing sessions
|
||||
|
||||
**Why graceful cleanup?**
|
||||
|
||||
**Old approach (v3):**
|
||||
```typescript
|
||||
// ❌ Aggressive cleanup
|
||||
SessionEnd → DELETE /worker/session → Worker stops immediately
|
||||
```
|
||||
|
||||
**Problems:**
|
||||
- Interrupted summary generation
|
||||
- Lost pending observations
|
||||
- Race conditions
|
||||
|
||||
**New approach (v4.1.0+):**
|
||||
```typescript
|
||||
// ✅ Graceful completion
|
||||
SessionEnd → UPDATE sessions SET completed_at = NOW()
|
||||
Worker sees completion → Finishes processing → Exits naturally
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Worker finishes important operations
|
||||
- Summaries complete successfully
|
||||
- Clean state transitions
|
||||
|
||||
**Source:** `src/hooks/cleanup-hook.ts` → `plugin/scripts/cleanup-hook.js`
|
||||
|
||||
---
|
||||
|
||||
## Hook Execution Flow
|
||||
|
||||
### Session Lifecycle
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Claude
|
||||
participant Hooks
|
||||
participant Worker
|
||||
participant DB
|
||||
|
||||
User->>Claude: Start Claude Code
|
||||
Claude->>Hooks: SessionStart hook
|
||||
Hooks->>DB: Query recent context
|
||||
DB-->>Hooks: Session summaries + observations
|
||||
Hooks-->>Claude: Inject context
|
||||
Note over Claude: Context available for session
|
||||
|
||||
User->>Claude: Submit prompt
|
||||
Claude->>Hooks: UserPromptSubmit hook
|
||||
Hooks->>DB: Create session record
|
||||
Hooks->>Worker: Start worker (if not running)
|
||||
Worker-->>DB: Ready to process
|
||||
|
||||
Claude->>Claude: Execute tools
|
||||
Claude->>Hooks: PostToolUse (multiple times)
|
||||
Hooks->>DB: Queue observations
|
||||
Note over Worker: Polls queue, processes observations
|
||||
|
||||
Worker->>Worker: AI compression
|
||||
Worker->>DB: Store compressed observations
|
||||
Worker->>Hooks: Trigger summary hook
|
||||
Hooks->>DB: Store session summary
|
||||
|
||||
User->>Claude: Finish
|
||||
Claude->>Hooks: SessionEnd hook
|
||||
Hooks->>DB: Mark session complete
|
||||
Worker->>DB: Check completion
|
||||
Worker->>Worker: Finish processing
|
||||
Worker->>Worker: Exit gracefully
|
||||
```
|
||||
|
||||
### Hook Timing
|
||||
|
||||
| Event | Timing | Blocking | Timeout | Output Handling |
|
||||
|-------|--------|----------|---------|-----------------|
|
||||
| **SessionStart (smart-install)** | Before session | No | 300s | stderr (info) |
|
||||
| **SessionStart (context)** | Before session | No | 300s | stdout → context |
|
||||
| **SessionStart (user-message)** | Before session | No | 10s | stderr (info) |
|
||||
| **UserPromptSubmit** | Before processing | No | 120s | stdout → context |
|
||||
| **PostToolUse** | After tool | No | 120s | Transcript only |
|
||||
| **Summary** | Worker triggered | No | 120s | Database |
|
||||
| **SessionEnd** | On exit | No | 120s | Log only |
|
||||
|
||||
---
|
||||
|
||||
## The Worker Service Architecture
|
||||
|
||||
### Why a Background Worker?
|
||||
|
||||
**Problem:** Hooks must be fast (< 1 second)
|
||||
|
||||
**Reality:** AI compression takes 5-30 seconds per observation
|
||||
|
||||
**Solution:** Hooks enqueue observations, worker processes async
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ HOOK (Fast) │
|
||||
│ 1. Read stdin (< 1ms) │
|
||||
│ 2. Insert into queue (< 10ms) │
|
||||
│ 3. Return success (< 20ms total) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ (queue)
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ WORKER (Slow) │
|
||||
│ 1. Poll queue every 1s │
|
||||
│ 2. Process observation via Claude SDK (5-30s) │
|
||||
│ 3. Parse and store results │
|
||||
│ 4. Mark observation processed │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Bun Process Management
|
||||
|
||||
**Technology:** Bun (JavaScript runtime and process manager)
|
||||
|
||||
**Why Bun:**
|
||||
- Auto-restart on failure
|
||||
- Fast startup and low memory footprint
|
||||
- Built-in TypeScript support
|
||||
- Cross-platform (works on macOS, Linux, Windows)
|
||||
- No separate process manager needed
|
||||
|
||||
**Worker lifecycle:**
|
||||
```bash
|
||||
# Started by hooks automatically (if not running)
|
||||
npm run worker:start
|
||||
|
||||
# Status check
|
||||
npm run worker:status
|
||||
|
||||
# View logs
|
||||
npm run worker:logs
|
||||
|
||||
# Restart
|
||||
claude-mem restart
|
||||
|
||||
# Stop
|
||||
npm run worker:stop
|
||||
```
|
||||
|
||||
### Worker HTTP API
|
||||
|
||||
**Technology:** Express.js REST API on port 37777
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/health` | GET | Health check |
|
||||
| `/sessions` | POST | Create session |
|
||||
| `/sessions/:id` | GET | Get session status |
|
||||
| `/sessions/:id` | PATCH | Update session |
|
||||
| `/observations` | POST | Enqueue observation |
|
||||
| `/observations/:id` | GET | Get observation |
|
||||
|
||||
**Why HTTP API?**
|
||||
- Language-agnostic (hooks can be any language)
|
||||
- Easy debugging (curl commands)
|
||||
- Standard error handling
|
||||
- Proper async handling
|
||||
|
||||
---
|
||||
|
||||
## Design Patterns
|
||||
|
||||
### Pattern 1: Fire-and-Forget Hooks
|
||||
|
||||
**Principle:** Hooks should return immediately, not wait for completion
|
||||
|
||||
```typescript
|
||||
// ❌ Bad: Hook waits for processing
|
||||
export async function saveHook(stdin: HookInput) {
|
||||
const observation = parseInput(stdin);
|
||||
await processObservation(observation); // BLOCKS!
|
||||
return success();
|
||||
}
|
||||
|
||||
// ✅ Good: Hook enqueues and returns
|
||||
export async function saveHook(stdin: HookInput) {
|
||||
const observation = parseInput(stdin);
|
||||
await enqueueObservation(observation); // Fast
|
||||
return success(); // Immediate
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 2: Queue-Based Processing
|
||||
|
||||
**Principle:** Decouple capture from processing
|
||||
|
||||
```
|
||||
Hook (capture) → Queue (buffer) → Worker (process)
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Parallel hook execution safe
|
||||
- Worker failure doesn't affect hooks
|
||||
- Retry logic centralized
|
||||
- Backpressure handling
|
||||
|
||||
### Pattern 3: Graceful Degradation
|
||||
|
||||
**Principle:** Memory system failure shouldn't break Claude Code
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await captureObservation();
|
||||
} catch (error) {
|
||||
// Log error, but don't throw
|
||||
console.error('Memory capture failed:', error);
|
||||
return { continue: true, suppressOutput: true };
|
||||
}
|
||||
```
|
||||
|
||||
**Failure modes:**
|
||||
- Database locked → Skip observation, log error
|
||||
- Worker crashed → Auto-restart via Bun
|
||||
- Network issue → Retry with exponential backoff
|
||||
- Disk full → Warn user, disable memory
|
||||
|
||||
### Pattern 4: Progressive Enhancement
|
||||
|
||||
**Principle:** Core functionality works without memory, memory enhances it
|
||||
|
||||
```
|
||||
Without memory: Claude Code works normally
|
||||
With memory: Claude Code + context from past sessions
|
||||
Memory broken: Falls back to working normally
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hook Debugging
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable detailed hook execution logs:
|
||||
|
||||
```bash
|
||||
claude --debug
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```
|
||||
[DEBUG] Executing hooks for PostToolUse:Write
|
||||
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
|
||||
[DEBUG] Found 1 hook matchers in settings
|
||||
[DEBUG] Matched 1 hooks for query "Write"
|
||||
[DEBUG] Found 1 hook commands to execute
|
||||
[DEBUG] Executing hook command: ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js with timeout 60000ms
|
||||
[DEBUG] Hook command completed with status 0: {"continue":true,"suppressOutput":true}
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Hook not executing">
|
||||
**Symptoms:** Hook command never runs
|
||||
|
||||
**Debugging:**
|
||||
1. Check `/hooks` menu - is hook registered?
|
||||
2. Verify matcher pattern (case-sensitive!)
|
||||
3. Test command manually: `echo '{}' | node save-hook.js`
|
||||
4. Check file permissions (executable?)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Hook times out">
|
||||
**Symptoms:** Hook execution exceeds timeout
|
||||
|
||||
**Debugging:**
|
||||
1. Check timeout setting (default 60s)
|
||||
2. Identify slow operation (database? network?)
|
||||
3. Move slow operation to worker
|
||||
4. Increase timeout if necessary
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Context not injecting">
|
||||
**Symptoms:** SessionStart hook runs but context missing
|
||||
|
||||
**Debugging:**
|
||||
1. Check stdout (must be valid JSON or plain text)
|
||||
2. Verify no stderr output (pollutes JSON)
|
||||
3. Check exit code (must be 0)
|
||||
4. Look for npm install output (v4.3.1 fix)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Observations not captured">
|
||||
**Symptoms:** PostToolUse hook runs but observations missing
|
||||
|
||||
**Debugging:**
|
||||
1. Check database: `sqlite3 ~/.claude-mem/claude-mem.db "SELECT * FROM observation_queue"`
|
||||
2. Verify session exists: `SELECT * FROM sdk_sessions`
|
||||
3. Check worker status: `npm run worker:status`
|
||||
4. View worker logs: `npm run worker:logs`
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Testing Hooks Manually
|
||||
|
||||
```bash
|
||||
# Test context hook
|
||||
echo '{
|
||||
"session_id": "test123",
|
||||
"cwd": "/Users/alex/projects/my-app",
|
||||
"hook_event_name": "SessionStart",
|
||||
"source": "startup"
|
||||
}' | node plugin/scripts/context-hook.js
|
||||
|
||||
# Test save hook
|
||||
echo '{
|
||||
"session_id": "test123",
|
||||
"tool_name": "Edit",
|
||||
"tool_input": {"file_path": "test.ts"},
|
||||
"tool_output": {"success": true}
|
||||
}' | node plugin/scripts/save-hook.js
|
||||
|
||||
# Test with actual Claude Code
|
||||
claude --debug
|
||||
/hooks # View registered hooks
|
||||
# Submit prompt and watch debug output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Hook Execution Time
|
||||
|
||||
**Target:** < 100ms per hook
|
||||
|
||||
**Actual measurements:**
|
||||
|
||||
| Hook | Average | p95 | p99 |
|
||||
|------|---------|-----|-----|
|
||||
| SessionStart (smart-install, cached) | 10ms | 20ms | 40ms |
|
||||
| SessionStart (smart-install, first run) | 2500ms | 5000ms | 8000ms |
|
||||
| SessionStart (context) | 45ms | 120ms | 250ms |
|
||||
| SessionStart (user-message) | 5ms | 10ms | 15ms |
|
||||
| UserPromptSubmit | 12ms | 25ms | 50ms |
|
||||
| PostToolUse | 8ms | 15ms | 30ms |
|
||||
| SessionEnd | 5ms | 10ms | 20ms |
|
||||
|
||||
**Why smart-install is sometimes slow:**
|
||||
- First-time: Full npm install (2-5 seconds)
|
||||
- Cached: Version check only (~10ms)
|
||||
- Version change: Full npm install + worker restart
|
||||
|
||||
**Optimization (v5.0.3):**
|
||||
- Version caching with `.install-version` marker
|
||||
- Only install on version change or missing deps
|
||||
- Windows-specific error messages with build tool help
|
||||
|
||||
### Database Performance
|
||||
|
||||
**Schema optimizations:**
|
||||
- Indexes on `project`, `created_at_epoch`, `claude_session_id`
|
||||
- FTS5 virtual tables for full-text search
|
||||
- WAL mode for concurrent reads/writes
|
||||
|
||||
**Query patterns:**
|
||||
```sql
|
||||
-- Fast: Uses index on (project, created_at_epoch)
|
||||
SELECT * FROM session_summaries
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT 10
|
||||
|
||||
-- Fast: Uses index on claude_session_id
|
||||
SELECT * FROM sdk_sessions
|
||||
WHERE claude_session_id = ?
|
||||
LIMIT 1
|
||||
|
||||
-- Fast: FTS5 full-text search
|
||||
SELECT * FROM observations_fts
|
||||
WHERE observations_fts MATCH ?
|
||||
ORDER BY rank
|
||||
LIMIT 20
|
||||
```
|
||||
|
||||
### Worker Throughput
|
||||
|
||||
**Bottleneck:** Claude API latency (5-30s per observation)
|
||||
|
||||
**Mitigation:**
|
||||
- Process observations sequentially (simpler, more predictable)
|
||||
- Skip low-value observations (TodoWrite, ListMcpResourcesTool)
|
||||
- Batch summaries (generate every N observations, not every observation)
|
||||
|
||||
**Future optimization:**
|
||||
- Parallel processing (multiple workers)
|
||||
- Smart batching (combine related observations)
|
||||
- Lazy summarization (summarize only when needed)
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Hook Command Safety
|
||||
|
||||
**Risk:** Hooks execute arbitrary commands with user permissions
|
||||
|
||||
**Mitigations:**
|
||||
1. **Frozen at startup:** Hook configuration captured at start, changes require review
|
||||
2. **User review required:** `/hooks` menu shows changes, requires approval
|
||||
3. **Plugin isolation:** `${CLAUDE_PLUGIN_ROOT}` prevents path traversal
|
||||
4. **Input validation:** Hooks validate stdin schema before processing
|
||||
|
||||
### Data Privacy
|
||||
|
||||
**What gets stored:**
|
||||
- User prompts (raw text) - v4.2.0+
|
||||
- Tool inputs and outputs
|
||||
- File paths read/modified
|
||||
- Session summaries
|
||||
|
||||
**Privacy guarantees:**
|
||||
- All data stored locally in `~/.claude-mem/claude-mem.db`
|
||||
- No cloud uploads (API calls only for AI compression)
|
||||
- SQLite file permissions: user-only read/write
|
||||
- No analytics or telemetry
|
||||
|
||||
### API Key Protection
|
||||
|
||||
**Configuration:**
|
||||
- Anthropic API key in `~/.anthropic/api_key` or `ANTHROPIC_API_KEY` env var
|
||||
- Worker inherits environment from Claude Code
|
||||
- Never logged or stored in database
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
1. **Hooks are interfaces**: They define clean boundaries between systems
|
||||
2. **Non-blocking is critical**: Hooks must return fast, workers do the heavy lifting
|
||||
3. **Graceful degradation**: Memory system can fail without breaking Claude Code
|
||||
4. **Queue-based decoupling**: Capture and processing happen independently
|
||||
5. **Progressive disclosure**: Context injection uses index-first approach
|
||||
6. **Lifecycle alignment**: Each hook has a clear, single purpose
|
||||
|
||||
---
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [Claude Code Hooks Reference](https://docs.claude.com/claude-code/hooks) - Official documentation
|
||||
- [Progressive Disclosure](progressive-disclosure) - Context priming philosophy
|
||||
- [Architecture Evolution](architecture-evolution) - v3 to v4 journey
|
||||
- [Worker Service Design](architecture/worker-service) - Background processing details
|
||||
|
||||
---
|
||||
|
||||
*The hook-driven architecture enables Claude-Mem to be both powerful and invisible. Users never notice the memory system working - it just makes Claude smarter over time.*
|
||||
@@ -16,9 +16,8 @@ Install Claude-Mem directly from the plugin marketplace:
|
||||
|
||||
That's it! The plugin will automatically:
|
||||
- Download prebuilt binaries (no compilation needed)
|
||||
- Install all dependencies (including PM2 and SQLite binaries)
|
||||
- Install all dependencies (including SQLite binaries)
|
||||
- Configure hooks for session lifecycle management
|
||||
- Set up the MCP search server
|
||||
- Auto-start the worker service on first session
|
||||
|
||||
Start a new Claude Code session and you'll see context from previous sessions automatically loaded.
|
||||
@@ -27,7 +26,7 @@ Start a new Claude Code session and you'll see context from previous sessions au
|
||||
|
||||
- **Node.js**: 18.0.0 or higher
|
||||
- **Claude Code**: Latest version with plugin support
|
||||
- **PM2**: Process manager (bundled with plugin - no global install required)
|
||||
- **Bun**: JavaScript runtime and process manager (auto-installed if missing)
|
||||
- **SQLite 3**: For persistent storage (bundled)
|
||||
|
||||
## Advanced Installation
|
||||
@@ -70,12 +69,14 @@ cat plugin/hooks/hooks.json
|
||||
|
||||
#### 3. Data Directory Location
|
||||
|
||||
v4.0.0+ stores data in `${CLAUDE_PLUGIN_ROOT}/data/`:
|
||||
- Database: `${CLAUDE_PLUGIN_ROOT}/data/claude-mem.db`
|
||||
- Worker port file: `${CLAUDE_PLUGIN_ROOT}/data/worker.port`
|
||||
- Logs: `${CLAUDE_PLUGIN_ROOT}/data/logs/`
|
||||
Data is stored in `~/.claude-mem/`:
|
||||
- Database: `~/.claude-mem/claude-mem.db`
|
||||
- PID file: `~/.claude-mem/.worker.pid`
|
||||
- Port file: `~/.claude-mem/.worker.port`
|
||||
- Logs: `~/.claude-mem/logs/worker-YYYY-MM-DD.log`
|
||||
- Settings: `~/.claude-mem/settings.json`
|
||||
|
||||
For development/testing, you can override:
|
||||
Override with environment variable:
|
||||
```bash
|
||||
export CLAUDE_MEM_DATA_DIR=/custom/path
|
||||
```
|
||||
@@ -92,19 +93,17 @@ npm run worker:logs
|
||||
npm run test:context
|
||||
```
|
||||
|
||||
## Upgrading from v3.x
|
||||
## Upgrading
|
||||
|
||||
**BREAKING CHANGES - Please Read:**
|
||||
Upgrades are automatic when updating via the plugin marketplace. Key changes in recent versions:
|
||||
|
||||
v4.0.0 introduces breaking changes:
|
||||
**v7.1.0**: PM2 replaced with native Bun process management. Migration is automatic on first hook trigger.
|
||||
|
||||
- **Data Location Changed**: Database moved from `~/.claude-mem/` to `${CLAUDE_PLUGIN_ROOT}/data/` (inside plugin directory)
|
||||
- **Fresh Start Required**: No automatic migration from v3.x. You must start with a clean database
|
||||
- **Worker Auto-Starts**: Worker service now starts automatically - no manual `npm run worker:start` needed
|
||||
- **MCP Search Server**: 7 new search tools with full-text search and citations
|
||||
- **Enhanced Architecture**: Improved plugin integration and data organization
|
||||
**v7.0.0+**: 11 configuration settings, dual-tag privacy system.
|
||||
|
||||
See [CHANGELOG](https://github.com/thedotmack/claude-mem/blob/main/CHANGELOG.md) for complete details.
|
||||
**v5.4.0+**: Skill-based search replaces MCP tools, saving ~2,250 tokens per session.
|
||||
|
||||
See [CHANGELOG](https://github.com/thedotmack/claude-mem/blob/main/CHANGELOG.md) for complete version history.
|
||||
|
||||
## Next Steps
|
||||
|
||||
@@ -23,10 +23,13 @@ Restart Claude Code. Context from previous sessions will automatically appear in
|
||||
## Key Features
|
||||
|
||||
- 🧠 **Persistent Memory** - Context survives across sessions
|
||||
- 🔍 **7 Search Tools** - Query your project history via MCP
|
||||
- 🔍 **mem-search Skill** - Query your project history with natural language (~2,250 token savings)
|
||||
- 🌐 **Web Viewer UI** - Real-time memory stream visualization at http://localhost:37777
|
||||
- 🔒 **Privacy Control** - Use `<private>` tags to exclude sensitive content from storage
|
||||
- ⚙️ **Context Configuration** - Fine-grained control over what context gets injected
|
||||
- 🤖 **Automatic Operation** - No manual intervention required
|
||||
- 📊 **FTS5 Search** - Fast full-text search across observations
|
||||
- 🔗 **Citations** - Reference past decisions with `claude-mem://` URIs
|
||||
- 🔗 **Citations** - Reference past observations with IDs (access via http://localhost:37777/api/observation/{id} or view all in the web viewer at http://localhost:37777)
|
||||
|
||||
## How It Works
|
||||
|
||||
@@ -53,10 +56,12 @@ Restart Claude Code. Context from previous sessions will automatically appear in
|
||||
```
|
||||
|
||||
**Core Components:**
|
||||
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd
|
||||
2. **Worker Service** - HTTP API on port 37777 managed by PM2
|
||||
3. **SQLite Database** - Stores sessions, observations, summaries with FTS5 search
|
||||
4. **7 MCP Search Tools** - Query historical context with citations
|
||||
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts)
|
||||
2. **Smart Install** - Cached dependency checker (pre-hook script)
|
||||
3. **Worker Service** - HTTP API on port 37777 managed by Bun
|
||||
4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 search
|
||||
5. **mem-search Skill** - Query historical context with natural language
|
||||
6. **Web Viewer UI** - Real-time visualization with SSE and infinite scroll
|
||||
|
||||
See [Architecture Overview](architecture/overview) for details.
|
||||
|
||||
@@ -64,19 +69,25 @@ See [Architecture Overview](architecture/overview) for details.
|
||||
|
||||
- **Node.js**: 18.0.0 or higher
|
||||
- **Claude Code**: Latest version with plugin support
|
||||
- **PM2**: Process manager (bundled - no global install required)
|
||||
- **Bun**: JavaScript runtime and process manager (auto-installed if missing)
|
||||
- **SQLite 3**: For persistent storage (bundled)
|
||||
|
||||
## What's New in v4.2.3
|
||||
## What's New
|
||||
|
||||
**Security:**
|
||||
- Fixed FTS5 injection vulnerability in search functions
|
||||
- Added comprehensive test suite with 332 injection attack tests
|
||||
**v7.1.0 - Bun Migration:**
|
||||
- Replaced PM2 with native Bun process management
|
||||
- Switched from better-sqlite3 to bun:sqlite for faster database access
|
||||
- Automatic one-time migration on first hook trigger
|
||||
- Simplified cross-platform support
|
||||
|
||||
**Fixes:**
|
||||
- Fixed ESM/CJS compatibility for getDirname function
|
||||
- Fixed Windows PowerShell compatibility in SessionStart hook
|
||||
- Cross-platform dependency installation now works on Windows, macOS, and Linux
|
||||
**v7.0.0 - Context Configuration:**
|
||||
- 11 settings for fine-grained control over context injection
|
||||
- Dual-tag privacy system (`<private>` tags)
|
||||
|
||||
**Previous Highlights:**
|
||||
- **v5.5.0**: mem-search skill with 100% effectiveness rate
|
||||
- **v5.4.0**: Skill-based search (~2,250 tokens saved per session)
|
||||
- **v5.1.0**: Web viewer UI at http://localhost:37777
|
||||
|
||||
## Next Steps
|
||||
|
||||
@@ -0,0 +1,655 @@
|
||||
# Progressive Disclosure: Claude-Mem's Context Priming Philosophy
|
||||
|
||||
## Core Principle
|
||||
**Show what exists and its retrieval cost first. Let the agent decide what to fetch based on relevance and need.**
|
||||
|
||||
---
|
||||
|
||||
## What is Progressive Disclosure?
|
||||
|
||||
Progressive disclosure is an information architecture pattern where you reveal complexity gradually rather than all at once. In the context of AI agents, it means:
|
||||
|
||||
1. **Layer 1 (Index)**: Show lightweight metadata (titles, dates, types, token counts)
|
||||
2. **Layer 2 (Details)**: Fetch full content only when needed
|
||||
3. **Layer 3 (Deep Dive)**: Read original source files if required
|
||||
|
||||
This mirrors how humans work: We scan headlines before reading articles, review table of contents before diving into chapters, and check file names before opening files.
|
||||
|
||||
---
|
||||
|
||||
## The Problem: Context Pollution
|
||||
|
||||
Traditional RAG (Retrieval-Augmented Generation) systems fetch everything upfront:
|
||||
|
||||
```
|
||||
❌ Traditional Approach:
|
||||
┌─────────────────────────────────────┐
|
||||
│ Session Start │
|
||||
│ │
|
||||
│ [15,000 tokens of past sessions] │
|
||||
│ [8,000 tokens of observations] │
|
||||
│ [12,000 tokens of file summaries] │
|
||||
│ │
|
||||
│ Total: 35,000 tokens │
|
||||
│ Relevant: ~2,000 tokens (6%) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Problems:**
|
||||
- Wastes 94% of attention budget on irrelevant context
|
||||
- User prompt gets buried under mountain of history
|
||||
- Agent must process everything before understanding task
|
||||
- No way to know what's actually useful until after reading
|
||||
|
||||
---
|
||||
|
||||
## Claude-Mem's Solution: Progressive Disclosure
|
||||
|
||||
```
|
||||
✅ Progressive Disclosure Approach:
|
||||
┌─────────────────────────────────────┐
|
||||
│ Session Start │
|
||||
│ │
|
||||
│ Index of 50 observations: ~800 tokens│
|
||||
│ ↓ │
|
||||
│ Agent sees: "🔴 Hook timeout issue" │
|
||||
│ Agent decides: "Relevant!" │
|
||||
│ ↓ │
|
||||
│ Fetch observation #2543: ~120 tokens│
|
||||
│ │
|
||||
│ Total: 920 tokens │
|
||||
│ Relevant: 920 tokens (100%) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Agent controls its own context consumption
|
||||
- Directly relevant to current task
|
||||
- Can fetch more if needed
|
||||
- Can skip everything if not relevant
|
||||
- Clear cost/benefit for each retrieval decision
|
||||
|
||||
---
|
||||
|
||||
## How It Works in Claude-Mem
|
||||
|
||||
### The Index Format
|
||||
|
||||
Every SessionStart hook provides a compact index:
|
||||
|
||||
```markdown
|
||||
### Oct 26, 2025
|
||||
|
||||
**General**
|
||||
| ID | Time | T | Title | Tokens |
|
||||
|----|------|---|-------|--------|
|
||||
| #2586 | 12:58 AM | 🔵 | Context hook file exists but is empty | ~51 |
|
||||
| #2587 | ″ | 🔵 | Context hook script file is empty | ~46 |
|
||||
| #2589 | ″ | 🟡 | Investigated hook debug output docs | ~105 |
|
||||
|
||||
**src/hooks/context-hook.ts**
|
||||
| ID | Time | T | Title | Tokens |
|
||||
|----|------|---|-------|--------|
|
||||
| #2591 | 1:15 AM | ⚖️ | Stderr messaging abandoned | ~155 |
|
||||
| #2592 | 1:16 AM | ⚖️ | Web UI strategy redesigned | ~193 |
|
||||
```
|
||||
|
||||
**What the agent sees:**
|
||||
- **What exists**: Observation titles give semantic meaning
|
||||
- **When it happened**: Timestamps for temporal context
|
||||
- **What type**: Icons indicate observation category
|
||||
- **Retrieval cost**: Token counts for informed decisions
|
||||
- **Where to get it**: MCP search tools referenced at bottom
|
||||
|
||||
### The Legend System
|
||||
|
||||
```
|
||||
🎯 session-request - User's original goal
|
||||
🔴 gotcha - Critical edge case or pitfall
|
||||
🟡 problem-solution - Bug fix or workaround
|
||||
🔵 how-it-works - Technical explanation
|
||||
🟢 what-changed - Code/architecture change
|
||||
🟣 discovery - Learning or insight
|
||||
🟠 why-it-exists - Design rationale
|
||||
🟤 decision - Architecture decision
|
||||
⚖️ trade-off - Deliberate compromise
|
||||
```
|
||||
|
||||
**Purpose:**
|
||||
- Visual scanning (humans and AI both benefit)
|
||||
- Semantic categorization
|
||||
- Priority signaling (🔴 gotchas are more critical)
|
||||
- Pattern recognition across sessions
|
||||
|
||||
### Progressive Disclosure Instructions
|
||||
|
||||
The index includes usage guidance:
|
||||
|
||||
```markdown
|
||||
💡 **Progressive Disclosure:** This index shows WHAT exists and retrieval COST.
|
||||
- Use MCP search tools to fetch full observation details on-demand
|
||||
- Prefer searching observations over re-reading code for past decisions
|
||||
- Critical types (🔴 gotcha, 🟤 decision, ⚖️ trade-off) often worth fetching immediately
|
||||
```
|
||||
|
||||
**What this does:**
|
||||
- Teaches the agent the pattern
|
||||
- Suggests when to fetch (critical types)
|
||||
- Recommends search over code re-reading (efficiency)
|
||||
- Makes the system self-documenting
|
||||
|
||||
---
|
||||
|
||||
## The Philosophy: Context as Currency
|
||||
|
||||
### Mental Model: Token Budget as Money
|
||||
|
||||
Think of context window as a bank account:
|
||||
|
||||
| Approach | Metaphor | Outcome |
|
||||
|----------|----------|---------|
|
||||
| **Dump everything** | Spending your entire paycheck on groceries you might need someday | Waste, clutter, can't afford what you actually need |
|
||||
| **Fetch nothing** | Refusing to spend any money | Starvation, can't accomplish tasks |
|
||||
| **Progressive disclosure** | Check your pantry, make a shopping list, buy only what you need | Efficiency, room for unexpected needs |
|
||||
|
||||
### The Attention Budget
|
||||
|
||||
LLMs have finite attention:
|
||||
- Every token attends to every other token (n² relationships)
|
||||
- 100,000 token window ≠ 100,000 tokens of useful attention
|
||||
- Context "rot" happens as window fills
|
||||
- Later tokens get less attention than earlier ones
|
||||
|
||||
**Claude-Mem's approach:**
|
||||
- Start with ~1,000 tokens of index
|
||||
- Agent has 99,000 tokens free for task
|
||||
- Agent fetches ~200 tokens when needed
|
||||
- Final budget: ~98,000 tokens for actual work
|
||||
|
||||
### Design for Autonomy
|
||||
|
||||
> "As models improve, let them act intelligently"
|
||||
|
||||
Progressive disclosure treats the agent as an **intelligent information forager**, not a passive recipient of pre-selected context.
|
||||
|
||||
**Traditional RAG:**
|
||||
```
|
||||
System → [Decides relevance] → Agent
|
||||
↑
|
||||
Hope this helps!
|
||||
```
|
||||
|
||||
**Progressive Disclosure:**
|
||||
```
|
||||
System → [Shows index] → Agent → [Decides relevance] → [Fetches details]
|
||||
↑
|
||||
You know best!
|
||||
```
|
||||
|
||||
The agent knows:
|
||||
- The current task context
|
||||
- What information would help
|
||||
- How much budget to spend
|
||||
- When to stop searching
|
||||
|
||||
We don't.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
### 1. Make Costs Visible
|
||||
|
||||
Every item in the index shows token count:
|
||||
|
||||
```
|
||||
| #2591 | 1:15 AM | ⚖️ | Stderr messaging abandoned | ~155 |
|
||||
^^^^
|
||||
Retrieval cost
|
||||
```
|
||||
|
||||
**Why:**
|
||||
- Agent can make informed ROI decisions
|
||||
- Small observations (~50 tokens) are "cheap" to fetch
|
||||
- Large observations (~500 tokens) require stronger justification
|
||||
- Matches how humans think about effort
|
||||
|
||||
### 2. Use Semantic Compression
|
||||
|
||||
Titles compress full observations into ~10 words:
|
||||
|
||||
**Bad title:**
|
||||
```
|
||||
Observation about a thing
|
||||
```
|
||||
|
||||
**Good title:**
|
||||
```
|
||||
🔴 Hook timeout issue: 60s default too short for npm install
|
||||
```
|
||||
|
||||
**What makes a good title:**
|
||||
- Specific: Identifies exact issue
|
||||
- Actionable: Clear what to do
|
||||
- Self-contained: Doesn't require reading observation
|
||||
- Searchable: Contains key terms (hook, timeout, npm)
|
||||
- Categorized: Icon indicates type
|
||||
|
||||
### 3. Group by Context
|
||||
|
||||
Observations are grouped by:
|
||||
- **Date**: Temporal context
|
||||
- **File path**: Spatial context (work on specific files)
|
||||
- **Project**: Logical context
|
||||
|
||||
```markdown
|
||||
**src/hooks/context-hook.ts**
|
||||
| ID | Time | T | Title | Tokens |
|
||||
|----|------|---|-------|--------|
|
||||
| #2591 | 1:15 AM | ⚖️ | Stderr messaging abandoned | ~155 |
|
||||
| #2594 | 1:17 AM | 🟠 | Removed stderr section from docs | ~93 |
|
||||
```
|
||||
|
||||
**Benefit:** If agent is working on `src/hooks/context-hook.ts`, related observations are already grouped together.
|
||||
|
||||
### 4. Provide Retrieval Tools
|
||||
|
||||
The index is useless without retrieval mechanisms:
|
||||
|
||||
```markdown
|
||||
*Use claude-mem MCP search to access records with the given ID*
|
||||
```
|
||||
|
||||
**Available tools:**
|
||||
- `search_observations` - Full-text search
|
||||
- `find_by_concept` - Concept-based retrieval
|
||||
- `find_by_file` - File-based retrieval
|
||||
- `find_by_type` - Type-based retrieval
|
||||
- `get_recent_context` - Recent session summaries
|
||||
|
||||
Each tool supports `format: "index"` (default) and `format: "full"`.
|
||||
|
||||
---
|
||||
|
||||
## Real-World Example
|
||||
|
||||
### Scenario: Agent asked to fix a bug in hooks
|
||||
|
||||
**Without progressive disclosure:**
|
||||
```
|
||||
SessionStart injects 25,000 tokens of past context
|
||||
Agent reads everything
|
||||
Agent finds 1 relevant observation (buried in middle)
|
||||
Total tokens consumed: 25,000
|
||||
Relevant tokens: ~200
|
||||
Efficiency: 0.8%
|
||||
```
|
||||
|
||||
**With progressive disclosure:**
|
||||
```
|
||||
SessionStart shows index: ~800 tokens
|
||||
Agent sees title: "🔴 Hook timeout issue: 60s too short"
|
||||
Agent thinks: "This looks relevant to my bug!"
|
||||
Agent fetches observation #2543: ~155 tokens
|
||||
Total tokens consumed: 955
|
||||
Relevant tokens: 955
|
||||
Efficiency: 100%
|
||||
```
|
||||
|
||||
### The Index Entry
|
||||
|
||||
```markdown
|
||||
| #2543 | 2:14 PM | 🔴 | Hook timeout: 60s too short for npm install | ~155 |
|
||||
```
|
||||
|
||||
**What the agent learns WITHOUT fetching:**
|
||||
- There's a known gotcha (🔴) about hook timeouts
|
||||
- It's related to npm install taking too long
|
||||
- Full details are ~155 tokens (cheap)
|
||||
- Happened at 2:14 PM (recent)
|
||||
|
||||
**Decision tree:**
|
||||
```
|
||||
Is my task related to hooks? → YES
|
||||
Is my task related to timeouts? → YES
|
||||
Is my task related to npm? → YES
|
||||
155 tokens is cheap → FETCH IT
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## The Two-Tier Search Strategy
|
||||
|
||||
Claude-Mem implements progressive disclosure in search results too:
|
||||
|
||||
### Tier 1: Index Format (Default)
|
||||
|
||||
```typescript
|
||||
search_observations({
|
||||
query: "hook timeout",
|
||||
format: "index" // Default
|
||||
})
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
```
|
||||
Found 3 observations matching "hook timeout":
|
||||
|
||||
| ID | Date | Type | Title | Tokens |
|
||||
|----|------|------|-------|--------|
|
||||
| #2543 | Oct 26 | gotcha | Hook timeout: 60s too short | ~155 |
|
||||
| #2891 | Oct 25 | how-it-works | Hook timeout configuration | ~203 |
|
||||
| #2102 | Oct 20 | problem-solution | Fixed timeout in CI | ~89 |
|
||||
```
|
||||
|
||||
**Cost:** ~100 tokens for 3 results
|
||||
**Value:** Agent can scan and decide which to fetch
|
||||
|
||||
### Tier 2: Full Format (On-Demand)
|
||||
|
||||
```typescript
|
||||
search_observations({
|
||||
query: "hook timeout",
|
||||
format: "full",
|
||||
limit: 1 // Fetch just the most relevant
|
||||
})
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
```
|
||||
#2543 🔴 Hook timeout: 60s too short for npm install
|
||||
─────────────────────────────────────────────────
|
||||
Date: Oct 26, 2025 2:14 PM
|
||||
Type: gotcha
|
||||
Project: claude-mem
|
||||
|
||||
Narrative:
|
||||
Discovered that the default 60-second hook timeout is insufficient
|
||||
for npm install operations, especially with large dependency trees
|
||||
or slow network conditions. This causes SessionStart hook to fail
|
||||
silently, preventing context injection.
|
||||
|
||||
Facts:
|
||||
- Default timeout: 60 seconds
|
||||
- npm install with cold cache: ~90 seconds
|
||||
- Configured timeout: 120 seconds in plugin/hooks/hooks.json:25
|
||||
|
||||
Files Modified:
|
||||
- plugin/hooks/hooks.json
|
||||
|
||||
Concepts: hooks, timeout, npm, configuration
|
||||
```
|
||||
|
||||
**Cost:** ~155 tokens for full details
|
||||
**Value:** Complete understanding of the issue
|
||||
|
||||
---
|
||||
|
||||
## Cognitive Load Theory
|
||||
|
||||
Progressive disclosure is grounded in **Cognitive Load Theory**:
|
||||
|
||||
### Intrinsic Load
|
||||
The inherent difficulty of the task itself.
|
||||
|
||||
**Example:** "Fix authentication bug"
|
||||
- Must understand auth system
|
||||
- Must understand the bug
|
||||
- Must write the fix
|
||||
|
||||
This load is unavoidable.
|
||||
|
||||
### Extraneous Load
|
||||
The cognitive burden of poorly presented information.
|
||||
|
||||
**Traditional RAG adds extraneous load:**
|
||||
- Scanning irrelevant observations
|
||||
- Filtering out noise
|
||||
- Remembering what to ignore
|
||||
- Re-contextualizing after each section
|
||||
|
||||
**Progressive disclosure minimizes extraneous load:**
|
||||
- Scan titles (low effort)
|
||||
- Fetch only relevant (targeted effort)
|
||||
- Full attention on current task
|
||||
|
||||
### Germane Load
|
||||
The effort of building mental models and schemas.
|
||||
|
||||
**Progressive disclosure supports germane load:**
|
||||
- Consistent structure (legend, grouping)
|
||||
- Clear categorization (types, icons)
|
||||
- Semantic compression (good titles)
|
||||
- Explicit costs (token counts)
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
### ❌ Verbose Titles
|
||||
|
||||
**Bad:**
|
||||
```
|
||||
| #2543 | 2:14 PM | 🔴 | Investigation into the issue where hooks time out | ~155 |
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```
|
||||
| #2543 | 2:14 PM | 🔴 | Hook timeout: 60s too short for npm install | ~155 |
|
||||
```
|
||||
|
||||
### ❌ Hiding Costs
|
||||
|
||||
**Bad:**
|
||||
```
|
||||
| #2543 | 2:14 PM | 🔴 | Hook timeout issue |
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```
|
||||
| #2543 | 2:14 PM | 🔴 | Hook timeout issue | ~155 |
|
||||
```
|
||||
|
||||
### ❌ No Retrieval Path
|
||||
|
||||
**Bad:**
|
||||
```
|
||||
Here are 10 observations. [No instructions on how to get full details]
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```
|
||||
Here are 10 observations.
|
||||
*Use MCP search tools to fetch full observation details on-demand*
|
||||
```
|
||||
|
||||
### ❌ Defaulting to Full Format
|
||||
|
||||
**Bad:**
|
||||
```typescript
|
||||
search_observations({
|
||||
query: "hooks",
|
||||
format: "full" // Fetches everything
|
||||
})
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```typescript
|
||||
search_observations({
|
||||
query: "hooks",
|
||||
format: "index", // Scan first
|
||||
limit: 20
|
||||
})
|
||||
|
||||
// Then, if needed:
|
||||
search_observations({
|
||||
query: "hooks",
|
||||
format: "full",
|
||||
limit: 1 // Just the most relevant
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### Why Token Counts?
|
||||
|
||||
**Decision:** Show approximate token counts (~155, ~203) rather than exact counts.
|
||||
|
||||
**Rationale:**
|
||||
- Communicates scale (50 vs 500) without false precision
|
||||
- Maps to human intuition (small/medium/large)
|
||||
- Allows agent to budget attention
|
||||
- Encourages cost-conscious retrieval
|
||||
|
||||
### Why Icons Instead of Text Labels?
|
||||
|
||||
**Decision:** Use emoji icons (🔴, 🟡, 🔵) rather than text (GOTCHA, PROBLEM, HOWTO).
|
||||
|
||||
**Rationale:**
|
||||
- Visual scanning (pattern recognition)
|
||||
- Token efficient (1 char vs 10 chars)
|
||||
- Language-agnostic
|
||||
- Aesthetically distinct
|
||||
- Works for both humans and AI
|
||||
|
||||
### Why Index-First, Not Smart Pre-Fetch?
|
||||
|
||||
**Decision:** Always show index first, even if we "know" what's relevant.
|
||||
|
||||
**Rationale:**
|
||||
- We can't know what's relevant better than the agent
|
||||
- Pre-fetching assumes we understand the task
|
||||
- Agent knows current context, we don't
|
||||
- Respects agent autonomy
|
||||
- Fails gracefully (can always fetch more)
|
||||
|
||||
### Why Group by File Path?
|
||||
|
||||
**Decision:** Group observations by file path in addition to date.
|
||||
|
||||
**Rationale:**
|
||||
- Spatial locality: Work on file X likely needs context about file X
|
||||
- Reduces scanning effort
|
||||
- Matches how developers think
|
||||
- Clear semantic boundaries
|
||||
|
||||
---
|
||||
|
||||
## Measuring Success
|
||||
|
||||
Progressive disclosure is working when:
|
||||
|
||||
### ✅ Low Waste Ratio
|
||||
```
|
||||
Relevant Tokens / Total Context Tokens > 80%
|
||||
```
|
||||
|
||||
Most of the context consumed is actually useful.
|
||||
|
||||
### ✅ Selective Fetching
|
||||
```
|
||||
Index Shown: 50 observations
|
||||
Details Fetched: 2-3 observations
|
||||
```
|
||||
|
||||
Agent is being selective, not fetching everything.
|
||||
|
||||
### ✅ Fast Task Completion
|
||||
```
|
||||
Session with index: 30 seconds to find relevant context
|
||||
Session without: 90 seconds scanning all context
|
||||
```
|
||||
|
||||
Time-to-relevant-information is faster.
|
||||
|
||||
### ✅ Appropriate Depth
|
||||
```
|
||||
Simple task: Only index needed
|
||||
Medium task: 1-2 observations fetched
|
||||
Complex task: 5-10 observations + code reads
|
||||
```
|
||||
|
||||
Depth scales with task complexity.
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Adaptive Index Size
|
||||
|
||||
```typescript
|
||||
// Vary index size based on session type
|
||||
SessionStart({ source: "startup" }):
|
||||
→ Show last 10 sessions (small index)
|
||||
|
||||
SessionStart({ source: "resume" }):
|
||||
→ Show only current session (micro index)
|
||||
|
||||
SessionStart({ source: "compact" }):
|
||||
→ Show last 20 sessions (larger index)
|
||||
```
|
||||
|
||||
### Relevance Scoring
|
||||
|
||||
```typescript
|
||||
// Use embeddings to pre-sort index by relevance
|
||||
search_observations({
|
||||
query: "authentication bug",
|
||||
format: "index",
|
||||
sort: "relevance" // Based on semantic similarity
|
||||
})
|
||||
```
|
||||
|
||||
### Cost Forecasting
|
||||
|
||||
```markdown
|
||||
💡 **Budget Estimate:**
|
||||
- Fetching all 🔴 gotchas: ~450 tokens
|
||||
- Fetching all file-related: ~1,200 tokens
|
||||
- Fetching everything: ~8,500 tokens
|
||||
```
|
||||
|
||||
### Progressive Detail Levels
|
||||
|
||||
```
|
||||
Layer 1: Index (titles only)
|
||||
Layer 2: Summaries (2-3 sentences)
|
||||
Layer 3: Full details (complete observation)
|
||||
Layer 4: Source files (referenced code)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
1. **Show, don't tell**: Index reveals what exists without forcing consumption
|
||||
2. **Cost-conscious**: Make retrieval costs visible for informed decisions
|
||||
3. **Agent autonomy**: Let the agent decide what's relevant
|
||||
4. **Semantic compression**: Good titles make or break the system
|
||||
5. **Consistent structure**: Patterns reduce cognitive load
|
||||
6. **Two-tier everything**: Index first, details on-demand
|
||||
7. **Context as currency**: Spend wisely on high-value information
|
||||
|
||||
---
|
||||
|
||||
## Remember
|
||||
|
||||
> "The best interface is one that disappears when not needed, and appears exactly when it is."
|
||||
|
||||
Progressive disclosure respects the agent's intelligence and autonomy. We provide the map; the agent chooses the path.
|
||||
|
||||
---
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [Context Engineering for AI Agents](context-engineering) - Foundational principles
|
||||
- [Claude-Mem Architecture](architecture/overview) - How it all fits together
|
||||
- Cognitive Load Theory (Sweller, 1988)
|
||||
- Information Foraging Theory (Pirolli & Card, 1999)
|
||||
- Progressive Disclosure (Nielsen Norman Group)
|
||||
|
||||
---
|
||||
|
||||
*This philosophy emerged from real-world usage of Claude-Mem across hundreds of coding sessions. The pattern works because it aligns with both human cognition and LLM attention mechanics.*
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 250 53" width="250" height="55" data-date-format="longDate">
|
||||
<rect xmlns="http://www.w3.org/2000/svg" stroke="#b5a0d9" stroke-width="1" fill="#1a1a1a" x="0.5" y="0.5" width="249" height="53" rx="10"/>
|
||||
<foreignObject width="198" height="17" style="font-size: 9px;color: rgb(200, 180, 230);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="6" y="10" selection="true">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">GITHUB TRENDING</div>
|
||||
</foreignObject>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Слой_1" viewBox="0 0 80 80" width="48" height="45" x="10" y="8">
|
||||
<path fill="#b5a0d9" d="M70.71,40.31C75.74,44.3,80,37.86,80,37.86s-5.64-2.17-8.55,0.61c0.59-1.62,1.02-3.31,1.28-5.01 c4.08,2.16,6.44-2.95,6.44-2.95s-4.41-0.97-6.26,1.4c0.08-0.91,0.12-1.82,0.1-2.73c-0.01-0.36-0.02-0.73-0.05-1.09 c2.96-3.68-1.73-6.99-1.73-6.99s-2.14,5.09,0.98,7.09c0.02,0.33,0.03,0.66,0.03,1c0.01,0.76-0.03,1.52-0.1,2.27 c-0.85-2.69-4.91-3.69-4.91-3.69s-0.13,5.78,4.68,5.48c-0.28,1.69-0.73,3.35-1.34,4.95c-0.19-4.03-5.79-6.33-5.79-6.33 s-1.33,7.55,5.01,8.16c-0.38,0.8-0.8,1.57-1.25,2.32c-0.56,0.95-1.21,1.84-1.89,2.71c0.97-3.99-3.96-7.72-3.96-7.72 s-3.18,6.94,2.73,9.15c-0.38,0.43-0.8,0.81-1.2,1.21c-0.21,0.2-0.43,0.38-0.64,0.58l-0.32,0.29c-0.11,0.09-0.22,0.18-0.33,0.27 l-0.67,0.54l-0.7,0.51c-0.08,0.05-0.16,0.11-0.23,0.16c1.62-3.42-2.07-7.77-2.07-7.77s-4.21,5.55,0.49,8.78 c-1.34,0.79-2.74,1.45-4.2,1.98c1.91-2.59-0.23-6.89-0.23-6.89s-4.66,3.77-1.52,7.46c-1.15,0.33-2.33,0.57-3.51,0.74 c1.46-1.68,0.55-4.83,0.55-4.83s-3.7,2.03-2.18,5c-0.52,0.03-1.05,0.07-1.57,0.06c-0.29,0-0.57,0.01-0.86,0l-0.86-0.04 c-0.85-0.06-1.7-0.15-2.54-0.28l0.68-0.27l0.42-0.17l0.41-0.19l0.82-0.38c0,0,0.01,0,0.01,0c0.39-0.18,0.55-0.65,0.37-1.03 c-0.18-0.39-0.65-0.55-1.03-0.37l-0.04,0.02l-0.77,0.37l-0.39,0.18l-0.39,0.16l-0.79,0.33l-0.8,0.29l-0.4,0.14l-0.41,0.12L40,53.6 l-0.51-0.15l-0.41-0.12l-0.4-0.14l-0.8-0.29l-0.79-0.33l-0.39-0.16l-0.39-0.18l-0.77-0.37l-0.04-0.02c0,0,0,0-0.01,0 c-0.39-0.18-0.85-0.01-1.03,0.38c-0.18,0.39-0.01,0.85,0.38,1.03l0.82,0.38l0.41,0.19l0.42,0.17l0.68,0.27 c-0.84,0.14-1.69,0.22-2.54,0.28l-0.86,0.04c-0.29,0.01-0.57,0-0.86,0c-0.53,0.01-1.05-0.03-1.57-0.06c1.51-2.98-2.18-5-2.18-5 s-0.92,3.15,0.55,4.83c-1.19-0.16-2.36-0.41-3.51-0.74c3.15-3.7-1.52-7.46-1.52-7.46s-2.14,4.31-0.23,6.89 c-1.46-0.53-2.86-1.19-4.2-1.98c4.7-3.22,0.49-8.78,0.49-8.78s-3.69,4.34-2.07,7.77c-0.08-0.05-0.16-0.1-0.23-0.16l-0.7-0.51 l-0.67-0.54c-0.11-0.09-0.23-0.18-0.33-0.27l-0.32-0.29c-0.21-0.19-0.43-0.38-0.64-0.58c-0.4-0.4-0.82-0.79-1.2-1.21 c5.91-2.21,2.73-9.15,2.73-9.15s-4.93,3.73-3.96,7.72c-0.68-0.86-1.33-1.76-1.89-2.71c-0.46-0.75-0.87-1.53-1.25-2.32 c6.33-0.61,5.01-8.16,5.01-8.16s-5.6,2.31-5.79,6.33c-0.61-1.6-1.06-3.26-1.34-4.95c4.81,0.3,4.68-5.48,4.68-5.48 s-4.05,0.99-4.91,3.69c-0.07-0.76-0.1-1.51-0.1-2.27c0-0.33,0.01-0.66,0.03-1c3.11-2.01,0.98-7.09,0.98-7.09s-4.69,3.31-1.73,6.99 C7,28.46,6.99,28.82,6.98,29.18c-0.02,0.91,0.01,1.82,0.1,2.73c-1.84-2.38-6.26-1.4-6.26-1.4s2.37,5.11,6.44,2.95 c0.26,1.71,0.69,3.39,1.28,5.01C5.64,35.69,0,37.86,0,37.86s4.26,6.43,9.29,2.45c0.39,0.87,0.83,1.72,1.31,2.54 c0.47,0.83,1.01,1.63,1.58,2.4C8.71,43.7,4.11,47,4.11,47s5.7,5.1,9.56,0.08c0.04,0.04,0.07,0.08,0.11,0.12 c0.39,0.45,0.82,0.87,1.24,1.3c0.21,0.21,0.44,0.41,0.66,0.61l0.33,0.3c0.11,0.1,0.23,0.19,0.34,0.29l0.69,0.57l0.23,0.17 c-3.34-0.34-6.58,3.29-6.58,3.29s6.19,3.47,8.69-1.83c1.2,0.75,2.47,1.41,3.78,1.96c-2.76,0.6-4.62,4.13-4.62,4.13 s5.89,1.62,6.98-3.26c1.03,0.32,2.07,0.58,3.13,0.78c-1.63,0.99-2.39,3.38-2.39,3.38s4.31,0.39,4.61-3.07 c0.07,0.01,0.14,0.02,0.21,0.02c0.6,0.04,1.2,0.1,1.8,0.09c0.3,0,0.6,0.02,0.9,0.01l0.9-0.03c1.2-0.07,2.41-0.18,3.59-0.42 l0.45-0.08c0.15-0.03,0.29-0.07,0.44-0.1L40,55.13l0.81,0.19c0.15,0.03,0.29,0.07,0.44,0.1l0.45,0.08c1.18,0.23,2.39,0.35,3.59,0.42 l0.9,0.03c0.3,0.01,0.6-0.01,0.9-0.01c0.6,0,1.2-0.06,1.8-0.09c0.07-0.01,0.14-0.02,0.21-0.02c0.31,3.45,4.61,3.07,4.61,3.07 s-0.76-2.39-2.39-3.38c1.06-0.2,2.11-0.46,3.13-0.78c1.09,4.88,6.98,3.26,6.98,3.26s-1.86-3.52-4.62-4.13 c1.31-0.55,2.57-1.21,3.78-1.96c2.5,5.3,8.69,1.83,8.69,1.83s-3.24-3.63-6.58-3.29l0.23-0.17l0.69-0.57 c0.11-0.1,0.23-0.19,0.34-0.29l0.33-0.3c0.22-0.2,0.45-0.4,0.66-0.61c0.42-0.43,0.85-0.84,1.24-1.3c0.03-0.04,0.07-0.08,0.11-0.12 C70.19,52.1,75.89,47,75.89,47s-4.6-3.31-8.08-1.75c0.57-0.77,1.11-1.56,1.58-2.4C69.88,42.03,70.31,41.18,70.71,40.31z"/>
|
||||
</svg>
|
||||
<foreignObject width="230" height="35" style="font-size: 14px;color: rgb(200, 180, 230);font-family: Arial;font-weight: 700;text-align: left;letter-spacing: 0em;line-height: 1.5;" x="64" y="24">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">#1 Repository Of The Day</div>
|
||||
</foreignObject>
|
||||
<foreignObject width="141" height="36" style="font-size: 18px;color: rgb(180, 160, 217);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="-36" y="9">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">1</div>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 250 53" width="250" height="55" data-date-format="longDate">
|
||||
<rect xmlns="http://www.w3.org/2000/svg" stroke="#4a0e99" stroke-width="1" fill="#FFFFFF" x="0.5" y="0.5" width="249" height="53" rx="10"/>
|
||||
<foreignObject width="198" height="17" style="font-size: 9px;color: rgb(67, 39, 135);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="6" y="10" selection="true">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">GITHUB TRENDING</div>
|
||||
</foreignObject>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Слой_1" viewBox="0 0 80 80" width="48" height="45" x="10" y="8">
|
||||
<path fill="#49278e" d="M70.71,40.31C75.74,44.3,80,37.86,80,37.86s-5.64-2.17-8.55,0.61c0.59-1.62,1.02-3.31,1.28-5.01 c4.08,2.16,6.44-2.95,6.44-2.95s-4.41-0.97-6.26,1.4c0.08-0.91,0.12-1.82,0.1-2.73c-0.01-0.36-0.02-0.73-0.05-1.09 c2.96-3.68-1.73-6.99-1.73-6.99s-2.14,5.09,0.98,7.09c0.02,0.33,0.03,0.66,0.03,1c0.01,0.76-0.03,1.52-0.1,2.27 c-0.85-2.69-4.91-3.69-4.91-3.69s-0.13,5.78,4.68,5.48c-0.28,1.69-0.73,3.35-1.34,4.95c-0.19-4.03-5.79-6.33-5.79-6.33 s-1.33,7.55,5.01,8.16c-0.38,0.8-0.8,1.57-1.25,2.32c-0.56,0.95-1.21,1.84-1.89,2.71c0.97-3.99-3.96-7.72-3.96-7.72 s-3.18,6.94,2.73,9.15c-0.38,0.43-0.8,0.81-1.2,1.21c-0.21,0.2-0.43,0.38-0.64,0.58l-0.32,0.29c-0.11,0.09-0.22,0.18-0.33,0.27 l-0.67,0.54l-0.7,0.51c-0.08,0.05-0.16,0.11-0.23,0.16c1.62-3.42-2.07-7.77-2.07-7.77s-4.21,5.55,0.49,8.78 c-1.34,0.79-2.74,1.45-4.2,1.98c1.91-2.59-0.23-6.89-0.23-6.89s-4.66,3.77-1.52,7.46c-1.15,0.33-2.33,0.57-3.51,0.74 c1.46-1.68,0.55-4.83,0.55-4.83s-3.7,2.03-2.18,5c-0.52,0.03-1.05,0.07-1.57,0.06c-0.29,0-0.57,0.01-0.86,0l-0.86-0.04 c-0.85-0.06-1.7-0.15-2.54-0.28l0.68-0.27l0.42-0.17l0.41-0.19l0.82-0.38c0,0,0.01,0,0.01,0c0.39-0.18,0.55-0.65,0.37-1.03 c-0.18-0.39-0.65-0.55-1.03-0.37l-0.04,0.02l-0.77,0.37l-0.39,0.18l-0.39,0.16l-0.79,0.33l-0.8,0.29l-0.4,0.14l-0.41,0.12L40,53.6 l-0.51-0.15l-0.41-0.12l-0.4-0.14l-0.8-0.29l-0.79-0.33l-0.39-0.16l-0.39-0.18l-0.77-0.37l-0.04-0.02c0,0,0,0-0.01,0 c-0.39-0.18-0.85-0.01-1.03,0.38c-0.18,0.39-0.01,0.85,0.38,1.03l0.82,0.38l0.41,0.19l0.42,0.17l0.68,0.27 c-0.84,0.14-1.69,0.22-2.54,0.28l-0.86,0.04c-0.29,0.01-0.57,0-0.86,0c-0.53,0.01-1.05-0.03-1.57-0.06c1.51-2.98-2.18-5-2.18-5 s-0.92,3.15,0.55,4.83c-1.19-0.16-2.36-0.41-3.51-0.74c3.15-3.7-1.52-7.46-1.52-7.46s-2.14,4.31-0.23,6.89 c-1.46-0.53-2.86-1.19-4.2-1.98c4.7-3.22,0.49-8.78,0.49-8.78s-3.69,4.34-2.07,7.77c-0.08-0.05-0.16-0.1-0.23-0.16l-0.7-0.51 l-0.67-0.54c-0.11-0.09-0.23-0.18-0.33-0.27l-0.32-0.29c-0.21-0.19-0.43-0.38-0.64-0.58c-0.4-0.4-0.82-0.79-1.2-1.21 c5.91-2.21,2.73-9.15,2.73-9.15s-4.93,3.73-3.96,7.72c-0.68-0.86-1.33-1.76-1.89-2.71c-0.46-0.75-0.87-1.53-1.25-2.32 c6.33-0.61,5.01-8.16,5.01-8.16s-5.6,2.31-5.79,6.33c-0.61-1.6-1.06-3.26-1.34-4.95c4.81,0.3,4.68-5.48,4.68-5.48 s-4.05,0.99-4.91,3.69c-0.07-0.76-0.1-1.51-0.1-2.27c0-0.33,0.01-0.66,0.03-1c3.11-2.01,0.98-7.09,0.98-7.09s-4.69,3.31-1.73,6.99 C7,28.46,6.99,28.82,6.98,29.18c-0.02,0.91,0.01,1.82,0.1,2.73c-1.84-2.38-6.26-1.4-6.26-1.4s2.37,5.11,6.44,2.95 c0.26,1.71,0.69,3.39,1.28,5.01C5.64,35.69,0,37.86,0,37.86s4.26,6.43,9.29,2.45c0.39,0.87,0.83,1.72,1.31,2.54 c0.47,0.83,1.01,1.63,1.58,2.4C8.71,43.7,4.11,47,4.11,47s5.7,5.1,9.56,0.08c0.04,0.04,0.07,0.08,0.11,0.12 c0.39,0.45,0.82,0.87,1.24,1.3c0.21,0.21,0.44,0.41,0.66,0.61l0.33,0.3c0.11,0.1,0.23,0.19,0.34,0.29l0.69,0.57l0.23,0.17 c-3.34-0.34-6.58,3.29-6.58,3.29s6.19,3.47,8.69-1.83c1.2,0.75,2.47,1.41,3.78,1.96c-2.76,0.6-4.62,4.13-4.62,4.13 s5.89,1.62,6.98-3.26c1.03,0.32,2.07,0.58,3.13,0.78c-1.63,0.99-2.39,3.38-2.39,3.38s4.31,0.39,4.61-3.07 c0.07,0.01,0.14,0.02,0.21,0.02c0.6,0.04,1.2,0.1,1.8,0.09c0.3,0,0.6,0.02,0.9,0.01l0.9-0.03c1.2-0.07,2.41-0.18,3.59-0.42 l0.45-0.08c0.15-0.03,0.29-0.07,0.44-0.1L40,55.13l0.81,0.19c0.15,0.03,0.29,0.07,0.44,0.1l0.45,0.08c1.18,0.23,2.39,0.35,3.59,0.42 l0.9,0.03c0.3,0.01,0.6-0.01,0.9-0.01c0.6,0,1.2-0.06,1.8-0.09c0.07-0.01,0.14-0.02,0.21-0.02c0.31,3.45,4.61,3.07,4.61,3.07 s-0.76-2.39-2.39-3.38c1.06-0.2,2.11-0.46,3.13-0.78c1.09,4.88,6.98,3.26,6.98,3.26s-1.86-3.52-4.62-4.13 c1.31-0.55,2.57-1.21,3.78-1.96c2.5,5.3,8.69,1.83,8.69,1.83s-3.24-3.63-6.58-3.29l0.23-0.17l0.69-0.57 c0.11-0.1,0.23-0.19,0.34-0.29l0.33-0.3c0.22-0.2,0.45-0.4,0.66-0.61c0.42-0.43,0.85-0.84,1.24-1.3c0.03-0.04,0.07-0.08,0.11-0.12 C70.19,52.1,75.89,47,75.89,47s-4.6-3.31-8.08-1.75c0.57-0.77,1.11-1.56,1.58-2.4C69.88,42.03,70.31,41.18,70.71,40.31z"/>
|
||||
</svg>
|
||||
<foreignObject width="230" height="35" style="font-size: 14px;color: rgb(67, 39, 135);font-family: Arial;font-weight: 700;text-align: left;letter-spacing: 0em;line-height: 1.5;" x="64" y="24">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">#1 Repository Of The Day</div>
|
||||
</foreignObject>
|
||||
<foreignObject width="141" height="36" style="font-size: 18px;color: rgb(74, 14, 153);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="-36" y="9">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">1</div>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -5,17 +5,183 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
# Troubleshooting Guide
|
||||
|
||||
## Quick Diagnostic Tool
|
||||
|
||||
Describe any issues you're experiencing to Claude, and the troubleshoot skill will automatically activate to provide diagnosis and fixes.
|
||||
|
||||
The troubleshoot skill will:
|
||||
- ✅ Check worker status and health
|
||||
- ✅ Verify database existence and integrity
|
||||
- ✅ Test worker service connectivity
|
||||
- ✅ Validate dependencies installation
|
||||
- ✅ Check port configuration and availability
|
||||
- ✅ Provide automated fixes for common issues
|
||||
|
||||
The skill includes comprehensive diagnostics, automated repair sequences, and detailed troubleshooting workflows for all common issues. Simply describe the problem naturally to invoke it.
|
||||
|
||||
---
|
||||
|
||||
## v5.x Specific Issues
|
||||
|
||||
### Viewer UI Not Loading
|
||||
|
||||
**Symptoms**: Cannot access http://localhost:37777, page doesn't load, or shows connection error.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check if worker is running on port 37777:
|
||||
```bash
|
||||
lsof -i :37777
|
||||
# or
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
2. Verify worker is healthy:
|
||||
```bash
|
||||
curl http://localhost:37777/health
|
||||
```
|
||||
|
||||
3. Check worker logs for errors:
|
||||
```bash
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
4. Restart worker service:
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
5. Check for port conflicts:
|
||||
```bash
|
||||
# If port 37777 is in use by another service
|
||||
export CLAUDE_MEM_WORKER_PORT=38000
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Theme Toggle Not Persisting
|
||||
|
||||
**Symptoms**: Theme preference (light/dark mode) resets after browser refresh.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check browser localStorage is enabled:
|
||||
```javascript
|
||||
// In browser console
|
||||
localStorage.getItem('claude-mem-settings')
|
||||
```
|
||||
|
||||
2. Verify settings endpoint is working:
|
||||
```bash
|
||||
curl http://localhost:37777/api/settings
|
||||
```
|
||||
|
||||
3. Clear localStorage and try again:
|
||||
```javascript
|
||||
// In browser console
|
||||
localStorage.removeItem('claude-mem-settings')
|
||||
```
|
||||
|
||||
4. Check for browser privacy mode (blocks localStorage)
|
||||
|
||||
### SSE Connection Issues
|
||||
|
||||
**Symptoms**: Viewer shows "Disconnected" status, updates not appearing in real-time.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check SSE endpoint is accessible:
|
||||
```bash
|
||||
curl -N http://localhost:37777/stream
|
||||
```
|
||||
|
||||
2. Check browser console for errors:
|
||||
- Open DevTools (F12)
|
||||
- Look for EventSource errors
|
||||
- Check Network tab for failed /stream requests
|
||||
|
||||
3. Verify worker is running:
|
||||
```bash
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
4. Check for network/proxy issues blocking SSE
|
||||
- Corporate firewalls may block SSE
|
||||
- Try disabling VPN temporarily
|
||||
|
||||
5. Restart worker and refresh browser:
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
### Chroma/Python Dependency Issues (v5.0.0+)
|
||||
|
||||
**Symptoms**: Installation fails with chromadb or Python-related errors.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Verify Python 3.8+ is installed:
|
||||
```bash
|
||||
python --version
|
||||
# or
|
||||
python3 --version
|
||||
```
|
||||
|
||||
2. Install chromadb manually:
|
||||
```bash
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack
|
||||
npm install chromadb
|
||||
```
|
||||
|
||||
3. Check chromadb health:
|
||||
```bash
|
||||
npm run chroma:health
|
||||
```
|
||||
|
||||
4. Windows-specific: Ensure Python is in PATH:
|
||||
```bash
|
||||
where python
|
||||
# Should show Python installation path
|
||||
```
|
||||
|
||||
5. If Chroma continues to fail, hybrid search will gracefully degrade to SQLite FTS5 only
|
||||
|
||||
### Smart Install Caching Issues (v5.0.3+)
|
||||
|
||||
**Symptoms**: Dependencies not updating after plugin update, stale version marker.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Clear install cache:
|
||||
```bash
|
||||
rm ~/.claude/plugins/marketplaces/thedotmack/.install-version
|
||||
```
|
||||
|
||||
2. Force reinstall:
|
||||
```bash
|
||||
cd ~/.claude/plugins/marketplaces/thedotmack
|
||||
npm install --force
|
||||
```
|
||||
|
||||
3. Check version marker:
|
||||
```bash
|
||||
cat ~/.claude/plugins/marketplaces/thedotmack/.install-version
|
||||
cat ~/.claude/plugins/marketplaces/thedotmack/package.json | grep version
|
||||
```
|
||||
|
||||
4. Restart Claude Code after manual install
|
||||
|
||||
|
||||
## Worker Service Issues
|
||||
|
||||
### Worker Service Not Starting
|
||||
|
||||
**Symptoms**: Worker doesn't start, or `pm2 status` shows no processes.
|
||||
**Symptoms**: Worker doesn't start, or worker status shows it's not running.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check if PM2 is running:
|
||||
1. Check worker status:
|
||||
```bash
|
||||
pm2 status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
2. Try starting manually:
|
||||
@@ -30,14 +196,14 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
4. Full reset:
|
||||
```bash
|
||||
pm2 delete claude-mem-worker
|
||||
npm run worker:stop
|
||||
npm run worker:start
|
||||
```
|
||||
|
||||
5. Verify PM2 is installed:
|
||||
5. Verify Bun is installed:
|
||||
```bash
|
||||
which pm2
|
||||
npm list pm2
|
||||
which bun
|
||||
bun --version
|
||||
```
|
||||
|
||||
### Port Allocation Failed
|
||||
@@ -59,7 +225,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
3. Or use a different port:
|
||||
```bash
|
||||
export CLAUDE_MEM_WORKER_PORT=38000
|
||||
npm run worker:restart
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
4. Verify new port:
|
||||
@@ -69,7 +235,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
### Worker Keeps Crashing
|
||||
|
||||
**Symptoms**: Worker restarts repeatedly, PM2 shows high restart count.
|
||||
**Symptoms**: Worker restarts repeatedly or fails to stay running.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
@@ -78,23 +244,21 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
2. Check memory usage:
|
||||
2. Check worker status:
|
||||
```bash
|
||||
pm2 status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
3. Increase memory limit in `ecosystem.config.cjs`:
|
||||
```javascript
|
||||
{
|
||||
max_memory_restart: '2G' // Increase if needed
|
||||
}
|
||||
```
|
||||
|
||||
4. Check database for corruption:
|
||||
3. Check database for corruption:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "PRAGMA integrity_check;"
|
||||
```
|
||||
|
||||
4. Verify Bun installation:
|
||||
```bash
|
||||
bun --version
|
||||
```
|
||||
|
||||
### Worker Not Processing Observations
|
||||
|
||||
**Symptoms**: Observations saved but not processed, no summaries generated.
|
||||
@@ -118,7 +282,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
4. Restart worker:
|
||||
```bash
|
||||
npm run worker:restart
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
## Hook Issues
|
||||
@@ -237,7 +401,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
1. Close all connections:
|
||||
```bash
|
||||
pm2 stop claude-mem-worker
|
||||
npm run worker:stop
|
||||
```
|
||||
|
||||
2. Check for stale locks:
|
||||
@@ -355,7 +519,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
2. Verify search server is built:
|
||||
```bash
|
||||
ls -l plugin/scripts/search-server.js
|
||||
ls -l plugin/scripts/mcp-server.cjs
|
||||
```
|
||||
|
||||
3. Rebuild if needed:
|
||||
@@ -469,29 +633,21 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
**Symptoms**: Worker uses too much memory, frequent restarts.
|
||||
**Symptoms**: Worker uses too much memory.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check current usage:
|
||||
```bash
|
||||
pm2 status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
2. Increase memory limit:
|
||||
```javascript
|
||||
// In ecosystem.config.cjs
|
||||
{
|
||||
max_memory_restart: '2G'
|
||||
}
|
||||
```
|
||||
|
||||
3. Restart worker:
|
||||
2. Restart worker:
|
||||
```bash
|
||||
npm run worker:restart
|
||||
claude-mem restart
|
||||
```
|
||||
|
||||
4. Clean up old data (see "Database Too Large" above)
|
||||
3. Clean up old data (see "Database Too Large" above)
|
||||
|
||||
## Installation Issues
|
||||
|
||||
@@ -565,7 +721,7 @@ description: "Common issues and solutions for Claude-Mem"
|
||||
|
||||
```bash
|
||||
export DEBUG=claude-mem:*
|
||||
npm run worker:restart
|
||||
claude-mem restart
|
||||
npm run worker:logs
|
||||
```
|
||||
|
||||
@@ -586,10 +742,10 @@ sqlite3 ~/.claude-mem/claude-mem.db "
|
||||
|
||||
```bash
|
||||
# Check if worker is running
|
||||
pm2 status
|
||||
npm run worker:status
|
||||
|
||||
# View logs
|
||||
pm2 logs claude-mem-worker
|
||||
npm run worker:logs
|
||||
|
||||
# Check port file
|
||||
cat ~/.claude-mem/worker.port
|
||||
@@ -625,7 +781,7 @@ SELECT created_at, tool_name FROM observations ORDER BY created_at DESC LIMIT 10
|
||||
|
||||
**Cause**: Worker not running or port mismatch.
|
||||
|
||||
**Solution**: Restart worker with `npm run worker:restart`.
|
||||
**Solution**: Restart worker with `claude-mem restart`.
|
||||
|
||||
### "Database is locked"
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
---
|
||||
title: Claude Desktop Skill
|
||||
description: Use claude-mem memory search in Claude Desktop with the mem-search skill
|
||||
icon: desktop
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Availability:** The mem-search skill works with Claude Desktop on macOS and Windows.
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
Claude Desktop can access your claude-mem memory database through the **mem-search** skill. This allows you to search past sessions, decisions, and observations directly from Claude Desktop conversations.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before installing the skill, ensure:
|
||||
|
||||
1. **claude-mem is installed** and the worker service is running
|
||||
2. **MCP server is configured** in Claude Desktop (the skill uses the `mem-search` MCP server)
|
||||
|
||||
### Verify Worker is Running
|
||||
|
||||
```bash
|
||||
curl http://localhost:37777/api/health
|
||||
# Should return: {"status":"ok"}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Step 1: Download the Skill
|
||||
|
||||
Download the skill package from the repository:
|
||||
|
||||
<Card title="mem-search.zip" icon="download" href="https://github.com/thedotmack/claude-mem/raw/main/plugin/skills/mem-search.zip">
|
||||
Download the mem-search skill for Claude Desktop
|
||||
</Card>
|
||||
|
||||
Or build from source:
|
||||
|
||||
```bash
|
||||
npm run build # Generates plugin/skills/mem-search.zip
|
||||
```
|
||||
|
||||
### Step 2: Install in Claude Desktop
|
||||
|
||||
1. Open **Claude Desktop**
|
||||
2. Go to **Settings** (gear icon)
|
||||
3. Navigate to **Skills**
|
||||
4. Click **Install Skill** or drag the `mem-search.zip` file
|
||||
5. Confirm installation
|
||||
|
||||
### Step 3: Configure MCP Server
|
||||
|
||||
The skill requires the `mem-search` MCP server. Add this to your Claude Desktop configuration:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS">
|
||||
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"mem-search": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/Users/YOUR_USERNAME/.claude/plugins/marketplaces/thedotmack/plugin/scripts/mcp-server.cjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Windows">
|
||||
Edit `%APPDATA%\Claude\claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"mem-search": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"C:\\Users\\YOUR_USERNAME\\.claude\\plugins\\marketplaces\\thedotmack\\plugin\\scripts\\mcp-server.cjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
Replace `YOUR_USERNAME` with your actual username. Restart Claude Desktop after editing the configuration.
|
||||
</Warning>
|
||||
|
||||
### Step 4: Restart Claude Desktop
|
||||
|
||||
Close and reopen Claude Desktop for the MCP server configuration to take effect.
|
||||
|
||||
## Usage
|
||||
|
||||
Once installed, the skill auto-activates when you ask about past work:
|
||||
|
||||
```
|
||||
"What did we do last session?"
|
||||
"Did we fix this bug before?"
|
||||
"How did we implement authentication?"
|
||||
"What decisions did we make about the API?"
|
||||
"Show me changes to worker-service.ts"
|
||||
```
|
||||
|
||||
## Available MCP Tools
|
||||
|
||||
The skill provides access to these MCP tools:
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `search` | Unified search across observations, sessions, and prompts |
|
||||
| `timeline` | Get chronological context around a query or observation ID |
|
||||
| `get_observation` | Fetch a single observation by ID |
|
||||
| `get_observations` | Fetch multiple observations efficiently |
|
||||
| `get_session` | Fetch session summary by ID |
|
||||
| `get_prompt` | Fetch user prompt by ID |
|
||||
| `get_recent_context` | Get recent timeline items |
|
||||
| `get_context_timeline` | Get timeline around a specific observation |
|
||||
| `help` | Load detailed usage instructions |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Skill Not Appearing
|
||||
|
||||
1. Verify the zip file was properly installed
|
||||
2. Check Claude Desktop's skill installation logs
|
||||
3. Restart Claude Desktop
|
||||
|
||||
### MCP Server Connection Failed
|
||||
|
||||
1. Verify the worker is running: `curl http://localhost:37777/api/health`
|
||||
2. Check the MCP server path in configuration
|
||||
3. Look for errors in Claude Desktop logs
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS">
|
||||
```bash
|
||||
# View Claude Desktop logs
|
||||
tail -f ~/Library/Logs/Claude/claude.log
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Windows">
|
||||
Check `%APPDATA%\Claude\logs\`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Search Returns No Results
|
||||
|
||||
1. Ensure claude-mem has recorded sessions (check http://localhost:37777)
|
||||
2. Verify the database exists: `ls ~/.claude-mem/claude-mem.db`
|
||||
3. Test the API directly: `curl "http://localhost:37777/api/search?query=test"`
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Search Tools" icon="magnifying-glass" href="/usage/search-tools">
|
||||
Complete search API reference
|
||||
</Card>
|
||||
<Card title="Platform Integration" icon="plug" href="/platform-integration">
|
||||
Build custom integrations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,295 @@
|
||||
---
|
||||
title: "Memory Export/Import"
|
||||
description: "Share knowledge across claude-mem installations with duplicate prevention"
|
||||
---
|
||||
|
||||
# Memory Export/Import Scripts
|
||||
|
||||
Share your claude-mem knowledge with other users! These scripts allow you to export specific memories (observations, sessions, summaries, and prompts) and import them into another claude-mem installation.
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Share Windows compatibility knowledge** with Windows users
|
||||
- **Share bug fix patterns** with contributors
|
||||
- **Share project-specific learnings** across teams
|
||||
- **Backup specific memory sets** for safekeeping
|
||||
|
||||
## How It Works
|
||||
|
||||
### Export Script
|
||||
|
||||
Searches the database using **hybrid search** (combines ChromaDB vector embeddings with FTS5 full-text search) and exports all matching:
|
||||
- **Observations** - Individual learnings and discoveries
|
||||
- **Sessions** - Session metadata
|
||||
- **Summaries** - Session summaries
|
||||
- **Prompts** - User prompts that led to the work
|
||||
|
||||
Output is a portable JSON file that can be shared.
|
||||
|
||||
> **Privacy Note:** Export files contain all matching memory data in plain text. Review exports before sharing to ensure no sensitive information (API keys, passwords, private paths) is included.
|
||||
|
||||
### Import Script
|
||||
|
||||
Imports memories with **duplicate prevention**:
|
||||
- Checks if each record already exists before inserting
|
||||
- Skips duplicates automatically
|
||||
- Maintains data integrity with transactional imports
|
||||
- Reports what was imported vs. skipped
|
||||
|
||||
**Duplicate Detection Strategy:**
|
||||
- **Sessions**: By `claude_session_id` (unique)
|
||||
- **Summaries**: By `sdk_session_id` (unique)
|
||||
- **Observations**: By `sdk_session_id` + `title` + `created_at_epoch` (composite)
|
||||
- **Prompts**: By `claude_session_id` + `prompt_number` (composite)
|
||||
|
||||
## Usage
|
||||
|
||||
### Export Memories
|
||||
|
||||
```bash
|
||||
# Export all Windows-related memories
|
||||
npx tsx scripts/export-memories.ts "windows" windows-memories.json
|
||||
|
||||
# Export bug fixes
|
||||
npx tsx scripts/export-memories.ts "bugfix" bugfixes.json
|
||||
|
||||
# Export specific feature work
|
||||
npx tsx scripts/export-memories.ts "progressive disclosure" progressive-disclosure.json
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
1. `<query>` - Search query (uses hybrid semantic + full-text search)
|
||||
2. `<output-file>` - Output JSON file path
|
||||
3. `--project=name` - Optional: filter results to a specific project
|
||||
|
||||
**Example Output:**
|
||||
```
|
||||
🔍 Searching for: "windows"
|
||||
✅ Found 54 observations
|
||||
✅ Found 12 sessions
|
||||
✅ Found 12 summaries
|
||||
✅ Found 7 prompts
|
||||
|
||||
📦 Export complete!
|
||||
📄 Output: windows-memories.json
|
||||
📊 Stats:
|
||||
• 54 observations
|
||||
• 12 sessions
|
||||
• 12 summaries
|
||||
• 7 prompts
|
||||
```
|
||||
|
||||
### Import Memories
|
||||
|
||||
```bash
|
||||
# Import from an export file
|
||||
npx tsx scripts/import-memories.ts windows-memories.json
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
1. `<input-file>` - Input JSON file (from export script)
|
||||
|
||||
**Example Output:**
|
||||
```
|
||||
📦 Import file: windows-memories.json
|
||||
📅 Exported: 2025-12-10T23:45:00.000Z
|
||||
🔍 Query: "windows"
|
||||
📊 Contains:
|
||||
• 54 observations
|
||||
• 12 sessions
|
||||
• 12 summaries
|
||||
• 7 prompts
|
||||
|
||||
🔄 Importing sessions...
|
||||
✅ Imported: 12, Skipped: 0
|
||||
🔄 Importing summaries...
|
||||
✅ Imported: 12, Skipped: 0
|
||||
🔄 Importing observations...
|
||||
✅ Imported: 54, Skipped: 0
|
||||
🔄 Importing prompts...
|
||||
✅ Imported: 7, Skipped: 0
|
||||
|
||||
✅ Import complete!
|
||||
📊 Summary:
|
||||
Sessions: 12 imported, 0 skipped
|
||||
Summaries: 12 imported, 0 skipped
|
||||
Observations: 54 imported, 0 skipped
|
||||
Prompts: 7 imported, 0 skipped
|
||||
```
|
||||
|
||||
### Re-importing (Duplicate Prevention)
|
||||
|
||||
If you run the import again on the same file, duplicates are automatically skipped:
|
||||
|
||||
```
|
||||
🔄 Importing sessions...
|
||||
✅ Imported: 0, Skipped: 12 ← All skipped (already exist)
|
||||
🔄 Importing summaries...
|
||||
✅ Imported: 0, Skipped: 12
|
||||
🔄 Importing observations...
|
||||
✅ Imported: 0, Skipped: 54
|
||||
🔄 Importing prompts...
|
||||
✅ Imported: 0, Skipped: 7
|
||||
```
|
||||
|
||||
## Sharing Memories
|
||||
|
||||
### For Export Authors
|
||||
|
||||
1. **Export your memories:**
|
||||
```bash
|
||||
npx tsx scripts/export-memories.ts "windows" windows-memories.json
|
||||
```
|
||||
|
||||
2. **Share the JSON file** via:
|
||||
- GitHub gist
|
||||
- Project repository (`shared-memories/`)
|
||||
- Direct file transfer
|
||||
- Package in releases
|
||||
|
||||
3. **Document what's included:**
|
||||
- What query was used
|
||||
- What knowledge is contained
|
||||
- Who might benefit from it
|
||||
|
||||
### For Import Users
|
||||
|
||||
1. **Download the export file** to your local machine
|
||||
|
||||
2. **Review what's in it** (optional):
|
||||
```bash
|
||||
cat windows-memories.json | jq '.totalObservations, .totalSessions'
|
||||
```
|
||||
|
||||
3. **Import into your database:**
|
||||
```bash
|
||||
npx tsx scripts/import-memories.ts windows-memories.json
|
||||
```
|
||||
|
||||
4. **Verify import** by searching:
|
||||
```bash
|
||||
curl "http://localhost:37777/api/search?query=windows&format=index&limit=10"
|
||||
```
|
||||
|
||||
## JSON Export Format
|
||||
|
||||
```json
|
||||
{
|
||||
"exportedAt": "2025-12-10T23:45:00.000Z",
|
||||
"exportedAtEpoch": 1733876700000,
|
||||
"query": "windows",
|
||||
"totalObservations": 54,
|
||||
"totalSessions": 12,
|
||||
"totalSummaries": 12,
|
||||
"totalPrompts": 7,
|
||||
"observations": [ /* array of observation objects */ ],
|
||||
"sessions": [ /* array of session objects */ ],
|
||||
"summaries": [ /* array of summary objects */ ],
|
||||
"prompts": [ /* array of prompt objects */ ]
|
||||
}
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
✅ **Duplicate Prevention** - Won't re-import existing records
|
||||
✅ **Transactional** - All-or-nothing imports (database stays consistent)
|
||||
✅ **Read-only Export** - Export script opens database in read-only mode
|
||||
✅ **Dependency Ordering** - Sessions imported before observations/summaries
|
||||
✅ **Validation** - Checks database exists before starting
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Export by Project
|
||||
|
||||
```bash
|
||||
# Export only claude-mem project memories
|
||||
npx tsx scripts/export-memories.ts "bugfix" bugfixes.json --project=claude-mem
|
||||
|
||||
# Export all memories for a specific project
|
||||
npx tsx scripts/export-memories.ts "" all-project.json --project=my-app
|
||||
```
|
||||
|
||||
### Export by Type
|
||||
|
||||
```bash
|
||||
# Export only discoveries
|
||||
npx tsx scripts/export-memories.ts "type:discovery" discoveries.json
|
||||
|
||||
# Export only bug fixes
|
||||
npx tsx scripts/export-memories.ts "type:bugfix" bugfixes.json
|
||||
```
|
||||
|
||||
### Export by Date Range
|
||||
|
||||
You can filter the export after exporting:
|
||||
|
||||
```bash
|
||||
# Export all memories, then filter manually with jq
|
||||
npx tsx scripts/export-memories.ts "" all-memories.json
|
||||
cat all-memories.json | jq '.observations |= map(select(.created_at_epoch > 1700000000000))' > recent-memories.json
|
||||
```
|
||||
|
||||
### Combine Multiple Exports
|
||||
|
||||
```bash
|
||||
# Export different topics
|
||||
npx tsx scripts/export-memories.ts "windows" windows.json
|
||||
npx tsx scripts/export-memories.ts "linux" linux.json
|
||||
|
||||
# Import both
|
||||
npx tsx scripts/import-memories.ts windows.json
|
||||
npx tsx scripts/import-memories.ts linux.json
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database Not Found
|
||||
|
||||
```
|
||||
❌ Database not found at: /Users/you/.claude-mem/claude-mem.db
|
||||
```
|
||||
|
||||
**Solution:** Make sure claude-mem is installed and has been run at least once.
|
||||
|
||||
### Import File Not Found
|
||||
|
||||
```
|
||||
❌ Input file not found: windows-memories.json
|
||||
```
|
||||
|
||||
**Solution:** Check the file path. Use absolute paths if needed.
|
||||
|
||||
### Partial Import
|
||||
|
||||
If import fails mid-way, the transaction is rolled back - your database remains unchanged. Fix the issue and try again.
|
||||
|
||||
## Contributing Memory Sets
|
||||
|
||||
If you've exported valuable knowledge that others might benefit from:
|
||||
|
||||
1. Create a PR to the `shared-memories/` directory
|
||||
2. Include a README describing what's in the export
|
||||
3. Tag with relevant keywords (windows, linux, bugfix, etc.)
|
||||
4. Community members can then import your knowledge!
|
||||
|
||||
## Examples of Useful Exports
|
||||
|
||||
**Windows Compatibility Knowledge:**
|
||||
```bash
|
||||
npx tsx scripts/export-memories.ts "windows compatibility installation" windows-fixes.json
|
||||
```
|
||||
|
||||
**Progressive Disclosure Architecture:**
|
||||
```bash
|
||||
npx tsx scripts/export-memories.ts "progressive disclosure architecture token" pd-patterns.json
|
||||
```
|
||||
|
||||
**Bug Fix Patterns:**
|
||||
```bash
|
||||
npx tsx scripts/export-memories.ts "bugfix error handling" bugfix-patterns.json
|
||||
```
|
||||
|
||||
**Performance Optimization:**
|
||||
```bash
|
||||
npx tsx scripts/export-memories.ts "performance optimization caching" perf-tips.json
|
||||
```
|
||||
@@ -0,0 +1,215 @@
|
||||
---
|
||||
title: "Getting Started"
|
||||
description: "Learn how Claude-Mem works automatically in the background"
|
||||
---
|
||||
|
||||
# Getting Started with Claude-Mem
|
||||
|
||||
## Automatic Operation
|
||||
|
||||
Claude-Mem works automatically once installed. No manual intervention required!
|
||||
|
||||
### The Full Cycle
|
||||
|
||||
1. **Start Claude Code** - Context from last 10 sessions appears automatically
|
||||
2. **Work normally** - Every tool execution is captured
|
||||
3. **Claude finishes responding** - Stop hook automatically generates and saves a summary
|
||||
4. **Next session** - Previous work appears in context
|
||||
|
||||
### What Gets Captured
|
||||
|
||||
Every time Claude uses a tool, claude-mem captures it:
|
||||
|
||||
- **Read** - File reads and content access
|
||||
- **Write** - New file creation
|
||||
- **Edit** - File modifications
|
||||
- **Bash** - Command executions
|
||||
- **Glob** - File pattern searches
|
||||
- **Grep** - Content searches
|
||||
- And all other Claude Code tools
|
||||
|
||||
### What Gets Processed
|
||||
|
||||
The worker service processes tool observations and extracts:
|
||||
|
||||
- **Title** - Brief description of what happened
|
||||
- **Subtitle** - Additional context
|
||||
- **Narrative** - Detailed explanation
|
||||
- **Facts** - Key learnings as bullet points
|
||||
- **Concepts** - Relevant tags and categories
|
||||
- **Type** - Classification (decision, bugfix, feature, etc.)
|
||||
- **Files** - Which files were read or modified
|
||||
|
||||
### Session Summaries
|
||||
|
||||
When Claude finishes responding (triggering the Stop hook), a summary is automatically generated with:
|
||||
|
||||
- **Request** - What you asked for
|
||||
- **Investigated** - What Claude explored
|
||||
- **Learned** - Key discoveries and insights
|
||||
- **Completed** - What was accomplished
|
||||
- **Next Steps** - What to do next
|
||||
|
||||
### Context Injection
|
||||
|
||||
When you start a new Claude Code session, the SessionStart hook:
|
||||
|
||||
1. Queries the database for recent observations in your project (default: 50)
|
||||
2. Retrieves recent session summaries for context
|
||||
3. Displays observations in a chronological timeline with session markers
|
||||
4. Shows full summary details (Investigated, Learned, Completed, Next Steps) **only if the summary was generated after the last observation**
|
||||
5. Injects formatted context into Claude's initial context
|
||||
|
||||
**Summary Display Logic:**
|
||||
|
||||
The most recent summary's full details appear at the end of the context display **only when** the summary was generated after the most recent observation. This ensures you see summary details when they represent the latest state of your project, but not when new observations have been captured since the last summary.
|
||||
|
||||
For example:
|
||||
- ✅ **Shows summary**: Last observation at 2:00 PM, summary generated at 2:05 PM → Summary details appear
|
||||
- ❌ **Hides summary**: Summary generated at 2:00 PM, new observation at 2:05 PM → Summary details hidden (outdated)
|
||||
|
||||
This prevents showing stale summaries when new work has been captured but not yet summarized.
|
||||
|
||||
This means Claude "remembers" what happened in previous sessions!
|
||||
|
||||
## Manual Commands (Optional)
|
||||
|
||||
### Worker Management
|
||||
|
||||
v4.0+ auto-starts the worker on first session. Manual commands below are optional.
|
||||
|
||||
```bash
|
||||
# Start worker service (optional - auto-starts automatically)
|
||||
npm run worker:start
|
||||
|
||||
# Stop worker service
|
||||
npm run worker:stop
|
||||
|
||||
# Restart worker service
|
||||
claude-mem restart
|
||||
|
||||
# View worker logs
|
||||
npm run worker:logs
|
||||
|
||||
# Check worker status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
npm test
|
||||
|
||||
# Test context injection
|
||||
npm run test:context
|
||||
|
||||
# Verbose context test
|
||||
npm run test:context:verbose
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Build hooks and worker
|
||||
npm run build
|
||||
|
||||
# Build only hooks
|
||||
npm run build:hooks
|
||||
|
||||
# Publish to NPM (maintainers only)
|
||||
npm run publish:npm
|
||||
```
|
||||
|
||||
## Viewing Stored Context
|
||||
|
||||
Context is stored in SQLite database at `~/.claude-mem/claude-mem.db`.
|
||||
|
||||
Query the database directly:
|
||||
|
||||
```bash
|
||||
# Open database
|
||||
sqlite3 ~/.claude-mem/claude-mem.db
|
||||
|
||||
# View recent sessions
|
||||
SELECT session_id, project, created_at, status
|
||||
FROM sdk_sessions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
|
||||
# View session summaries
|
||||
SELECT session_id, request, completed, learned
|
||||
FROM session_summaries
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 5;
|
||||
|
||||
# View observations for a session
|
||||
SELECT tool_name, created_at
|
||||
FROM observations
|
||||
WHERE session_id = 'YOUR_SESSION_ID';
|
||||
```
|
||||
|
||||
## Understanding Progressive Disclosure
|
||||
|
||||
Context injection uses progressive disclosure for efficient token usage:
|
||||
|
||||
### Layer 1: Index Display (Session Start)
|
||||
- Shows observation titles with token cost estimates
|
||||
- Displays session markers in chronological timeline
|
||||
- Groups observations by file for visual clarity
|
||||
- Shows full summary details **only if** generated after last observation
|
||||
- Token cost: ~50-200 tokens for index view
|
||||
|
||||
### Layer 2: On-Demand Details (mem-search Skill)
|
||||
- Ask naturally: "What bugs did we fix?" or "How did we implement X?"
|
||||
- Claude auto-invokes mem-search skill to fetch full details
|
||||
- Search by concept, file, type, or keyword
|
||||
- Timeline context around specific observations
|
||||
- Token cost: ~100-500 tokens per observation fetched
|
||||
- Skill uses HTTP API (v5.4.0+) for efficient retrieval
|
||||
|
||||
### Layer 3: Perfect Recall (Code Access)
|
||||
- Read source files directly when needed
|
||||
- Access original transcripts and raw data
|
||||
- Full context available on-demand
|
||||
|
||||
This ensures efficient token usage while maintaining access to complete history when needed.
|
||||
|
||||
## Multi-Prompt Sessions & `/clear` Behavior
|
||||
|
||||
Claude-Mem supports sessions that span multiple user prompts:
|
||||
|
||||
- **prompt_counter**: Tracks total prompts in a session
|
||||
- **prompt_number**: Identifies specific prompt within session
|
||||
- **Session continuity**: Observations and summaries link across prompts
|
||||
|
||||
### Important Note About `/clear`
|
||||
|
||||
When you use `/clear`, the session doesn't end - it continues with a new prompt number. This means:
|
||||
|
||||
- ✅ **Context is re-injected** from recent sessions (SessionStart hook fires with `source: "clear"`)
|
||||
- ✅ **Observations are still being captured** and added to the current session
|
||||
- ✅ **A summary will be generated** when Claude finishes responding (Stop hook fires)
|
||||
|
||||
The `/clear` command clears the conversation context visible to Claude AND re-injects fresh context from recent sessions, while the underlying session continues tracking observations.
|
||||
|
||||
## Searching Your History (v5.4.0+)
|
||||
|
||||
Claude-Mem uses the mem-search skill for querying your project history. Simply ask naturally:
|
||||
|
||||
```
|
||||
"What bugs did we fix last session?"
|
||||
"How did we implement authentication?"
|
||||
"What changes were made to worker-service.ts?"
|
||||
"Show me recent work on this project"
|
||||
```
|
||||
|
||||
Claude automatically recognizes your intent and invokes the mem-search skill, which uses HTTP API endpoints to query your memory efficiently.
|
||||
|
||||
**Token Savings**: ~2,250 tokens per session start vs previous MCP approach
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Skill-Based Search](/usage/search-tools) - Learn how to search your project history
|
||||
- [Architecture Overview](/architecture/overview) - Understand how it works
|
||||
- [Troubleshooting](/troubleshooting) - Common issues and solutions
|
||||
@@ -0,0 +1,195 @@
|
||||
---
|
||||
title: "Private Tags"
|
||||
description: "Control what gets stored in memory with privacy tags"
|
||||
---
|
||||
|
||||
# Private Tags
|
||||
|
||||
## Overview
|
||||
|
||||
Use `<private>` tags to mark content you don't want persisted in claude-mem's observation database. This gives you fine-grained control over what gets remembered across sessions.
|
||||
|
||||
## How It Works
|
||||
|
||||
Wrap any content in `<private>` tags:
|
||||
|
||||
```
|
||||
<private>
|
||||
This content will not be stored in memory
|
||||
</private>
|
||||
```
|
||||
|
||||
Claude can see and use this content during the current session, but it won't be saved as an observation.
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Sensitive Information
|
||||
|
||||
```
|
||||
Please analyze this error:
|
||||
|
||||
<private>
|
||||
Error: Database connection failed
|
||||
Host: internal-db-prod.company.com
|
||||
Port: 5432
|
||||
User: admin_user
|
||||
</private>
|
||||
|
||||
What might be causing this?
|
||||
```
|
||||
|
||||
Claude sees the full error but only the question gets stored.
|
||||
|
||||
### 2. Temporary Context
|
||||
|
||||
```
|
||||
<private>
|
||||
Here's some background context just for this session:
|
||||
- Project deadline is tomorrow
|
||||
- This is a hotfix for production
|
||||
- Manager asked for this specifically
|
||||
</private>
|
||||
|
||||
Help me fix this bug quickly.
|
||||
```
|
||||
|
||||
### 3. Debugging Information
|
||||
|
||||
```
|
||||
<private>
|
||||
Debug output from previous run:
|
||||
[... 500 lines of logs ...]
|
||||
</private>
|
||||
|
||||
Based on these logs, what's the root cause?
|
||||
```
|
||||
|
||||
### 4. Exploratory Prompts
|
||||
|
||||
```
|
||||
<private>
|
||||
I'm just brainstorming here, not making a final decision
|
||||
</private>
|
||||
|
||||
What are some wild approaches to solving this?
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Tag Behavior
|
||||
|
||||
- **Multiline support**: Tags can wrap multiple lines of content
|
||||
- **Multiple tags**: You can use multiple `<private>` sections in one message
|
||||
- **Nested tags**: Inner tags are included in outer tag removal
|
||||
- **Always active**: No configuration needed - works automatically
|
||||
|
||||
### What Gets Filtered
|
||||
|
||||
The `<private>` tag filters content from storage and memory:
|
||||
- **User prompt storage** - Tags are stripped before saving to the user_prompts table
|
||||
- **Tool inputs** - Parameters passed to tools are filtered before observation creation
|
||||
- **Tool responses** - Output from tools is filtered before observation creation
|
||||
- **All searchable content** - Private content never reaches the database or search indices
|
||||
|
||||
**Important**: Tags are stripped during storage, not from the live conversation. Claude sees the full content including `<private>` tags during the session, and they only disappear when content is persisted to the database.
|
||||
|
||||
### What Doesn't Get Filtered
|
||||
|
||||
- Session summaries (generated from non-private observations only)
|
||||
- Claude's responses (not captured by claude-mem)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: API Keys
|
||||
|
||||
```
|
||||
<private>
|
||||
API_KEY=sk-proj-abc123xyz789
|
||||
</private>
|
||||
|
||||
Test this API connection for me
|
||||
```
|
||||
|
||||
The API key won't be stored, but Claude can use it during the session.
|
||||
|
||||
### Example 2: Personal Notes
|
||||
|
||||
```
|
||||
<private>
|
||||
Note to self: This is for the Smith project - the one we discussed
|
||||
last Tuesday. Don't confuse with the Jones project.
|
||||
</private>
|
||||
|
||||
Review the authentication implementation and suggest improvements.
|
||||
```
|
||||
|
||||
The personal context helps Claude understand your request without polluting your observation history.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Don't over-tag**: Only use `<private>` for content you genuinely don't want stored
|
||||
2. **Context matters**: Claude's understanding of your project comes from observations - excessive private tagging reduces future context quality
|
||||
3. **Secrets belong elsewhere**: While `<private>` prevents storage, sensitive data should still use proper secrets management
|
||||
4. **Test it works**: Check `~/.claude-mem/silent.log` if you're unsure whether tags are being stripped
|
||||
|
||||
## Verification
|
||||
|
||||
To verify tags are working:
|
||||
|
||||
1. Submit a prompt with `<private>` tags
|
||||
2. Check the database to ensure private content is not stored:
|
||||
```bash
|
||||
# Check user prompts
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT prompt_text FROM user_prompts ORDER BY created_at_epoch DESC LIMIT 1;"
|
||||
|
||||
# Check observations
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT narrative FROM observations ORDER BY created_at_epoch DESC LIMIT 1;"
|
||||
```
|
||||
3. The private content should NOT appear in either user_prompts or observations
|
||||
4. The `<private>` tags themselves should also be stripped
|
||||
|
||||
## Architecture
|
||||
|
||||
The `<private>` tag uses an **edge processing pattern**:
|
||||
|
||||
- Content is filtered at the hook layer before any storage
|
||||
- **UserPromptSubmit hook**: Strips tags from user prompts before saving to the user_prompts table (your typed prompts are cleaned before database storage)
|
||||
- **PostToolUse hook**: Strips tags from serialized tool_input and tool_response JSON before observation creation
|
||||
- Filtering happens before data reaches the worker service or database
|
||||
- This keeps the worker simple and follows a one-way data stream
|
||||
- Tags remain visible in the live conversation but are stripped from all persistent storage
|
||||
|
||||
**Tag Stripping Scope**: The implementation strips tags from the *serialized JSON representations* of tool inputs and tool responses, not from the original user prompt text in the conversation UI. The user prompt text you type is stored in a separate table (user_prompts) where tags are also stripped before storage.
|
||||
|
||||
This design ensures that private content never reaches the database, search indices, or memory agent, maintaining a clean separation between ephemeral and persistent data.
|
||||
|
||||
## Related Features
|
||||
|
||||
- [Search Tools](/usage/search-tools) - How to search past observations
|
||||
- [Getting Started](/usage/getting-started) - Basic usage guide
|
||||
- [Configuration](/configuration) - System settings and environment variables
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tags Not Being Stripped
|
||||
|
||||
1. Verify correct syntax: `<private>content</private>`
|
||||
2. Check `~/.claude-mem/silent.log` for errors
|
||||
3. Ensure worker is running: `npm run worker:status`
|
||||
4. Restart worker: `claude-mem restart`
|
||||
|
||||
### Partial Content Stored
|
||||
|
||||
If content appears partially in observations:
|
||||
- Ensure tags are properly closed
|
||||
- Check for typos in tag names
|
||||
- Verify content is inside tool executions (not just in your prompt text)
|
||||
|
||||
### Silent Log Shows Errors
|
||||
|
||||
If you see errors in `~/.claude-mem/silent.log`:
|
||||
```
|
||||
[save-hook] stripMemoryTags received non-string: { type: 'object' }
|
||||
```
|
||||
|
||||
This is usually harmless - it indicates defensive type checking is working. However, if you see these frequently, it may indicate a bug. Please report it at https://github.com/thedotmack/claude-mem/issues
|
||||
@@ -0,0 +1,403 @@
|
||||
---
|
||||
title: "mem-search Skill"
|
||||
description: "Query your project history with natural language"
|
||||
---
|
||||
|
||||
# mem-search Skill Usage
|
||||
|
||||
Once claude-mem is installed as a plugin, you can search your project history using natural language. Claude automatically invokes the mem-search skill when you ask about past work.
|
||||
|
||||
## How It Works
|
||||
|
||||
**v5.5.0 Enhancement**: The search skill was renamed to "mem-search" for better scope differentiation, with effectiveness increased from 67% to 100% and enhanced concrete triggers (85% vs 44%).
|
||||
|
||||
**v5.4.0 Architecture**: Claude-Mem uses a skill-based search architecture instead of MCP tools, saving ~2,250 tokens per session start through progressive disclosure.
|
||||
|
||||
**Simple Usage:**
|
||||
- Just ask naturally: *"What did we do last session?"*
|
||||
- Claude recognizes the intent and invokes the mem-search skill
|
||||
- The skill uses HTTP API endpoints to query your memory
|
||||
- Results are formatted and presented to you
|
||||
|
||||
**Benefits:**
|
||||
- **Token Efficient**: ~250 tokens (skill frontmatter) vs ~2,500 tokens (MCP tool definitions)
|
||||
- **Natural Language**: No need to learn specific tool syntax
|
||||
- **Progressive Disclosure**: Only loads detailed instructions when needed
|
||||
- **Auto-Invoked**: Claude knows when to search based on your questions
|
||||
- **Scope Differentiation**: "mem-search" clearly distinguishes from native conversation memory
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Operation | Purpose |
|
||||
|-------------------------|----------------------------------------------|
|
||||
| Search Observations | Full-text search across observations |
|
||||
| Search Sessions | Full-text search across session summaries |
|
||||
| Search Prompts | Full-text search across raw user prompts |
|
||||
| By Concept | Find observations tagged with concepts |
|
||||
| By File | Find observations referencing files |
|
||||
| By Type | Find observations by type |
|
||||
| Recent Context | Get recent session context |
|
||||
| Timeline | Get unified timeline around a specific point |
|
||||
| Timeline by Query | Search and get timeline context in one step |
|
||||
| API Help | Get search API documentation |
|
||||
|
||||
## Example Queries
|
||||
|
||||
### Natural Language Queries
|
||||
|
||||
**Search Observations:**
|
||||
```
|
||||
"What bugs did we fix related to authentication?"
|
||||
"Show me all decisions about the build system"
|
||||
"Find refactoring work on the database"
|
||||
```
|
||||
|
||||
**Search Sessions:**
|
||||
```
|
||||
"What did we learn about hooks?"
|
||||
"What was accomplished in the API implementation?"
|
||||
"Show me recent work on this project"
|
||||
```
|
||||
|
||||
**Search Prompts:**
|
||||
```
|
||||
"When did I ask about authentication features?"
|
||||
"Find all my requests about dark mode"
|
||||
```
|
||||
|
||||
**Note**: Claude automatically translates your natural language queries into the appropriate search operations.
|
||||
|
||||
### Search by File
|
||||
|
||||
```
|
||||
"Show me everything related to worker-service.ts"
|
||||
"What changes were made to migrations.ts?"
|
||||
"Find all work on the database file"
|
||||
```
|
||||
|
||||
### Search by Concept
|
||||
|
||||
```
|
||||
"Show observations tagged with architecture"
|
||||
"Find all security-related observations"
|
||||
"What patterns have we used?"
|
||||
```
|
||||
|
||||
### Search by Type
|
||||
|
||||
```
|
||||
"Find all feature implementations"
|
||||
"Show me all decisions and discoveries"
|
||||
"What bugs have we fixed?"
|
||||
```
|
||||
|
||||
### Recent Context
|
||||
|
||||
```
|
||||
"Show me what we've been working on"
|
||||
"Get context from the last 5 sessions"
|
||||
"What happened recently on this project?"
|
||||
```
|
||||
|
||||
### Timeline Queries
|
||||
|
||||
**Get timeline around a specific point:**
|
||||
```
|
||||
"What was happening when we implemented authentication?"
|
||||
"Show me the context around that bug fix"
|
||||
"What led to the decision to refactor the database?"
|
||||
```
|
||||
|
||||
**Timeline by query:**
|
||||
```
|
||||
"Find when we added the viewer UI and show what happened around that time"
|
||||
"Search for authentication work and show the timeline"
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- See the complete narrative arc around key events
|
||||
- All record types (observations, sessions, prompts) in chronological view
|
||||
- Understand what was happening before and after important changes
|
||||
|
||||
## Search Strategy
|
||||
|
||||
The mem-search skill uses a progressive disclosure pattern to efficiently retrieve information:
|
||||
|
||||
### 1. Ask Naturally
|
||||
|
||||
Start with a natural language question:
|
||||
```
|
||||
"What bugs did we fix related to authentication?"
|
||||
```
|
||||
|
||||
### 2. Claude Invokes mem-search Skill
|
||||
|
||||
Claude recognizes your intent and loads the mem-search skill (~250 tokens for skill frontmatter).
|
||||
|
||||
### 3. Skill Uses HTTP API
|
||||
|
||||
The skill calls the appropriate HTTP endpoint (e.g., `/api/search/observations`) with the query.
|
||||
|
||||
### 4. Results Formatted
|
||||
|
||||
Results are formatted and presented to you, usually starting with an index/summary format.
|
||||
|
||||
### 5. Deep Dive if Needed
|
||||
|
||||
If you need more details, ask follow-up questions:
|
||||
```
|
||||
"Tell me more about observation #123"
|
||||
"Show me the full details of that decision"
|
||||
```
|
||||
|
||||
**Benefits of This Approach:**
|
||||
- **Token Efficient**: Only loads what you need, when you need it
|
||||
- **Natural**: No syntax to learn
|
||||
- **Progressive**: Start with overview, drill down as needed
|
||||
- **Automatic**: Claude handles the search invocation
|
||||
|
||||
## Advanced Filtering
|
||||
|
||||
You can refine searches using natural language filters:
|
||||
|
||||
### Date Ranges
|
||||
|
||||
```
|
||||
"What bugs did we fix in October?"
|
||||
"Show me work from last week"
|
||||
"Find decisions made between October 1-31"
|
||||
```
|
||||
|
||||
### Multiple Types
|
||||
|
||||
```
|
||||
"Show me all decisions and features"
|
||||
"Find bugfixes and refactorings"
|
||||
```
|
||||
|
||||
### Concepts
|
||||
|
||||
```
|
||||
"Find database work related to architecture and performance"
|
||||
"Show security observations"
|
||||
```
|
||||
|
||||
### File-Specific
|
||||
|
||||
```
|
||||
"Show refactoring work that touched worker-service.ts"
|
||||
"Find changes to auth files"
|
||||
```
|
||||
|
||||
### Project Filtering
|
||||
|
||||
```
|
||||
"Show authentication work on my-app project"
|
||||
"What have we done on this codebase?"
|
||||
```
|
||||
|
||||
**Note**: Claude translates your natural language into the appropriate API filters automatically.
|
||||
|
||||
## Under the Hood: HTTP API
|
||||
|
||||
The mem-search skill uses HTTP endpoints on the worker service (port 37777):
|
||||
|
||||
- `GET /api/search/observations` - Full-text search observations
|
||||
- `GET /api/search/sessions` - Full-text search session summaries
|
||||
- `GET /api/search/prompts` - Full-text search user prompts
|
||||
- `GET /api/search/by-concept` - Find observations by concept tag
|
||||
- `GET /api/search/by-file` - Find work related to specific files
|
||||
- `GET /api/search/by-type` - Find observations by type
|
||||
- `GET /api/context/recent` - Get recent session context
|
||||
- `GET /api/context/timeline` - Get timeline around specific point
|
||||
- `GET /api/timeline/by-query` - Search + timeline in one call
|
||||
- `GET /api/search/help` - API documentation
|
||||
|
||||
These endpoints use FTS5 full-text search with support for:
|
||||
- Boolean operators (AND, OR, NOT)
|
||||
- Phrase searches
|
||||
- Column-specific searches
|
||||
- Date range filtering
|
||||
- Project filtering
|
||||
|
||||
## Result Metadata
|
||||
|
||||
All results include rich metadata:
|
||||
|
||||
```
|
||||
## JWT authentication decision
|
||||
|
||||
**Type**: decision
|
||||
**Date**: 2025-10-21 14:23:45
|
||||
**Concepts**: authentication, security, architecture
|
||||
**Files Read**: src/auth/middleware.ts, src/utils/jwt.ts
|
||||
**Files Modified**: src/auth/jwt-strategy.ts
|
||||
|
||||
**Narrative**:
|
||||
Decided to implement JWT-based authentication instead of session-based
|
||||
authentication for better scalability and stateless design...
|
||||
|
||||
**Facts**:
|
||||
• JWT tokens expire after 1 hour
|
||||
• Refresh tokens stored in httpOnly cookies
|
||||
• Token signing uses RS256 algorithm
|
||||
• Public keys rotated every 30 days
|
||||
```
|
||||
|
||||
## Citations
|
||||
|
||||
All search results include observation IDs that can be accessed via the HTTP API:
|
||||
|
||||
- `http://localhost:37777/api/observation/{id}` - Get specific observation by ID
|
||||
- View all observations in the web viewer at `http://localhost:37777`
|
||||
|
||||
These citations enable referencing specific historical context in your work.
|
||||
|
||||
## Token Management
|
||||
|
||||
### Token Efficiency Tips
|
||||
|
||||
1. **Start with index format**: ~50-100 tokens per result
|
||||
2. **Use small limits**: Start with 3-5 results
|
||||
3. **Apply filters**: Narrow results before searching
|
||||
4. **Paginate**: Use offset to browse results in batches
|
||||
|
||||
### Token Estimates
|
||||
|
||||
| Format | Tokens per Result |
|
||||
|--------|-------------------|
|
||||
| Index | 50-100 |
|
||||
| Full | 500-1000 |
|
||||
|
||||
**Example**:
|
||||
- 20 results in index format: ~1,000-2,000 tokens
|
||||
- 20 results in full format: ~10,000-20,000 tokens
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### 1. Debugging Issues
|
||||
|
||||
Find what went wrong:
|
||||
```
|
||||
search_observations with query="error database connection" and type="bugfix"
|
||||
```
|
||||
|
||||
### 2. Understanding Decisions
|
||||
|
||||
Review architectural choices:
|
||||
```
|
||||
find_by_type with type="decision" and format="index"
|
||||
```
|
||||
|
||||
Then deep dive on specific decisions:
|
||||
```
|
||||
search_observations with query="[DECISION TITLE]" and format="full"
|
||||
```
|
||||
|
||||
### 3. Code Archaeology
|
||||
|
||||
Find when a file was modified:
|
||||
```
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
```
|
||||
|
||||
### 4. Feature History
|
||||
|
||||
Track feature development:
|
||||
```
|
||||
search_sessions with query="authentication feature"
|
||||
search_user_prompts with query="add authentication"
|
||||
```
|
||||
|
||||
### 5. Learning from Past Work
|
||||
|
||||
Review refactoring patterns:
|
||||
```
|
||||
find_by_type with type="refactor" and limit=10
|
||||
```
|
||||
|
||||
### 6. Context Recovery
|
||||
|
||||
Restore context after time away:
|
||||
```
|
||||
get_recent_context with limit=5
|
||||
search_sessions with query="[YOUR PROJECT NAME]" and orderBy="date_desc"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Index first, full later**: Always start with index format
|
||||
2. **Small limits**: Start with 3-5 results to avoid token limits
|
||||
3. **Use filters**: Narrow results before searching
|
||||
4. **Specific queries**: More specific = better results
|
||||
5. **Review citations**: Use citations to reference past decisions
|
||||
6. **Date filtering**: Use date ranges for time-based searches
|
||||
7. **Type filtering**: Use types to categorize searches
|
||||
8. **Concept tags**: Use concepts for thematic searches
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Results Found
|
||||
|
||||
1. Check database has data:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations;"
|
||||
```
|
||||
|
||||
2. Try broader natural language query:
|
||||
```
|
||||
"Show me anything about authentication" # Broader
|
||||
vs
|
||||
"Find exact JWT authentication implementation" # Too specific
|
||||
```
|
||||
|
||||
3. Ask without filters first:
|
||||
```
|
||||
"What do we have about auth?"
|
||||
# Then narrow down
|
||||
"Show me auth-related decisions"
|
||||
```
|
||||
|
||||
### Worker Service Not Running
|
||||
|
||||
If search isn't working, check the worker service:
|
||||
|
||||
```bash
|
||||
npm run worker:status # Check worker status
|
||||
claude-mem restart # Restart if needed
|
||||
npm run worker:logs # View logs
|
||||
```
|
||||
|
||||
Or describe the issue to Claude and the troubleshoot skill will automatically activate to provide diagnosis.
|
||||
|
||||
### Performance Issues
|
||||
|
||||
If searches seem slow:
|
||||
1. Be more specific in your queries
|
||||
2. Ask for recent work (naturally filters by date)
|
||||
3. Specify the project you're interested in
|
||||
4. Ask for fewer results initially
|
||||
|
||||
## Technical Details
|
||||
|
||||
**Architecture Change (v5.4.0)**:
|
||||
- **Before**: 9 MCP tools (~2,500 tokens in tool definitions per session start)
|
||||
- **After**: 1 mem-search skill (~250 tokens in frontmatter, full instructions loaded on-demand)
|
||||
- **Savings**: ~2,250 tokens per session start
|
||||
- **Migration**: Transparent - users don't need to change how they ask questions
|
||||
|
||||
**v5.5.0 Enhancement**: Renamed from "search" to "mem-search" with improved effectiveness (67% → 100%) and enhanced triggers (44% → 85%).
|
||||
|
||||
**How the Skill Works:**
|
||||
1. User asks a question about past work
|
||||
2. Claude recognizes the intent matches the mem-search skill description
|
||||
3. Skill loads full instructions from `plugin/skills/mem-search/SKILL.md`
|
||||
4. Skill uses `curl` to call HTTP API endpoints
|
||||
5. Results formatted and returned to Claude
|
||||
6. Claude presents results to user
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Architecture Overview](/architecture/overview) - System components
|
||||
- [Database Schema](/architecture/database) - Understanding the data
|
||||
- [Getting Started](/usage/getting-started) - Automatic operation
|
||||
@@ -1,176 +0,0 @@
|
||||
---
|
||||
title: "Getting Started"
|
||||
description: "Learn how Claude-Mem works automatically in the background"
|
||||
---
|
||||
|
||||
# Getting Started with Claude-Mem
|
||||
|
||||
## Automatic Operation
|
||||
|
||||
Claude-Mem works automatically once installed. No manual intervention required!
|
||||
|
||||
### The Full Cycle
|
||||
|
||||
1. **Start Claude Code** - Context from last 3 sessions appears automatically
|
||||
2. **Work normally** - Every tool execution is captured
|
||||
3. **Stop Claude** - Summary is generated and saved
|
||||
4. **Next session** - Previous work appears in context
|
||||
|
||||
### What Gets Captured
|
||||
|
||||
Every time Claude uses a tool, claude-mem captures it:
|
||||
|
||||
- **Read** - File reads and content access
|
||||
- **Write** - New file creation
|
||||
- **Edit** - File modifications
|
||||
- **Bash** - Command executions
|
||||
- **Glob** - File pattern searches
|
||||
- **Grep** - Content searches
|
||||
- And all other Claude Code tools
|
||||
|
||||
### What Gets Processed
|
||||
|
||||
The worker service processes tool observations and extracts:
|
||||
|
||||
- **Title** - Brief description of what happened
|
||||
- **Subtitle** - Additional context
|
||||
- **Narrative** - Detailed explanation
|
||||
- **Facts** - Key learnings as bullet points
|
||||
- **Concepts** - Relevant tags and categories
|
||||
- **Type** - Classification (decision, bugfix, feature, etc.)
|
||||
- **Files** - Which files were read or modified
|
||||
|
||||
### Session Summaries
|
||||
|
||||
When you stop Claude (or a session ends), a summary is generated with:
|
||||
|
||||
- **Request** - What you asked for
|
||||
- **Investigated** - What Claude explored
|
||||
- **Learned** - Key discoveries and insights
|
||||
- **Completed** - What was accomplished
|
||||
- **Next Steps** - What to do next
|
||||
|
||||
### Context Injection
|
||||
|
||||
When you start a new Claude Code session, the SessionStart hook:
|
||||
|
||||
1. Queries the database for recent sessions in your project
|
||||
2. Retrieves the last 10 session summaries
|
||||
3. Formats them with three-tier verbosity (most recent = most detail)
|
||||
4. Injects them into Claude's initial context
|
||||
|
||||
This means Claude "remembers" what happened in previous sessions!
|
||||
|
||||
## Manual Commands (Optional)
|
||||
|
||||
### Worker Management
|
||||
|
||||
v4.0+ auto-starts the worker on first session. Manual commands below are optional.
|
||||
|
||||
```bash
|
||||
# Start worker service (optional - auto-starts automatically)
|
||||
npm run worker:start
|
||||
|
||||
# Stop worker service
|
||||
npm run worker:stop
|
||||
|
||||
# Restart worker service
|
||||
npm run worker:restart
|
||||
|
||||
# View worker logs
|
||||
npm run worker:logs
|
||||
|
||||
# Check worker status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
npm test
|
||||
|
||||
# Test context injection
|
||||
npm run test:context
|
||||
|
||||
# Verbose context test
|
||||
npm run test:context:verbose
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Build hooks and worker
|
||||
npm run build
|
||||
|
||||
# Build only hooks
|
||||
npm run build:hooks
|
||||
|
||||
# Publish to NPM (maintainers only)
|
||||
npm run publish:npm
|
||||
```
|
||||
|
||||
## Viewing Stored Context
|
||||
|
||||
Context is stored in SQLite database at `~/.claude-mem/claude-mem.db`.
|
||||
|
||||
Query the database directly:
|
||||
|
||||
```bash
|
||||
# Open database
|
||||
sqlite3 ~/.claude-mem/claude-mem.db
|
||||
|
||||
# View recent sessions
|
||||
SELECT session_id, project, created_at, status
|
||||
FROM sdk_sessions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
|
||||
# View session summaries
|
||||
SELECT session_id, request, completed, learned
|
||||
FROM session_summaries
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 5;
|
||||
|
||||
# View observations for a session
|
||||
SELECT tool_name, created_at
|
||||
FROM observations
|
||||
WHERE session_id = 'YOUR_SESSION_ID';
|
||||
```
|
||||
|
||||
## Understanding Verbosity Levels
|
||||
|
||||
Context injection uses three-tier verbosity for efficient token usage:
|
||||
|
||||
### Tier 1 (Most Recent Session)
|
||||
- Full summary with all details
|
||||
- Request, investigated, learned, completed, next_steps, notes
|
||||
- ~500-1000 tokens
|
||||
|
||||
### Tier 2 (Sessions 2-5)
|
||||
- Medium detail
|
||||
- Request, learned, completed
|
||||
- ~200-400 tokens
|
||||
|
||||
### Tier 3 (Sessions 6-10)
|
||||
- Brief summary
|
||||
- Request and completed only
|
||||
- ~100-200 tokens
|
||||
|
||||
This ensures you get maximum detail for recent work while still having context from older sessions.
|
||||
|
||||
## Multi-Prompt Sessions
|
||||
|
||||
Claude-Mem supports sessions that span multiple user prompts:
|
||||
|
||||
- **prompt_counter**: Tracks total prompts in a session
|
||||
- **prompt_number**: Identifies specific prompt within session
|
||||
- **Session continuity**: Observations and summaries link across prompts
|
||||
|
||||
When you use `/clear`, the session doesn't end - it continues with a new prompt number. This preserves context across conversation restarts.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [MCP Search Tools](/usage/search-tools) - Learn how to search your project history
|
||||
- [Architecture Overview](/architecture/overview) - Understand how it works
|
||||
- [Troubleshooting](/troubleshooting) - Common issues and solutions
|
||||
@@ -1,426 +0,0 @@
|
||||
---
|
||||
title: "MCP Search Tools"
|
||||
description: "Query your project history with 7 specialized search tools"
|
||||
---
|
||||
|
||||
# MCP Search Tools Usage
|
||||
|
||||
Once claude-mem is installed as a plugin, 7 search tools become available in your Claude Code sessions for querying project history.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Tool | Purpose |
|
||||
|-------------------------|----------------------------------------------|
|
||||
| search_observations | Full-text search across observations |
|
||||
| search_sessions | Full-text search across session summaries |
|
||||
| search_user_prompts | Full-text search across raw user prompts |
|
||||
| find_by_concept | Find observations tagged with concepts |
|
||||
| find_by_file | Find observations referencing files |
|
||||
| find_by_type | Find observations by type |
|
||||
| get_recent_context | Get recent session context |
|
||||
|
||||
## Example Queries
|
||||
|
||||
### search_observations
|
||||
|
||||
Find all decisions about the build system:
|
||||
```
|
||||
Use search_observations to find all decisions about the build system
|
||||
```
|
||||
|
||||
Find bugs related to authentication:
|
||||
```
|
||||
search_observations with query="authentication" and type="bugfix"
|
||||
```
|
||||
|
||||
Search for refactoring work:
|
||||
```
|
||||
search_observations with query="refactor database" and type="refactor"
|
||||
```
|
||||
|
||||
### search_sessions
|
||||
|
||||
Find what we learned about hooks:
|
||||
```
|
||||
Use search_sessions to find what we learned about hooks
|
||||
```
|
||||
|
||||
Search for completed work on the API:
|
||||
```
|
||||
search_sessions with query="API implementation"
|
||||
```
|
||||
|
||||
### search_user_prompts
|
||||
|
||||
Find when user asked about authentication:
|
||||
```
|
||||
search_user_prompts with query="authentication feature"
|
||||
```
|
||||
|
||||
Trace user requests for a specific feature:
|
||||
```
|
||||
search_user_prompts with query="dark mode"
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- See exactly what the user asked for (vs what was implemented)
|
||||
- Detect patterns in repeated requests
|
||||
- Debug miscommunications between user intent and implementation
|
||||
|
||||
### find_by_file
|
||||
|
||||
Show everything related to worker-service.ts:
|
||||
```
|
||||
Use find_by_file to show me everything related to worker-service.ts
|
||||
```
|
||||
|
||||
Find all work on the database migration file:
|
||||
```
|
||||
find_by_file with filePath="migrations.ts"
|
||||
```
|
||||
|
||||
### find_by_concept
|
||||
|
||||
Show observations tagged with 'architecture':
|
||||
```
|
||||
Use find_by_concept to show observations tagged with 'architecture'
|
||||
```
|
||||
|
||||
Find all 'security' related observations:
|
||||
```
|
||||
find_by_concept with concept="security"
|
||||
```
|
||||
|
||||
### find_by_type
|
||||
|
||||
Find all feature implementations:
|
||||
```
|
||||
find_by_type with type="feature"
|
||||
```
|
||||
|
||||
Find all decisions and discoveries:
|
||||
```
|
||||
find_by_type with type=["decision", "discovery"]
|
||||
```
|
||||
|
||||
### get_recent_context
|
||||
|
||||
Get the last 5 sessions for context:
|
||||
```
|
||||
get_recent_context with limit=5
|
||||
```
|
||||
|
||||
Get recent context for debugging:
|
||||
```
|
||||
Use get_recent_context to show me what we've been working on
|
||||
```
|
||||
|
||||
## Search Strategy
|
||||
|
||||
### 1. Start with Index Format
|
||||
|
||||
**Always use index format first** to get an overview:
|
||||
|
||||
```
|
||||
search_observations with query="authentication" and format="index"
|
||||
```
|
||||
|
||||
**Why?**
|
||||
- Index format uses ~10x fewer tokens than full format
|
||||
- See titles, dates, and sources to identify relevant results
|
||||
- Avoid hitting MCP token limits
|
||||
|
||||
### 2. Review Results
|
||||
|
||||
Look at the index results to identify items of interest:
|
||||
|
||||
```
|
||||
1. [decision] Implement JWT authentication
|
||||
Date: 2025-10-21 14:23:45
|
||||
Source: claude-mem://observation/123
|
||||
|
||||
2. [feature] Add user authentication endpoints
|
||||
Date: 2025-10-21 13:15:22
|
||||
Source: claude-mem://observation/124
|
||||
|
||||
3. [bugfix] Fix authentication token expiry
|
||||
Date: 2025-10-20 16:45:30
|
||||
Source: claude-mem://observation/125
|
||||
```
|
||||
|
||||
### 3. Deep Dive with Full Format
|
||||
|
||||
Only use full format for specific items:
|
||||
|
||||
```
|
||||
search_observations with query="JWT authentication" and format="full" and limit=3
|
||||
```
|
||||
|
||||
### 4. Use Filters to Narrow Results
|
||||
|
||||
Combine filters for precise searches:
|
||||
|
||||
```
|
||||
search_observations with query="authentication" and type="decision" and dateRange={start: "2025-10-20", end: "2025-10-21"}
|
||||
```
|
||||
|
||||
## Advanced Filtering
|
||||
|
||||
### Date Ranges
|
||||
|
||||
Search within specific time periods:
|
||||
|
||||
```json
|
||||
{
|
||||
"dateRange": {
|
||||
"start": "2025-10-01",
|
||||
"end": "2025-10-31"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or use epoch timestamps:
|
||||
|
||||
```json
|
||||
{
|
||||
"dateRange": {
|
||||
"start": 1729449600,
|
||||
"end": 1732128000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Types
|
||||
|
||||
Search across multiple observation types:
|
||||
|
||||
```
|
||||
find_by_type with type=["decision", "feature", "refactor"]
|
||||
```
|
||||
|
||||
### Multiple Concepts
|
||||
|
||||
Search observations with specific concepts:
|
||||
|
||||
```
|
||||
search_observations with query="database" and concepts=["architecture", "performance"]
|
||||
```
|
||||
|
||||
### File Filtering
|
||||
|
||||
Search observations that touched specific files:
|
||||
|
||||
```
|
||||
search_observations with query="refactor" and files="worker-service.ts"
|
||||
```
|
||||
|
||||
### Project Filtering
|
||||
|
||||
Search within specific projects:
|
||||
|
||||
```
|
||||
search_observations with query="authentication" and project="my-app"
|
||||
```
|
||||
|
||||
## FTS5 Query Syntax
|
||||
|
||||
The `query` parameter supports SQLite FTS5 full-text search syntax:
|
||||
|
||||
### Simple Queries
|
||||
```
|
||||
"authentication" # Single word
|
||||
"error handling" # Multiple words (OR)
|
||||
```
|
||||
|
||||
### Boolean Operators
|
||||
```
|
||||
"error" AND "handling" # Both terms required
|
||||
"bug" OR "fix" # Either term
|
||||
"bug" NOT "feature" # First term, not second
|
||||
```
|
||||
|
||||
### Phrase Searches
|
||||
```
|
||||
"'exact phrase'" # Exact phrase match
|
||||
```
|
||||
|
||||
### Column Searches
|
||||
```
|
||||
title:"authentication" # Search specific column
|
||||
narrative:"bug fix" # Search narrative field
|
||||
```
|
||||
|
||||
## Result Metadata
|
||||
|
||||
All results include rich metadata:
|
||||
|
||||
```
|
||||
## JWT authentication decision
|
||||
|
||||
**Type**: decision
|
||||
**Date**: 2025-10-21 14:23:45
|
||||
**Concepts**: authentication, security, architecture
|
||||
**Files Read**: src/auth/middleware.ts, src/utils/jwt.ts
|
||||
**Files Modified**: src/auth/jwt-strategy.ts
|
||||
|
||||
**Narrative**:
|
||||
Decided to implement JWT-based authentication instead of session-based
|
||||
authentication for better scalability and stateless design...
|
||||
|
||||
**Facts**:
|
||||
• JWT tokens expire after 1 hour
|
||||
• Refresh tokens stored in httpOnly cookies
|
||||
• Token signing uses RS256 algorithm
|
||||
• Public keys rotated every 30 days
|
||||
```
|
||||
|
||||
## Citations
|
||||
|
||||
All search results include citations using the `claude-mem://` URI scheme:
|
||||
|
||||
- `claude-mem://observation/123` - Specific observation
|
||||
- `claude-mem://session/abc-456` - Specific session
|
||||
- `claude-mem://user-prompt/789` - Specific user prompt
|
||||
|
||||
These citations enable referencing specific historical context in your work.
|
||||
|
||||
## Token Management
|
||||
|
||||
### Token Efficiency Tips
|
||||
|
||||
1. **Start with index format**: ~50-100 tokens per result
|
||||
2. **Use small limits**: Start with 3-5 results
|
||||
3. **Apply filters**: Narrow results before searching
|
||||
4. **Paginate**: Use offset to browse results in batches
|
||||
|
||||
### Token Estimates
|
||||
|
||||
| Format | Tokens per Result |
|
||||
|--------|-------------------|
|
||||
| Index | 50-100 |
|
||||
| Full | 500-1000 |
|
||||
|
||||
**Example**:
|
||||
- 20 results in index format: ~1,000-2,000 tokens
|
||||
- 20 results in full format: ~10,000-20,000 tokens
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### 1. Debugging Issues
|
||||
|
||||
Find what went wrong:
|
||||
```
|
||||
search_observations with query="error database connection" and type="bugfix"
|
||||
```
|
||||
|
||||
### 2. Understanding Decisions
|
||||
|
||||
Review architectural choices:
|
||||
```
|
||||
find_by_type with type="decision" and format="index"
|
||||
```
|
||||
|
||||
Then deep dive on specific decisions:
|
||||
```
|
||||
search_observations with query="[DECISION TITLE]" and format="full"
|
||||
```
|
||||
|
||||
### 3. Code Archaeology
|
||||
|
||||
Find when a file was modified:
|
||||
```
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
```
|
||||
|
||||
### 4. Feature History
|
||||
|
||||
Track feature development:
|
||||
```
|
||||
search_sessions with query="authentication feature"
|
||||
search_user_prompts with query="add authentication"
|
||||
```
|
||||
|
||||
### 5. Learning from Past Work
|
||||
|
||||
Review refactoring patterns:
|
||||
```
|
||||
find_by_type with type="refactor" and limit=10
|
||||
```
|
||||
|
||||
### 6. Context Recovery
|
||||
|
||||
Restore context after time away:
|
||||
```
|
||||
get_recent_context with limit=5
|
||||
search_sessions with query="[YOUR PROJECT NAME]" and orderBy="date_desc"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Index first, full later**: Always start with index format
|
||||
2. **Small limits**: Start with 3-5 results to avoid token limits
|
||||
3. **Use filters**: Narrow results before searching
|
||||
4. **Specific queries**: More specific = better results
|
||||
5. **Review citations**: Use citations to reference past decisions
|
||||
6. **Date filtering**: Use date ranges for time-based searches
|
||||
7. **Type filtering**: Use types to categorize searches
|
||||
8. **Concept tags**: Use concepts for thematic searches
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Results Found
|
||||
|
||||
1. Check database has data:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations;"
|
||||
```
|
||||
|
||||
2. Try broader query:
|
||||
```
|
||||
search_observations with query="authentication" # Good
|
||||
vs
|
||||
search_observations with query="'exact JWT authentication implementation'" # Too specific
|
||||
```
|
||||
|
||||
3. Remove filters:
|
||||
```
|
||||
# Start broad
|
||||
search_observations with query="auth"
|
||||
|
||||
# Then add filters
|
||||
search_observations with query="auth" and type="decision"
|
||||
```
|
||||
|
||||
### Token Limit Errors
|
||||
|
||||
1. Use index format:
|
||||
```
|
||||
search_observations with query="..." and format="index"
|
||||
```
|
||||
|
||||
2. Reduce limit:
|
||||
```
|
||||
search_observations with query="..." and limit=3
|
||||
```
|
||||
|
||||
3. Use pagination:
|
||||
```
|
||||
# First page
|
||||
search_observations with query="..." and limit=5 and offset=0
|
||||
|
||||
# Second page
|
||||
search_observations with query="..." and limit=5 and offset=5
|
||||
```
|
||||
|
||||
### Search Too Slow
|
||||
|
||||
1. Use more specific queries
|
||||
2. Add date range filters
|
||||
3. Add type/concept filters
|
||||
4. Reduce result limit
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [MCP Search Architecture](/architecture/mcp-search) - Technical details
|
||||
- [Database Schema](/architecture/database) - Understanding the data
|
||||
- [Getting Started](/usage/getting-started) - Automatic operation
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* PM2 Ecosystem Configuration for claude-mem Worker Service
|
||||
*
|
||||
* Usage:
|
||||
* pm2 start ecosystem.config.cjs
|
||||
* pm2 stop claude-mem-worker
|
||||
* pm2 restart claude-mem-worker
|
||||
* pm2 logs claude-mem-worker
|
||||
* pm2 status
|
||||
*/
|
||||
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
// Determine log directory
|
||||
const logDir = path.join(os.homedir(), '.claude-mem', 'logs');
|
||||
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'claude-mem-worker',
|
||||
script: './plugin/scripts/worker-service.cjs',
|
||||
interpreter: 'node',
|
||||
instances: 1,
|
||||
exec_mode: 'fork',
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '500M',
|
||||
min_uptime: '10s',
|
||||
max_restarts: 10,
|
||||
restart_delay: 4000,
|
||||
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
CLAUDE_MEM_WORKER_PORT: 37777, // Fixed port for reliability
|
||||
FORCE_COLOR: '1'
|
||||
},
|
||||
|
||||
// Logging
|
||||
error_file: path.join(logDir, 'worker-error.log'),
|
||||
out_file: path.join(logDir, 'worker-out.log'),
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss.SSS Z',
|
||||
merge_logs: true,
|
||||
|
||||
// Keep logs from last 7 days
|
||||
log_type: 'json',
|
||||
|
||||
// Process management
|
||||
kill_timeout: 5000,
|
||||
listen_timeout: 10000,
|
||||
shutdown_with_message: true,
|
||||
|
||||
// PM2 Plus (optional monitoring)
|
||||
// instance_var: 'INSTANCE_ID',
|
||||
// pmx: true
|
||||
}]
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.4",
|
||||
"version": "7.4.3",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
@@ -25,55 +25,58 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/thedotmack/claude-mem/issues"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"node": ">=18.0.0",
|
||||
"bun": ">=1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node scripts/build-hooks.js",
|
||||
"build:hooks": "node scripts/build-hooks.js",
|
||||
"release": "node scripts/publish.js",
|
||||
"prepublishOnly": "npm run build",
|
||||
"test": "node --test tests/",
|
||||
"build-and-sync": "npm run build && npm run sync-marketplace && sleep 1 && cd ~/.claude/plugins/marketplaces/thedotmack && npm run worker:restart",
|
||||
"test": "vitest",
|
||||
"test:parser": "npx tsx src/sdk/parser.test.ts",
|
||||
"test:context": "echo '{\"session_id\":\"test-'$(date +%s)'\",\"cwd\":\"'$(pwd)'\",\"source\":\"startup\"}' | node plugin/scripts/context-hook.js 2>/dev/null",
|
||||
"test:context:verbose": "echo '{\"session_id\":\"test-'$(date +%s)'\",\"cwd\":\"'$(pwd)'\",\"source\":\"startup\"}' | node plugin/scripts/context-hook.js",
|
||||
"import:xml": "tsx src/bin/import-xml-observations.ts",
|
||||
"cleanup:duplicates": "tsx src/bin/cleanup-duplicates.ts",
|
||||
"worker:start": "pm2 start ecosystem.config.cjs",
|
||||
"worker:stop": "pm2 stop claude-mem-worker",
|
||||
"worker:restart": "pm2 restart claude-mem-worker",
|
||||
"worker:logs": "pm2 logs claude-mem-worker",
|
||||
"worker:status": "pm2 status claude-mem-worker"
|
||||
"sync-marketplace": "node scripts/sync-marketplace.cjs",
|
||||
"sync-marketplace:force": "node scripts/sync-marketplace.cjs --force",
|
||||
"build:binaries": "node scripts/build-worker-binary.js",
|
||||
"worker:start": "bun plugin/scripts/worker-cli.js start",
|
||||
"worker:stop": "bun plugin/scripts/worker-cli.js stop",
|
||||
"worker:restart": "bun plugin/scripts/worker-cli.js restart",
|
||||
"worker:status": "bun plugin/scripts/worker-cli.js status",
|
||||
"worker:logs": "tail -n 50 ~/.claude-mem/logs/worker-$(date +%Y-%m-%d).log",
|
||||
"changelog:generate": "node scripts/generate-changelog.js",
|
||||
"discord:notify": "node scripts/discord-release-notify.js",
|
||||
"usage:analyze": "node scripts/analyze-usage.js",
|
||||
"usage:today": "node scripts/analyze-usage.js $(date +%Y-%m-%d)",
|
||||
"translate-readme": "bun scripts/translate-readme/cli.ts -v -o docs/i18n README.md",
|
||||
"translate:tier1": "npm run translate-readme -- zh ja pt-br ko es de fr",
|
||||
"translate:tier2": "npm run translate-readme -- he ar ru pl cs nl tr uk",
|
||||
"translate:tier3": "npm run translate-readme -- vi id th hi bn ro sv",
|
||||
"translate:tier4": "npm run translate-readme -- it el hu fi da no",
|
||||
"translate:all": "npm run translate:tier1 && npm run translate:tier2 && npm run translate:tier3 && npm run translate:tier4",
|
||||
"bug-report": "npx tsx scripts/bug-report/cli.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.1.23",
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.1.67",
|
||||
"@modelcontextprotocol/sdk": "^1.20.1",
|
||||
"better-sqlite3": "^11.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"express": "^4.18.2",
|
||||
"glob": "^11.0.3",
|
||||
"handlebars": "^4.7.8",
|
||||
"pm2": "^5.3.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"zod-to-json-schema": "^3.24.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.8",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.0.0",
|
||||
"esbuild": "^0.20.0",
|
||||
"@types/react": "^18.3.5",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"esbuild": "^0.25.12",
|
||||
"tsx": "^4.20.6",
|
||||
"typescript": "^5.3.0"
|
||||
},
|
||||
"files": [
|
||||
"plugin",
|
||||
"src",
|
||||
"scripts",
|
||||
"docs",
|
||||
"ecosystem.config.cjs",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
]
|
||||
"typescript": "^5.3.0",
|
||||
"vitest": "^4.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "4.2.4",
|
||||
"version": "7.4.3",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"claude-mem-search": {
|
||||
"mem-search": {
|
||||
"type": "stdio",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/search-server.js"
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/mcp-server.cjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "cd \"${CLAUDE_PLUGIN_ROOT}/..\" && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 120
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/smart-install.js\" && node \"${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js\"",
|
||||
"timeout": 300
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/user-message-hook.js\"",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -17,7 +23,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js\"",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
@@ -29,7 +35,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js\"",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
@@ -40,7 +46,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js\"",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
@@ -51,7 +57,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js\"",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "claude-mem-plugin",
|
||||
"version": "7.4.2",
|
||||
"private": true,
|
||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||
"type": "module",
|
||||
"dependencies": {},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"bun": ">=1.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/bin/bash
|
||||
# claude-mem-settings.sh - User settings manager for claude-mem plugin
|
||||
|
||||
USER_SETTINGS_FILE="$HOME/.claude/settings.json"
|
||||
|
||||
# Function to check if jq is available
|
||||
check_jq() {
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Error: jq is required for JSON manipulation"
|
||||
echo "Install with: brew install jq"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to create settings file if it doesn't exist
|
||||
ensure_settings_file() {
|
||||
if [ ! -f "$USER_SETTINGS_FILE" ]; then
|
||||
mkdir -p "$(dirname "$USER_SETTINGS_FILE")"
|
||||
echo '{}' > "$USER_SETTINGS_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get current model setting
|
||||
get_model() {
|
||||
if [ -f "$USER_SETTINGS_FILE" ]; then
|
||||
jq -r '.env.CLAUDE_MEM_MODEL // "claude-sonnet-4-5"' "$USER_SETTINGS_FILE"
|
||||
else
|
||||
echo "claude-sonnet-4-5"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to set model setting
|
||||
set_model() {
|
||||
local model=$1
|
||||
|
||||
ensure_settings_file
|
||||
|
||||
# Update or create the env.CLAUDE_MEM_MODEL setting
|
||||
jq --arg model "$model" '.env.CLAUDE_MEM_MODEL = $model' "$USER_SETTINGS_FILE" > tmp.json && mv tmp.json "$USER_SETTINGS_FILE"
|
||||
echo "Set CLAUDE_MEM_MODEL to: $model"
|
||||
}
|
||||
|
||||
# Function to remove model setting
|
||||
remove_model() {
|
||||
if [ -f "$USER_SETTINGS_FILE" ]; then
|
||||
jq 'del(.env.CLAUDE_MEM_MODEL)' "$USER_SETTINGS_FILE" > tmp.json && mv tmp.json "$USER_SETTINGS_FILE"
|
||||
echo "Removed CLAUDE_MEM_MODEL (will use default: claude-sonnet-4-5)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to list available models
|
||||
list_models() {
|
||||
echo "Available models:"
|
||||
echo " claude-haiku-4-5 - Fast and efficient"
|
||||
echo " claude-sonnet-4-5 - Balanced (default)"
|
||||
echo " claude-opus-4 - Most capable"
|
||||
echo " claude-3-7-sonnet - Alternative version"
|
||||
}
|
||||
|
||||
# Interactive menu
|
||||
show_menu() {
|
||||
echo "Claude Mem Plugin - Model Configuration"
|
||||
echo "======================================"
|
||||
echo "Current model: $(get_model)"
|
||||
echo "Settings file: $USER_SETTINGS_FILE"
|
||||
echo ""
|
||||
echo "1) Set model"
|
||||
echo "2) Remove model setting (use default)"
|
||||
echo "3) List available models"
|
||||
echo "4) Exit"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main interactive loop
|
||||
main() {
|
||||
check_jq
|
||||
|
||||
while true; do
|
||||
show_menu
|
||||
read -p "Choose an option (1-4): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
list_models
|
||||
echo ""
|
||||
read -p "Enter model name: " model
|
||||
set_model "$model"
|
||||
;;
|
||||
2)
|
||||
remove_model
|
||||
;;
|
||||
3)
|
||||
list_models
|
||||
;;
|
||||
4)
|
||||
echo "Goodbye!"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please choose 1-4."
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
done
|
||||
}
|
||||
|
||||
# Run main if script is executed directly
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
@@ -0,0 +1,451 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Smart Install Script for claude-mem
|
||||
*
|
||||
* Ensures Bun runtime and uv (Python package manager) are installed
|
||||
* (auto-installs if missing) and handles dependency installation when needed.
|
||||
*/
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { execSync, spawnSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
import { homedir } from 'os';
|
||||
|
||||
const ROOT = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack');
|
||||
const MARKER = join(ROOT, '.install-version');
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
|
||||
/**
|
||||
* Check if Bun is installed and accessible
|
||||
*/
|
||||
function isBunInstalled() {
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
return bunPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Bun executable path (from PATH or common install locations)
|
||||
*/
|
||||
function getBunPath() {
|
||||
// Try PATH first
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
if (result.status === 0) return 'bun';
|
||||
} catch {
|
||||
// Not in PATH
|
||||
}
|
||||
|
||||
// Check common installation paths
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
for (const bunPath of bunPaths) {
|
||||
if (existsSync(bunPath)) return bunPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bun version if installed
|
||||
*/
|
||||
function getBunVersion() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) return null;
|
||||
|
||||
try {
|
||||
const result = spawnSync(bunPath, ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0 ? result.stdout.trim() : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if uv is installed and accessible
|
||||
*/
|
||||
function isUvInstalled() {
|
||||
try {
|
||||
const result = spawnSync('uv', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const uvPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')]
|
||||
: [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv'];
|
||||
|
||||
return uvPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uv version if installed
|
||||
*/
|
||||
function getUvVersion() {
|
||||
try {
|
||||
const result = spawnSync('uv', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0 ? result.stdout.trim() : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Bun automatically based on platform
|
||||
*/
|
||||
function installBun() {
|
||||
console.error('🔧 Bun not found. Installing Bun runtime...');
|
||||
|
||||
try {
|
||||
if (IS_WINDOWS) {
|
||||
// Windows: Use PowerShell installer
|
||||
console.error(' Installing via PowerShell...');
|
||||
execSync('powershell -c "irm bun.sh/install.ps1 | iex"', {
|
||||
stdio: 'inherit',
|
||||
shell: true
|
||||
});
|
||||
} else {
|
||||
// Unix/macOS: Use curl installer
|
||||
console.error(' Installing via curl...');
|
||||
execSync('curl -fsSL https://bun.sh/install | bash', {
|
||||
stdio: 'inherit',
|
||||
shell: true
|
||||
});
|
||||
}
|
||||
|
||||
// Verify installation
|
||||
if (isBunInstalled()) {
|
||||
const version = getBunVersion();
|
||||
console.error(`✅ Bun ${version} installed successfully`);
|
||||
return true;
|
||||
} else {
|
||||
// Bun may be installed but not in PATH yet for this session
|
||||
// Try common installation paths
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
for (const bunPath of bunPaths) {
|
||||
if (existsSync(bunPath)) {
|
||||
console.error(`✅ Bun installed at ${bunPath}`);
|
||||
console.error('⚠️ Please restart your terminal or add Bun to PATH:');
|
||||
if (IS_WINDOWS) {
|
||||
console.error(` $env:Path += ";${join(homedir(), '.bun', 'bin')}"`);
|
||||
} else {
|
||||
console.error(` export PATH="$HOME/.bun/bin:$PATH"`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Bun installation completed but binary not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to install Bun automatically');
|
||||
console.error(' Please install manually:');
|
||||
if (IS_WINDOWS) {
|
||||
console.error(' - winget install Oven-sh.Bun');
|
||||
console.error(' - Or: powershell -c "irm bun.sh/install.ps1 | iex"');
|
||||
} else {
|
||||
console.error(' - curl -fsSL https://bun.sh/install | bash');
|
||||
console.error(' - Or: brew install oven-sh/bun/bun');
|
||||
}
|
||||
console.error(' Then restart your terminal and try again.');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install uv automatically based on platform
|
||||
*/
|
||||
function installUv() {
|
||||
console.error('🐍 Installing uv for Python/Chroma support...');
|
||||
|
||||
try {
|
||||
if (IS_WINDOWS) {
|
||||
// Windows: Use PowerShell installer
|
||||
console.error(' Installing via PowerShell...');
|
||||
execSync('powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"', {
|
||||
stdio: 'inherit',
|
||||
shell: true
|
||||
});
|
||||
} else {
|
||||
// Unix/macOS: Use curl installer
|
||||
console.error(' Installing via curl...');
|
||||
execSync('curl -LsSf https://astral.sh/uv/install.sh | sh', {
|
||||
stdio: 'inherit',
|
||||
shell: true
|
||||
});
|
||||
}
|
||||
|
||||
// Verify installation
|
||||
if (isUvInstalled()) {
|
||||
const version = getUvVersion();
|
||||
console.error(`✅ uv ${version} installed successfully`);
|
||||
return true;
|
||||
} else {
|
||||
// uv may be installed but not in PATH yet for this session
|
||||
// Try common installation paths
|
||||
const uvPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')]
|
||||
: [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv'];
|
||||
|
||||
for (const uvPath of uvPaths) {
|
||||
if (existsSync(uvPath)) {
|
||||
console.error(`✅ uv installed at ${uvPath}`);
|
||||
console.error('⚠️ Please restart your terminal or add uv to PATH:');
|
||||
if (IS_WINDOWS) {
|
||||
console.error(` $env:Path += ";${join(homedir(), '.local', 'bin')}"`);
|
||||
} else {
|
||||
console.error(` export PATH="$HOME/.local/bin:$PATH"`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('uv installation completed but binary not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to install uv automatically');
|
||||
console.error(' Please install manually:');
|
||||
if (IS_WINDOWS) {
|
||||
console.error(' - winget install astral-sh.uv');
|
||||
console.error(' - Or: powershell -c "irm https://astral.sh/uv/install.ps1 | iex"');
|
||||
} else {
|
||||
console.error(' - curl -LsSf https://astral.sh/uv/install.sh | sh');
|
||||
console.error(' - Or: brew install uv (macOS)');
|
||||
}
|
||||
console.error(' Then restart your terminal and try again.');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the claude-mem CLI command to PATH
|
||||
* Creates a wrapper script in ~/.local/bin (Unix) or %LOCALAPPDATA%\Programs\claude-mem (Windows)
|
||||
*/
|
||||
function installCLI() {
|
||||
const CLI_NAME = 'claude-mem';
|
||||
const WORKER_CLI = join(ROOT, 'plugin', 'scripts', 'worker-cli.js');
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
// Windows: Create .cmd file in LocalAppData
|
||||
const cliDir = join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'Programs', 'claude-mem');
|
||||
const cliPath = join(cliDir, `${CLI_NAME}.cmd`);
|
||||
const markerPath = join(cliDir, '.cli-installed');
|
||||
|
||||
// Skip if already installed
|
||||
if (existsSync(markerPath)) return;
|
||||
|
||||
try {
|
||||
// Create directory if needed
|
||||
if (!existsSync(cliDir)) {
|
||||
execSync(`mkdir "${cliDir}"`, { stdio: 'ignore', shell: true });
|
||||
}
|
||||
|
||||
// Get Bun path for the wrapper
|
||||
const bunPath = getBunPath() || 'bun';
|
||||
|
||||
// Create the wrapper script
|
||||
const cmdContent = `@echo off
|
||||
"${bunPath}" "${WORKER_CLI}" %*
|
||||
`;
|
||||
writeFileSync(cliPath, cmdContent);
|
||||
writeFileSync(markerPath, new Date().toISOString());
|
||||
|
||||
console.error(`✅ CLI installed: ${cliPath}`);
|
||||
console.error('');
|
||||
console.error('📋 Add to PATH (run once in PowerShell as Admin):');
|
||||
console.error(` [Environment]::SetEnvironmentVariable("Path", $env:Path + ";${cliDir}", "User")`);
|
||||
console.error('');
|
||||
console.error(' Then restart your terminal and use: claude-mem start|stop|restart|status');
|
||||
} catch (error) {
|
||||
console.error(`⚠️ Could not install CLI: ${error.message}`);
|
||||
console.error(` You can still use: bun "${WORKER_CLI}" <command>`);
|
||||
}
|
||||
} else {
|
||||
// Unix: Create shell script in ~/.local/bin
|
||||
const cliDir = join(homedir(), '.local', 'bin');
|
||||
const cliPath = join(cliDir, CLI_NAME);
|
||||
const markerPath = join(ROOT, '.cli-installed');
|
||||
|
||||
// Skip if already installed
|
||||
if (existsSync(markerPath) && existsSync(cliPath)) return;
|
||||
|
||||
try {
|
||||
// Create directory if needed
|
||||
if (!existsSync(cliDir)) {
|
||||
execSync(`mkdir -p "${cliDir}"`, { stdio: 'ignore', shell: true });
|
||||
}
|
||||
|
||||
// Get Bun path for the wrapper
|
||||
const bunPath = getBunPath() || 'bun';
|
||||
|
||||
// Create the wrapper script
|
||||
const shContent = `#!/usr/bin/env bash
|
||||
# claude-mem CLI wrapper - manages the worker service
|
||||
exec "${bunPath}" "${WORKER_CLI}" "$@"
|
||||
`;
|
||||
writeFileSync(cliPath, shContent, { mode: 0o755 });
|
||||
writeFileSync(markerPath, new Date().toISOString());
|
||||
|
||||
console.error(`✅ CLI installed: ${cliPath}`);
|
||||
|
||||
// Check if ~/.local/bin is in PATH
|
||||
const pathDirs = (process.env.PATH || '').split(':');
|
||||
const localBinInPath = pathDirs.some(p => p === cliDir || p === '$HOME/.local/bin' || p.endsWith('/.local/bin'));
|
||||
|
||||
if (!localBinInPath) {
|
||||
console.error('');
|
||||
console.error('📋 Add to PATH (add to ~/.bashrc or ~/.zshrc):');
|
||||
console.error(' export PATH="$HOME/.local/bin:$PATH"');
|
||||
console.error('');
|
||||
console.error(' Then restart your terminal and use: claude-mem start|stop|restart|status');
|
||||
} else {
|
||||
console.error(' Usage: claude-mem start|stop|restart|status');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`⚠️ Could not install CLI: ${error.message}`);
|
||||
console.error(` You can still use: bun "${WORKER_CLI}" <command>`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if dependencies need to be installed
|
||||
*/
|
||||
function needsInstall() {
|
||||
if (!existsSync(join(ROOT, 'node_modules'))) return true;
|
||||
try {
|
||||
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
||||
const marker = JSON.parse(readFileSync(MARKER, 'utf-8'));
|
||||
return pkg.version !== marker.version || getBunVersion() !== marker.bun;
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install dependencies using Bun with npm fallback
|
||||
*
|
||||
* Bun has issues with npm alias packages (e.g., string-width-cjs, strip-ansi-cjs)
|
||||
* that are defined in package-lock.json. When bun fails with 404 errors for these
|
||||
* packages, we fall back to npm which handles aliases correctly.
|
||||
*/
|
||||
function installDeps() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) {
|
||||
throw new Error('Bun executable not found');
|
||||
}
|
||||
|
||||
console.error('📦 Installing dependencies with Bun...');
|
||||
|
||||
// Quote path for Windows paths with spaces
|
||||
const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath;
|
||||
|
||||
let bunSucceeded = false;
|
||||
try {
|
||||
execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
bunSucceeded = true;
|
||||
} catch {
|
||||
// First attempt failed, try with force flag
|
||||
try {
|
||||
execSync(`${bunCmd} install --force`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
bunSucceeded = true;
|
||||
} catch {
|
||||
// Bun failed completely, will try npm fallback
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to npm if bun failed (handles npm alias packages correctly)
|
||||
if (!bunSucceeded) {
|
||||
console.error('⚠️ Bun install failed, falling back to npm...');
|
||||
console.error(' (This can happen with npm alias packages like *-cjs)');
|
||||
try {
|
||||
execSync('npm install', { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
} catch (npmError) {
|
||||
throw new Error('Both bun and npm install failed: ' + npmError.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Write version marker
|
||||
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
||||
writeFileSync(MARKER, JSON.stringify({
|
||||
version: pkg.version,
|
||||
bun: getBunVersion(),
|
||||
uv: getUvVersion(),
|
||||
installedAt: new Date().toISOString()
|
||||
}));
|
||||
}
|
||||
|
||||
// Main execution
|
||||
try {
|
||||
// Step 1: Ensure Bun is installed (REQUIRED)
|
||||
if (!isBunInstalled()) {
|
||||
installBun();
|
||||
|
||||
// Re-check after installation
|
||||
if (!isBunInstalled()) {
|
||||
console.error('❌ Bun is required but not available in PATH');
|
||||
console.error(' Please restart your terminal after installation');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Ensure uv is installed (REQUIRED for vector search)
|
||||
if (!isUvInstalled()) {
|
||||
installUv();
|
||||
|
||||
// Re-check after installation
|
||||
if (!isUvInstalled()) {
|
||||
console.error('❌ uv is required but not available in PATH');
|
||||
console.error(' Please restart your terminal after installation');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Install dependencies if needed
|
||||
if (needsInstall()) {
|
||||
installDeps();
|
||||
console.error('✅ Dependencies installed');
|
||||
}
|
||||
|
||||
// Step 4: Install CLI to PATH
|
||||
installCLI();
|
||||
} catch (e) {
|
||||
console.error('❌ Installation failed:', e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bun
|
||||
"use strict";var m=Object.create;var w=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var g=(e,i,n,o)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of I(i))!x.call(e,s)&&s!==n&&w(e,s,{get:()=>i[s],enumerable:!(o=u(i,s))||o.enumerable});return e};var k=(e,i,n)=>(n=e!=null?m(f(e)):{},g(i||!e||!e.__esModule?w(n,"default",{value:e,enumerable:!0}):n,e));var c=require("child_process"),p=k(require("path"),1),y=process.platform==="win32",P=__dirname,l=p.default.join(P,"worker-service.cjs"),t=null,a=!1;function r(e){let i=new Date().toISOString();console.log(`[${i}] [wrapper] ${e}`)}function h(){r(`Spawning inner worker: ${l}`),t=(0,c.spawn)(process.execPath,[l],{stdio:["inherit","inherit","inherit","ipc"],env:{...process.env,CLAUDE_MEM_MANAGED:"true"},cwd:p.default.dirname(l)}),t.on("message",async e=>{(e.type==="restart"||e.type==="shutdown")&&(r(`${e.type} requested by inner`),a=!0,await d(),r("Exiting wrapper"),process.exit(0))}),t.on("exit",(e,i)=>{r(`Inner exited with code=${e}, signal=${i}`),t=null,a||(r("Inner exited unexpectedly, wrapper exiting (hooks will restart if needed)"),process.exit(e??1))}),t.on("error",e=>{r(`Inner error: ${e.message}`)})}async function d(){if(!t||!t.pid){r("No inner process to kill");return}let e=t.pid;if(r(`Killing inner process tree (pid=${e})`),y)try{(0,c.execSync)(`taskkill /PID ${e} /T /F`,{timeout:1e4,stdio:"ignore"}),r(`taskkill completed for pid=${e}`)}catch(i){r(`taskkill failed (process may be dead): ${i}`)}else{t.kill("SIGTERM");let i=new Promise(o=>{if(!t){o();return}t.on("exit",()=>o())}),n=new Promise(o=>setTimeout(()=>o(),5e3));await Promise.race([i,n]),t&&!t.killed&&(r("Inner did not exit gracefully, force killing"),t.kill("SIGKILL"))}await S(e,5e3),t=null,r("Inner process terminated")}async function S(e,i){let n=Date.now();for(;Date.now()-n<i;)try{process.kill(e,0),await new Promise(o=>setTimeout(o,100))}catch{return}r(`Timeout waiting for process ${e} to exit`)}process.on("SIGTERM",async()=>{r("Wrapper received SIGTERM"),a=!0,await d(),process.exit(0)});process.on("SIGINT",async()=>{r("Wrapper received SIGINT"),a=!0,await d(),process.exit(0)});r("Wrapper starting");h();
|
||||
@@ -0,0 +1,329 @@
|
||||
---
|
||||
name: mem-search
|
||||
description: Search claude-mem's persistent cross-session memory database. Use when user asks "did we already solve this?", "how did we do X last time?", or needs work from previous sessions.
|
||||
---
|
||||
|
||||
# Memory Search
|
||||
|
||||
Search past work across all sessions. Simple workflow: search → get IDs → fetch details by ID.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use when users ask about PREVIOUS sessions (not current conversation):
|
||||
|
||||
- "Did we already fix this?"
|
||||
- "How did we solve X last time?"
|
||||
- "What happened last week?"
|
||||
|
||||
## The Workflow
|
||||
|
||||
**ALWAYS follow this exact flow:**
|
||||
|
||||
1. **Search** - Get an index of results with IDs
|
||||
2. **Timeline** - Get context around top results to understand what was happening
|
||||
3. **Review** - Look at titles/dates/context, pick relevant IDs
|
||||
4. **Fetch** - Get full details ONLY for those IDs
|
||||
|
||||
### Step 1: Search Everything
|
||||
|
||||
Use the `search` MCP tool:
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- `query` - Search term
|
||||
- `limit: 20` - You can request large indexes as necessary
|
||||
- `project` - Project name (required)
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
search(query="authentication", limit=20, project="my-project")
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
|
||||
```
|
||||
| ID | Time | T | Title | Read | Work |
|
||||
|----|------|---|-------|------|------|
|
||||
| #11131 | 3:48 PM | 🟣 | Added JWT authentication | ~75 | 🛠️ 450 |
|
||||
| #10942 | 2:15 PM | 🔴 | Fixed auth token expiration | ~50 | 🛠️ 200 |
|
||||
```
|
||||
|
||||
### Step 2: Get Timeline Context
|
||||
|
||||
You MUST understand "what was happening" around a result.
|
||||
|
||||
Use the `timeline` MCP tool:
|
||||
|
||||
**Example with observation ID:**
|
||||
|
||||
```
|
||||
timeline(anchor=11131, depth_before=3, depth_after=3, project="my-project")
|
||||
```
|
||||
|
||||
**Example with query (finds anchor automatically):**
|
||||
|
||||
```
|
||||
timeline(query="authentication", depth_before=3, depth_after=3, project="my-project")
|
||||
```
|
||||
|
||||
**Returns exactly `depth_before + 1 + depth_after` items** - observations, sessions, and prompts interleaved chronologically around the anchor.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- User asks "what was happening when..."
|
||||
- Need to understand sequence of events
|
||||
- Want broader context around a specific observation
|
||||
|
||||
### Step 3: Pick IDs
|
||||
|
||||
Review the index results (and timeline if used). Identify which IDs are actually relevant. Discard the rest.
|
||||
|
||||
### Step 4: Fetch by ID
|
||||
|
||||
For each relevant ID, fetch full details using MCP tools:
|
||||
|
||||
**Fetch multiple observations (ALWAYS use for 2+ IDs):**
|
||||
|
||||
```
|
||||
get_observations(ids=[11131, 10942, 10855])
|
||||
```
|
||||
|
||||
**With ordering and limit:**
|
||||
|
||||
```
|
||||
get_observations(
|
||||
ids=[11131, 10942, 10855],
|
||||
orderBy="date_desc",
|
||||
limit=10,
|
||||
project="my-project"
|
||||
)
|
||||
```
|
||||
|
||||
**Fetch single observation (only when fetching exactly 1):**
|
||||
|
||||
```
|
||||
get_observation(id=11131)
|
||||
```
|
||||
|
||||
**Fetch session:**
|
||||
|
||||
```
|
||||
get_session(id=2005) # Just the number from S2005
|
||||
```
|
||||
|
||||
**Fetch prompt:**
|
||||
|
||||
```
|
||||
get_prompt(id=5421)
|
||||
```
|
||||
|
||||
**ID formats:**
|
||||
|
||||
- Observations: Just the number (11131)
|
||||
- Sessions: Just the number (2005) from "S2005"
|
||||
- Prompts: Just the number (5421)
|
||||
|
||||
**Batch optimization:**
|
||||
|
||||
- **ALWAYS use `get_observations` for 2+ observations**
|
||||
- 10-100x more efficient than individual fetches
|
||||
- Single HTTP request vs N requests
|
||||
- Returns all results in one response
|
||||
- Supports ordering and filtering
|
||||
|
||||
## Search Parameters
|
||||
|
||||
**Basic:**
|
||||
|
||||
- `query` - What to search for (required)
|
||||
- `limit` - How many results (default 20)
|
||||
- `project` - Filter by project name (required)
|
||||
|
||||
**Filters (optional):**
|
||||
|
||||
- `type` - Filter to "observations", "sessions", or "prompts"
|
||||
- `dateStart` - Start date (YYYY-MM-DD or epoch timestamp)
|
||||
- `dateEnd` - End date (YYYY-MM-DD or epoch timestamp)
|
||||
- `obs_type` - Filter observations by type (comma-separated): bugfix, feature, decision, discovery, change
|
||||
|
||||
## Examples
|
||||
|
||||
**Find recent bug fixes:**
|
||||
|
||||
Use the `search` MCP tool with filters:
|
||||
|
||||
```
|
||||
search(query="bug", type="observations", obs_type="bugfix", limit=20, project="my-project")
|
||||
```
|
||||
|
||||
**Find what happened last week:**
|
||||
|
||||
Use date filters:
|
||||
|
||||
```
|
||||
search(type="observations", dateStart="2025-11-11", limit=20, project="my-project")
|
||||
```
|
||||
|
||||
**Search everything:**
|
||||
|
||||
Simple query search:
|
||||
|
||||
```
|
||||
search(query="database migration", limit=20, project="my-project")
|
||||
```
|
||||
|
||||
**Get detailed instructions:**
|
||||
|
||||
Use the `help` tool to load full instructions on-demand:
|
||||
|
||||
```
|
||||
help(topic="workflow") # Get 4-step workflow
|
||||
help(topic="search_params") # Get parameters reference
|
||||
help(topic="examples") # Get usage examples
|
||||
help(topic="all") # Get complete guide
|
||||
```
|
||||
|
||||
## Why This Workflow?
|
||||
|
||||
**Token efficiency:**
|
||||
|
||||
- **Search results:** ~50-100 tokens per result (table index)
|
||||
- **Full observation:** ~500-1000 tokens each
|
||||
- **10x savings** - only fetch full when you know it's relevant
|
||||
|
||||
**Batch fetching:**
|
||||
|
||||
- **Individual fetches:** 10 HTTP requests, ~5-10s latency
|
||||
- **Batch fetch:** 1 HTTP request, ~0.5-1s latency
|
||||
- **10-100x faster** for multi-observation queries
|
||||
|
||||
**Clarity:**
|
||||
|
||||
- See everything first (table index)
|
||||
- Get timeline context around interesting results
|
||||
- Pick what matters based on context
|
||||
- Fetch details only for what you need (batch when possible)
|
||||
|
||||
---
|
||||
|
||||
**Remember:**
|
||||
|
||||
- ALWAYS get timeline context to understand what was happening
|
||||
- ALWAYS use `get_observations` when fetching 2+ observations
|
||||
- The workflow is optimized: search → timeline → batch fetch = 10-100x faster
|
||||
|
||||
---
|
||||
|
||||
## Tool Reference
|
||||
|
||||
Comprehensive parameter documentation for all memory tools. For MCP usage, call `help(topic="search")` to load specific tool docs.
|
||||
|
||||
### search
|
||||
|
||||
Search across all memory types (observations, sessions, prompts).
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `query` (string, optional) - Search term for full-text search
|
||||
- `limit` (number, optional) - Maximum results to return. Default: 20, Max: 100
|
||||
- `offset` (number, optional) - Number of results to skip. Default: 0
|
||||
- `project` (string, required) - Project name to filter by
|
||||
- `type` (string, optional) - Filter by type: "observations", "sessions", "prompts"
|
||||
- `dateStart` (string, optional) - Start date filter (YYYY-MM-DD or epoch ms)
|
||||
- `dateEnd` (string, optional) - End date filter (YYYY-MM-DD or epoch ms)
|
||||
- `obs_type` (string, optional) - Filter observations by type (comma-separated): bugfix, feature, decision, discovery, change
|
||||
- `orderBy` (string, optional) - Sort order: "date_desc" (default), "date_asc", "relevance"
|
||||
|
||||
**Returns:** Table of results with IDs, timestamps, types, titles
|
||||
|
||||
### timeline
|
||||
|
||||
Get chronological context around a specific point in time or observation.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `anchor` (number, optional) - Observation ID to center timeline around. If not provided, uses most recent result from query
|
||||
- `query` (string, optional) - Search term to find anchor automatically (if anchor not provided)
|
||||
- `depth_before` (number, optional) - Items before anchor. Default: 5, Max: 20
|
||||
- `depth_after` (number, optional) - Items after anchor. Default: 5, Max: 20
|
||||
- `project` (string, required) - Project name to filter by
|
||||
|
||||
**Returns:** Exactly `depth_before + 1 + depth_after` items in chronological order, with observations, sessions, and prompts interleaved
|
||||
|
||||
### get_recent_context
|
||||
|
||||
Get the most recent observations from current or recent sessions.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `limit` (number, optional) - Maximum observations to return. Default: 10, Max: 50
|
||||
- `project` (string, required) - Project name to filter by
|
||||
|
||||
**Returns:** Recent observations in reverse chronological order
|
||||
|
||||
### get_context_timeline
|
||||
|
||||
Get timeline context around a specific observation ID.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `anchor` (number, required) - Observation ID to center timeline around
|
||||
- `depth_before` (number, optional) - Items before anchor. Default: 5, Max: 20
|
||||
- `depth_after` (number, optional) - Items after anchor. Default: 5, Max: 20
|
||||
- `project` (string, optional) - Project name to filter by
|
||||
|
||||
**Returns:** Timeline items centered on the anchor observation
|
||||
|
||||
### get_observation
|
||||
|
||||
Fetch a single observation by ID with full details.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `id` (number, required) - Observation ID to fetch
|
||||
|
||||
**Returns:** Complete observation object with title, subtitle, narrative, facts, concepts, files, timestamps
|
||||
|
||||
### get_observations
|
||||
|
||||
Batch fetch multiple observations by IDs. Always prefer this over individual fetches for 2+ observations.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `ids` (array of numbers, required) - Array of observation IDs to fetch
|
||||
- `orderBy` (string, optional) - Sort order: "date_desc" (default), "date_asc"
|
||||
- `limit` (number, optional) - Maximum observations to return. Default: no limit
|
||||
- `project` (string, optional) - Project name to filter by
|
||||
|
||||
**Returns:** Array of complete observation objects, 10-100x faster than individual fetches
|
||||
|
||||
### get_session
|
||||
|
||||
Fetch a single session by ID with metadata.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `id` (number, required) - Session ID to fetch (just the number, not "S2005" format)
|
||||
|
||||
**Returns:** Session object with ID, start time, end time, project, model info
|
||||
|
||||
### get_prompt
|
||||
|
||||
Fetch a single prompt by ID with full text.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `id` (number, required) - Prompt ID to fetch
|
||||
|
||||
**Returns:** Prompt object with ID, text, timestamp, session reference
|
||||
|
||||
### help
|
||||
|
||||
Load detailed instructions for specific topics or all documentation.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `topic` (string, optional) - Specific topic to load: "workflow", "search", "timeline", "get_recent_context", "get_context_timeline", "get_observation", "get_observations", "get_session", "get_prompt", "all". Default: "all"
|
||||
|
||||
**Returns:** Formatted documentation for the requested topic
|
||||
@@ -0,0 +1,124 @@
|
||||
# Search by Concept
|
||||
|
||||
Find observations tagged with specific concepts.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "What discoveries did we make?"
|
||||
- User asks: "What patterns did we identify?"
|
||||
- User asks: "What gotchas did we encounter?"
|
||||
- Looking for observations with semantic tags
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-concept?concept=discovery&format=index&limit=5"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **concept** (required): Concept tag to search for
|
||||
- `discovery` - New discoveries and insights
|
||||
- `problem-solution` - Problems and their solutions
|
||||
- `what-changed` - Change descriptions
|
||||
- `how-it-works` - Explanations of mechanisms
|
||||
- `pattern` - Identified patterns
|
||||
- `gotcha` - Edge cases and gotchas
|
||||
- `change` - General changes
|
||||
- **format**: "index" (summary) or "full" (complete details). Default: "full"
|
||||
- **limit**: Number of results (default: 20, max: 100)
|
||||
- **project**: Filter by project name (optional)
|
||||
- **dateStart/dateEnd**: Filter by date range (optional)
|
||||
|
||||
## When to Use Each Format
|
||||
|
||||
**Use format=index for:**
|
||||
- Quick overviews of observations by concept
|
||||
- Finding IDs for deeper investigation
|
||||
- Listing multiple results
|
||||
- **Token cost: ~50-100 per result**
|
||||
|
||||
**Use format=full for:**
|
||||
- Complete details including narrative, facts, files, concepts
|
||||
- Understanding the full context of specific observations
|
||||
- **Token cost: ~500-1000 per result**
|
||||
|
||||
## Example Response (format=index)
|
||||
|
||||
```json
|
||||
{
|
||||
"concept": "discovery",
|
||||
"count": 3,
|
||||
"format": "index",
|
||||
"results": [
|
||||
{
|
||||
"id": 1240,
|
||||
"type": "discovery",
|
||||
"title": "Worker service uses PM2 for process management",
|
||||
"subtitle": "Discovered persistent background worker pattern",
|
||||
"created_at_epoch": 1699564800000,
|
||||
"project": "claude-mem",
|
||||
"concepts": ["discovery", "how-it-works"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
For format=index, present as a compact list:
|
||||
|
||||
```markdown
|
||||
Found 3 observations tagged with "discovery":
|
||||
|
||||
🔵 **#1240** Worker service uses PM2 for process management
|
||||
> Discovered persistent background worker pattern
|
||||
> Nov 9, 2024 • claude-mem
|
||||
> Tags: discovery, how-it-works
|
||||
|
||||
🔵 **#1241** FTS5 full-text search enables instant searches
|
||||
> SQLite FTS5 virtual tables provide sub-100ms search
|
||||
> Nov 9, 2024 • claude-mem
|
||||
> Tags: discovery, pattern
|
||||
```
|
||||
|
||||
For complete formatting guidelines, see [formatting.md](formatting.md).
|
||||
|
||||
## Available Concepts
|
||||
|
||||
| Concept | Description | When to Use |
|
||||
|---------|-------------|-------------|
|
||||
| `discovery` | New discoveries and insights | Finding what was learned |
|
||||
| `problem-solution` | Problems and their solutions | Finding how issues were resolved |
|
||||
| `what-changed` | Change descriptions | Understanding what changed |
|
||||
| `how-it-works` | Explanations of mechanisms | Learning how things work |
|
||||
| `pattern` | Identified patterns | Finding design patterns |
|
||||
| `gotcha` | Edge cases and gotchas | Learning about pitfalls |
|
||||
| `change` | General changes | Tracking modifications |
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Missing concept parameter:**
|
||||
```json
|
||||
{"error": "Missing required parameter: concept"}
|
||||
```
|
||||
Fix: Add the concept parameter
|
||||
|
||||
**Invalid concept:**
|
||||
```json
|
||||
{"error": "Invalid concept: foobar. Valid concepts: discovery, problem-solution, what-changed, how-it-works, pattern, gotcha, change"}
|
||||
```
|
||||
Fix: Use one of the valid concept values
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use format=index first to see overview
|
||||
2. Start with limit=5-10 to avoid token overload
|
||||
3. Combine concepts with type filtering for precision
|
||||
4. Use `discovery` for learning what was found during investigation
|
||||
5. Use `problem-solution` for finding how past issues were resolved
|
||||
|
||||
**Token Efficiency:**
|
||||
- Start with format=index (~50-100 tokens per result)
|
||||
- Use format=full only for relevant items (~500-1000 tokens per result)
|
||||
- See [../principles/progressive-disclosure.md](../principles/progressive-disclosure.md)
|
||||
@@ -0,0 +1,127 @@
|
||||
# Search by File
|
||||
|
||||
Find all work related to a specific file path.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "What changes to auth/login.ts?"
|
||||
- User asks: "What work was done on this file?"
|
||||
- User asks: "Show me the history of src/services/worker.ts"
|
||||
- Looking for all observations that reference a file
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=src/services/worker-service.ts&format=index&limit=10"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **filePath** (required): File path to search for (supports partial matching)
|
||||
- Full path: `src/services/worker-service.ts`
|
||||
- Partial path: `worker-service.ts`
|
||||
- Directory: `src/hooks/`
|
||||
- **format**: "index" (summary) or "full" (complete details). Default: "full"
|
||||
- **limit**: Number of results (default: 20, max: 100)
|
||||
- **project**: Filter by project name (optional)
|
||||
- **dateStart/dateEnd**: Filter by date range (optional)
|
||||
|
||||
## When to Use Each Format
|
||||
|
||||
**Use format=index for:**
|
||||
- Quick overviews of work on a file
|
||||
- Finding IDs for deeper investigation
|
||||
- Listing multiple changes
|
||||
- **Token cost: ~50-100 per result**
|
||||
|
||||
**Use format=full for:**
|
||||
- Complete details including narrative, facts, files, concepts
|
||||
- Understanding the full context of specific changes
|
||||
- **Token cost: ~500-1000 per result**
|
||||
|
||||
## Example Response (format=index)
|
||||
|
||||
```json
|
||||
{
|
||||
"filePath": "src/services/worker-service.ts",
|
||||
"count": 8,
|
||||
"format": "index",
|
||||
"results": [
|
||||
{
|
||||
"id": 1245,
|
||||
"type": "refactor",
|
||||
"title": "Simplified worker health check logic",
|
||||
"subtitle": "Removed redundant PM2 status check",
|
||||
"created_at_epoch": 1699564800000,
|
||||
"project": "claude-mem",
|
||||
"files": ["src/services/worker-service.ts", "src/services/worker-utils.ts"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
For format=index, present as a compact list:
|
||||
|
||||
```markdown
|
||||
Found 8 observations related to "src/services/worker-service.ts":
|
||||
|
||||
🔄 **#1245** Simplified worker health check logic
|
||||
> Removed redundant PM2 status check
|
||||
> Nov 9, 2024 • claude-mem
|
||||
> Files: worker-service.ts, worker-utils.ts
|
||||
|
||||
🟣 **#1246** Added SSE endpoint for real-time updates
|
||||
> Implemented Server-Sent Events for viewer UI
|
||||
> Nov 8, 2024 • claude-mem
|
||||
> Files: worker-service.ts
|
||||
```
|
||||
|
||||
For complete formatting guidelines, see [formatting.md](formatting.md).
|
||||
|
||||
## Partial Path Matching
|
||||
|
||||
The file path parameter supports partial matching:
|
||||
|
||||
```bash
|
||||
# These all match "src/services/worker-service.ts"
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=worker-service.ts&format=index"
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=services/worker&format=index"
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=worker-service&format=index"
|
||||
```
|
||||
|
||||
## Directory Searches
|
||||
|
||||
Search for all work in a directory:
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=src/hooks/&format=index&limit=20"
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Missing filePath parameter:**
|
||||
```json
|
||||
{"error": "Missing required parameter: filePath"}
|
||||
```
|
||||
Fix: Add the filePath parameter
|
||||
|
||||
**No results found:**
|
||||
```json
|
||||
{"filePath": "nonexistent.ts", "count": 0, "results": []}
|
||||
```
|
||||
Response: "No observations found for 'nonexistent.ts'. Try a partial path or check the spelling."
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use format=index first to see overview of all changes
|
||||
2. Start with partial paths (e.g., filename only) for broader matches
|
||||
3. Use full paths when you need specific file matches
|
||||
4. Combine with dateStart to see recent changes: `?filePath=worker.ts&dateStart=2024-11-01`
|
||||
5. Use directory searches to see all work in a module
|
||||
|
||||
**Token Efficiency:**
|
||||
- Start with format=index (~50-100 tokens per result)
|
||||
- Use format=full only for relevant items (~500-1000 tokens per result)
|
||||
- See [../principles/progressive-disclosure.md](../principles/progressive-disclosure.md)
|
||||
@@ -0,0 +1,123 @@
|
||||
# Search by Type
|
||||
|
||||
Find observations by type: bugfix, feature, refactor, decision, discovery, or change.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "What bugs did we fix?"
|
||||
- User asks: "What features did we add?"
|
||||
- User asks: "What decisions did we make?"
|
||||
- Looking for specific types of work
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-type?type=bugfix&format=index&limit=5"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **type** (required): One or more types (comma-separated)
|
||||
- `bugfix` - Bug fixes
|
||||
- `feature` - New features
|
||||
- `refactor` - Code refactoring
|
||||
- `decision` - Architectural/design decisions
|
||||
- `discovery` - Discoveries and insights
|
||||
- `change` - General changes
|
||||
- **format**: "index" (summary) or "full" (complete details). Default: "full"
|
||||
- **limit**: Number of results (default: 20, max: 100)
|
||||
- **project**: Filter by project name (optional)
|
||||
- **dateStart/dateEnd**: Filter by date range (optional)
|
||||
|
||||
## When to Use Each Format
|
||||
|
||||
**Use format=index for:**
|
||||
- Quick overviews of work by type
|
||||
- Finding IDs for deeper investigation
|
||||
- Listing multiple results
|
||||
- **Token cost: ~50-100 per result**
|
||||
|
||||
**Use format=full for:**
|
||||
- Complete details including narrative, facts, files, concepts
|
||||
- Understanding the full context of specific observations
|
||||
- **Token cost: ~500-1000 per result**
|
||||
|
||||
## Example Response (format=index)
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "bugfix",
|
||||
"count": 5,
|
||||
"format": "index",
|
||||
"results": [
|
||||
{
|
||||
"id": 1235,
|
||||
"type": "bugfix",
|
||||
"title": "Fixed token expiration edge case",
|
||||
"subtitle": "Handled race condition in refresh flow",
|
||||
"created_at_epoch": 1699564800000,
|
||||
"project": "api-server"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
For format=index, present as a compact list with type emojis:
|
||||
|
||||
```markdown
|
||||
Found 5 bugfixes:
|
||||
|
||||
🔴 **#1235** Fixed token expiration edge case
|
||||
> Handled race condition in refresh flow
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
🔴 **#1236** Resolved memory leak in worker
|
||||
> Fixed event listener cleanup
|
||||
> Nov 8, 2024 • worker-service
|
||||
```
|
||||
|
||||
**Type Emojis:**
|
||||
- 🔴 bugfix
|
||||
- 🟣 feature
|
||||
- 🔄 refactor
|
||||
- 🔵 discovery
|
||||
- 🧠 decision
|
||||
- ✅ change
|
||||
|
||||
For complete formatting guidelines, see [formatting.md](formatting.md).
|
||||
|
||||
## Multiple Types
|
||||
|
||||
To search for multiple types:
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-type?type=bugfix,feature&format=index&limit=10"
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Missing type parameter:**
|
||||
```json
|
||||
{"error": "Missing required parameter: type"}
|
||||
```
|
||||
Fix: Add the type parameter
|
||||
|
||||
**Invalid type:**
|
||||
```json
|
||||
{"error": "Invalid type: foobar. Valid types: bugfix, feature, refactor, decision, discovery, change"}
|
||||
```
|
||||
Fix: Use one of the valid type values
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use format=index first to see overview
|
||||
2. Start with limit=5-10 to avoid token overload
|
||||
3. Combine with dateStart for recent work: `?type=bugfix&dateStart=2024-11-01`
|
||||
4. Use project filtering when working on one codebase
|
||||
|
||||
**Token Efficiency:**
|
||||
- Start with format=index (~50-100 tokens per result)
|
||||
- Use format=full only for relevant items (~500-1000 tokens per result)
|
||||
- See [../principles/progressive-disclosure.md](../principles/progressive-disclosure.md)
|
||||
@@ -0,0 +1,251 @@
|
||||
# Common Workflows
|
||||
|
||||
Step-by-step guides for typical user requests using the search API.
|
||||
|
||||
## Workflow 1: Understanding Past Work
|
||||
|
||||
**User asks:** "What did we do last session?" or "Catch me up on recent work"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Get recent context** (fastest path):
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/context/recent?limit=3"
|
||||
```
|
||||
|
||||
2. **Present as narrative:**
|
||||
```markdown
|
||||
## Recent Work
|
||||
|
||||
### Session #545 - Nov 9, 2024
|
||||
Implemented JWT authentication system
|
||||
|
||||
**Completed:**
|
||||
- Added token-based auth with refresh tokens
|
||||
- Created JWT signing and verification logic
|
||||
|
||||
**Key Learning:** JWT expiration requires careful handling of refresh race conditions
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- Single request gets both sessions and observations
|
||||
- Optimized for "catch me up" questions
|
||||
- ~1,500-2,500 tokens for 3 sessions
|
||||
|
||||
---
|
||||
|
||||
## Workflow 2: Finding Specific Bug Fixes
|
||||
|
||||
**User asks:** "What bugs did we fix?" or "Show me recent bug fixes"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Search by type** (index format first):
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-type?type=bugfix&format=index&limit=5"
|
||||
```
|
||||
|
||||
2. **Review index results**, identify relevant items
|
||||
|
||||
3. **Get full details** for specific bugs:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-type?type=bugfix&format=full&limit=1&offset=2"
|
||||
```
|
||||
|
||||
4. **Present findings:**
|
||||
```markdown
|
||||
Found 5 bug fixes:
|
||||
|
||||
🔴 **#1235** Fixed token expiration edge case
|
||||
> Handled race condition in refresh flow
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
[Click for full details on #1235]
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- Progressive disclosure: index first, full details selectively
|
||||
- Type-specific search is more efficient than generic search
|
||||
- ~250-500 tokens for index, ~750-1000 per full detail
|
||||
|
||||
---
|
||||
|
||||
## Workflow 3: Understanding File History
|
||||
|
||||
**User asks:** "What changes to auth/login.ts?" or "Show me work on this file"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Search by file** (index format):
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=auth/login.ts&format=index&limit=10"
|
||||
```
|
||||
|
||||
2. **Review chronological changes**
|
||||
|
||||
3. **Get full details** for specific changes:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/by-file?filePath=auth/login.ts&format=full&limit=1&offset=3"
|
||||
```
|
||||
|
||||
4. **Present as file timeline:**
|
||||
```markdown
|
||||
## History of auth/login.ts
|
||||
|
||||
🟣 **#1230** Added JWT authentication (Nov 9)
|
||||
🔴 **#1235** Fixed token expiration bug (Nov 9)
|
||||
🔄 **#1240** Refactored auth flow (Nov 8)
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- File-specific search finds all related work
|
||||
- Index format shows chronological overview
|
||||
- Selective full details for deep dives
|
||||
|
||||
---
|
||||
|
||||
## Workflow 4: Timeline Investigation
|
||||
|
||||
**User asks:** "What was happening when we deployed?" or "Show me context around that bug fix"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Find the event** using search:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/observations?query=deployment&format=index&limit=5"
|
||||
```
|
||||
|
||||
2. **Note observation ID** (e.g., #1234)
|
||||
|
||||
3. **Get timeline context**:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/timeline/context?anchor=1234&depth_before=10&depth_after=10"
|
||||
```
|
||||
|
||||
4. **Present as chronological narrative:**
|
||||
```markdown
|
||||
## Timeline: Deployment
|
||||
|
||||
### Before (10 records)
|
||||
**2:45 PM** - 🟣 Prepared deployment scripts
|
||||
**2:50 PM** - 💬 User asked: "Are we ready to deploy?"
|
||||
|
||||
### ⭐ Anchor Point (2:55 PM)
|
||||
🎯 **Observation #1234**: Deployed to production
|
||||
|
||||
### After (10 records)
|
||||
**3:00 PM** - 🔴 Fixed post-deployment routing issue
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- Timeline shows temporal context (what happened before/after)
|
||||
- Captures causality between events
|
||||
- All record types (observations, sessions, prompts) interleaved
|
||||
|
||||
---
|
||||
|
||||
## Workflow 5: Quick Timeline (One Request)
|
||||
|
||||
**User asks:** "Timeline of authentication work"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Use timeline-by-query** (auto mode):
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/timeline/by-query?query=authentication&mode=auto&depth_before=10&depth_after=10"
|
||||
```
|
||||
|
||||
2. **Present timeline directly:**
|
||||
```markdown
|
||||
## Timeline: Authentication
|
||||
|
||||
**Best Match:** 🟣 Observation #1234 - Implemented JWT authentication
|
||||
|
||||
### Context (21 records)
|
||||
[... timeline around best match ...]
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- Single request combines search + timeline
|
||||
- Fastest path when query is specific
|
||||
- Auto mode uses top result as anchor
|
||||
|
||||
**Alternative:** Use interactive mode for broad queries:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/timeline/by-query?query=auth&mode=interactive&limit=5"
|
||||
```
|
||||
Then choose anchor manually.
|
||||
|
||||
---
|
||||
|
||||
## Workflow 6: Search Composition
|
||||
|
||||
**User asks:** "What features did we add to the authentication system recently?"
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Combine filters** for precision:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/observations?query=authentication&type=feature&dateStart=2024-11-01&format=index&limit=10"
|
||||
```
|
||||
|
||||
2. **Review filtered results**
|
||||
|
||||
3. **Get full details** for relevant features:
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/observations?query=authentication&type=feature&format=full&limit=1&offset=2"
|
||||
```
|
||||
|
||||
4. **Present findings:**
|
||||
```markdown
|
||||
Found 10 authentication features added in November:
|
||||
|
||||
🟣 **#1234** Implemented JWT authentication (Nov 9)
|
||||
🟣 **#1236** Added refresh token rotation (Nov 9)
|
||||
🟣 **#1238** Implemented OAuth2 flow (Nov 7)
|
||||
```
|
||||
|
||||
**Why this workflow:**
|
||||
- Multiple filters narrow results before requesting full details
|
||||
- Type + query + dateStart/dateEnd = precise targeting
|
||||
- Progressive disclosure: index first, full details selectively
|
||||
|
||||
---
|
||||
|
||||
## Workflow Selection Guide
|
||||
|
||||
| User Request | Workflow | Operation | Token Cost |
|
||||
|--------------|----------|-----------|------------|
|
||||
| "What did we do last session?" | #1 | recent-context | 1,500-2,500 |
|
||||
| "What bugs did we fix?" | #2 | by-type | 500-3,000 |
|
||||
| "What changes to file.ts?" | #3 | by-file | 500-3,000 |
|
||||
| "What was happening then?" | #4 | search → timeline | 3,500-6,000 |
|
||||
| "Timeline of X work" | #5 | timeline-by-query | 3,000-4,000 |
|
||||
| "Recent features added?" | #6 | observations + filters | 500-3,000 |
|
||||
|
||||
## General Principles
|
||||
|
||||
1. **Start with index format** - Always use `format=index` first
|
||||
2. **Use specialized tools** - by-type, by-file, by-concept when applicable
|
||||
3. **Compose operations** - Combine search + timeline for investigations
|
||||
4. **Filter early** - Use type, dateStart/dateEnd, project to narrow before expanding
|
||||
5. **Progressive disclosure** - Load full details only for relevant items
|
||||
|
||||
## Token Budget Awareness
|
||||
|
||||
**Quick queries** (500-1,500 tokens):
|
||||
- Recent context (limit=3)
|
||||
- Index search (limit=5-10)
|
||||
- Filtered searches
|
||||
|
||||
**Medium queries** (1,500-4,000 tokens):
|
||||
- Recent context (limit=5-10)
|
||||
- Full details (3-5 items)
|
||||
- Timeline (depth 10/10)
|
||||
|
||||
**Deep queries** (4,000-8,000 tokens):
|
||||
- Timeline (depth 20/20)
|
||||
- Full details (10+ items)
|
||||
- Multiple composed operations
|
||||
|
||||
Always start with minimal token investment, expand only when needed.
|
||||
@@ -0,0 +1,403 @@
|
||||
# Response Formatting Guidelines
|
||||
|
||||
How to present search results to users for maximum clarity and usefulness.
|
||||
|
||||
## General Principles
|
||||
|
||||
1. **Progressive disclosure** - Show index results first, full details on demand
|
||||
2. **Visual hierarchy** - Use emojis, bold, and structure for scannability
|
||||
3. **Context-aware** - Tailor presentation to user's question
|
||||
4. **Actionable** - Include IDs for follow-up queries
|
||||
5. **Token-efficient** - Balance detail with token budget
|
||||
|
||||
---
|
||||
|
||||
## Format: Index Results
|
||||
|
||||
**When to use:** First response to searches, overviews, multiple results
|
||||
|
||||
**Structure:**
|
||||
```markdown
|
||||
Found {count} results for "{query}":
|
||||
|
||||
{emoji} **#{id}** {title}
|
||||
> {subtitle}
|
||||
> {date} • {project}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
Found 5 results for "authentication":
|
||||
|
||||
🟣 **#1234** Implemented JWT authentication
|
||||
> Added token-based auth with refresh tokens
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
🔴 **#1235** Fixed token expiration edge case
|
||||
> Handled race condition in refresh flow
|
||||
> Nov 9, 2024 • api-server
|
||||
```
|
||||
|
||||
**Type Emojis:**
|
||||
- 🔴 bugfix
|
||||
- 🟣 feature
|
||||
- 🔄 refactor
|
||||
- 🔵 discovery
|
||||
- 🧠 decision
|
||||
- ✅ change
|
||||
- 🎯 session
|
||||
- 💬 prompt
|
||||
|
||||
**What to include:**
|
||||
- ✅ ID (for follow-up)
|
||||
- ✅ Type emoji
|
||||
- ✅ Title
|
||||
- ✅ Subtitle (if available)
|
||||
- ✅ Date (human-readable)
|
||||
- ✅ Project name
|
||||
- ❌ Don't include full narrative/facts/files in index format
|
||||
|
||||
---
|
||||
|
||||
## Format: Full Results
|
||||
|
||||
**When to use:** User requests details, specific items selected from index
|
||||
|
||||
**Structure:**
|
||||
```markdown
|
||||
## {emoji} {type} #{id}: {title}
|
||||
|
||||
**Summary:** {subtitle}
|
||||
|
||||
**What happened:**
|
||||
{narrative}
|
||||
|
||||
**Key Facts:**
|
||||
- {fact1}
|
||||
- {fact2}
|
||||
|
||||
**Files modified:**
|
||||
- {file1}
|
||||
- {file2}
|
||||
|
||||
**Concepts:** {concepts}
|
||||
|
||||
**Date:** {human_readable_date}
|
||||
**Project:** {project}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
## 🟣 Feature #1234: Implemented JWT authentication
|
||||
|
||||
**Summary:** Added token-based auth with refresh tokens
|
||||
|
||||
**What happened:**
|
||||
Implemented a complete JWT authentication system with access and refresh tokens. Access tokens expire after 15 minutes, refresh tokens after 7 days. Added token signing with RS256 algorithm and proper key rotation infrastructure.
|
||||
|
||||
**Key Facts:**
|
||||
- Access tokens use 15-minute expiration
|
||||
- Refresh tokens stored in httpOnly cookies
|
||||
- RS256 algorithm with key rotation support
|
||||
- Token refresh endpoint handles race conditions gracefully
|
||||
|
||||
**Files modified:**
|
||||
- src/auth/jwt.ts (created)
|
||||
- src/auth/refresh.ts (created)
|
||||
- src/middleware/auth.ts (modified)
|
||||
|
||||
**Concepts:** how-it-works, pattern
|
||||
|
||||
**Date:** November 9, 2024 at 2:55 PM
|
||||
**Project:** api-server
|
||||
```
|
||||
|
||||
**What to include:**
|
||||
- ✅ Full title with emoji and ID
|
||||
- ✅ Summary/subtitle
|
||||
- ✅ Complete narrative
|
||||
- ✅ All key facts
|
||||
- ✅ All files (with status: created/modified/deleted)
|
||||
- ✅ Concepts/tags
|
||||
- ✅ Precise timestamp
|
||||
- ✅ Project name
|
||||
|
||||
---
|
||||
|
||||
## Format: Timeline Results
|
||||
|
||||
**When to use:** Temporal investigations, "what was happening" questions
|
||||
|
||||
**Structure:**
|
||||
```markdown
|
||||
## Timeline: {anchor_description}
|
||||
|
||||
### Before ({count} records)
|
||||
|
||||
**{time}** - {emoji} {type} #{id}: {title}
|
||||
**{time}** - {emoji} {type} #{id}: {title}
|
||||
|
||||
### ⭐ Anchor Point ({time})
|
||||
{emoji} **{type} #{id}**: {title}
|
||||
|
||||
### After ({count} records)
|
||||
|
||||
**{time}** - {emoji} {type} #{id}: {title}
|
||||
**{time}** - {emoji} {type} #{id}: {title}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
## Timeline: Deployment
|
||||
|
||||
### Before (10 records)
|
||||
|
||||
**2:30 PM** - 🟣 #1230: Prepared deployment scripts
|
||||
**2:45 PM** - 🔄 #1232: Updated configuration files
|
||||
**2:50 PM** - 💬 User asked: "Are we ready to deploy?"
|
||||
|
||||
### ⭐ Anchor Point (2:55 PM)
|
||||
🎯 **Session #545**: Deployed to production
|
||||
|
||||
### After (10 records)
|
||||
|
||||
**3:00 PM** - 🔴 #1235: Fixed post-deployment routing issue
|
||||
**3:10 PM** - 🔵 #1236: Discovered caching behavior in production
|
||||
**3:15 PM** - 🧠 #1237: Decided to add health check endpoint
|
||||
```
|
||||
|
||||
**What to include:**
|
||||
- ✅ Chronological ordering (oldest to newest)
|
||||
- ✅ Human-readable times (not epochs)
|
||||
- ✅ Clear anchor point marker (⭐)
|
||||
- ✅ Mix of all record types (observations, sessions, prompts)
|
||||
- ✅ Concise titles (not full narratives)
|
||||
- ✅ Type emojis for quick scanning
|
||||
|
||||
---
|
||||
|
||||
## Format: Session Summaries
|
||||
|
||||
**When to use:** Recent context, "what did we do" questions
|
||||
|
||||
**Structure:**
|
||||
```markdown
|
||||
## Recent Work on {project}
|
||||
|
||||
### 🎯 Session #{id} - {date}
|
||||
|
||||
**Request:** {user_request}
|
||||
|
||||
**Completed:**
|
||||
- {completion1}
|
||||
- {completion2}
|
||||
|
||||
**Key Learning:** {learning}
|
||||
|
||||
**Observations:**
|
||||
- {emoji} **#{obs_id}** {obs_title}
|
||||
- Files: {file_list}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
## Recent Work on api-server
|
||||
|
||||
### 🎯 Session #545 - November 9, 2024
|
||||
|
||||
**Request:** Add JWT authentication with refresh tokens
|
||||
|
||||
**Completed:**
|
||||
- Implemented token-based auth with refresh logic
|
||||
- Added JWT signing and verification
|
||||
- Created refresh token rotation
|
||||
|
||||
**Key Learning:** JWT expiration requires careful handling of refresh race conditions
|
||||
|
||||
**Observations:**
|
||||
- 🟣 **#1234** Implemented JWT authentication
|
||||
- Files: jwt.ts, refresh.ts, middleware/auth.ts
|
||||
- 🔴 **#1235** Fixed token expiration edge case
|
||||
- Files: refresh.ts
|
||||
```
|
||||
|
||||
**What to include:**
|
||||
- ✅ Session ID and date
|
||||
- ✅ Original user request
|
||||
- ✅ What was completed (bulleted list)
|
||||
- ✅ Key learnings/insights
|
||||
- ✅ Linked observations with file lists
|
||||
- ✅ Clear hierarchy (session → observations)
|
||||
|
||||
---
|
||||
|
||||
## Format: User Prompts
|
||||
|
||||
**When to use:** "What did I ask" questions, prompt searches
|
||||
|
||||
**Structure:**
|
||||
```markdown
|
||||
Found {count} user prompts:
|
||||
|
||||
💬 **Prompt #{id}** (Session #{session_id})
|
||||
> "{preview_text}"
|
||||
> {date} • {project}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
Found 5 user prompts about "authentication":
|
||||
|
||||
💬 **Prompt #1250** (Session #545)
|
||||
> "How do I implement JWT authentication with refresh tokens? I need to handle token expiration..."
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
💬 **Prompt #1251** (Session #546)
|
||||
> "The auth tokens are expiring too quickly. Can you help debug the refresh flow?"
|
||||
> Nov 8, 2024 • api-server
|
||||
```
|
||||
|
||||
**What to include:**
|
||||
- ✅ Prompt ID
|
||||
- ✅ Session ID (for context linking)
|
||||
- ✅ Preview text (200 chars for index, full text for full format)
|
||||
- ✅ Date and project
|
||||
- ✅ Quote formatting for prompt text
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
**No results found:**
|
||||
```markdown
|
||||
No results found for "{query}". Try:
|
||||
- Different search terms
|
||||
- Broader keywords
|
||||
- Checking spelling
|
||||
- Using partial paths (for file searches)
|
||||
```
|
||||
|
||||
**Service unavailable:**
|
||||
```markdown
|
||||
The search service isn't available. Check if the worker is running:
|
||||
|
||||
```bash
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
If the worker is stopped, restart it:
|
||||
|
||||
```bash
|
||||
claude-mem restart
|
||||
```
|
||||
```
|
||||
|
||||
**Invalid parameters:**
|
||||
```markdown
|
||||
Invalid search parameters:
|
||||
- {parameter}: {error_message}
|
||||
|
||||
See the [API help](help.md) for valid parameter options.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Context-Aware Presentation
|
||||
|
||||
Tailor formatting to user's question:
|
||||
|
||||
**"What bugs did we fix?"**
|
||||
→ Use index format, emphasize date/type, group by recency
|
||||
|
||||
**"How did we implement X?"**
|
||||
→ Use full format for best match, include complete narrative and files
|
||||
|
||||
**"What was happening when..."**
|
||||
→ Use timeline format, emphasize chronology and causality
|
||||
|
||||
**"Catch me up on recent work"**
|
||||
→ Use session summary format, focus on high-level accomplishments
|
||||
|
||||
---
|
||||
|
||||
## Token Budget Guidelines
|
||||
|
||||
**Minimal presentation (~100-200 tokens):**
|
||||
- Index format with 3-5 results
|
||||
- Compact list structure
|
||||
- Essential metadata only
|
||||
|
||||
**Standard presentation (~500-1,000 tokens):**
|
||||
- Index format with 10-15 results
|
||||
- Include subtitles and context
|
||||
- Clear formatting and emojis
|
||||
|
||||
**Detailed presentation (~1,500-3,000 tokens):**
|
||||
- Full format for 2-3 items
|
||||
- Complete narratives and facts
|
||||
- Timeline with 20-30 records
|
||||
|
||||
**Comprehensive presentation (~5,000+ tokens):**
|
||||
- Multiple full results
|
||||
- Deep timelines (40+ records)
|
||||
- Session summaries with observations
|
||||
|
||||
Always start minimal, expand only when needed.
|
||||
|
||||
---
|
||||
|
||||
## Markdown Best Practices
|
||||
|
||||
1. **Use headers (##, ###)** for hierarchy
|
||||
2. **Bold important elements** (IDs, titles, dates)
|
||||
3. **Quote user text** (prompts, questions)
|
||||
4. **Bullet lists** for facts and files
|
||||
5. **Code blocks** for commands and examples
|
||||
6. **Emojis** for type indicators
|
||||
7. **Horizontal rules (---)** for section breaks
|
||||
8. **Blockquotes (>)** for subtitles and previews
|
||||
|
||||
---
|
||||
|
||||
## Examples by Use Case
|
||||
|
||||
### Use Case 1: Quick Overview
|
||||
User: "What did we do last session?"
|
||||
|
||||
```markdown
|
||||
## Recent Work
|
||||
|
||||
### 🎯 Session #545 - November 9, 2024
|
||||
Implemented JWT authentication system
|
||||
|
||||
**Key accomplishment:** Added token-based auth with refresh tokens
|
||||
**Key learning:** JWT expiration requires careful handling of refresh race conditions
|
||||
```
|
||||
|
||||
### Use Case 2: Specific Investigation
|
||||
User: "How did we implement JWT authentication?"
|
||||
|
||||
```markdown
|
||||
## 🟣 Feature #1234: Implemented JWT authentication
|
||||
|
||||
**What happened:**
|
||||
Implemented a complete JWT authentication system with access and refresh tokens. Access tokens expire after 15 minutes, refresh tokens after 7 days. Added token signing with RS256 algorithm.
|
||||
|
||||
**Files:**
|
||||
- src/auth/jwt.ts (created)
|
||||
- src/auth/refresh.ts (created)
|
||||
- src/middleware/auth.ts (modified)
|
||||
|
||||
**Key insight:** Refresh race conditions require atomic token exchange logic.
|
||||
```
|
||||
|
||||
### Use Case 3: Timeline Investigation
|
||||
User: "What was happening around the deployment?"
|
||||
|
||||
```markdown
|
||||
## Timeline: Deployment
|
||||
|
||||
[... chronological timeline with before/after context ...]
|
||||
```
|
||||
|
||||
Choose presentation style based on user's question and information needs.
|
||||
@@ -0,0 +1,171 @@
|
||||
# API Help
|
||||
|
||||
Get comprehensive API documentation for all search endpoints.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "What search operations are available?"
|
||||
- User asks: "How do I use the search API?"
|
||||
- Need reference documentation for endpoints
|
||||
- Want to see all available parameters
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/help"
|
||||
```
|
||||
|
||||
## Response Structure
|
||||
|
||||
Returns complete API documentation:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "6.5.0",
|
||||
"base_url": "http://localhost:37777/api",
|
||||
"endpoints": [
|
||||
{
|
||||
"path": "/search/observations",
|
||||
"method": "GET",
|
||||
"description": "Search observations using full-text search",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "query",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "Search terms"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"default": "full",
|
||||
"options": ["index", "full"],
|
||||
"description": "Response format"
|
||||
}
|
||||
],
|
||||
"example": "curl -s \"http://localhost:37777/api/search/observations?query=authentication&format=index&limit=5\""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
Present as reference documentation:
|
||||
|
||||
```markdown
|
||||
## claude-mem Search API Reference
|
||||
|
||||
Base URL: `http://localhost:37777/api`
|
||||
|
||||
### Search Operations
|
||||
|
||||
**1. Search Observations**
|
||||
- **Endpoint:** `GET /search/observations`
|
||||
- **Description:** Search observations using full-text search
|
||||
- **Parameters:**
|
||||
- `query` (required, string): Search terms
|
||||
- `format` (optional, string): "index" or "full" (default: "full")
|
||||
- `limit` (optional, number): Max results (default: 20, max: 100)
|
||||
- **Example:**
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/observations?query=authentication&format=index&limit=5"
|
||||
```
|
||||
|
||||
[... continue for all endpoints ...]
|
||||
```
|
||||
|
||||
## Endpoint Categories
|
||||
|
||||
The API help response organizes endpoints by category:
|
||||
|
||||
1. **Full-Text Search**
|
||||
- `/search/observations`
|
||||
- `/search/sessions`
|
||||
- `/search/prompts`
|
||||
|
||||
2. **Filtered Search**
|
||||
- `/search/by-type`
|
||||
- `/search/by-concept`
|
||||
- `/search/by-file`
|
||||
|
||||
3. **Context Retrieval**
|
||||
- `/context/recent`
|
||||
- `/timeline/context`
|
||||
- `/timeline/by-query`
|
||||
|
||||
4. **Utilities**
|
||||
- `/help`
|
||||
|
||||
## Common Parameters
|
||||
|
||||
Many endpoints share these parameters:
|
||||
|
||||
- **format**: "index" (summary) or "full" (complete details)
|
||||
- **limit**: Number of results to return
|
||||
- **offset**: Number of results to skip (for pagination)
|
||||
- **project**: Filter by project name
|
||||
- **dateStart/dateEnd**: Filter by date range
|
||||
- `dateStart`: Start date (YYYY-MM-DD or epoch timestamp)
|
||||
- `dateEnd`: End date (YYYY-MM-DD or epoch timestamp)
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Worker not running:**
|
||||
Connection refused error. Response: "The search API isn't available. Check if worker is running: `npm run worker:status`"
|
||||
|
||||
**Invalid endpoint:**
|
||||
```json
|
||||
{"error": "Not found"}
|
||||
```
|
||||
Response: "Invalid API endpoint. Use /api/help to see available endpoints."
|
||||
|
||||
## Tips
|
||||
|
||||
1. Save help response for reference during investigation
|
||||
2. Use examples as starting point for your queries
|
||||
3. Check required parameters before making requests
|
||||
4. Refer to format options for each endpoint
|
||||
5. All endpoints use GET method with query parameters
|
||||
|
||||
**Token Efficiency:**
|
||||
- Help response: ~2,000-3,000 tokens (complete API reference)
|
||||
- Use sparingly - refer to operation-specific docs instead
|
||||
- Keep help response cached for repeated reference
|
||||
|
||||
## When to Use Help
|
||||
|
||||
**Use help when:**
|
||||
- Starting to use the search API
|
||||
- Need complete parameter reference
|
||||
- Forgot which endpoints are available
|
||||
- Want to see all options at once
|
||||
|
||||
**Don't use help when:**
|
||||
- You know which operation you need (use operation-specific docs)
|
||||
- Just need examples (use common-workflows.md)
|
||||
- Token budget is limited (help is comprehensive)
|
||||
|
||||
## Alternative to Help Endpoint
|
||||
|
||||
Instead of calling `/api/help`, you can:
|
||||
|
||||
1. **Use SKILL.md** - Quick decision guide with operation links
|
||||
2. **Use operation docs** - Detailed guides for specific endpoints
|
||||
3. **Use common-workflows.md** - Step-by-step examples
|
||||
4. **Use formatting.md** - Response presentation templates
|
||||
|
||||
The help endpoint is most useful when you need complete API reference in one response.
|
||||
|
||||
## API Versioning
|
||||
|
||||
The help response includes version information:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "6.5.0"
|
||||
}
|
||||
```
|
||||
|
||||
Check version to ensure compatibility with documentation.
|
||||
@@ -0,0 +1,124 @@
|
||||
# Search Observations (Semantic + Full-Text Hybrid)
|
||||
|
||||
Search all observations using natural language queries.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "How did we implement authentication?"
|
||||
- User asks: "What bugs did we fix?"
|
||||
- User asks: "What features did we add?"
|
||||
- Looking for past work by keyword or topic
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/observations?query=authentication&format=index&limit=5"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **query** (optional): Natural language search query - uses semantic search (ChromaDB) for ranking with SQLite FTS5 fallback (e.g., "authentication", "bug fix", "database migration"). Can be omitted for filter-only searches.
|
||||
- **format**: "index" (summary) or "full" (complete details). Default: "full"
|
||||
- **limit**: Number of results (default: 20, max: 100)
|
||||
- **project**: Filter by project name (optional)
|
||||
- **dateStart/dateEnd**: Filter by date range (optional) - `dateStart` and/or `dateEnd` (YYYY-MM-DD format or epoch timestamp)
|
||||
- **obs_type**: Filter by observation type (comma-separated): bugfix, feature, refactor, decision, discovery, change (optional)
|
||||
- **concepts**: Filter by concept tags (comma-separated, optional)
|
||||
- **files**: Filter by file paths (comma-separated, optional)
|
||||
|
||||
**Important**: When omitting `query`, you MUST provide at least one filter (project, dateStart/dateEnd, obs_type, concepts, or files)
|
||||
|
||||
## When to Use Each Format
|
||||
|
||||
**Use format=index for:**
|
||||
- Quick overviews
|
||||
- Finding IDs for deeper investigation
|
||||
- Listing multiple results
|
||||
- **Token cost: ~50-100 per result**
|
||||
|
||||
**Use format=full for:**
|
||||
- Complete details including narrative, facts, files, concepts
|
||||
- Understanding the full context of specific observations
|
||||
- **Token cost: ~500-1000 per result**
|
||||
|
||||
## Example Response (format=index)
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "authentication",
|
||||
"count": 5,
|
||||
"format": "index",
|
||||
"results": [
|
||||
{
|
||||
"id": 1234,
|
||||
"type": "feature",
|
||||
"title": "Implemented JWT authentication",
|
||||
"subtitle": "Added token-based auth with refresh tokens",
|
||||
"created_at_epoch": 1699564800000,
|
||||
"project": "api-server",
|
||||
"score": 0.95
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
For format=index, present as a compact list:
|
||||
|
||||
```markdown
|
||||
Found 5 results for "authentication":
|
||||
|
||||
1. **#1234** [feature] Implemented JWT authentication
|
||||
> Added token-based auth with refresh tokens
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
2. **#1235** [bugfix] Fixed token expiration edge case
|
||||
> Handled race condition in refresh flow
|
||||
> Nov 9, 2024 • api-server
|
||||
```
|
||||
|
||||
**Include:** ID (for follow-up), type emoji (🔴 bugfix, 🟣 feature, 🔄 refactor, 🔵 discovery, 🧠 decision, ✅ change), title, subtitle, date, project.
|
||||
|
||||
For complete formatting guidelines, see formatting.md (documentation coming soon).
|
||||
|
||||
## Filter-Only Examples
|
||||
|
||||
Search without query text (direct SQLite filtering):
|
||||
|
||||
```bash
|
||||
# Get all observations from November 2025
|
||||
curl -s "http://localhost:37777/api/search?type=observations&dateStart=2025-11-01&format=index"
|
||||
|
||||
# Get all bug fixes from a specific project
|
||||
curl -s "http://localhost:37777/api/search?type=observations&obs_type=bugfix&project=api-server&format=index"
|
||||
|
||||
# Get all observations from last 7 days
|
||||
curl -s "http://localhost:37777/api/search?type=observations&dateStart=2025-11-11&format=index"
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Missing query and filters:**
|
||||
```json
|
||||
{"error": "Either query or filters required for search"}
|
||||
```
|
||||
Fix: Provide either a query parameter OR at least one filter (project, dateStart/dateEnd, obs_type, concepts, files)
|
||||
|
||||
**No results found:**
|
||||
```json
|
||||
{"query": "foobar", "count": 0, "results": []}
|
||||
```
|
||||
Response: "No results found for 'foobar'. Try different search terms."
|
||||
|
||||
## Tips
|
||||
|
||||
1. Be specific: "authentication JWT" > "auth"
|
||||
2. Start with format=index and limit=5-10
|
||||
3. Use project filtering when working on one codebase
|
||||
4. If no results, try broader terms or check spelling
|
||||
|
||||
**Token Efficiency:**
|
||||
- Start with format=index (~50-100 tokens per result)
|
||||
- Use format=full only for relevant items (~500-1000 tokens per result)
|
||||
- See [../principles/progressive-disclosure.md](../principles/progressive-disclosure.md)
|
||||
@@ -0,0 +1,125 @@
|
||||
# Search User Prompts (Full-Text)
|
||||
|
||||
Search raw user prompts to find what was actually asked across all sessions.
|
||||
|
||||
## When to Use
|
||||
|
||||
- User asks: "What did I ask about authentication?"
|
||||
- User asks: "Find my question about database migrations"
|
||||
- User asks: "When did I ask about testing?"
|
||||
- Looking for specific user questions or requests
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:37777/api/search/prompts?query=authentication&format=index&limit=5"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **query** (required): Search terms (e.g., "authentication", "how do I", "bug fix")
|
||||
- **format**: "index" (truncated prompts) or "full" (complete prompt text). Default: "full"
|
||||
- **limit**: Number of results (default: 20, max: 100)
|
||||
- **project**: Filter by project name (optional)
|
||||
- **dateStart/dateEnd**: Filter by date range (optional)
|
||||
|
||||
## When to Use Each Format
|
||||
|
||||
**Use format=index for:**
|
||||
- Quick overviews of what was asked
|
||||
- Finding prompt IDs for full text
|
||||
- Listing multiple prompts
|
||||
- **Token cost: ~50-100 per result (truncated to 200 chars)**
|
||||
|
||||
**Use format=full for:**
|
||||
- Complete prompt text
|
||||
- Understanding the full user request
|
||||
- **Token cost: Variable (depends on prompt length, typically 100-300 tokens)**
|
||||
|
||||
## Example Response (format=index)
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "authentication",
|
||||
"count": 5,
|
||||
"format": "index",
|
||||
"results": [
|
||||
{
|
||||
"id": 1250,
|
||||
"session_id": "S545",
|
||||
"prompt_preview": "How do I implement JWT authentication with refresh tokens? I need to handle token expiration...",
|
||||
"created_at_epoch": 1699564800000,
|
||||
"project": "api-server"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How to Present Results
|
||||
|
||||
For format=index, present as a compact list:
|
||||
|
||||
```markdown
|
||||
Found 5 user prompts about "authentication":
|
||||
|
||||
💬 **Prompt #1250** (Session #545)
|
||||
> "How do I implement JWT authentication with refresh tokens? I need to handle token expiration..."
|
||||
> Nov 9, 2024 • api-server
|
||||
|
||||
💬 **Prompt #1251** (Session #546)
|
||||
> "The auth tokens are expiring too quickly. Can you help debug the refresh flow?"
|
||||
> Nov 8, 2024 • api-server
|
||||
```
|
||||
|
||||
For complete formatting guidelines, see [formatting.md](formatting.md).
|
||||
|
||||
## What Gets Searched
|
||||
|
||||
User prompts search covers:
|
||||
- All user messages sent to Claude Code
|
||||
- Raw text as typed by the user
|
||||
- Multi-turn conversations (each message is a separate prompt)
|
||||
- Questions, requests, commands, and clarifications
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Missing query parameter:**
|
||||
```json
|
||||
{"error": "Missing required parameter: query"}
|
||||
```
|
||||
Fix: Add the query parameter
|
||||
|
||||
**No results found:**
|
||||
```json
|
||||
{"query": "foobar", "count": 0, "results": []}
|
||||
```
|
||||
Response: "No user prompts found for 'foobar'. Try different search terms."
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use exact phrases in quotes: `?query="how do I"` for precise matches
|
||||
2. Start with format=index to see preview, then get full text if needed
|
||||
3. Use dateStart to find recent questions: `?query=bug&dateStart=2024-11-01`
|
||||
4. Prompts show what was asked, sessions/observations show what was done
|
||||
5. Combine with session search to see both question and answer
|
||||
|
||||
**Token Efficiency:**
|
||||
- Start with format=index (~50-100 tokens per result, prompt truncated to 200 chars)
|
||||
- Use format=full only for relevant items (100-300 tokens per result)
|
||||
- See [../principles/progressive-disclosure.md](../principles/progressive-disclosure.md)
|
||||
|
||||
## When to Use Prompts vs Sessions
|
||||
|
||||
**Use prompts search when:**
|
||||
- Looking for specific user questions
|
||||
- Trying to remember what was asked
|
||||
- Finding original request wording
|
||||
|
||||
**Use sessions search when:**
|
||||
- Looking for what was accomplished
|
||||
- Understanding work summaries
|
||||
- Getting high-level context
|
||||
|
||||
**Combine both when:**
|
||||
- Understanding the full conversation (what was asked + what was done)
|
||||
- Investigating how a request was interpreted
|
||||