meridian-dev 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/BOOTSTRAP_PROMPT.md +110 -0
- package/README.md +344 -0
- package/backup/hooks/session-end.sh +44 -0
- package/backup/hooks/session-start.sh +37 -0
- package/backup/setup.sh +156 -0
- package/bin/meridian.js +100 -0
- package/doctor.sh +173 -0
- package/install.sh +62 -0
- package/journal-summary.sh +577 -0
- package/package.json +42 -0
- package/setup.sh +407 -0
- package/specializations/claude-code/CLAUDE.md-global-fragment.md +52 -0
- package/specializations/claude-code/CLAUDE.md-repo-fragment.md +16 -0
- package/specializations/claude-code/README.md +96 -0
- package/specializations/claude-code/commands/doctor.md +31 -0
- package/specializations/claude-code/commands/init-memory.md +127 -0
- package/specializations/claude-code/commands/init-team.md +335 -0
- package/specializations/claude-code/commands/journal.md +66 -0
- package/specializations/claude-code/hooks/check-global-state.sh +68 -0
- package/specializations/claude-code/settings.json +10 -0
- package/specializations/cursor/README.md +112 -0
- package/specializations/cursor/global-rule.mdc +53 -0
- package/specializations/cursor/repo-rule.mdc +25 -0
- package/specializations/generic/README.md +47 -0
- package/templates/global.md +73 -0
- package/templates/memory-file.md +18 -0
- package/templates/personal-state.md +14 -0
- package/templates/product-state.md +39 -0
- package/templates/repo-state.md +18 -0
- package/templates/session-protocol-fragment.md +46 -0
- package/templates/strategy-state.md +37 -0
- package/templates/team-state.md +29 -0
- package/uninstall.sh +85 -0
package/setup.sh
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Skip Tissue — Setup Script
|
|
3
|
+
# Installs the memory system for your AI coding assistant.
|
|
4
|
+
# Safe to re-run (idempotent). Backs up existing files before modifying.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# bash setup.sh # Interactive — prompts for tool choice
|
|
8
|
+
# bash setup.sh --tool claude-code # Non-interactive
|
|
9
|
+
# bash setup.sh --tool cursor
|
|
10
|
+
# bash setup.sh --tool generic
|
|
11
|
+
# bash setup.sh --dry-run # Preview changes without modifying files
|
|
12
|
+
# bash setup.sh --help # Show this help
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
+
TOOL=""
|
|
18
|
+
DRY_RUN=false
|
|
19
|
+
REPO_DIR=""
|
|
20
|
+
UPDATE=false
|
|
21
|
+
|
|
22
|
+
# ── Argument parsing ──────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
usage() {
|
|
25
|
+
cat <<USAGE
|
|
26
|
+
Usage: bash setup.sh [OPTIONS]
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
--tool=TOOL Specify tool without prompt (claude-code, cursor, generic)
|
|
30
|
+
--tool TOOL Same as above (space-separated form)
|
|
31
|
+
--repo=PATH Install per-repo rule into PATH (Cursor only)
|
|
32
|
+
--repo PATH Same as above (space-separated form)
|
|
33
|
+
--update Update mode: overwrite hook scripts and commands (memory files untouched)
|
|
34
|
+
--dry-run Preview what would be installed without modifying files
|
|
35
|
+
--help Show this help message
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
bash setup.sh
|
|
39
|
+
bash setup.sh --tool claude-code
|
|
40
|
+
bash setup.sh --tool=cursor --repo .
|
|
41
|
+
bash setup.sh --tool claude-code --update --dry-run
|
|
42
|
+
USAGE
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
while [[ $# -gt 0 ]]; do
|
|
46
|
+
case "$1" in
|
|
47
|
+
--tool=*) TOOL="${1#--tool=}"; shift ;;
|
|
48
|
+
--tool)
|
|
49
|
+
if [ -z "${2:-}" ]; then
|
|
50
|
+
echo "Error: --tool requires a value (claude-code, cursor, or generic)"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
TOOL="$2"; shift 2 ;;
|
|
54
|
+
--repo=*) REPO_DIR="$(cd "${1#--repo=}" 2>/dev/null && pwd || echo "")"; shift ;;
|
|
55
|
+
--repo)
|
|
56
|
+
if [ -z "${2:-}" ]; then
|
|
57
|
+
echo "Error: --repo requires a path"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
REPO_DIR="$(cd "$2" 2>/dev/null && pwd || echo "")"; shift 2 ;;
|
|
61
|
+
--update) UPDATE=true; shift ;;
|
|
62
|
+
--dry-run) DRY_RUN=true; shift ;;
|
|
63
|
+
--help) usage; exit 0 ;;
|
|
64
|
+
*) shift ;;
|
|
65
|
+
esac
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
GREEN='\033[0;32m'
|
|
71
|
+
YELLOW='\033[1;33m'
|
|
72
|
+
RED='\033[0;31m'
|
|
73
|
+
RESET='\033[0m'
|
|
74
|
+
|
|
75
|
+
log() { echo -e "${GREEN}✓${RESET} $1"; }
|
|
76
|
+
warn() { echo -e "${YELLOW}⚠${RESET} $1"; }
|
|
77
|
+
info() { echo " $1"; }
|
|
78
|
+
header() { echo ""; echo -e "${GREEN}── $1 ──${RESET}"; }
|
|
79
|
+
|
|
80
|
+
backup_if_exists() {
|
|
81
|
+
local file="$1"
|
|
82
|
+
if [ -f "$file" ]; then
|
|
83
|
+
local backup="${file}.bak.$(date +%Y%m%d%H%M%S)"
|
|
84
|
+
cp "$file" "$backup"
|
|
85
|
+
warn "Backed up existing $file → $backup"
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
run() {
|
|
90
|
+
if [ "$DRY_RUN" = true ]; then
|
|
91
|
+
info "[dry-run] $*"
|
|
92
|
+
else
|
|
93
|
+
"$@"
|
|
94
|
+
fi
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
append_if_missing() {
|
|
98
|
+
local needle="$1"
|
|
99
|
+
local content="$2"
|
|
100
|
+
local file="$3"
|
|
101
|
+
if ! grep -qF "$needle" "$file" 2>/dev/null; then
|
|
102
|
+
echo "$content" >> "$file"
|
|
103
|
+
log "Appended to $file"
|
|
104
|
+
else
|
|
105
|
+
info "Already present in $file — skipped"
|
|
106
|
+
fi
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# ── Tool selection ─────────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
if [ -z "$TOOL" ]; then
|
|
112
|
+
echo ""
|
|
113
|
+
echo "Skip Tissue — Setup"
|
|
114
|
+
echo "─────────────────────"
|
|
115
|
+
echo "Which AI tool are you setting up for?"
|
|
116
|
+
echo " 1) Claude Code"
|
|
117
|
+
echo " 2) Cursor"
|
|
118
|
+
echo " 3) Generic (system prompt / manual)"
|
|
119
|
+
echo ""
|
|
120
|
+
read -rp "Enter choice [1-3]: " choice
|
|
121
|
+
case "$choice" in
|
|
122
|
+
1) TOOL="claude-code" ;;
|
|
123
|
+
2) TOOL="cursor" ;;
|
|
124
|
+
3) TOOL="generic" ;;
|
|
125
|
+
*) echo "Invalid choice. Exiting."; exit 1 ;;
|
|
126
|
+
esac
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
SPEC_DIR="$SCRIPT_DIR/specializations/$TOOL"
|
|
130
|
+
if [ ! -d "$SPEC_DIR" ]; then
|
|
131
|
+
echo -e "${RED}Error:${RESET} No specialization found for '$TOOL' at $SPEC_DIR"
|
|
132
|
+
echo "Available: $(ls "$SCRIPT_DIR/specializations/")"
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
echo ""
|
|
137
|
+
echo "Installing Skip Tissue for: $TOOL"
|
|
138
|
+
[ "$DRY_RUN" = true ] && warn "Dry-run mode — no files will be modified"
|
|
139
|
+
[ "$UPDATE" = true ] && warn "Update mode: overwriting hook scripts and commands (memory files untouched)"
|
|
140
|
+
|
|
141
|
+
# ── Tool-specific config ───────────────────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
case "$TOOL" in
|
|
144
|
+
claude-code)
|
|
145
|
+
MEMORY_DIR="$HOME/.claude"
|
|
146
|
+
MEMORY_SUBDIR="$HOME/.claude/memory"
|
|
147
|
+
GLOBAL_STATE="$HOME/.claude/global-state.md"
|
|
148
|
+
ADMIN_STATE="$HOME/.claude/state.md"
|
|
149
|
+
GLOBAL_CLAUDE_MD="$HOME/.claude/CLAUDE.md"
|
|
150
|
+
;;
|
|
151
|
+
cursor)
|
|
152
|
+
MEMORY_DIR="$HOME/.ai-memory"
|
|
153
|
+
MEMORY_SUBDIR="$HOME/.ai-memory/memory"
|
|
154
|
+
GLOBAL_STATE="$HOME/.ai-memory/global.md"
|
|
155
|
+
ADMIN_STATE="$HOME/.ai-memory/state.md"
|
|
156
|
+
GLOBAL_CLAUDE_MD="" # No global instructions file for Cursor
|
|
157
|
+
;;
|
|
158
|
+
generic)
|
|
159
|
+
MEMORY_DIR="$HOME/.ai-memory"
|
|
160
|
+
MEMORY_SUBDIR="$HOME/.ai-memory/memory"
|
|
161
|
+
GLOBAL_STATE="$HOME/.ai-memory/global.md"
|
|
162
|
+
ADMIN_STATE="$HOME/.ai-memory/state.md"
|
|
163
|
+
GLOBAL_CLAUDE_MD=""
|
|
164
|
+
;;
|
|
165
|
+
esac
|
|
166
|
+
|
|
167
|
+
# ── Step 1: Directories ────────────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
header "Creating directories"
|
|
170
|
+
|
|
171
|
+
run mkdir -p "$MEMORY_SUBDIR/journal"
|
|
172
|
+
log "Memory directories: $MEMORY_SUBDIR/journal"
|
|
173
|
+
|
|
174
|
+
if [ "$TOOL" = "claude-code" ]; then
|
|
175
|
+
run mkdir -p "$HOME/.claude/hooks"
|
|
176
|
+
run mkdir -p "$HOME/.claude/commands"
|
|
177
|
+
log "Claude Code hooks and commands directories"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# ── Step 2: Global state file ─────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
header "Global state file"
|
|
183
|
+
|
|
184
|
+
if [ ! -f "$GLOBAL_STATE" ]; then
|
|
185
|
+
if [ "$TOOL" = "claude-code" ]; then
|
|
186
|
+
if [ "$DRY_RUN" = false ]; then
|
|
187
|
+
sed \
|
|
188
|
+
-e 's|~/.ai-memory/|~/.claude/|g' \
|
|
189
|
+
-e 's|\.ai-memory/state\.md|.claude/state.md|g' \
|
|
190
|
+
"$SCRIPT_DIR/templates/global.md" > "$GLOBAL_STATE"
|
|
191
|
+
else
|
|
192
|
+
info "[dry-run] Would sed (path substitution) templates/global.md > $GLOBAL_STATE"
|
|
193
|
+
fi
|
|
194
|
+
else
|
|
195
|
+
run cp "$SCRIPT_DIR/templates/global.md" "$GLOBAL_STATE"
|
|
196
|
+
fi
|
|
197
|
+
log "Created $GLOBAL_STATE"
|
|
198
|
+
warn "Edit $GLOBAL_STATE to add your name, preferences, and projects"
|
|
199
|
+
else
|
|
200
|
+
info "Already exists: $GLOBAL_STATE — skipped"
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# ── Step 3: Admin state file (team/personal split) ───────────────────────────
|
|
204
|
+
# For team repos, use templates/team-state.md (committed, shared context).
|
|
205
|
+
# For personal notes, use templates/personal-state.md (gitignored, private).
|
|
206
|
+
# The admin state file at ADMIN_STATE is the non-repo catch-all (email, admin, misc).
|
|
207
|
+
|
|
208
|
+
header "Admin state file"
|
|
209
|
+
|
|
210
|
+
if [ ! -f "$ADMIN_STATE" ]; then
|
|
211
|
+
run cp "$SCRIPT_DIR/templates/repo-state.md" "$ADMIN_STATE"
|
|
212
|
+
log "Created $ADMIN_STATE"
|
|
213
|
+
else
|
|
214
|
+
info "Already exists: $ADMIN_STATE — skipped"
|
|
215
|
+
fi
|
|
216
|
+
|
|
217
|
+
# ── Step 4: Tool-specific files ───────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
header "Tool-specific files ($TOOL)"
|
|
220
|
+
|
|
221
|
+
case "$TOOL" in
|
|
222
|
+
claude-code)
|
|
223
|
+
# Global CLAUDE.md fragment
|
|
224
|
+
if [ -n "$GLOBAL_CLAUDE_MD" ]; then
|
|
225
|
+
touch "$GLOBAL_CLAUDE_MD"
|
|
226
|
+
append_if_missing "Session State Protocol" \
|
|
227
|
+
"$(cat "$SPEC_DIR/CLAUDE.md-global-fragment.md")" \
|
|
228
|
+
"$GLOBAL_CLAUDE_MD"
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Hook script
|
|
232
|
+
HOOK_DEST="$HOME/.claude/hooks/check-global-state.sh"
|
|
233
|
+
if [ ! -f "$HOOK_DEST" ] || [ "$UPDATE" = true ]; then
|
|
234
|
+
run cp "$SPEC_DIR/hooks/check-global-state.sh" "$HOOK_DEST"
|
|
235
|
+
run chmod +x "$HOOK_DEST"
|
|
236
|
+
log "Installed hook: $HOOK_DEST"
|
|
237
|
+
else
|
|
238
|
+
info "Hook already exists: $HOOK_DEST — skipped"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
# init-memory command
|
|
242
|
+
CMD_DEST="$HOME/.claude/commands/init-memory.md"
|
|
243
|
+
if [ ! -f "$CMD_DEST" ] || [ "$UPDATE" = true ]; then
|
|
244
|
+
run cp "$SPEC_DIR/commands/init-memory.md" "$CMD_DEST"
|
|
245
|
+
log "Installed command: /init-memory"
|
|
246
|
+
else
|
|
247
|
+
info "/init-memory command already exists — skipped"
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
# doctor command
|
|
251
|
+
DOCTOR_CMD_DEST="$HOME/.claude/commands/doctor.md"
|
|
252
|
+
if [ ! -f "$DOCTOR_CMD_DEST" ] || [ "$UPDATE" = true ]; then
|
|
253
|
+
run cp "$SPEC_DIR/commands/doctor.md" "$DOCTOR_CMD_DEST"
|
|
254
|
+
log "Installed command: /doctor"
|
|
255
|
+
else
|
|
256
|
+
info "/doctor command already exists — skipped"
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# doctor.sh script
|
|
260
|
+
run mkdir -p "$HOME/.claude/skip-tissue"
|
|
261
|
+
DOCTOR_DEST="$HOME/.claude/skip-tissue/doctor.sh"
|
|
262
|
+
if [ ! -f "$DOCTOR_DEST" ] || [ "$UPDATE" = true ]; then
|
|
263
|
+
run cp "$SCRIPT_DIR/doctor.sh" "$DOCTOR_DEST"
|
|
264
|
+
run chmod +x "$DOCTOR_DEST"
|
|
265
|
+
log "Installed doctor script: $DOCTOR_DEST"
|
|
266
|
+
else
|
|
267
|
+
info "doctor.sh already exists: $DOCTOR_DEST — skipped"
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
# journal-summary.sh script
|
|
271
|
+
JOURNAL_DEST="$HOME/.claude/skip-tissue/journal-summary.sh"
|
|
272
|
+
if [ ! -f "$JOURNAL_DEST" ] || [ "$UPDATE" = true ]; then
|
|
273
|
+
run cp "$SCRIPT_DIR/journal-summary.sh" "$JOURNAL_DEST"
|
|
274
|
+
run chmod +x "$JOURNAL_DEST"
|
|
275
|
+
log "Installed journal summary script: $JOURNAL_DEST"
|
|
276
|
+
else
|
|
277
|
+
info "journal-summary.sh already exists: $JOURNAL_DEST — skipped"
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
# /journal command
|
|
281
|
+
JOURNAL_CMD_DEST="$HOME/.claude/commands/journal.md"
|
|
282
|
+
if [ ! -f "$JOURNAL_CMD_DEST" ] || [ "$UPDATE" = true ]; then
|
|
283
|
+
run cp "$SPEC_DIR/commands/journal.md" "$JOURNAL_CMD_DEST"
|
|
284
|
+
log "Installed command: /journal"
|
|
285
|
+
else
|
|
286
|
+
info "/journal command already exists — skipped"
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
# /init-team command
|
|
290
|
+
TEAM_CMD_DEST="$HOME/.claude/commands/init-team.md"
|
|
291
|
+
if [ ! -f "$TEAM_CMD_DEST" ] || [ "$UPDATE" = true ]; then
|
|
292
|
+
if [ -f "$SPEC_DIR/commands/init-team.md" ]; then
|
|
293
|
+
run cp "$SPEC_DIR/commands/init-team.md" "$TEAM_CMD_DEST"
|
|
294
|
+
log "Installed command: /init-team"
|
|
295
|
+
fi
|
|
296
|
+
else
|
|
297
|
+
info "/init-team command already exists — skipped"
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
# settings.json — merge hook, don't overwrite
|
|
301
|
+
SETTINGS="$HOME/.claude/settings.json"
|
|
302
|
+
HOOK_CMD="bash ~/.claude/hooks/check-global-state.sh"
|
|
303
|
+
|
|
304
|
+
if [ ! -f "$SETTINGS" ]; then
|
|
305
|
+
run cp "$SPEC_DIR/settings.json" "$SETTINGS"
|
|
306
|
+
log "Created $SETTINGS with hook registration"
|
|
307
|
+
else
|
|
308
|
+
if ! grep -q "check-global-state" "$SETTINGS" 2>/dev/null; then
|
|
309
|
+
# Merge hook into existing settings.json using Python
|
|
310
|
+
if [ "$DRY_RUN" = false ]; then
|
|
311
|
+
# Write to temp file first (atomic write)
|
|
312
|
+
TMP_SETTINGS="$(mktemp)"
|
|
313
|
+
if python3 - "$SETTINGS" "$HOOK_CMD" "$TMP_SETTINGS" <<'PYEOF' 2>/dev/null; then
|
|
314
|
+
import json, sys
|
|
315
|
+
settings_path, hook_cmd, out_path = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
316
|
+
try:
|
|
317
|
+
with open(settings_path) as f:
|
|
318
|
+
settings = json.load(f)
|
|
319
|
+
except (json.JSONDecodeError, IOError):
|
|
320
|
+
sys.exit(1)
|
|
321
|
+
hooks = settings.setdefault("hooks", {})
|
|
322
|
+
session_start = hooks.setdefault("SessionStart", [])
|
|
323
|
+
if not isinstance(session_start, list):
|
|
324
|
+
sys.exit(1)
|
|
325
|
+
hook_entry = {"type": "command", "command": hook_cmd}
|
|
326
|
+
if not any(h.get("command") == hook_cmd for h in session_start if isinstance(h, dict)):
|
|
327
|
+
session_start.append(hook_entry)
|
|
328
|
+
with open(out_path, "w") as f:
|
|
329
|
+
json.dump(settings, f, indent=2)
|
|
330
|
+
f.write("\n")
|
|
331
|
+
PYEOF
|
|
332
|
+
mv "$TMP_SETTINGS" "$SETTINGS"
|
|
333
|
+
log "Merged SessionStart hook into existing $SETTINGS"
|
|
334
|
+
else
|
|
335
|
+
rm -f "$TMP_SETTINGS"
|
|
336
|
+
warn "Could not auto-merge hook into $SETTINGS (malformed JSON or python3 unavailable)."
|
|
337
|
+
warn "Manually add the SessionStart hook from: $SPEC_DIR/settings.json"
|
|
338
|
+
fi
|
|
339
|
+
else
|
|
340
|
+
info "[dry-run] Would merge hook into $SETTINGS"
|
|
341
|
+
fi
|
|
342
|
+
else
|
|
343
|
+
info "Hook already registered in settings.json — skipped"
|
|
344
|
+
fi
|
|
345
|
+
fi
|
|
346
|
+
;;
|
|
347
|
+
|
|
348
|
+
cursor)
|
|
349
|
+
# Global rules
|
|
350
|
+
run mkdir -p "$HOME/.cursor/rules"
|
|
351
|
+
GLOBAL_RULE="$HOME/.cursor/rules/ai-memory.mdc"
|
|
352
|
+
if [ ! -f "$GLOBAL_RULE" ] || [ "${UPDATE:-false}" = true ]; then
|
|
353
|
+
run cp "$SPEC_DIR/global-rule.mdc" "$GLOBAL_RULE"
|
|
354
|
+
log "Installed global Cursor rule: $GLOBAL_RULE"
|
|
355
|
+
else
|
|
356
|
+
info "Global Cursor rule already exists — skipped"
|
|
357
|
+
fi
|
|
358
|
+
|
|
359
|
+
# Per-repo rule (if --repo was passed)
|
|
360
|
+
if [ -n "${REPO_DIR:-}" ]; then
|
|
361
|
+
if [ -d "$REPO_DIR" ]; then
|
|
362
|
+
RULE_DIR="$REPO_DIR/.cursor/rules"
|
|
363
|
+
run mkdir -p "$RULE_DIR"
|
|
364
|
+
if [ ! -f "$RULE_DIR/memory.mdc" ] || [ "${UPDATE:-false}" = true ]; then
|
|
365
|
+
run cp "$SPEC_DIR/repo-rule.mdc" "$RULE_DIR/memory.mdc"
|
|
366
|
+
log "Installed repo rule: $RULE_DIR/memory.mdc"
|
|
367
|
+
warn "Edit $RULE_DIR/memory.mdc to add repo name and initial status"
|
|
368
|
+
else
|
|
369
|
+
info "Repo rule already exists — skipped"
|
|
370
|
+
fi
|
|
371
|
+
else
|
|
372
|
+
warn "--repo path not found or not a directory: $REPO_DIR"
|
|
373
|
+
fi
|
|
374
|
+
fi
|
|
375
|
+
;;
|
|
376
|
+
|
|
377
|
+
generic)
|
|
378
|
+
info "Generic setup complete. See $SPEC_DIR/README.md for system prompt instructions."
|
|
379
|
+
;;
|
|
380
|
+
esac
|
|
381
|
+
|
|
382
|
+
# ── Step 5: Summary ───────────────────────────────────────────────────────────
|
|
383
|
+
|
|
384
|
+
header "Done"
|
|
385
|
+
|
|
386
|
+
echo ""
|
|
387
|
+
echo "Memory kit installed for $TOOL."
|
|
388
|
+
echo ""
|
|
389
|
+
echo "Next steps:"
|
|
390
|
+
echo " 1. Edit $GLOBAL_STATE with your preferences and projects"
|
|
391
|
+
|
|
392
|
+
if [ "$TOOL" = "claude-code" ]; then
|
|
393
|
+
echo " 2. Open a repo and run /init-memory to set it up"
|
|
394
|
+
echo " 3. Start a Claude Code session — it will load your state automatically"
|
|
395
|
+
echo " 4. Run /journal for a weekly digest of your AI session logs"
|
|
396
|
+
elif [ "$TOOL" = "cursor" ]; then
|
|
397
|
+
echo " 2. Open a repo and run: bash setup.sh --tool cursor --repo <path>"
|
|
398
|
+
echo " 3. Start a Cursor session — the global rule loads your state automatically"
|
|
399
|
+
echo " 4. See specializations/cursor/README.md for full documentation"
|
|
400
|
+
else
|
|
401
|
+
echo " 2. Add the session protocol to your tool's system prompt"
|
|
402
|
+
echo " See: specializations/generic/README.md"
|
|
403
|
+
fi
|
|
404
|
+
|
|
405
|
+
echo ""
|
|
406
|
+
echo " Full documentation: README.md"
|
|
407
|
+
echo ""
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
## Session State Protocol (Skip Tissue)
|
|
3
|
+
|
|
4
|
+
**Memory system:** Hierarchical plain-markdown files. No CLI tools, no databases.
|
|
5
|
+
|
|
6
|
+
### File Hierarchy
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
~/.claude/
|
|
10
|
+
global-state.md # Thin index — ALWAYS load at session start
|
|
11
|
+
state.md # Admin/non-repo work
|
|
12
|
+
memory/ # Topic files — load on demand
|
|
13
|
+
<topic>.md
|
|
14
|
+
journal/YYYY-MM-DD.md # Daily log
|
|
15
|
+
|
|
16
|
+
<repo>/.claude/
|
|
17
|
+
state.md # Per-repo state — load when working in that repo
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Session Start (REQUIRED)
|
|
21
|
+
|
|
22
|
+
1. Read `~/.claude/global-state.md`
|
|
23
|
+
2. Read `.claude/team-state.md` (shared team context) and `.claude/personal-state.md` (your personal context) in the current repo, if they exist. Fall back to `.claude/state.md` for older repos not yet migrated. (Or `~/.claude/state.md` if in home dir.)
|
|
24
|
+
3. Check the Memory Files table in global-state.md — load any `~/.claude/memory/` files whose keywords match this session's topic
|
|
25
|
+
4. Summarize current state, then ask: **"What's the goal for this session? What does success look like?"**
|
|
26
|
+
|
|
27
|
+
### Mid-Session
|
|
28
|
+
|
|
29
|
+
If work drifts from the stated goal, flag it: *"Quick check — we set out to [goal]. This feels like [tangent]. Stay the course or pivot?"*
|
|
30
|
+
|
|
31
|
+
### Session End (on "stop" / "done" / "pause" / "tomorrow")
|
|
32
|
+
|
|
33
|
+
1. Update `.claude/team-state.md` with shared changes and `.claude/personal-state.md` with personal changes. (For older repos not yet migrated, update `.claude/state.md` as before.)
|
|
34
|
+
2. Update the Active Projects row in `~/.claude/global-state.md`
|
|
35
|
+
3. Create/update topic files in `~/.claude/memory/` for significant new cross-repo context
|
|
36
|
+
4. Append to `~/.claude/memory/journal/YYYY-MM-DD.md`:
|
|
37
|
+
```
|
|
38
|
+
## [Repo] — [Title]
|
|
39
|
+
**Why:** [Stated goal]
|
|
40
|
+
**What:** [What was done]
|
|
41
|
+
**Outcome:** [Did we hit it?]
|
|
42
|
+
**On track?:** [Focused or drift?]
|
|
43
|
+
**Lessons:** [Cross-session learnings]
|
|
44
|
+
```
|
|
45
|
+
5. Confirm: **"State saved. Say 'let's continue' next time."**
|
|
46
|
+
|
|
47
|
+
### Rules
|
|
48
|
+
|
|
49
|
+
- Keep `global-state.md` under 80 lines. Detail goes in `~/.claude/memory/` files.
|
|
50
|
+
- Per-repo `state.md` stays focused on that repo only.
|
|
51
|
+
- New cross-repo topics get new files in `~/.claude/memory/`, not appended to global-state.md.
|
|
52
|
+
- Do NOT use ruvector/claude-flow memory CLI. It writes empty databases. Plain files only.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
## Session State Protocol
|
|
3
|
+
|
|
4
|
+
**At session start (REQUIRED):**
|
|
5
|
+
1. Read `~/.claude/global-state.md` — preferences, active projects, memory file manifest
|
|
6
|
+
2. Read `.claude/team-state.md` in this repo — shared team context (architecture decisions, conventions, sprint focus, gotchas)
|
|
7
|
+
3. Read `.claude/personal-state.md` in this repo — your personal context (current focus, working notes, opinions)
|
|
8
|
+
4. Check the Memory Files table in global-state.md — load any `~/.claude/memory/` files relevant to this session's topic
|
|
9
|
+
|
|
10
|
+
**At session end (when user says stop/done/pause/tomorrow):**
|
|
11
|
+
1. Update `.claude/team-state.md` with shared context: architecture decisions, conventions, gotchas the whole team should know
|
|
12
|
+
2. Update `.claude/personal-state.md` with personal context: your next steps, working notes, opinions
|
|
13
|
+
3. Update the project's row in `~/.claude/global-state.md` Active Projects table
|
|
14
|
+
4. If significant new cross-repo context was created (patterns, strategies, decisions), create or update a file in `~/.claude/memory/` and add it to the Memory Files manifest in global-state.md
|
|
15
|
+
|
|
16
|
+
**Do NOT use ruvector/claude-flow memory CLI for state storage.** Use plain markdown files only.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Claude Code Specialization
|
|
2
|
+
|
|
3
|
+
This directory contains everything needed to wire the Skip Tissue into Claude Code specifically.
|
|
4
|
+
|
|
5
|
+
## What's Different About Claude Code
|
|
6
|
+
|
|
7
|
+
Claude Code reads a `CLAUDE.md` file at the root of every repo (and `~/.claude/CLAUDE.md` globally) as persistent instructions. It also supports:
|
|
8
|
+
- **Hooks** — shell scripts that run on session start/end, file edits, commands
|
|
9
|
+
- **Custom slash commands** — markdown files in `.claude/commands/` become `/command-name` shortcuts
|
|
10
|
+
- **Settings** — `~/.claude/settings.json` controls hooks and behavior
|
|
11
|
+
|
|
12
|
+
The memory directory for Claude Code is `~/.claude/` (not `~/.ai-memory/`).
|
|
13
|
+
|
|
14
|
+
## File Map
|
|
15
|
+
|
|
16
|
+
| File | Install to | Purpose |
|
|
17
|
+
|------|-----------|---------|
|
|
18
|
+
| `CLAUDE.md-global-fragment.md` | Append to `~/.claude/CLAUDE.md` | Tells Claude to load memory files at session start |
|
|
19
|
+
| `CLAUDE.md-repo-fragment.md` | Append to `<repo>/CLAUDE.md` | Repo-level session protocol |
|
|
20
|
+
| `settings.json` | Merge into `~/.claude/settings.json` | Registers the anti-drift hook |
|
|
21
|
+
| `hooks/check-global-state.sh` | Copy to `~/.claude/hooks/` | Warns when global index is stale |
|
|
22
|
+
| `commands/init-memory.md` | Copy to `~/.claude/commands/` | Adds `/init-memory` slash command |
|
|
23
|
+
|
|
24
|
+
The `setup.sh` at the kit root handles all of this automatically.
|
|
25
|
+
|
|
26
|
+
## Manual Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 1. Create directories
|
|
30
|
+
mkdir -p ~/.claude/hooks ~/.claude/commands ~/.claude/memory/journal
|
|
31
|
+
|
|
32
|
+
# 2. Copy the global CLAUDE.md fragment
|
|
33
|
+
cat specializations/claude-code/CLAUDE.md-global-fragment.md >> ~/.claude/CLAUDE.md
|
|
34
|
+
|
|
35
|
+
# 3. Install hook script
|
|
36
|
+
cp specializations/claude-code/hooks/check-global-state.sh ~/.claude/hooks/
|
|
37
|
+
chmod +x ~/.claude/hooks/check-global-state.sh
|
|
38
|
+
|
|
39
|
+
# 4. Install init-memory command
|
|
40
|
+
cp specializations/claude-code/commands/init-memory.md ~/.claude/commands/
|
|
41
|
+
|
|
42
|
+
# 5. Merge settings.json
|
|
43
|
+
# If ~/.claude/settings.json doesn't exist:
|
|
44
|
+
cp specializations/claude-code/settings.json ~/.claude/settings.json
|
|
45
|
+
# If it already exists, manually add the "hooks" block from settings.json
|
|
46
|
+
|
|
47
|
+
# 6. Copy global state template
|
|
48
|
+
cp ../../templates/global.md ~/.claude/global-state.md
|
|
49
|
+
# Edit it to add your preferences and projects
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Per-Repo Setup
|
|
53
|
+
|
|
54
|
+
For each repo you work in:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd ~/repos/your-org/your-repo
|
|
58
|
+
mkdir -p .claude
|
|
59
|
+
|
|
60
|
+
# Copy repo state template
|
|
61
|
+
cp ~/.claude/skip-tissue/templates/repo-state.md .claude/state.md
|
|
62
|
+
# Fill it in with current branch, status, next steps
|
|
63
|
+
|
|
64
|
+
# Add session protocol to repo CLAUDE.md
|
|
65
|
+
cat ~/.claude/skip-tissue/specializations/claude-code/CLAUDE.md-repo-fragment.md >> CLAUDE.md
|
|
66
|
+
|
|
67
|
+
# Add gitignore entries (IMPORTANT — see note below)
|
|
68
|
+
echo ".claude/state.md" >> .gitignore
|
|
69
|
+
echo ".claude/settings.local.json" >> .gitignore
|
|
70
|
+
echo ".claude/memory.db" >> .gitignore
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or just run `/init-memory` inside Claude Code after setup.
|
|
74
|
+
|
|
75
|
+
## Gitignore Warning
|
|
76
|
+
|
|
77
|
+
**Never add `.claude/` to `.gitignore` as a whole directory.**
|
|
78
|
+
|
|
79
|
+
Claude Code stores skills, commands, and settings in `.claude/` that should be tracked in git. If you ignore the whole directory, git won't track those files — and negation rules like `!.claude/commands/` won't rescue them (git doesn't descend into ignored directories).
|
|
80
|
+
|
|
81
|
+
**Correct pattern:**
|
|
82
|
+
```gitignore
|
|
83
|
+
# Claude Code — local only, don't track
|
|
84
|
+
.claude/state.md
|
|
85
|
+
.claude/settings.local.json
|
|
86
|
+
.claude/memory.db
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Wrong:**
|
|
90
|
+
```gitignore
|
|
91
|
+
.claude/ ← this breaks skills and commands
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Memory Directory Note
|
|
95
|
+
|
|
96
|
+
Claude Code uses `~/.claude/` as its home. This kit uses that same directory rather than `~/.ai-memory/` so that Claude's native file loading works correctly. The file paths in your `global-state.md` will reference `~/.claude/memory/` accordingly.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run Skip Tissue health check — validates hooks, state files, backup status, and memory file sizes.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Skip Tissue — Doctor
|
|
6
|
+
|
|
7
|
+
Run a health check on the memory system.
|
|
8
|
+
|
|
9
|
+
## Step 1: Check if doctor.sh is available
|
|
10
|
+
|
|
11
|
+
Look for `~/.claude/skip-tissue/doctor.sh`. If found, run it:
|
|
12
|
+
```bash
|
|
13
|
+
bash ~/.claude/skip-tissue/doctor.sh
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If not found, perform the checks manually:
|
|
17
|
+
|
|
18
|
+
## Step 2: Manual checks
|
|
19
|
+
|
|
20
|
+
1. **Hook registered?** — Does `~/.claude/settings.json` contain "check-global-state"?
|
|
21
|
+
2. **Global state current?** — Read `~/.claude/global-state.md`. When was it last updated?
|
|
22
|
+
3. **Backup status** — Check `~/.claude/.backup-last-push` and `~/.claude/.backup-last-error`
|
|
23
|
+
4. **Repos** — Scan `~/repos`, `~/code`, `~/dev` for `.claude/state.md` files
|
|
24
|
+
5. **Memory files** — List files in `~/.claude/memory/`, flag any over 8KB
|
|
25
|
+
|
|
26
|
+
## Step 3: Report findings
|
|
27
|
+
|
|
28
|
+
Report in this format:
|
|
29
|
+
- ✓ items that are working correctly
|
|
30
|
+
- ⚠ items that need attention (not broken, but worth knowing)
|
|
31
|
+
- ✗ items that are broken (with how to fix)
|