@unifiedmemory/cli 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/.env.example +27 -6
- package/CHANGELOG.md +232 -0
- package/README.md +207 -132
- package/commands/init.js +246 -69
- package/commands/login.js +9 -95
- package/commands/org.js +9 -38
- package/index.js +17 -26
- package/lib/config.js +42 -24
- package/lib/jwt-utils.js +63 -0
- package/lib/mcp-server.js +1 -1
- package/lib/memory-instructions.js +72 -0
- package/lib/org-selection-ui.js +104 -0
- package/lib/provider-detector.js +69 -75
- package/lib/token-refresh.js +1 -18
- package/lib/token-storage.js +15 -2
- package/lib/welcome.js +40 -0
- package/package.json +6 -4
- package/HOOK_SETUP.md +0 -338
- package/lib/hooks.js +0 -43
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unifiedmemory/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "UnifiedMemory CLI - AI code assistant integration",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -31,13 +31,15 @@
|
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://unifiedmemory.ai",
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@iarna/toml": "^2.2.5",
|
|
34
35
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
36
|
+
"axios": "^1.6.2",
|
|
35
37
|
"chalk": "^5.3.0",
|
|
36
38
|
"commander": "^11.1.0",
|
|
39
|
+
"dotenv": "^16.6.1",
|
|
40
|
+
"fs-extra": "^11.2.0",
|
|
37
41
|
"inquirer": "^13.0.1",
|
|
38
|
-
"open": "^10.0.3"
|
|
39
|
-
"axios": "^1.6.2",
|
|
40
|
-
"fs-extra": "^11.2.0"
|
|
42
|
+
"open": "^10.0.3"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"pkg": "^5.8.1"
|
package/HOOK_SETUP.md
DELETED
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
# UnifiedMemory CLI Hook Integration
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
This document explains how to set up automatic vault recording using Claude Code hooks with the `um note create` CLI command.
|
|
6
|
-
|
|
7
|
-
## Background
|
|
8
|
-
|
|
9
|
-
Claude Code's "prompt" type hooks are not supported outside REPL mode. To work around this limitation, we've implemented a command-style hook that calls the `um note create` CLI command directly.
|
|
10
|
-
|
|
11
|
-
## Components
|
|
12
|
-
|
|
13
|
-
### 1. CLI Command: `um note create`
|
|
14
|
-
|
|
15
|
-
A new CLI command that creates notes in the vault:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
um note create "<summary text>" [options]
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Options**:
|
|
22
|
-
- `--topic <topic>` - Topic for the note (default: "general")
|
|
23
|
-
- `--source <source>` - Source identifier (default: "um-cli")
|
|
24
|
-
- `--confidence <confidence>` - Confidence score 0-1 (default: "0.7")
|
|
25
|
-
- `--tags <tags>` - Comma-separated tags
|
|
26
|
-
- `--metadata <json>` - Additional metadata as JSON string
|
|
27
|
-
|
|
28
|
-
**Example**:
|
|
29
|
-
```bash
|
|
30
|
-
um note create "Completed implementation of user authentication" \
|
|
31
|
-
--topic "development" \
|
|
32
|
-
--source "manual" \
|
|
33
|
-
--confidence "0.9" \
|
|
34
|
-
--tags "auth,feature,completed"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. Hook Script: `.claude/hooks/post-exit-plan-mode.sh`
|
|
38
|
-
|
|
39
|
-
A shell script that automatically calls `um note create` after exiting plan mode:
|
|
40
|
-
|
|
41
|
-
**Location**: `<project>/.claude/hooks/post-exit-plan-mode.sh`
|
|
42
|
-
|
|
43
|
-
**Requirements**:
|
|
44
|
-
- Must be executable (`chmod +x`)
|
|
45
|
-
- Update the `UM_CLI` path to point to your um-cli installation
|
|
46
|
-
|
|
47
|
-
### 3. Hook Configuration: `.claude/settings.json`
|
|
48
|
-
|
|
49
|
-
Configure Claude Code to run the hook:
|
|
50
|
-
|
|
51
|
-
```json
|
|
52
|
-
{
|
|
53
|
-
"hooks": {
|
|
54
|
-
"PostToolUse": [
|
|
55
|
-
{
|
|
56
|
-
"matcher": "ExitPlanMode",
|
|
57
|
-
"hooks": [
|
|
58
|
-
{
|
|
59
|
-
"type": "command",
|
|
60
|
-
"command": "./.claude/hooks/post-exit-plan-mode.sh 'Plan summary: Completed plan mode session'",
|
|
61
|
-
"statusMessage": "Recording plan to vault..."
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Setup Instructions
|
|
71
|
-
|
|
72
|
-
### Step 1: Install um-cli
|
|
73
|
-
|
|
74
|
-
The `um` CLI should be installed and configured:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# Authenticate
|
|
78
|
-
um login
|
|
79
|
-
|
|
80
|
-
# Initialize project
|
|
81
|
-
cd <your-project>
|
|
82
|
-
um init
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
This creates:
|
|
86
|
-
- `~/.um/auth.json` - User authentication
|
|
87
|
-
- `.um/config.json` - Project configuration (org_id, project_id)
|
|
88
|
-
|
|
89
|
-
### Step 2: Create Hook Script
|
|
90
|
-
|
|
91
|
-
Create `.claude/hooks/post-exit-plan-mode.sh` in your project:
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
mkdir -p .claude/hooks
|
|
95
|
-
cat > .claude/hooks/post-exit-plan-mode.sh << 'EOF'
|
|
96
|
-
#!/usr/bin/env bash
|
|
97
|
-
set -e
|
|
98
|
-
|
|
99
|
-
SUMMARY="$@"
|
|
100
|
-
if [ -z "$SUMMARY" ]; then
|
|
101
|
-
SUMMARY=$(cat)
|
|
102
|
-
fi
|
|
103
|
-
if [ -z "$SUMMARY" ]; then
|
|
104
|
-
SUMMARY="Plan completed and exited plan mode"
|
|
105
|
-
fi
|
|
106
|
-
|
|
107
|
-
# Update this path to your um-cli installation
|
|
108
|
-
UM_CLI="/path/to/vault/um-cli/index.js"
|
|
109
|
-
|
|
110
|
-
if [ ! -f "$UM_CLI" ]; then
|
|
111
|
-
echo "Error: um CLI not found at $UM_CLI" >&2
|
|
112
|
-
exit 1
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
node "$UM_CLI" note create "$SUMMARY" \
|
|
116
|
-
--topic "plans" \
|
|
117
|
-
--source "claude-code-hook" \
|
|
118
|
-
--confidence "0.8" \
|
|
119
|
-
--tags "plan,automated" \
|
|
120
|
-
2>&1
|
|
121
|
-
|
|
122
|
-
exit 0
|
|
123
|
-
EOF
|
|
124
|
-
|
|
125
|
-
chmod +x .claude/hooks/post-exit-plan-mode.sh
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Step 3: Configure Hook in Settings
|
|
129
|
-
|
|
130
|
-
Update `.claude/settings.json` (or `.claude/settings.local.json`):
|
|
131
|
-
|
|
132
|
-
```json
|
|
133
|
-
{
|
|
134
|
-
"hooks": {
|
|
135
|
-
"PostToolUse": [
|
|
136
|
-
{
|
|
137
|
-
"matcher": "ExitPlanMode",
|
|
138
|
-
"hooks": [
|
|
139
|
-
{
|
|
140
|
-
"type": "command",
|
|
141
|
-
"command": "./.claude/hooks/post-exit-plan-mode.sh 'Plan summary: Completed plan mode session'",
|
|
142
|
-
"statusMessage": "Recording plan to vault..."
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
}
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Step 4: Test the Setup
|
|
152
|
-
|
|
153
|
-
Test the CLI command manually:
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
cd <your-project>
|
|
157
|
-
um note create "Test note from CLI" --topic "testing"
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Test the hook script:
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
./.claude/hooks/post-exit-plan-mode.sh "Test note from hook"
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## How It Works
|
|
167
|
-
|
|
168
|
-
### Authentication Flow
|
|
169
|
-
|
|
170
|
-
1. **User Context**: Loaded from `~/.um/auth.json` (created by `um login`)
|
|
171
|
-
- User ID from JWT `decoded.sub`
|
|
172
|
-
- Organization ID from `selectedOrg.id` or fallback to user ID
|
|
173
|
-
|
|
174
|
-
2. **Project Context**: Loaded from `.um/config.json` (created by `um init`)
|
|
175
|
-
- Organization ID
|
|
176
|
-
- Project ID
|
|
177
|
-
- Project name
|
|
178
|
-
|
|
179
|
-
3. **API Call**: The `um note create` command:
|
|
180
|
-
- Builds authentication headers (Authorization, X-Org-Id, X-User-Id)
|
|
181
|
-
- Injects org/proj/user into tool arguments
|
|
182
|
-
- Calls the MCP gateway's `create_note` tool
|
|
183
|
-
- Returns success/failure status
|
|
184
|
-
|
|
185
|
-
### Hook Execution
|
|
186
|
-
|
|
187
|
-
When you exit plan mode in Claude Code:
|
|
188
|
-
|
|
189
|
-
1. Claude Code detects `ExitPlanMode` tool usage
|
|
190
|
-
2. Matches the `PostToolUse` hook with `matcher: "ExitPlanMode"`
|
|
191
|
-
3. Executes the command hook: `.claude/hooks/post-exit-plan-mode.sh`
|
|
192
|
-
4. Hook script calls: `node um-cli/index.js note create "..."`
|
|
193
|
-
5. CLI command creates the note in vault
|
|
194
|
-
6. Success/failure status shown in Claude Code
|
|
195
|
-
|
|
196
|
-
## Troubleshooting
|
|
197
|
-
|
|
198
|
-
### Error: "Not authenticated"
|
|
199
|
-
|
|
200
|
-
```bash
|
|
201
|
-
# Re-authenticate
|
|
202
|
-
um login
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Error: "No project configuration found"
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
# Re-initialize project
|
|
209
|
-
cd <your-project>
|
|
210
|
-
um init
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### Error: "um CLI not found"
|
|
214
|
-
|
|
215
|
-
Update the `UM_CLI` path in the hook script to point to your installation:
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
UM_CLI="/absolute/path/to/vault/um-cli/index.js"
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Error: Hook not executing
|
|
222
|
-
|
|
223
|
-
1. Ensure the hook script is executable:
|
|
224
|
-
```bash
|
|
225
|
-
chmod +x .claude/hooks/post-exit-plan-mode.sh
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
2. Test the hook manually:
|
|
229
|
-
```bash
|
|
230
|
-
./.claude/hooks/post-exit-plan-mode.sh "Test message"
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
3. Check Claude Code settings are valid JSON
|
|
234
|
-
|
|
235
|
-
### Error: "Tool execution failed"
|
|
236
|
-
|
|
237
|
-
Check authentication headers are being set correctly:
|
|
238
|
-
|
|
239
|
-
```bash
|
|
240
|
-
# Check auth file exists
|
|
241
|
-
cat ~/.um/auth.json | jq .
|
|
242
|
-
|
|
243
|
-
# Check project config exists
|
|
244
|
-
cat .um/config.json | jq .
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Customization
|
|
248
|
-
|
|
249
|
-
### Change Hook Trigger
|
|
250
|
-
|
|
251
|
-
Instead of `PostToolUse:ExitPlanMode`, you can trigger on other events:
|
|
252
|
-
|
|
253
|
-
```json
|
|
254
|
-
{
|
|
255
|
-
"hooks": {
|
|
256
|
-
"SessionEnd": [
|
|
257
|
-
{
|
|
258
|
-
"hooks": [
|
|
259
|
-
{
|
|
260
|
-
"type": "command",
|
|
261
|
-
"command": "./.claude/hooks/record-session.sh 'Session summary'",
|
|
262
|
-
"statusMessage": "Recording session to vault..."
|
|
263
|
-
}
|
|
264
|
-
]
|
|
265
|
-
}
|
|
266
|
-
]
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Available hook types:
|
|
272
|
-
- `PreToolUse` - Before any tool execution
|
|
273
|
-
- `PostToolUse` - After any tool execution
|
|
274
|
-
- `PostToolUseFailure` - After tool execution fails
|
|
275
|
-
- `SessionStart` - When session starts
|
|
276
|
-
- `SessionEnd` - When session ends
|
|
277
|
-
- `PreCompact` - Before context summarization
|
|
278
|
-
|
|
279
|
-
### Customize Note Properties
|
|
280
|
-
|
|
281
|
-
Edit the hook script to change topic, source, confidence, or tags:
|
|
282
|
-
|
|
283
|
-
```bash
|
|
284
|
-
node "$UM_CLI" note create "$SUMMARY" \
|
|
285
|
-
--topic "my-custom-topic" \
|
|
286
|
-
--source "my-source" \
|
|
287
|
-
--confidence "0.9" \
|
|
288
|
-
--tags "custom,tags,here" \
|
|
289
|
-
2>&1
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Add Metadata
|
|
293
|
-
|
|
294
|
-
Pass JSON metadata:
|
|
295
|
-
|
|
296
|
-
```bash
|
|
297
|
-
node "$UM_CLI" note create "$SUMMARY" \
|
|
298
|
-
--metadata '{"branch":"main","commit":"abc123"}' \
|
|
299
|
-
2>&1
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## Security Notes
|
|
303
|
-
|
|
304
|
-
- Authentication tokens are stored in `~/.um/auth.json` (user-only permissions)
|
|
305
|
-
- Project config in `.um/config.json` contains no secrets (only IDs)
|
|
306
|
-
- The CLI command inherits user's authentication automatically
|
|
307
|
-
- Hook scripts run with the same permissions as Claude Code
|
|
308
|
-
|
|
309
|
-
## Alternatives to Hooks
|
|
310
|
-
|
|
311
|
-
If you don't want automatic recording, you can manually call the CLI:
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
# After exiting plan mode
|
|
315
|
-
um note create "Completed feature X implementation" \
|
|
316
|
-
--topic "development" \
|
|
317
|
-
--confidence "0.9"
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Or ask Claude Code to record notes explicitly:
|
|
321
|
-
|
|
322
|
-
```
|
|
323
|
-
User: Record this plan to the vault
|
|
324
|
-
Claude: [Uses mcp__vault__create_note tool directly]
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
## Files Modified
|
|
328
|
-
|
|
329
|
-
This implementation required the following changes:
|
|
330
|
-
|
|
331
|
-
1. **New file**: `um-cli/commands/record.js` - CLI command implementation
|
|
332
|
-
2. **Modified**: `um-cli/index.js` - Added `note create` command registration
|
|
333
|
-
3. **New file**: `.claude/hooks/post-exit-plan-mode.sh` - Hook script (per-project)
|
|
334
|
-
4. **Modified**: `.claude/settings.json` - Hook configuration (per-project)
|
|
335
|
-
|
|
336
|
-
## Summary
|
|
337
|
-
|
|
338
|
-
This solution bypasses the "prompt hooks not supported outside REPL" limitation by using command-style hooks to call the `um note create` CLI command directly. All authentication infrastructure (schema transformation, parameter injection, headers) works perfectly - the only issue was with Claude Code's hook mechanism, which we've now resolved.
|
package/lib/hooks.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export function generateClaudePromptSubmitHook(mcpUrl, accessToken) {
|
|
2
|
-
return `#!/bin/bash
|
|
3
|
-
# UnifiedMemory Context Recording Hook
|
|
4
|
-
|
|
5
|
-
HOOK_DATA=$(cat)
|
|
6
|
-
|
|
7
|
-
# Read project config
|
|
8
|
-
UM_CONFIG=".um/config.json"
|
|
9
|
-
PROJECT_ID=""
|
|
10
|
-
ORG_ID=""
|
|
11
|
-
|
|
12
|
-
if [ -f "$UM_CONFIG" ]; then
|
|
13
|
-
PROJECT_ID=$(jq -r '.project_id // empty' "$UM_CONFIG" 2>/dev/null)
|
|
14
|
-
ORG_ID=$(jq -r '.org_id // empty' "$UM_CONFIG" 2>/dev/null)
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
# Extract context
|
|
18
|
-
USER_MESSAGE=$(echo "$HOOK_DATA" | jq -r '.userMessage // empty')
|
|
19
|
-
CONVERSATION_ID=$(echo "$HOOK_DATA" | jq -r '.conversationId // empty')
|
|
20
|
-
WORKING_DIR=$(pwd)
|
|
21
|
-
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
22
|
-
|
|
23
|
-
# Send to UnifiedMemory (if configured)
|
|
24
|
-
if [ -n "$PROJECT_ID" ]; then
|
|
25
|
-
curl -s -X POST "${mcpUrl}/hooks/pre-submit" \\
|
|
26
|
-
-H "Content-Type: application/json" \\
|
|
27
|
-
-H "Authorization: Bearer ${accessToken}" \\
|
|
28
|
-
-H "X-Project-Id: $PROJECT_ID" \\
|
|
29
|
-
-H "X-Org-Id: $ORG_ID" \\
|
|
30
|
-
-d "{
|
|
31
|
-
\\"event\\": \\"pre_response\\",
|
|
32
|
-
\\"timestamp\\": \\"$TIMESTAMP\\",
|
|
33
|
-
\\"conversation_id\\": \\"$CONVERSATION_ID\\",
|
|
34
|
-
\\"working_directory\\": \\"$WORKING_DIR\\",
|
|
35
|
-
\\"user_message\\": \\"$USER_MESSAGE\\",
|
|
36
|
-
\\"project_id\\": \\"$PROJECT_ID\\"
|
|
37
|
-
}" >/dev/null 2>&1
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
# Pass through original data
|
|
41
|
-
echo "$HOOK_DATA"
|
|
42
|
-
`;
|
|
43
|
-
}
|