laminark 0.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 +147 -0
- package/package.json +65 -0
- package/plugin/.claude-plugin/plugin.json +13 -0
- package/plugin/.mcp.json +12 -0
- package/plugin/CLAUDE.md +10 -0
- package/plugin/commands/recall.md +55 -0
- package/plugin/commands/remember.md +34 -0
- package/plugin/commands/resume.md +45 -0
- package/plugin/commands/stash.md +34 -0
- package/plugin/commands/status.md +33 -0
- package/plugin/dist/analysis/worker.d.ts +1 -0
- package/plugin/dist/analysis/worker.js +233 -0
- package/plugin/dist/analysis/worker.js.map +1 -0
- package/plugin/dist/config-t8LZeB-u.mjs +90 -0
- package/plugin/dist/config-t8LZeB-u.mjs.map +1 -0
- package/plugin/dist/hooks/handler.d.ts +286 -0
- package/plugin/dist/hooks/handler.d.ts.map +1 -0
- package/plugin/dist/hooks/handler.js +2413 -0
- package/plugin/dist/hooks/handler.js.map +1 -0
- package/plugin/dist/index.d.ts +447 -0
- package/plugin/dist/index.d.ts.map +1 -0
- package/plugin/dist/index.js +7334 -0
- package/plugin/dist/index.js.map +1 -0
- package/plugin/dist/observations-CorAAc1A.d.mts +192 -0
- package/plugin/dist/observations-CorAAc1A.d.mts.map +1 -0
- package/plugin/dist/tool-registry-e710BvXq.mjs +3574 -0
- package/plugin/dist/tool-registry-e710BvXq.mjs.map +1 -0
- package/plugin/hooks/hooks.json +78 -0
- package/plugin/laminark.db +0 -0
- package/plugin/package.json +17 -0
- package/plugin/scripts/README.md +65 -0
- package/plugin/scripts/bump-version.sh +42 -0
- package/plugin/scripts/dev-sync.sh +58 -0
- package/plugin/scripts/ensure-deps.sh +15 -0
- package/plugin/scripts/install.sh +139 -0
- package/plugin/scripts/local-install.sh +138 -0
- package/plugin/scripts/uninstall.sh +133 -0
- package/plugin/scripts/update.sh +39 -0
- package/plugin/scripts/verify-install.sh +87 -0
- package/plugin/skills/status/SKILL.md +6 -0
- package/plugin/ui/activity.js +197 -0
- package/plugin/ui/app.js +1612 -0
- package/plugin/ui/graph.js +2560 -0
- package/plugin/ui/help/activity-feed.png +0 -0
- package/plugin/ui/help/analysis-panel.png +0 -0
- package/plugin/ui/help/graph-toolbar.png +0 -0
- package/plugin/ui/help/graph-view.png +0 -0
- package/plugin/ui/help/settings.png +0 -0
- package/plugin/ui/help/timeline.png +0 -0
- package/plugin/ui/help.js +932 -0
- package/plugin/ui/index.html +756 -0
- package/plugin/ui/settings.js +1414 -0
- package/plugin/ui/styles.css +3856 -0
- package/plugin/ui/timeline.js +652 -0
- package/plugin/ui/tools.js +826 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Laminark: persistent adaptive memory for Claude Code",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"SessionStart": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
11
|
+
"statusMessage": "Loading Laminark memory context...",
|
|
12
|
+
"timeout": 10
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"PreToolUse": [
|
|
18
|
+
{
|
|
19
|
+
"matcher": "",
|
|
20
|
+
"hooks": [
|
|
21
|
+
{
|
|
22
|
+
"type": "command",
|
|
23
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
24
|
+
"timeout": 2
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"PostToolUse": [
|
|
30
|
+
{
|
|
31
|
+
"hooks": [
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
35
|
+
"async": true,
|
|
36
|
+
"timeout": 30
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"PostToolUseFailure": [
|
|
42
|
+
{
|
|
43
|
+
"hooks": [
|
|
44
|
+
{
|
|
45
|
+
"type": "command",
|
|
46
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
47
|
+
"async": true,
|
|
48
|
+
"timeout": 30
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"Stop": [
|
|
54
|
+
{
|
|
55
|
+
"hooks": [
|
|
56
|
+
{
|
|
57
|
+
"type": "command",
|
|
58
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
59
|
+
"async": true,
|
|
60
|
+
"timeout": 15
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"SessionEnd": [
|
|
66
|
+
{
|
|
67
|
+
"hooks": [
|
|
68
|
+
{
|
|
69
|
+
"type": "command",
|
|
70
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-deps.sh node ${CLAUDE_PLUGIN_ROOT}/dist/hooks/handler.js",
|
|
71
|
+
"async": true,
|
|
72
|
+
"timeout": 15
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "laminark-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Laminark plugin runtime dependencies",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.42",
|
|
9
|
+
"@hono/node-server": "^1.19.9",
|
|
10
|
+
"@huggingface/transformers": "^3.8.1",
|
|
11
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
12
|
+
"better-sqlite3": "^12.6.2",
|
|
13
|
+
"hono": "^4.11.9",
|
|
14
|
+
"sqlite-vec": "^0.1.7-alpha.2",
|
|
15
|
+
"zod": "^4.3.6"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Scripts
|
|
2
|
+
|
|
3
|
+
## Installation Scripts
|
|
4
|
+
|
|
5
|
+
| Script | Purpose |
|
|
6
|
+
|--------|---------|
|
|
7
|
+
| `install.sh` | Full install: npm global + MCP server + hooks |
|
|
8
|
+
| `local-install.sh` | Dev install: npm link + MCP server + hooks (points at repo) |
|
|
9
|
+
| `update.sh` | Update: `npm update -g laminark` |
|
|
10
|
+
| `uninstall.sh` | Remove MCP server, hooks, and npm package |
|
|
11
|
+
| `verify-install.sh` | Check installation status |
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
Laminark installs via three steps:
|
|
16
|
+
|
|
17
|
+
1. **npm package** — `npm install -g laminark` puts `laminark-server` and `laminark-hook` on PATH
|
|
18
|
+
2. **MCP server** — `claude mcp add-json` registers the MCP server in `~/.claude/settings.json`
|
|
19
|
+
3. **Hooks** — Hook entries are merged into `~/.claude/settings.json` to capture session events
|
|
20
|
+
|
|
21
|
+
## Version Bumping
|
|
22
|
+
|
|
23
|
+
Laminark uses `MILESTONE.PHASE.SEQUENTIAL` versioning aligned with GSD (Get Shit Done) workflow.
|
|
24
|
+
|
|
25
|
+
### Format: `M.P.S`
|
|
26
|
+
- **M** = Milestone generation (1, 2, 3...)
|
|
27
|
+
- **P** = Absolute phase number (1, 2, 3... 21+)
|
|
28
|
+
- **S** = Sequential release within phase (0, 1, 2...)
|
|
29
|
+
|
|
30
|
+
### Automatic Bumping (CI/CD)
|
|
31
|
+
|
|
32
|
+
The GitHub Actions workflow automatically bumps the **patch** version (S) on every push to master:
|
|
33
|
+
```bash
|
|
34
|
+
2.21.0 → 2.21.1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This is for incremental fixes and updates within the same phase.
|
|
38
|
+
|
|
39
|
+
### Manual Bumping
|
|
40
|
+
|
|
41
|
+
When starting a **new phase** or **milestone**, manually run:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# New phase (phase 21 → 22)
|
|
45
|
+
./scripts/bump-version.sh phase
|
|
46
|
+
# 2.21.0 → 2.22.0
|
|
47
|
+
|
|
48
|
+
# New milestone (generation 2 → 3)
|
|
49
|
+
./scripts/bump-version.sh milestone
|
|
50
|
+
# 2.21.0 → 3.22.0
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then commit and push:
|
|
54
|
+
```bash
|
|
55
|
+
git add package.json
|
|
56
|
+
git commit -m "chore: bump to vX.Y.0 for phase Z"
|
|
57
|
+
git push
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Version History
|
|
61
|
+
|
|
62
|
+
- **v1.8.0** - Phase 8 (Milestone v1.0 complete)
|
|
63
|
+
- **v2.16.0** - Phase 16 (Milestone v2.0 complete)
|
|
64
|
+
- **v2.18.0** - Phase 18 (Milestone v2.1 complete)
|
|
65
|
+
- **v2.21.0** - Phase 21 (Milestone v2.2 complete)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Bump version using MILESTONE.PHASE.SEQUENTIAL format
|
|
3
|
+
# Usage: ./scripts/bump-version.sh [patch|phase|milestone]
|
|
4
|
+
#
|
|
5
|
+
# Examples:
|
|
6
|
+
# ./scripts/bump-version.sh patch # 2.21.0 -> 2.21.1 (default)
|
|
7
|
+
# ./scripts/bump-version.sh phase # 2.21.0 -> 2.22.0 (new phase)
|
|
8
|
+
# ./scripts/bump-version.sh milestone # 2.21.0 -> 3.22.0 (new milestone)
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
ROOT="$SCRIPT_DIR/.."
|
|
13
|
+
|
|
14
|
+
BUMP_TYPE="${1:-patch}"
|
|
15
|
+
|
|
16
|
+
CURRENT=$(node -e "console.log(require('$ROOT/package.json').version)")
|
|
17
|
+
|
|
18
|
+
# Parse current version
|
|
19
|
+
IFS='.' read -r MILESTONE PHASE SEQUENTIAL <<< "$CURRENT"
|
|
20
|
+
|
|
21
|
+
# Determine next version based on bump type
|
|
22
|
+
case "$BUMP_TYPE" in
|
|
23
|
+
patch)
|
|
24
|
+
NEXT="$MILESTONE.$PHASE.$((SEQUENTIAL + 1))"
|
|
25
|
+
;;
|
|
26
|
+
phase)
|
|
27
|
+
NEXT="$MILESTONE.$((PHASE + 1)).0"
|
|
28
|
+
;;
|
|
29
|
+
milestone)
|
|
30
|
+
NEXT="$((MILESTONE + 1)).$((PHASE + 1)).0"
|
|
31
|
+
;;
|
|
32
|
+
*)
|
|
33
|
+
echo "Error: Invalid bump type '$BUMP_TYPE'. Use: patch, phase, or milestone" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
;;
|
|
36
|
+
esac
|
|
37
|
+
|
|
38
|
+
# Update version in all files
|
|
39
|
+
sed -i "s/\"version\": \"$CURRENT\"/\"version\": \"$NEXT\"/" \
|
|
40
|
+
"$ROOT/package.json"
|
|
41
|
+
|
|
42
|
+
echo "$NEXT"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Sync dev plugin build to the cached Claude Code plugin installation.
|
|
3
|
+
# Run after `npm run build` to hot-update the running plugin without restarting.
|
|
4
|
+
#
|
|
5
|
+
# Usage: ./plugin/scripts/dev-sync.sh
|
|
6
|
+
#
|
|
7
|
+
# Note: Static files (UI, hooks) take effect immediately on next page load.
|
|
8
|
+
# Compiled server code (dist/) requires a Claude Code session restart
|
|
9
|
+
# to pick up API changes.
|
|
10
|
+
|
|
11
|
+
set -e
|
|
12
|
+
|
|
13
|
+
CLAUDE_HOME="${CLAUDE_HOME:-$HOME/.claude}"
|
|
14
|
+
CACHE_BASE="$CLAUDE_HOME/plugins/cache/laminark/laminark"
|
|
15
|
+
|
|
16
|
+
# Resolve the repo root (script lives in plugin/scripts/)
|
|
17
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
19
|
+
PLUGIN_SRC="$REPO_ROOT/plugin"
|
|
20
|
+
|
|
21
|
+
# Verify source exists
|
|
22
|
+
if [ ! -d "$PLUGIN_SRC/dist" ]; then
|
|
23
|
+
echo "Error: plugin/dist/ not found. Run 'npm run build' first."
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Find cached installation(s)
|
|
28
|
+
if [ ! -d "$CACHE_BASE" ]; then
|
|
29
|
+
echo "Error: No cached Laminark plugin found at $CACHE_BASE"
|
|
30
|
+
echo "Install Laminark first: claude plugin add laminark"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Sync to every cached version (usually just one)
|
|
35
|
+
SYNCED=0
|
|
36
|
+
for CACHE_DIR in "$CACHE_BASE"/*/; do
|
|
37
|
+
[ -d "$CACHE_DIR" ] || continue
|
|
38
|
+
VERSION=$(basename "$CACHE_DIR")
|
|
39
|
+
|
|
40
|
+
rsync -a --delete \
|
|
41
|
+
--exclude '*.db' \
|
|
42
|
+
--exclude '*.db-wal' \
|
|
43
|
+
--exclude '*.db-shm' \
|
|
44
|
+
--exclude 'node_modules' \
|
|
45
|
+
"$PLUGIN_SRC/" "$CACHE_DIR"
|
|
46
|
+
|
|
47
|
+
echo "Synced to $VERSION"
|
|
48
|
+
SYNCED=$((SYNCED + 1))
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
if [ "$SYNCED" -eq 0 ]; then
|
|
52
|
+
echo "Error: No version directories found in $CACHE_BASE"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Done. $SYNCED cached installation(s) updated."
|
|
58
|
+
echo "UI changes are live. API changes need a session restart."
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Auto-install production dependencies if missing (first run after plugin install)
|
|
3
|
+
PLUGIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
4
|
+
if [ ! -d "$PLUGIN_ROOT/node_modules/better-sqlite3/build" ]; then
|
|
5
|
+
# Use local tmp dir to avoid EXDEV errors on btrfs subvolumes / cross-device setups
|
|
6
|
+
NPM_TMP="$PLUGIN_ROOT/.npm-tmp"
|
|
7
|
+
mkdir -p "$NPM_TMP"
|
|
8
|
+
# Install deps without running install scripts (sharp build fails without node-addon-api)
|
|
9
|
+
# then selectively rebuild better-sqlite3 which needs its native addon
|
|
10
|
+
TMPDIR="$NPM_TMP" npm install --prefix "$PLUGIN_ROOT" --omit=dev --ignore-scripts --silent --cache "$NPM_TMP/cache" 2>/dev/null
|
|
11
|
+
npm rebuild --prefix "$PLUGIN_ROOT" better-sqlite3 --silent 2>/dev/null
|
|
12
|
+
rm -rf "$NPM_TMP"
|
|
13
|
+
fi
|
|
14
|
+
cd "$PLUGIN_ROOT"
|
|
15
|
+
exec "$@"
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Install Laminark via npm + MCP server registration
|
|
3
|
+
# Fully standalone — no git clone required.
|
|
4
|
+
#
|
|
5
|
+
# Usage: curl -fsSL https://raw.githubusercontent.com/NoobyNull/Laminark/master/plugin/scripts/install.sh | bash
|
|
6
|
+
# or: ./plugin/scripts/install.sh
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
echo "Laminark Installer"
|
|
11
|
+
echo "=================="
|
|
12
|
+
echo ""
|
|
13
|
+
|
|
14
|
+
# Check prerequisites
|
|
15
|
+
if ! command -v node &> /dev/null; then
|
|
16
|
+
echo "Error: node not found"
|
|
17
|
+
echo "Please install Node.js >= 22: https://nodejs.org"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
NODE_MAJOR=$(node -e "console.log(process.versions.node.split('.')[0])")
|
|
22
|
+
if [ "$NODE_MAJOR" -lt 22 ]; then
|
|
23
|
+
echo "Error: Node.js >= 22 required (found v$(node -v))"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
if ! command -v npm &> /dev/null; then
|
|
28
|
+
echo "Error: npm not found"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if ! command -v claude &> /dev/null; then
|
|
33
|
+
echo "Error: claude CLI not found"
|
|
34
|
+
echo "Please install Claude Code first: https://claude.com/claude-code"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Check if already installed
|
|
39
|
+
CURRENT_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "")
|
|
40
|
+
if [ -n "$CURRENT_VERSION" ]; then
|
|
41
|
+
echo "Currently installed: v$CURRENT_VERSION"
|
|
42
|
+
echo "Reinstalling..."
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Step 1: Install via npm
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Installing laminark globally via npm..."
|
|
48
|
+
npm install -g laminark
|
|
49
|
+
echo "✓ npm package installed"
|
|
50
|
+
|
|
51
|
+
# Step 2: Register MCP server
|
|
52
|
+
echo ""
|
|
53
|
+
echo "Registering MCP server with Claude Code..."
|
|
54
|
+
claude mcp add-json laminark '{"command":"laminark-server"}' -s user
|
|
55
|
+
echo "✓ MCP server registered"
|
|
56
|
+
|
|
57
|
+
# Step 3: Configure hooks in ~/.claude/settings.json
|
|
58
|
+
echo ""
|
|
59
|
+
echo "Configuring hooks..."
|
|
60
|
+
SETTINGS_FILE="${CLAUDE_HOME:-$HOME/.claude}/settings.json"
|
|
61
|
+
|
|
62
|
+
node -e '
|
|
63
|
+
const fs = require("fs");
|
|
64
|
+
const path = require("path");
|
|
65
|
+
const settingsPath = process.argv[1];
|
|
66
|
+
|
|
67
|
+
// Ensure directory exists
|
|
68
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
69
|
+
|
|
70
|
+
let settings = {};
|
|
71
|
+
if (fs.existsSync(settingsPath)) {
|
|
72
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!settings.hooks) settings.hooks = {};
|
|
76
|
+
|
|
77
|
+
const hookEvents = {
|
|
78
|
+
SessionStart: { type: "command", command: "laminark-hook", statusMessage: "Loading Laminark memory context...", timeout: 10 },
|
|
79
|
+
PreToolUse: { type: "command", command: "laminark-hook", timeout: 2 },
|
|
80
|
+
PostToolUse: { type: "command", command: "laminark-hook", async: true, timeout: 30 },
|
|
81
|
+
PostToolUseFailure: { type: "command", command: "laminark-hook", async: true, timeout: 30 },
|
|
82
|
+
Stop: { type: "command", command: "laminark-hook", async: true, timeout: 15 },
|
|
83
|
+
SessionEnd: { type: "command", command: "laminark-hook", async: true, timeout: 15 }
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
for (const [event, hookConfig] of Object.entries(hookEvents)) {
|
|
87
|
+
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
88
|
+
|
|
89
|
+
// Remove any existing laminark hooks, then re-add (ensures up-to-date config)
|
|
90
|
+
settings.hooks[event] = settings.hooks[event].filter(entry =>
|
|
91
|
+
!(entry.hooks && entry.hooks.some(h => h.command && h.command.includes("laminark")))
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
settings.hooks[event].push({
|
|
95
|
+
hooks: [hookConfig]
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
100
|
+
' "$SETTINGS_FILE"
|
|
101
|
+
|
|
102
|
+
echo "✓ Hooks configured"
|
|
103
|
+
|
|
104
|
+
# Done
|
|
105
|
+
NEW_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "unknown")
|
|
106
|
+
echo ""
|
|
107
|
+
echo "✓ Laminark v$NEW_VERSION installed successfully!"
|
|
108
|
+
echo ""
|
|
109
|
+
echo "Next steps:"
|
|
110
|
+
echo " 1. Start a new Claude Code session"
|
|
111
|
+
echo " 2. Verify with: /mcp (should show laminark tools)"
|
|
112
|
+
|
|
113
|
+
# Step 4: Recommend GSD (Get Shit Done) workflow plugin
|
|
114
|
+
echo ""
|
|
115
|
+
GSD_INSTALLED=false
|
|
116
|
+
if [ -d "${CLAUDE_HOME:-$HOME/.claude}/commands/gsd" ] || [ -d "${CLAUDE_HOME:-$HOME/.claude}/plugins/gsd" ]; then
|
|
117
|
+
GSD_INSTALLED=true
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [ "$GSD_INSTALLED" = false ]; then
|
|
121
|
+
echo "Recommended: Install GSD (Get Shit Done) by @gsd-framework"
|
|
122
|
+
echo " GSD is an independent workflow plugin for Claude Code that pairs"
|
|
123
|
+
echo " well with Laminark — it handles project planning, phased execution,"
|
|
124
|
+
echo " and atomic commits while Laminark provides persistent memory."
|
|
125
|
+
echo " (GSD does not endorse or recommend Laminark — this is our suggestion.)"
|
|
126
|
+
echo ""
|
|
127
|
+
echo " Install: claude plugin add gsd"
|
|
128
|
+
echo " More info: https://github.com/gsd-framework/gsd"
|
|
129
|
+
echo ""
|
|
130
|
+
if [ -t 0 ]; then
|
|
131
|
+
read -rp "Install GSD now? [y/N] " INSTALL_GSD
|
|
132
|
+
if [[ "$INSTALL_GSD" =~ ^[Yy]$ ]]; then
|
|
133
|
+
echo ""
|
|
134
|
+
claude plugin add gsd 2>/dev/null && echo "✓ GSD installed" || echo " GSD install skipped (install manually with: claude plugin add gsd)"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
exit 0
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Local development installation for Laminark
|
|
3
|
+
# Uses npm link + MCP server registration + hooks pointing at repo dist/
|
|
4
|
+
#
|
|
5
|
+
# Usage: ./plugin/scripts/local-install.sh [path-to-laminark]
|
|
6
|
+
# Default path: current directory (.)
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
# Parse path argument (default to current directory)
|
|
11
|
+
PLUGIN_PATH="${1:-.}"
|
|
12
|
+
|
|
13
|
+
# Resolve to absolute path
|
|
14
|
+
if [[ "$PLUGIN_PATH" != /* ]]; then
|
|
15
|
+
PLUGIN_PATH="$(cd "$PLUGIN_PATH" && pwd)"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
echo "Laminark Local Installer"
|
|
19
|
+
echo "========================"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "Installing from: $PLUGIN_PATH"
|
|
22
|
+
|
|
23
|
+
# Validate prerequisites
|
|
24
|
+
if [ ! -d "$PLUGIN_PATH/plugin/dist" ]; then
|
|
25
|
+
echo "Error: plugin/dist/ directory not found in $PLUGIN_PATH"
|
|
26
|
+
echo "Please run 'npm install && npm run build' first"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if ! command -v claude &> /dev/null; then
|
|
31
|
+
echo "Error: claude CLI not found"
|
|
32
|
+
echo "Please install Claude Code first: https://claude.com/claude-code"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Get version from package.json
|
|
37
|
+
if [ -f "$PLUGIN_PATH/package.json" ]; then
|
|
38
|
+
NEW_VERSION=$(grep '"version"' "$PLUGIN_PATH/package.json" | head -1 | sed -E 's/.*"version": "([^"]+)".*/\1/')
|
|
39
|
+
echo "Version: v$NEW_VERSION"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Step 1: npm link from repo root
|
|
43
|
+
echo ""
|
|
44
|
+
echo "Linking package globally..."
|
|
45
|
+
cd "$PLUGIN_PATH"
|
|
46
|
+
npm link
|
|
47
|
+
echo "✓ npm link complete"
|
|
48
|
+
|
|
49
|
+
# Step 2: Register MCP server
|
|
50
|
+
echo ""
|
|
51
|
+
echo "Registering MCP server with Claude Code..."
|
|
52
|
+
claude mcp add-json laminark '{"command":"laminark-server"}' -s user
|
|
53
|
+
echo "✓ MCP server registered"
|
|
54
|
+
|
|
55
|
+
# Step 3: Configure hooks using repo's dist/hooks/handler.js
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Configuring hooks (dev mode - pointing at repo)..."
|
|
58
|
+
SETTINGS_FILE="${CLAUDE_HOME:-$HOME/.claude}/settings.json"
|
|
59
|
+
HANDLER_PATH="$PLUGIN_PATH/plugin/dist/hooks/handler.js"
|
|
60
|
+
|
|
61
|
+
node -e '
|
|
62
|
+
const fs = require("fs");
|
|
63
|
+
const settingsPath = process.argv[1];
|
|
64
|
+
const handlerPath = process.argv[2];
|
|
65
|
+
const hookCmd = `node "${handlerPath}"`;
|
|
66
|
+
|
|
67
|
+
let settings = {};
|
|
68
|
+
if (fs.existsSync(settingsPath)) {
|
|
69
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!settings.hooks) settings.hooks = {};
|
|
73
|
+
|
|
74
|
+
const hookEvents = {
|
|
75
|
+
SessionStart: { type: "command", command: hookCmd, statusMessage: "Loading Laminark memory context...", timeout: 10 },
|
|
76
|
+
PreToolUse: { type: "command", command: hookCmd, timeout: 2 },
|
|
77
|
+
PostToolUse: { type: "command", command: hookCmd, async: true, timeout: 30 },
|
|
78
|
+
PostToolUseFailure: { type: "command", command: hookCmd, async: true, timeout: 30 },
|
|
79
|
+
Stop: { type: "command", command: hookCmd, async: true, timeout: 15 },
|
|
80
|
+
SessionEnd: { type: "command", command: hookCmd, async: true, timeout: 15 }
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
for (const [event, hookConfig] of Object.entries(hookEvents)) {
|
|
84
|
+
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
85
|
+
|
|
86
|
+
// Remove any existing laminark hooks for this event
|
|
87
|
+
settings.hooks[event] = settings.hooks[event].filter(entry =>
|
|
88
|
+
!(entry.hooks && entry.hooks.some(h => h.command && h.command.includes("laminark")))
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Add the dev hook
|
|
92
|
+
settings.hooks[event].push({
|
|
93
|
+
hooks: [hookConfig]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
98
|
+
' "$SETTINGS_FILE" "$HANDLER_PATH"
|
|
99
|
+
|
|
100
|
+
echo "✓ Hooks configured (dev: $HANDLER_PATH)"
|
|
101
|
+
|
|
102
|
+
# Done
|
|
103
|
+
echo ""
|
|
104
|
+
echo "✓ Laminark v$NEW_VERSION installed locally!"
|
|
105
|
+
echo ""
|
|
106
|
+
echo "Next steps:"
|
|
107
|
+
echo " 1. Start a new Claude Code session"
|
|
108
|
+
echo " 2. Verify with: /mcp (should show laminark tools)"
|
|
109
|
+
echo ""
|
|
110
|
+
echo "To switch to production install: npm install -g laminark && ./plugin/scripts/install.sh"
|
|
111
|
+
|
|
112
|
+
# Step 4: Recommend GSD (Get Shit Done) workflow plugin
|
|
113
|
+
echo ""
|
|
114
|
+
GSD_INSTALLED=false
|
|
115
|
+
if [ -d "${CLAUDE_HOME:-$HOME/.claude}/commands/gsd" ] || [ -d "${CLAUDE_HOME:-$HOME/.claude}/plugins/gsd" ]; then
|
|
116
|
+
GSD_INSTALLED=true
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
if [ "$GSD_INSTALLED" = false ]; then
|
|
120
|
+
echo "Recommended: Install GSD (Get Shit Done) by @gsd-framework"
|
|
121
|
+
echo " GSD is an independent workflow plugin for Claude Code that pairs"
|
|
122
|
+
echo " well with Laminark — it handles project planning, phased execution,"
|
|
123
|
+
echo " and atomic commits while Laminark provides persistent memory."
|
|
124
|
+
echo " (GSD does not endorse or recommend Laminark — this is our suggestion.)"
|
|
125
|
+
echo ""
|
|
126
|
+
echo " Install: claude plugin add gsd"
|
|
127
|
+
echo " More info: https://github.com/gsd-framework/gsd"
|
|
128
|
+
echo ""
|
|
129
|
+
if [ -t 0 ]; then
|
|
130
|
+
read -rp "Install GSD now? [y/N] " INSTALL_GSD
|
|
131
|
+
if [[ "$INSTALL_GSD" =~ ^[Yy]$ ]]; then
|
|
132
|
+
echo ""
|
|
133
|
+
claude plugin add gsd 2>/dev/null && echo "✓ GSD installed" || echo " GSD install skipped (install manually with: claude plugin add gsd)"
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
exit 0
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Uninstall Laminark: remove MCP server, hooks, and npm package
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
echo "Laminark Uninstaller"
|
|
7
|
+
echo "===================="
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Check if claude CLI is available
|
|
11
|
+
if ! command -v claude &> /dev/null; then
|
|
12
|
+
echo "Warning: claude CLI not found, skipping MCP/hook cleanup"
|
|
13
|
+
SKIP_CLAUDE=true
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Check what's installed
|
|
17
|
+
NPM_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "")
|
|
18
|
+
if [ -n "$NPM_VERSION" ]; then
|
|
19
|
+
echo "npm package: v$NPM_VERSION"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Check MCP registration
|
|
23
|
+
if [ "$SKIP_CLAUDE" != "true" ]; then
|
|
24
|
+
if claude mcp list 2>/dev/null | grep -q "laminark"; then
|
|
25
|
+
echo "MCP server: registered"
|
|
26
|
+
MCP_REGISTERED=true
|
|
27
|
+
fi
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
echo ""
|
|
31
|
+
|
|
32
|
+
# Ask for confirmation
|
|
33
|
+
read -p "Are you sure you want to uninstall Laminark? (y/N): " -n 1 -r
|
|
34
|
+
echo ""
|
|
35
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
36
|
+
echo "Uninstall cancelled."
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Step 1: Remove MCP server
|
|
41
|
+
if [ "$MCP_REGISTERED" = "true" ]; then
|
|
42
|
+
echo ""
|
|
43
|
+
echo "Removing MCP server..."
|
|
44
|
+
claude mcp remove laminark -s user 2>/dev/null || true
|
|
45
|
+
echo "✓ MCP server removed"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Step 2: Remove hooks from settings.json
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Removing hooks from settings..."
|
|
51
|
+
SETTINGS_FILE="${CLAUDE_HOME:-$HOME/.claude}/settings.json"
|
|
52
|
+
|
|
53
|
+
if [ -f "$SETTINGS_FILE" ]; then
|
|
54
|
+
node -e '
|
|
55
|
+
const fs = require("fs");
|
|
56
|
+
const settingsPath = process.argv[1];
|
|
57
|
+
|
|
58
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
59
|
+
|
|
60
|
+
if (settings.hooks) {
|
|
61
|
+
for (const [event, entries] of Object.entries(settings.hooks)) {
|
|
62
|
+
settings.hooks[event] = entries.filter(entry =>
|
|
63
|
+
!(entry.hooks && entry.hooks.some(h => h.command && h.command.includes("laminark")))
|
|
64
|
+
);
|
|
65
|
+
// Remove empty arrays
|
|
66
|
+
if (settings.hooks[event].length === 0) {
|
|
67
|
+
delete settings.hooks[event];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Remove empty hooks object
|
|
71
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
72
|
+
delete settings.hooks;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Remove laminark from enabledPlugins if present
|
|
77
|
+
if (settings.enabledPlugins) {
|
|
78
|
+
for (const key of Object.keys(settings.enabledPlugins)) {
|
|
79
|
+
if (key.includes("laminark")) {
|
|
80
|
+
delete settings.enabledPlugins[key];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
86
|
+
' "$SETTINGS_FILE"
|
|
87
|
+
echo "✓ Hooks removed"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Step 3: Uninstall npm package
|
|
91
|
+
if [ -n "$NPM_VERSION" ]; then
|
|
92
|
+
echo ""
|
|
93
|
+
echo "Uninstalling npm package..."
|
|
94
|
+
npm uninstall -g laminark
|
|
95
|
+
echo "✓ npm package removed"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Step 4: Optional data cleanup
|
|
99
|
+
echo ""
|
|
100
|
+
echo "Data cleanup options:"
|
|
101
|
+
echo " 1. Keep all data (can reinstall later without losing memories)"
|
|
102
|
+
echo " 2. Remove everything (all memories and data)"
|
|
103
|
+
echo ""
|
|
104
|
+
read -p "Choose option (1-2, default=1): " -n 1 -r CLEANUP_OPTION
|
|
105
|
+
echo ""
|
|
106
|
+
|
|
107
|
+
case $CLEANUP_OPTION in
|
|
108
|
+
2)
|
|
109
|
+
DATA_DIR="$HOME/.laminark"
|
|
110
|
+
if [ -d "$DATA_DIR" ]; then
|
|
111
|
+
echo ""
|
|
112
|
+
echo "WARNING: This will delete all your memories and observations!"
|
|
113
|
+
read -p "Delete $DATA_DIR? (y/N): " -n 1 -r
|
|
114
|
+
echo ""
|
|
115
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
116
|
+
rm -rf "$DATA_DIR"
|
|
117
|
+
echo "✓ Data directory removed: $DATA_DIR"
|
|
118
|
+
else
|
|
119
|
+
echo " Kept data directory: $DATA_DIR"
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
;;
|
|
123
|
+
*)
|
|
124
|
+
echo "Keeping all data."
|
|
125
|
+
;;
|
|
126
|
+
esac
|
|
127
|
+
|
|
128
|
+
echo ""
|
|
129
|
+
echo "✓ Uninstall complete!"
|
|
130
|
+
echo ""
|
|
131
|
+
echo "To reinstall: npm install -g laminark && ./plugin/scripts/install.sh"
|
|
132
|
+
|
|
133
|
+
exit 0
|