@adverant/nexus-memory-skill 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -14
- package/SKILL.md +155 -31
- package/hooks/auto-recall.sh +161 -0
- package/hooks/episode-summary.sh +223 -0
- package/install.sh +355 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
### Give Your AI Perfect Recall — Across Every Session, Every Project, Forever
|
|
12
12
|
|
|
13
|
+
[](https://www.npmjs.com/package/@adverant/nexus-memory-skill)
|
|
14
|
+
[](https://www.npmjs.com/package/@adverant/nexus-memory-skill)
|
|
13
15
|
[](LICENSE)
|
|
14
16
|
[](https://claude.ai/code)
|
|
15
17
|
[](https://adverant.ai)
|
|
@@ -114,20 +116,44 @@ Unlike simple vector search, **GraphRAG** (Graph-based Retrieval Augmented Gener
|
|
|
114
116
|
|
|
115
117
|
## Quick Start
|
|
116
118
|
|
|
117
|
-
### One-
|
|
119
|
+
### One-Line Install (Recommended)
|
|
118
120
|
|
|
119
121
|
```bash
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
curl -fsSL https://raw.githubusercontent.com/adverant/nexus-memory-skill/main/install.sh | bash
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This will:
|
|
126
|
+
1. Install all skill files and hooks
|
|
127
|
+
2. Configure automatic memory (auto-recall + auto-store)
|
|
128
|
+
3. Open a browser to get your free API key
|
|
129
|
+
4. Verify everything works
|
|
130
|
+
|
|
131
|
+
### Install via npm
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npm install -g @adverant/nexus-memory-skill
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Then run the installer:
|
|
138
|
+
```bash
|
|
139
|
+
$(npm root -g)/@adverant/nexus-memory-skill/install.sh
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Install via Git
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
git clone https://github.com/adverant/nexus-memory-skill.git
|
|
146
|
+
cd nexus-memory-skill
|
|
147
|
+
./install.sh
|
|
124
148
|
```
|
|
125
149
|
|
|
126
150
|
### Verify Installation
|
|
127
151
|
|
|
128
152
|
```bash
|
|
129
|
-
ls -la ~/.claude/skills/nexus-memory/SKILL.md && echo "
|
|
130
|
-
ls -la ~/.claude/hooks/
|
|
153
|
+
ls -la ~/.claude/skills/nexus-memory/SKILL.md && echo "Skill installed"
|
|
154
|
+
ls -la ~/.claude/hooks/auto-recall.sh && echo "Auto-recall hook installed"
|
|
155
|
+
ls -la ~/.claude/hooks/store-memory.sh && echo "Store hook installed"
|
|
156
|
+
ls -la ~/.claude/hooks/episode-summary.sh && echo "Episode summary hook installed"
|
|
131
157
|
```
|
|
132
158
|
|
|
133
159
|
### Manual Installation
|
|
@@ -140,28 +166,103 @@ ls -la ~/.claude/hooks/store-memory.sh && echo "✅ Hooks installed"
|
|
|
140
166
|
git clone https://github.com/adverant/nexus-memory-skill.git
|
|
141
167
|
```
|
|
142
168
|
|
|
143
|
-
2. **
|
|
169
|
+
2. **Create directories**
|
|
144
170
|
```bash
|
|
145
|
-
mkdir -p ~/.claude/skills
|
|
146
|
-
cp -r nexus-memory-skill ~/.claude/skills/nexus-memory
|
|
171
|
+
mkdir -p ~/.claude/skills/nexus-memory ~/.claude/hooks
|
|
147
172
|
```
|
|
148
173
|
|
|
149
|
-
3. **
|
|
174
|
+
3. **Copy skill and hooks**
|
|
150
175
|
```bash
|
|
176
|
+
cp nexus-memory-skill/SKILL.md ~/.claude/skills/nexus-memory/
|
|
151
177
|
cp nexus-memory-skill/hooks/*.sh ~/.claude/hooks/
|
|
152
178
|
chmod +x ~/.claude/hooks/*.sh
|
|
153
179
|
```
|
|
154
180
|
|
|
155
|
-
4. **
|
|
181
|
+
4. **Configure settings.json for automatic memory**
|
|
156
182
|
```bash
|
|
157
|
-
cat ~/.claude/
|
|
183
|
+
cat > ~/.claude/settings.json << 'EOF'
|
|
184
|
+
{
|
|
185
|
+
"hooks": {
|
|
186
|
+
"UserPromptSubmit": [
|
|
187
|
+
{
|
|
188
|
+
"matcher": "",
|
|
189
|
+
"hooks": [
|
|
190
|
+
{"type": "command", "command": "~/.claude/hooks/auto-recall.sh"},
|
|
191
|
+
{"type": "command", "command": "~/.claude/hooks/store-memory.sh"}
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
"PostToolUse": [
|
|
196
|
+
{
|
|
197
|
+
"matcher": "",
|
|
198
|
+
"hooks": [
|
|
199
|
+
{"type": "command", "command": "~/.claude/hooks/store-memory.sh"},
|
|
200
|
+
{"type": "command", "command": "~/.claude/hooks/episode-summary.sh"}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
EOF
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
5. **Get your API key**
|
|
210
|
+
|
|
211
|
+
Visit https://dashboard.adverant.ai/dashboard/api-keys and create a free API key.
|
|
212
|
+
|
|
213
|
+
6. **Configure API key**
|
|
214
|
+
```bash
|
|
215
|
+
echo "export NEXUS_API_KEY='your-api-key-here'" >> ~/.zshrc
|
|
216
|
+
source ~/.zshrc
|
|
158
217
|
```
|
|
159
218
|
|
|
160
219
|
</details>
|
|
161
220
|
|
|
162
221
|
---
|
|
163
222
|
|
|
164
|
-
##
|
|
223
|
+
## Automatic Memory (Zero-Config)
|
|
224
|
+
|
|
225
|
+
Once installed, Nexus Memory works **automatically** with no manual intervention:
|
|
226
|
+
|
|
227
|
+
### What Happens Automatically
|
|
228
|
+
|
|
229
|
+
| Event | Action | Hook |
|
|
230
|
+
|-------|--------|------|
|
|
231
|
+
| **You send a prompt** | Relevant memories are recalled and injected as context | `auto-recall.sh` |
|
|
232
|
+
| **You send a prompt** | Your prompt is stored for future recall | `store-memory.sh` |
|
|
233
|
+
| **A tool is used** | Tool inputs/outputs are captured | `store-memory.sh` |
|
|
234
|
+
| **Every 10 tool uses** | Conversation segment is summarized as an "episode" | `episode-summary.sh` |
|
|
235
|
+
|
|
236
|
+
### Example: Automatic Context
|
|
237
|
+
|
|
238
|
+
When you ask Claude about something you've worked on before:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
You: "How did we fix that CORS issue?"
|
|
242
|
+
|
|
243
|
+
[auto-recall.sh retrieves relevant memories]
|
|
244
|
+
|
|
245
|
+
Claude: "Based on my memory, you fixed the CORS issue by adding
|
|
246
|
+
credentials: 'include' to fetch options in src/api/client.ts.
|
|
247
|
+
This was needed because the server requires cookie authentication."
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**No manual recall needed** — relevant context is automatically provided.
|
|
251
|
+
|
|
252
|
+
### Environment Variables
|
|
253
|
+
|
|
254
|
+
| Variable | Default | Description |
|
|
255
|
+
|----------|---------|-------------|
|
|
256
|
+
| `NEXUS_API_KEY` | (required) | Your API key from dashboard.adverant.ai |
|
|
257
|
+
| `NEXUS_RECALL_LIMIT` | `5` | Number of memories to auto-recall per prompt |
|
|
258
|
+
| `NEXUS_EPISODE_THRESHOLD` | `10` | Tool uses before generating episode summary |
|
|
259
|
+
| `NEXUS_VERBOSE` | `0` | Set to `1` to see debug output |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Manual Usage
|
|
264
|
+
|
|
265
|
+
You can also manually store and recall memories:
|
|
165
266
|
|
|
166
267
|
### Store Memory
|
|
167
268
|
|
package/SKILL.md
CHANGED
|
@@ -8,6 +8,69 @@ allowed-tools: Bash
|
|
|
8
8
|
|
|
9
9
|
This skill integrates Claude Code with Nexus GraphRAG for persistent memory across ALL sessions and projects.
|
|
10
10
|
|
|
11
|
+
## Automatic Memory Features
|
|
12
|
+
|
|
13
|
+
When properly configured, Nexus Memory provides **fully automatic** memory management:
|
|
14
|
+
|
|
15
|
+
### Auto-Recall (On Every Prompt)
|
|
16
|
+
- Triggered automatically when you send a prompt
|
|
17
|
+
- Retrieves relevant context from past sessions
|
|
18
|
+
- Enriches Claude's responses with historical knowledge
|
|
19
|
+
- No manual intervention required
|
|
20
|
+
|
|
21
|
+
### Auto-Store (Continuous Capture)
|
|
22
|
+
- **UserPromptSubmit**: Every prompt you send is captured
|
|
23
|
+
- **PostToolUse**: Every tool execution result is stored
|
|
24
|
+
- Includes project context, timestamps, and session IDs
|
|
25
|
+
- Fire-and-forget async storage (non-blocking)
|
|
26
|
+
|
|
27
|
+
### Episode Summaries (Periodic)
|
|
28
|
+
- Automatically generated after every 10 tool uses
|
|
29
|
+
- Summarizes conversation segments for long-term memory
|
|
30
|
+
- Captures: topics discussed, decisions made, problems solved
|
|
31
|
+
- Stored with `event_type: "episode"` for easy retrieval
|
|
32
|
+
|
|
33
|
+
### Configuration
|
|
34
|
+
|
|
35
|
+
The automatic features are controlled by `~/.claude/settings.json`:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"hooks": {
|
|
40
|
+
"UserPromptSubmit": [
|
|
41
|
+
{
|
|
42
|
+
"matcher": "",
|
|
43
|
+
"hooks": [
|
|
44
|
+
{"type": "command", "command": "~/.claude/hooks/auto-recall.sh"},
|
|
45
|
+
{"type": "command", "command": "~/.claude/hooks/store-memory.sh"}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"PostToolUse": [
|
|
50
|
+
{
|
|
51
|
+
"matcher": "",
|
|
52
|
+
"hooks": [
|
|
53
|
+
{"type": "command", "command": "~/.claude/hooks/store-memory.sh"},
|
|
54
|
+
{"type": "command", "command": "~/.claude/hooks/episode-summary.sh"}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Environment Variables
|
|
63
|
+
|
|
64
|
+
| Variable | Default | Description |
|
|
65
|
+
|----------|---------|-------------|
|
|
66
|
+
| `NEXUS_API_KEY` | (required) | API key from dashboard.adverant.ai |
|
|
67
|
+
| `NEXUS_API_URL` | `https://api.adverant.ai` | API endpoint |
|
|
68
|
+
| `NEXUS_RECALL_LIMIT` | `5` | Number of memories to auto-recall |
|
|
69
|
+
| `NEXUS_EPISODE_THRESHOLD` | `10` | Tool count before episode summary |
|
|
70
|
+
| `NEXUS_VERBOSE` | `0` | Set to `1` for debug output |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
11
74
|
## IMPORTANT: First-Time Setup Check
|
|
12
75
|
|
|
13
76
|
**Before doing ANYTHING else, you MUST check if `NEXUS_API_KEY` is configured.**
|
|
@@ -28,6 +91,12 @@ if [ -z "$NEXUS_API_KEY" ]; then echo "NOT_CONFIGURED"; else echo "CONFIGURED";
|
|
|
28
91
|
2. **Ask the user to get their API key:**
|
|
29
92
|
> "Please get your API key from: **https://dashboard.adverant.ai/dashboard/api-keys**
|
|
30
93
|
>
|
|
94
|
+
> **Important:** When creating your API key in the dashboard:
|
|
95
|
+
> - Log in or create an account (this automatically creates your organization)
|
|
96
|
+
> - Navigate to API Keys section
|
|
97
|
+
> - Click "Create New Key"
|
|
98
|
+
> - Your key will be automatically scoped to your organization for proper data isolation
|
|
99
|
+
>
|
|
31
100
|
> Once you have it, paste it here and I'll configure it for you."
|
|
32
101
|
|
|
33
102
|
3. **When the user provides the API key, configure it automatically:**
|
|
@@ -95,24 +164,20 @@ The FileProcessAgent SmartRouter automatically routes files to the appropriate p
|
|
|
95
164
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process/url" \
|
|
96
165
|
-H "Content-Type: application/json" \
|
|
97
166
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
98
|
-
-H "X-Company-ID: adverant" \
|
|
99
|
-
-H "X-App-ID: claude-code" \
|
|
100
167
|
-d '{
|
|
101
168
|
"fileUrl": "YOUR_URL_HERE",
|
|
102
|
-
"filename": "filename"
|
|
103
|
-
"userId": "user-id"
|
|
169
|
+
"filename": "filename"
|
|
104
170
|
}'
|
|
105
171
|
```
|
|
106
172
|
|
|
173
|
+
> **Note:** The `X-Company-ID` header is automatically derived from your API key. Your data is isolated to your account.
|
|
174
|
+
|
|
107
175
|
### Upload Files Directly
|
|
108
176
|
|
|
109
177
|
```bash
|
|
110
178
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process" \
|
|
111
179
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
112
|
-
-
|
|
113
|
-
-H "X-App-ID: claude-code" \
|
|
114
|
-
-F "file=@/path/to/file" \
|
|
115
|
-
-F "userId=user-id"
|
|
180
|
+
-F "file=@/path/to/file"
|
|
116
181
|
```
|
|
117
182
|
|
|
118
183
|
---
|
|
@@ -125,7 +190,7 @@ You can ingest entire GitHub repositories into Nexus memory. This creates a "dig
|
|
|
125
190
|
- Voyage AI embeddings in Qdrant for semantic search
|
|
126
191
|
- GraphRAG episodic memory for context
|
|
127
192
|
|
|
128
|
-
###
|
|
193
|
+
### Public Repositories
|
|
129
194
|
|
|
130
195
|
Submit a GitHub repository URL to the FileProcessAgent:
|
|
131
196
|
|
|
@@ -133,15 +198,45 @@ Submit a GitHub repository URL to the FileProcessAgent:
|
|
|
133
198
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process/url" \
|
|
134
199
|
-H "Content-Type: application/json" \
|
|
135
200
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
136
|
-
-H "X-Company-ID: adverant" \
|
|
137
|
-
-H "X-App-ID: claude-code" \
|
|
138
201
|
-d '{
|
|
139
202
|
"fileUrl": "https://github.com/owner/repo",
|
|
140
|
-
"filename": "repository"
|
|
141
|
-
|
|
203
|
+
"filename": "repository"
|
|
204
|
+
}'
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Private Repositories
|
|
208
|
+
|
|
209
|
+
For private repositories, you need to provide a GitHub Personal Access Token (PAT) via the `X-GitHub-Token` header:
|
|
210
|
+
|
|
211
|
+
**Step 1: Create a GitHub PAT**
|
|
212
|
+
1. Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
|
|
213
|
+
2. Click "Generate new token (classic)"
|
|
214
|
+
3. Select scopes: `repo` (Full control of private repositories)
|
|
215
|
+
4. Copy the generated token
|
|
216
|
+
|
|
217
|
+
**Step 2: Set the token as an environment variable (recommended)**
|
|
218
|
+
```bash
|
|
219
|
+
export GITHUB_PAT='ghp_your_token_here'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Step 3: Ingest the private repository**
|
|
223
|
+
```bash
|
|
224
|
+
curl -X POST "https://api.adverant.ai/fileprocess/api/process/url" \
|
|
225
|
+
-H "Content-Type: application/json" \
|
|
226
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
227
|
+
-H "X-GitHub-Token: $GITHUB_PAT" \
|
|
228
|
+
-d '{
|
|
229
|
+
"fileUrl": "https://github.com/owner/private-repo",
|
|
230
|
+
"filename": "repository"
|
|
142
231
|
}'
|
|
143
232
|
```
|
|
144
233
|
|
|
234
|
+
**Security Notes:**
|
|
235
|
+
- Never commit your GitHub PAT to version control
|
|
236
|
+
- Use fine-grained tokens with minimal permissions when possible
|
|
237
|
+
- The token is only used for cloning and is not stored permanently
|
|
238
|
+
- Consider using GitHub App tokens for organization repositories
|
|
239
|
+
|
|
145
240
|
### Supported URL Formats
|
|
146
241
|
|
|
147
242
|
- `https://github.com/owner/repo`
|
|
@@ -182,6 +277,47 @@ echo '{"query": "authentication middleware implementation in owner/repo"}' | ~/.
|
|
|
182
277
|
echo '{"query": "how does the login function work in owner/repo"}' | ~/.claude/hooks/recall-memory.sh
|
|
183
278
|
```
|
|
184
279
|
|
|
280
|
+
### Check Sync Status
|
|
281
|
+
|
|
282
|
+
After starting a repository ingestion, you can check the progress and ETA:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Get repository ID from the ingestion response, then check status
|
|
286
|
+
REPO_ID="your-repo-id-from-response"
|
|
287
|
+
|
|
288
|
+
curl -s "https://api.adverant.ai/github/api/repositories/$REPO_ID/sync/status" \
|
|
289
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" | jq '.data.currentJob.progress'
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**Response Example:**
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"phase": "generating_embeddings",
|
|
296
|
+
"percentage": 72,
|
|
297
|
+
"filesProcessed": 450,
|
|
298
|
+
"totalFiles": 625,
|
|
299
|
+
"currentFile": "src/services/auth.ts",
|
|
300
|
+
"message": "Generating embeddings for parsed files",
|
|
301
|
+
"elapsedTime": "3m 45s",
|
|
302
|
+
"eta": "1m 30s",
|
|
303
|
+
"estimatedCompletionAt": "2025-12-29T18:05:00Z"
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Sync Phases:**
|
|
308
|
+
1. `cloning` - Cloning the repository
|
|
309
|
+
2. `parsing` - Discovering and parsing source files
|
|
310
|
+
3. `building_graph` - Building code graph in Neo4j
|
|
311
|
+
4. `generating_embeddings` - Creating Voyage AI embeddings
|
|
312
|
+
5. `extracting` - Extracting blame and history data
|
|
313
|
+
6. `complete` - Sync finished
|
|
314
|
+
|
|
315
|
+
**Quick Status Check (one-liner):**
|
|
316
|
+
```bash
|
|
317
|
+
curl -s "https://api.adverant.ai/github/api/repositories/$REPO_ID/sync/status" \
|
|
318
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" | jq '{state: .data.state, phase: .data.currentJob.progress.phase, progress: "\(.data.currentJob.progress.percentage)%", eta: .data.currentJob.progress.eta}'
|
|
319
|
+
```
|
|
320
|
+
|
|
185
321
|
---
|
|
186
322
|
|
|
187
323
|
## Video & YouTube Processing
|
|
@@ -192,8 +328,6 @@ Process videos for transcription, frame analysis, and metadata extraction:
|
|
|
192
328
|
# YouTube videos
|
|
193
329
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process/url" \
|
|
194
330
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
195
|
-
-H "X-Company-ID: adverant" \
|
|
196
|
-
-H "X-App-ID: claude-code" \
|
|
197
331
|
-H "Content-Type: application/json" \
|
|
198
332
|
-d '{"fileUrl": "https://youtube.com/watch?v=VIDEO_ID", "filename": "video"}'
|
|
199
333
|
```
|
|
@@ -214,10 +348,7 @@ Process geospatial and LiDAR data:
|
|
|
214
348
|
# GeoJSON, KML, Shapefile, LAS/LAZ files
|
|
215
349
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process" \
|
|
216
350
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
217
|
-
-
|
|
218
|
-
-H "X-App-ID: claude-code" \
|
|
219
|
-
-F "file=@/path/to/data.geojson" \
|
|
220
|
-
-F "userId=user-id"
|
|
351
|
+
-F "file=@/path/to/data.geojson"
|
|
221
352
|
```
|
|
222
353
|
|
|
223
354
|
**Supported Formats:**
|
|
@@ -242,10 +373,7 @@ Analyze executables and suspicious files:
|
|
|
242
373
|
# Binary analysis with CyberAgent
|
|
243
374
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process" \
|
|
244
375
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
245
|
-
-
|
|
246
|
-
-H "X-App-ID: claude-code" \
|
|
247
|
-
-F "file=@/path/to/binary.exe" \
|
|
248
|
-
-F "userId=user-id"
|
|
376
|
+
-F "file=@/path/to/binary.exe"
|
|
249
377
|
```
|
|
250
378
|
|
|
251
379
|
**Capabilities:**
|
|
@@ -271,10 +399,7 @@ Process PDFs, Office documents, and text files:
|
|
|
271
399
|
# Documents via MageAgent
|
|
272
400
|
curl -X POST "https://api.adverant.ai/fileprocess/api/process" \
|
|
273
401
|
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
274
|
-
-
|
|
275
|
-
-H "X-App-ID: claude-code" \
|
|
276
|
-
-F "file=@/path/to/document.pdf" \
|
|
277
|
-
-F "userId=user-id"
|
|
402
|
+
-F "file=@/path/to/document.pdf"
|
|
278
403
|
```
|
|
279
404
|
|
|
280
405
|
**Supported Formats:**
|
|
@@ -350,17 +475,16 @@ The hooks use the Nexus API Gateway at `https://api.adverant.ai`:
|
|
|
350
475
|
|
|
351
476
|
### Authentication
|
|
352
477
|
|
|
353
|
-
All requests require the
|
|
478
|
+
All requests require the Authorization header:
|
|
354
479
|
|
|
355
480
|
```
|
|
356
481
|
Authorization: Bearer <NEXUS_API_KEY>
|
|
357
|
-
X-Company-ID: adverant
|
|
358
|
-
X-App-ID: claude-code
|
|
359
|
-
X-User-ID: <user>
|
|
360
482
|
```
|
|
361
483
|
|
|
362
484
|
The `NEXUS_API_KEY` environment variable provides the Bearer token for authentication.
|
|
363
485
|
|
|
486
|
+
**Multi-tenancy:** Your company_id and user_id are automatically derived from your API key. There's no need to manually set `X-Company-ID` or `X-User-ID` headers - the backend determines tenant context from your API key ownership.
|
|
487
|
+
|
|
364
488
|
## Automatic Storage
|
|
365
489
|
|
|
366
490
|
The hooks automatically store:
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Nexus Memory - Auto Recall Hook
|
|
4
|
+
# Automatically recalls relevant context from Nexus GraphRAG on every user prompt.
|
|
5
|
+
#
|
|
6
|
+
# This hook is triggered on UserPromptSubmit to enrich Claude's context with
|
|
7
|
+
# relevant memories from past sessions, decisions, fixes, and learnings.
|
|
8
|
+
#
|
|
9
|
+
# Usage (automatic via settings.json):
|
|
10
|
+
# Triggered on every user prompt submission
|
|
11
|
+
#
|
|
12
|
+
# Environment Variables:
|
|
13
|
+
# NEXUS_API_KEY - API key for authentication (REQUIRED)
|
|
14
|
+
# NEXUS_API_URL - API endpoint (default: https://api.adverant.ai)
|
|
15
|
+
# NEXUS_COMPANY_ID - Company identifier (default: adverant)
|
|
16
|
+
# NEXUS_APP_ID - Application identifier (default: claude-code)
|
|
17
|
+
# NEXUS_VERBOSE - Set to 1 for debug output
|
|
18
|
+
# NEXUS_RECALL_LIMIT - Number of memories to recall (default: 5)
|
|
19
|
+
#
|
|
20
|
+
# Output:
|
|
21
|
+
# Returns relevant memories as context for Claude to use
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
set -o pipefail
|
|
25
|
+
|
|
26
|
+
# Configuration with environment variable overrides
|
|
27
|
+
NEXUS_API_KEY="${NEXUS_API_KEY:-}"
|
|
28
|
+
NEXUS_API_URL="${NEXUS_API_URL:-https://api.adverant.ai}"
|
|
29
|
+
COMPANY_ID="${NEXUS_COMPANY_ID:-adverant}"
|
|
30
|
+
APP_ID="${NEXUS_APP_ID:-claude-code}"
|
|
31
|
+
VERBOSE="${NEXUS_VERBOSE:-0}"
|
|
32
|
+
RECALL_LIMIT="${NEXUS_RECALL_LIMIT:-5}"
|
|
33
|
+
|
|
34
|
+
# Logging function
|
|
35
|
+
log() {
|
|
36
|
+
if [[ "$VERBOSE" == "1" ]]; then
|
|
37
|
+
echo "[auto-recall] $1" >&2
|
|
38
|
+
fi
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
log_error() {
|
|
42
|
+
echo "[auto-recall] ERROR: $1" >&2
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Skip if no API key (silently - don't block conversation)
|
|
46
|
+
if [[ -z "$NEXUS_API_KEY" ]]; then
|
|
47
|
+
log "NEXUS_API_KEY not set, skipping auto-recall"
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Check dependencies silently
|
|
52
|
+
if ! command -v jq &> /dev/null; then
|
|
53
|
+
log "jq not installed, skipping auto-recall"
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if ! command -v curl &> /dev/null; then
|
|
58
|
+
log "curl not installed, skipping auto-recall"
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Read input from stdin (the user's prompt)
|
|
63
|
+
INPUT=$(cat)
|
|
64
|
+
|
|
65
|
+
if [[ -z "$INPUT" ]]; then
|
|
66
|
+
log "No input provided, skipping"
|
|
67
|
+
exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
log "Received prompt: ${INPUT:0:100}..."
|
|
71
|
+
|
|
72
|
+
# Extract the user's prompt/query
|
|
73
|
+
QUERY=$(echo "$INPUT" | jq -r '.prompt // .content // .tool_input.command // empty' 2>/dev/null)
|
|
74
|
+
|
|
75
|
+
# Skip if no query content
|
|
76
|
+
if [[ -z "$QUERY" ]] || [[ "$QUERY" == "null" ]]; then
|
|
77
|
+
log "No query content, skipping"
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Truncate very long queries for recall
|
|
82
|
+
if [[ ${#QUERY} -gt 500 ]]; then
|
|
83
|
+
QUERY="${QUERY:0:500}"
|
|
84
|
+
log "Query truncated to 500 characters for recall"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Get current project for context
|
|
88
|
+
PROJECT_NAME=$(basename "$(pwd)")
|
|
89
|
+
PROJECT_DIR=$(pwd)
|
|
90
|
+
|
|
91
|
+
log "Query: ${QUERY:0:100}..."
|
|
92
|
+
log "Project: $PROJECT_NAME"
|
|
93
|
+
log "Limit: $RECALL_LIMIT"
|
|
94
|
+
|
|
95
|
+
# Build the recall payload with project context
|
|
96
|
+
PAYLOAD=$(jq -n \
|
|
97
|
+
--arg query "$QUERY" \
|
|
98
|
+
--argjson limit "$RECALL_LIMIT" \
|
|
99
|
+
--arg project "$PROJECT_NAME" \
|
|
100
|
+
'{
|
|
101
|
+
query: $query,
|
|
102
|
+
limit: $limit,
|
|
103
|
+
filters: {
|
|
104
|
+
project: $project
|
|
105
|
+
}
|
|
106
|
+
}')
|
|
107
|
+
|
|
108
|
+
log "Recalling from $NEXUS_API_URL/api/memory/recall"
|
|
109
|
+
|
|
110
|
+
# Search GraphRAG for relevant memories via API Gateway
|
|
111
|
+
# Use short timeout to not block conversation
|
|
112
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$NEXUS_API_URL/api/memory/recall" \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
115
|
+
-H "X-Company-ID: $COMPANY_ID" \
|
|
116
|
+
-H "X-App-ID: $APP_ID" \
|
|
117
|
+
-H "X-User-ID: ${USER:-unknown}" \
|
|
118
|
+
-d "$PAYLOAD" \
|
|
119
|
+
--max-time 5 2>&1)
|
|
120
|
+
|
|
121
|
+
# Parse response
|
|
122
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
123
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
124
|
+
|
|
125
|
+
log "Response code: $HTTP_CODE"
|
|
126
|
+
|
|
127
|
+
# Check for errors (silently fail - don't block conversation)
|
|
128
|
+
if [[ "$HTTP_CODE" != "200" ]]; then
|
|
129
|
+
log "Failed to recall memories (HTTP $HTTP_CODE), continuing without context"
|
|
130
|
+
exit 0
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Validate JSON response
|
|
134
|
+
if ! echo "$BODY" | jq . &>/dev/null; then
|
|
135
|
+
log "Invalid JSON response, continuing without context"
|
|
136
|
+
exit 0
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Extract memories and format as context
|
|
140
|
+
MEMORIES=$(echo "$BODY" | jq -r '.memories // []' 2>/dev/null)
|
|
141
|
+
MEMORY_COUNT=$(echo "$MEMORIES" | jq 'length' 2>/dev/null || echo "0")
|
|
142
|
+
|
|
143
|
+
log "Found $MEMORY_COUNT relevant memories"
|
|
144
|
+
|
|
145
|
+
# If we have memories, output them as context for Claude
|
|
146
|
+
if [[ "$MEMORY_COUNT" -gt 0 ]] && [[ "$MEMORY_COUNT" != "null" ]]; then
|
|
147
|
+
# Format memories as readable context
|
|
148
|
+
echo ""
|
|
149
|
+
echo "<nexus-memory-context>"
|
|
150
|
+
echo "The following relevant context was automatically recalled from Nexus Memory:"
|
|
151
|
+
echo ""
|
|
152
|
+
|
|
153
|
+
echo "$MEMORIES" | jq -r '.[] |
|
|
154
|
+
"- [\(.metadata.eventType // "context")] \(.content | if length > 300 then .[0:300] + "..." else . end)"
|
|
155
|
+
' 2>/dev/null | head -n 10
|
|
156
|
+
|
|
157
|
+
echo ""
|
|
158
|
+
echo "</nexus-memory-context>"
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
exit 0
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Nexus Memory - Episode Summary Hook
|
|
4
|
+
# Generates periodic summaries of conversation segments as "episodes" for long-term memory.
|
|
5
|
+
#
|
|
6
|
+
# This hook can be triggered:
|
|
7
|
+
# - At session end (Stop hook)
|
|
8
|
+
# - After N tool uses (counter-based)
|
|
9
|
+
# - Manually to summarize current conversation
|
|
10
|
+
#
|
|
11
|
+
# Episodes capture:
|
|
12
|
+
# - Topics discussed
|
|
13
|
+
# - Decisions made
|
|
14
|
+
# - Problems solved
|
|
15
|
+
# - Key learnings
|
|
16
|
+
#
|
|
17
|
+
# Usage:
|
|
18
|
+
# echo '{"conversation_summary": "...", "tool_count": 5}' | episode-summary.sh
|
|
19
|
+
#
|
|
20
|
+
# Environment Variables:
|
|
21
|
+
# NEXUS_API_KEY - API key for authentication (REQUIRED)
|
|
22
|
+
# NEXUS_API_URL - API endpoint (default: https://api.adverant.ai)
|
|
23
|
+
# NEXUS_COMPANY_ID - Company identifier (default: adverant)
|
|
24
|
+
# NEXUS_APP_ID - Application identifier (default: claude-code)
|
|
25
|
+
# NEXUS_VERBOSE - Set to 1 for debug output
|
|
26
|
+
# NEXUS_EPISODE_THRESHOLD - Tool count threshold for episode generation (default: 10)
|
|
27
|
+
#
|
|
28
|
+
|
|
29
|
+
set -o pipefail
|
|
30
|
+
|
|
31
|
+
# Configuration with environment variable overrides
|
|
32
|
+
NEXUS_API_KEY="${NEXUS_API_KEY:-}"
|
|
33
|
+
NEXUS_API_URL="${NEXUS_API_URL:-https://api.adverant.ai}"
|
|
34
|
+
COMPANY_ID="${NEXUS_COMPANY_ID:-adverant}"
|
|
35
|
+
APP_ID="${NEXUS_APP_ID:-claude-code}"
|
|
36
|
+
VERBOSE="${NEXUS_VERBOSE:-0}"
|
|
37
|
+
EPISODE_THRESHOLD="${NEXUS_EPISODE_THRESHOLD:-10}"
|
|
38
|
+
|
|
39
|
+
# State file for tracking tool count
|
|
40
|
+
STATE_DIR="${HOME}/.claude/session-env"
|
|
41
|
+
COUNTER_FILE="${STATE_DIR}/episode_counter"
|
|
42
|
+
|
|
43
|
+
# Logging function
|
|
44
|
+
log() {
|
|
45
|
+
if [[ "$VERBOSE" == "1" ]]; then
|
|
46
|
+
echo "[episode-summary] $1" >&2
|
|
47
|
+
fi
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
log_error() {
|
|
51
|
+
echo "[episode-summary] ERROR: $1" >&2
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Skip if no API key
|
|
55
|
+
if [[ -z "$NEXUS_API_KEY" ]]; then
|
|
56
|
+
log "NEXUS_API_KEY not set, skipping episode summary"
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Check dependencies
|
|
61
|
+
if ! command -v jq &> /dev/null; then
|
|
62
|
+
log "jq not installed, skipping episode summary"
|
|
63
|
+
exit 0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if ! command -v curl &> /dev/null; then
|
|
67
|
+
log "curl not installed, skipping episode summary"
|
|
68
|
+
exit 0
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Ensure state directory exists
|
|
72
|
+
mkdir -p "$STATE_DIR"
|
|
73
|
+
|
|
74
|
+
# Read input from stdin
|
|
75
|
+
INPUT=$(cat)
|
|
76
|
+
|
|
77
|
+
if [[ -z "$INPUT" ]]; then
|
|
78
|
+
log "No input provided"
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
log "Received input: ${INPUT:0:100}..."
|
|
83
|
+
|
|
84
|
+
# Extract fields from input
|
|
85
|
+
FORCE_SUMMARY=$(echo "$INPUT" | jq -r '.force // false' 2>/dev/null)
|
|
86
|
+
SESSION_END=$(echo "$INPUT" | jq -r '.session_end // false' 2>/dev/null)
|
|
87
|
+
CONTENT=$(echo "$INPUT" | jq -r '.content // .conversation_summary // .prompt // empty' 2>/dev/null)
|
|
88
|
+
|
|
89
|
+
# Get current counter
|
|
90
|
+
if [[ -f "$COUNTER_FILE" ]]; then
|
|
91
|
+
CURRENT_COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
|
|
92
|
+
else
|
|
93
|
+
CURRENT_COUNT=0
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# Increment counter
|
|
97
|
+
NEW_COUNT=$((CURRENT_COUNT + 1))
|
|
98
|
+
echo "$NEW_COUNT" > "$COUNTER_FILE"
|
|
99
|
+
|
|
100
|
+
log "Tool count: $NEW_COUNT (threshold: $EPISODE_THRESHOLD)"
|
|
101
|
+
|
|
102
|
+
# Determine if we should generate an episode summary
|
|
103
|
+
SHOULD_SUMMARIZE=false
|
|
104
|
+
|
|
105
|
+
if [[ "$FORCE_SUMMARY" == "true" ]]; then
|
|
106
|
+
SHOULD_SUMMARIZE=true
|
|
107
|
+
log "Forced summary requested"
|
|
108
|
+
elif [[ "$SESSION_END" == "true" ]]; then
|
|
109
|
+
SHOULD_SUMMARIZE=true
|
|
110
|
+
log "Session end summary"
|
|
111
|
+
elif [[ "$NEW_COUNT" -ge "$EPISODE_THRESHOLD" ]]; then
|
|
112
|
+
SHOULD_SUMMARIZE=true
|
|
113
|
+
log "Threshold reached, generating episode"
|
|
114
|
+
# Reset counter
|
|
115
|
+
echo "0" > "$COUNTER_FILE"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Exit if we shouldn't summarize
|
|
119
|
+
if [[ "$SHOULD_SUMMARIZE" != "true" ]]; then
|
|
120
|
+
log "Not generating episode yet (count: $NEW_COUNT/$EPISODE_THRESHOLD)"
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Get project context
|
|
125
|
+
PROJECT_NAME=$(basename "$(pwd)")
|
|
126
|
+
PROJECT_DIR=$(pwd)
|
|
127
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
128
|
+
SESSION_ID=$(date +%Y%m%d-%H%M%S)
|
|
129
|
+
|
|
130
|
+
# Skip if no content to summarize
|
|
131
|
+
if [[ -z "$CONTENT" ]] || [[ "$CONTENT" == "null" ]]; then
|
|
132
|
+
# Try to get recent content from session
|
|
133
|
+
CONTENT="Conversation segment in $PROJECT_NAME project"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Truncate very long content
|
|
137
|
+
if [[ ${#CONTENT} -gt 5000 ]]; then
|
|
138
|
+
CONTENT="${CONTENT:0:5000}... [truncated]"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Generate episode summary
|
|
142
|
+
# For now, we create a structured episode from the content
|
|
143
|
+
# Future enhancement: Use LLM to generate smart summaries
|
|
144
|
+
EPISODE_CONTENT=$(cat <<EOF
|
|
145
|
+
[Episode Summary - $PROJECT_NAME]
|
|
146
|
+
Timestamp: $TIMESTAMP
|
|
147
|
+
Project: $PROJECT_NAME
|
|
148
|
+
Directory: $PROJECT_DIR
|
|
149
|
+
|
|
150
|
+
Session Activity:
|
|
151
|
+
$CONTENT
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
This episode was automatically generated after $NEW_COUNT tool interactions.
|
|
155
|
+
EOF
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
log "Generating episode summary for $PROJECT_NAME"
|
|
159
|
+
|
|
160
|
+
# Build the payload
|
|
161
|
+
PAYLOAD=$(jq -n \
|
|
162
|
+
--arg content "$EPISODE_CONTENT" \
|
|
163
|
+
--arg session "$SESSION_ID" \
|
|
164
|
+
--arg project "$PROJECT_NAME" \
|
|
165
|
+
--arg projectDir "$PROJECT_DIR" \
|
|
166
|
+
--arg timestamp "$TIMESTAMP" \
|
|
167
|
+
--argjson toolCount "$NEW_COUNT" \
|
|
168
|
+
'{
|
|
169
|
+
content: $content,
|
|
170
|
+
tags: ["claude-code", "type:episode", "project:\($project)", "session:\($session)"],
|
|
171
|
+
metadata: {
|
|
172
|
+
sessionId: $session,
|
|
173
|
+
eventType: "episode",
|
|
174
|
+
projectDir: $projectDir,
|
|
175
|
+
projectName: $project,
|
|
176
|
+
timestamp: $timestamp,
|
|
177
|
+
toolCount: $toolCount,
|
|
178
|
+
isEpisodeSummary: true
|
|
179
|
+
}
|
|
180
|
+
}')
|
|
181
|
+
|
|
182
|
+
log "Storing episode to $NEXUS_API_URL/api/memory/store"
|
|
183
|
+
|
|
184
|
+
# Store to GraphRAG via API Gateway
|
|
185
|
+
if [[ "$VERBOSE" == "1" ]]; then
|
|
186
|
+
# Sync mode with output for debugging
|
|
187
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$NEXUS_API_URL/api/memory/store" \
|
|
188
|
+
-H "Content-Type: application/json" \
|
|
189
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
190
|
+
-H "X-Company-ID: $COMPANY_ID" \
|
|
191
|
+
-H "X-App-ID: $APP_ID" \
|
|
192
|
+
-H "X-User-ID: ${USER:-unknown}" \
|
|
193
|
+
-d "$PAYLOAD" \
|
|
194
|
+
--max-time 10 2>&1)
|
|
195
|
+
|
|
196
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
197
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
198
|
+
|
|
199
|
+
log "Response code: $HTTP_CODE"
|
|
200
|
+
log "Response body: $BODY"
|
|
201
|
+
|
|
202
|
+
if [[ "$HTTP_CODE" != "200" ]] && [[ "$HTTP_CODE" != "201" ]]; then
|
|
203
|
+
log_error "Failed to store episode (HTTP $HTTP_CODE)"
|
|
204
|
+
else
|
|
205
|
+
log "Episode stored successfully"
|
|
206
|
+
fi
|
|
207
|
+
else
|
|
208
|
+
# Async mode (fire-and-forget) for normal operation
|
|
209
|
+
(curl -s -X POST "$NEXUS_API_URL/api/memory/store" \
|
|
210
|
+
-H "Content-Type: application/json" \
|
|
211
|
+
-H "Authorization: Bearer $NEXUS_API_KEY" \
|
|
212
|
+
-H "X-Company-ID: $COMPANY_ID" \
|
|
213
|
+
-H "X-App-ID: $APP_ID" \
|
|
214
|
+
-H "X-User-ID: ${USER:-unknown}" \
|
|
215
|
+
-d "$PAYLOAD" \
|
|
216
|
+
--max-time 5 &>/dev/null) &
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
# Reset counter after successful summary
|
|
220
|
+
echo "0" > "$COUNTER_FILE"
|
|
221
|
+
|
|
222
|
+
log "Episode summary complete"
|
|
223
|
+
exit 0
|
package/install.sh
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Nexus Memory - Installation Script
|
|
4
|
+
# Installs the Nexus Memory skill for Claude Code with automatic memory features.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# curl -fsSL https://raw.githubusercontent.com/adverant/nexus-memory-skill/main/install.sh | bash
|
|
8
|
+
# OR
|
|
9
|
+
# ./install.sh
|
|
10
|
+
#
|
|
11
|
+
# What this script does:
|
|
12
|
+
# 1. Creates necessary directories (~/.claude/skills, ~/.claude/hooks)
|
|
13
|
+
# 2. Copies skill and hook files
|
|
14
|
+
# 3. Configures settings.json for automatic memory
|
|
15
|
+
# 4. Helps you set up your API key (opens browser if needed)
|
|
16
|
+
# 5. Verifies the installation
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
set -e
|
|
20
|
+
|
|
21
|
+
# Colors for output
|
|
22
|
+
RED='\033[0;31m'
|
|
23
|
+
GREEN='\033[0;32m'
|
|
24
|
+
YELLOW='\033[1;33m'
|
|
25
|
+
BLUE='\033[0;34m'
|
|
26
|
+
NC='\033[0m' # No Color
|
|
27
|
+
|
|
28
|
+
# Logging functions
|
|
29
|
+
log_info() {
|
|
30
|
+
echo -e "${BLUE}[INFO]${NC} $1"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
log_success() {
|
|
34
|
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
log_warn() {
|
|
38
|
+
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
log_error() {
|
|
42
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Check for required commands
|
|
46
|
+
check_dependencies() {
|
|
47
|
+
local missing=()
|
|
48
|
+
|
|
49
|
+
if ! command -v curl &> /dev/null; then
|
|
50
|
+
missing+=("curl")
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if ! command -v jq &> /dev/null; then
|
|
54
|
+
missing+=("jq")
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [ ${#missing[@]} -ne 0 ]; then
|
|
58
|
+
log_error "Missing required dependencies: ${missing[*]}"
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Please install them first:"
|
|
61
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
62
|
+
echo " brew install ${missing[*]}"
|
|
63
|
+
else
|
|
64
|
+
echo " sudo apt-get install ${missing[*]}"
|
|
65
|
+
fi
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Get the script directory (works for both local and remote install)
|
|
71
|
+
get_source_dir() {
|
|
72
|
+
if [ -d "$(dirname "$0")/hooks" ]; then
|
|
73
|
+
echo "$(cd "$(dirname "$0")" && pwd)"
|
|
74
|
+
else
|
|
75
|
+
# Remote install - download to temp directory
|
|
76
|
+
local temp_dir=$(mktemp -d)
|
|
77
|
+
log_info "Downloading Nexus Memory skill..."
|
|
78
|
+
git clone --depth 1 https://github.com/adverant/nexus-memory-skill.git "$temp_dir" 2>/dev/null || {
|
|
79
|
+
log_error "Failed to download. Please check your internet connection."
|
|
80
|
+
exit 1
|
|
81
|
+
}
|
|
82
|
+
echo "$temp_dir"
|
|
83
|
+
fi
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Create required directories
|
|
87
|
+
create_directories() {
|
|
88
|
+
log_info "Creating directories..."
|
|
89
|
+
mkdir -p ~/.claude/skills/nexus-memory
|
|
90
|
+
mkdir -p ~/.claude/hooks
|
|
91
|
+
mkdir -p ~/.claude/session-env
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Copy skill and hooks
|
|
95
|
+
install_files() {
|
|
96
|
+
local source_dir="$1"
|
|
97
|
+
|
|
98
|
+
log_info "Installing skill file..."
|
|
99
|
+
cp "$source_dir/SKILL.md" ~/.claude/skills/nexus-memory/SKILL.md
|
|
100
|
+
|
|
101
|
+
log_info "Installing hooks..."
|
|
102
|
+
cp "$source_dir/hooks/store-memory.sh" ~/.claude/hooks/
|
|
103
|
+
cp "$source_dir/hooks/recall-memory.sh" ~/.claude/hooks/
|
|
104
|
+
cp "$source_dir/hooks/auto-recall.sh" ~/.claude/hooks/
|
|
105
|
+
cp "$source_dir/hooks/episode-summary.sh" ~/.claude/hooks/
|
|
106
|
+
|
|
107
|
+
# Make hooks executable
|
|
108
|
+
chmod +x ~/.claude/hooks/store-memory.sh
|
|
109
|
+
chmod +x ~/.claude/hooks/recall-memory.sh
|
|
110
|
+
chmod +x ~/.claude/hooks/auto-recall.sh
|
|
111
|
+
chmod +x ~/.claude/hooks/episode-summary.sh
|
|
112
|
+
|
|
113
|
+
# Copy upload-document.sh if it exists
|
|
114
|
+
if [ -f "$source_dir/hooks/upload-document.sh" ]; then
|
|
115
|
+
cp "$source_dir/hooks/upload-document.sh" ~/.claude/hooks/
|
|
116
|
+
chmod +x ~/.claude/hooks/upload-document.sh
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
log_success "Files installed successfully"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# Configure settings.json
|
|
123
|
+
configure_settings() {
|
|
124
|
+
log_info "Configuring Claude Code settings..."
|
|
125
|
+
|
|
126
|
+
local settings_file=~/.claude/settings.json
|
|
127
|
+
|
|
128
|
+
# Create settings.json with automatic memory hooks
|
|
129
|
+
cat > "$settings_file" << 'EOF'
|
|
130
|
+
{
|
|
131
|
+
"hooks": {
|
|
132
|
+
"UserPromptSubmit": [
|
|
133
|
+
{
|
|
134
|
+
"matcher": "",
|
|
135
|
+
"hooks": [
|
|
136
|
+
{
|
|
137
|
+
"type": "command",
|
|
138
|
+
"command": "~/.claude/hooks/auto-recall.sh"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"type": "command",
|
|
142
|
+
"command": "~/.claude/hooks/store-memory.sh"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"PostToolUse": [
|
|
148
|
+
{
|
|
149
|
+
"matcher": "",
|
|
150
|
+
"hooks": [
|
|
151
|
+
{
|
|
152
|
+
"type": "command",
|
|
153
|
+
"command": "~/.claude/hooks/store-memory.sh"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"type": "command",
|
|
157
|
+
"command": "~/.claude/hooks/episode-summary.sh"
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
EOF
|
|
165
|
+
|
|
166
|
+
log_success "Settings configured for automatic memory"
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# Open browser to get API key
|
|
170
|
+
open_browser() {
|
|
171
|
+
local url="$1"
|
|
172
|
+
|
|
173
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
174
|
+
open "$url" 2>/dev/null || true
|
|
175
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
176
|
+
xdg-open "$url" 2>/dev/null || true
|
|
177
|
+
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
|
|
178
|
+
start "$url" 2>/dev/null || true
|
|
179
|
+
fi
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# Setup API key
|
|
183
|
+
setup_api_key() {
|
|
184
|
+
echo ""
|
|
185
|
+
log_info "Checking API key configuration..."
|
|
186
|
+
|
|
187
|
+
if [ -n "$NEXUS_API_KEY" ]; then
|
|
188
|
+
log_success "NEXUS_API_KEY is already configured"
|
|
189
|
+
return 0
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
echo ""
|
|
193
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
194
|
+
echo -e "${YELLOW} API Key Setup Required ${NC}"
|
|
195
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
196
|
+
echo ""
|
|
197
|
+
echo "Nexus Memory requires an API key to store and recall memories."
|
|
198
|
+
echo ""
|
|
199
|
+
echo "Steps to get your API key:"
|
|
200
|
+
echo " 1. A browser window will open to the Nexus Dashboard"
|
|
201
|
+
echo " 2. Log in or create a free account"
|
|
202
|
+
echo " 3. Navigate to 'API Keys' section"
|
|
203
|
+
echo " 4. Click 'Create New Key'"
|
|
204
|
+
echo " 5. Copy your new API key"
|
|
205
|
+
echo ""
|
|
206
|
+
|
|
207
|
+
read -p "Press Enter to open the dashboard in your browser..."
|
|
208
|
+
|
|
209
|
+
open_browser "https://dashboard.adverant.ai/dashboard/api-keys"
|
|
210
|
+
|
|
211
|
+
echo ""
|
|
212
|
+
echo "Paste your API key below (it will be hidden):"
|
|
213
|
+
read -s api_key
|
|
214
|
+
echo ""
|
|
215
|
+
|
|
216
|
+
if [ -z "$api_key" ]; then
|
|
217
|
+
log_warn "No API key provided. You can set it later with:"
|
|
218
|
+
echo " export NEXUS_API_KEY='your-api-key-here'"
|
|
219
|
+
return 1
|
|
220
|
+
fi
|
|
221
|
+
|
|
222
|
+
# Detect shell profile
|
|
223
|
+
local shell_profile=""
|
|
224
|
+
if [ -f ~/.zshrc ]; then
|
|
225
|
+
shell_profile=~/.zshrc
|
|
226
|
+
elif [ -f ~/.bashrc ]; then
|
|
227
|
+
shell_profile=~/.bashrc
|
|
228
|
+
elif [ -f ~/.bash_profile ]; then
|
|
229
|
+
shell_profile=~/.bash_profile
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
if [ -n "$shell_profile" ]; then
|
|
233
|
+
# Remove any existing NEXUS_API_KEY line
|
|
234
|
+
grep -v "^export NEXUS_API_KEY=" "$shell_profile" > "${shell_profile}.tmp" 2>/dev/null && mv "${shell_profile}.tmp" "$shell_profile"
|
|
235
|
+
|
|
236
|
+
# Add the new key
|
|
237
|
+
echo "export NEXUS_API_KEY='$api_key'" >> "$shell_profile"
|
|
238
|
+
log_success "API key added to $shell_profile"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
# Export for current session
|
|
242
|
+
export NEXUS_API_KEY="$api_key"
|
|
243
|
+
|
|
244
|
+
# Verify the key works
|
|
245
|
+
log_info "Verifying API key..."
|
|
246
|
+
local response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "https://api.adverant.ai/api/memory/recall" \
|
|
247
|
+
-H "Content-Type: application/json" \
|
|
248
|
+
-H "Authorization: Bearer $api_key" \
|
|
249
|
+
-d '{"query": "test", "limit": 1}' \
|
|
250
|
+
--max-time 10 2>/dev/null)
|
|
251
|
+
|
|
252
|
+
if [ "$response" = "200" ] || [ "$response" = "201" ]; then
|
|
253
|
+
log_success "API key verified successfully!"
|
|
254
|
+
elif [ "$response" = "401" ]; then
|
|
255
|
+
log_warn "API key verification failed (401). Please check your key is correct."
|
|
256
|
+
else
|
|
257
|
+
log_warn "Could not verify API key (HTTP $response). Please check your internet connection."
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
echo ""
|
|
261
|
+
log_info "To apply the API key in your current terminal, run:"
|
|
262
|
+
echo " source $shell_profile"
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
# Verify installation
|
|
266
|
+
verify_installation() {
|
|
267
|
+
echo ""
|
|
268
|
+
log_info "Verifying installation..."
|
|
269
|
+
|
|
270
|
+
local errors=0
|
|
271
|
+
|
|
272
|
+
if [ -f ~/.claude/skills/nexus-memory/SKILL.md ]; then
|
|
273
|
+
log_success "Skill file: OK"
|
|
274
|
+
else
|
|
275
|
+
log_error "Skill file: MISSING"
|
|
276
|
+
((errors++))
|
|
277
|
+
fi
|
|
278
|
+
|
|
279
|
+
for hook in store-memory.sh recall-memory.sh auto-recall.sh episode-summary.sh; do
|
|
280
|
+
if [ -x ~/.claude/hooks/$hook ]; then
|
|
281
|
+
log_success "Hook $hook: OK"
|
|
282
|
+
else
|
|
283
|
+
log_error "Hook $hook: MISSING or not executable"
|
|
284
|
+
((errors++))
|
|
285
|
+
fi
|
|
286
|
+
done
|
|
287
|
+
|
|
288
|
+
if [ -f ~/.claude/settings.json ]; then
|
|
289
|
+
log_success "Settings file: OK"
|
|
290
|
+
else
|
|
291
|
+
log_error "Settings file: MISSING"
|
|
292
|
+
((errors++))
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
if [ $errors -gt 0 ]; then
|
|
296
|
+
log_error "Installation completed with $errors error(s)"
|
|
297
|
+
return 1
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
return 0
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
# Print success message
|
|
304
|
+
print_success() {
|
|
305
|
+
echo ""
|
|
306
|
+
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
307
|
+
echo -e "${GREEN} Nexus Memory Installation Complete! ${NC}"
|
|
308
|
+
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
309
|
+
echo ""
|
|
310
|
+
echo "Automatic Memory Features Enabled:"
|
|
311
|
+
echo " - Auto-recall: Relevant memories fetched on every prompt"
|
|
312
|
+
echo " - Auto-store: Every prompt and tool use captured"
|
|
313
|
+
echo " - Episode summaries: Generated every 10 tool uses"
|
|
314
|
+
echo ""
|
|
315
|
+
echo "Manual Commands:"
|
|
316
|
+
echo " Store: echo '{\"content\": \"...\", \"event_type\": \"learning\"}' | ~/.claude/hooks/store-memory.sh"
|
|
317
|
+
echo " Recall: echo '{\"query\": \"...\"}' | ~/.claude/hooks/recall-memory.sh"
|
|
318
|
+
echo ""
|
|
319
|
+
echo "Environment Variables:"
|
|
320
|
+
echo " NEXUS_VERBOSE=1 Enable debug output"
|
|
321
|
+
echo " NEXUS_RECALL_LIMIT=10 Number of memories to auto-recall"
|
|
322
|
+
echo ""
|
|
323
|
+
echo "Documentation: https://github.com/adverant/nexus-memory-skill"
|
|
324
|
+
echo ""
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
# Main installation function
|
|
328
|
+
main() {
|
|
329
|
+
echo ""
|
|
330
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
331
|
+
echo -e "${BLUE} Nexus Memory Installer ${NC}"
|
|
332
|
+
echo -e "${BLUE} Give Your AI Perfect Recall — Across Every Session ${NC}"
|
|
333
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
334
|
+
echo ""
|
|
335
|
+
|
|
336
|
+
check_dependencies
|
|
337
|
+
|
|
338
|
+
local source_dir
|
|
339
|
+
source_dir=$(get_source_dir)
|
|
340
|
+
|
|
341
|
+
create_directories
|
|
342
|
+
install_files "$source_dir"
|
|
343
|
+
configure_settings
|
|
344
|
+
setup_api_key
|
|
345
|
+
|
|
346
|
+
if verify_installation; then
|
|
347
|
+
print_success
|
|
348
|
+
else
|
|
349
|
+
log_error "Installation verification failed. Please check the errors above."
|
|
350
|
+
exit 1
|
|
351
|
+
fi
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
# Run main
|
|
355
|
+
main "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adverant/nexus-memory-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Claude Code skill for persistent memory via Nexus GraphRAG - store and recall memories across all sessions and projects",
|
|
5
5
|
"main": "SKILL.md",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"README.md",
|
|
31
31
|
"LICENSE",
|
|
32
32
|
"hooks/",
|
|
33
|
-
"docs/"
|
|
33
|
+
"docs/",
|
|
34
|
+
"install.sh"
|
|
34
35
|
],
|
|
35
36
|
"publishConfig": {
|
|
36
37
|
"access": "public",
|