chore: merge upstream v12.7.2 + keep local fixes
# Conflicts: # plugin/scripts/context-generator.cjs # plugin/scripts/mcp-server.cjs # plugin/scripts/worker-service.cjs
This commit is contained in:
@@ -1,17 +1,24 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "12.5.1",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"version": "12.7.2",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
},
|
||||
"repository": "https://github.com/thedotmack/claude-mem",
|
||||
"license": "AGPL-3.0",
|
||||
"keywords": [
|
||||
"claude",
|
||||
"claude-code",
|
||||
"claude-agent-sdk",
|
||||
"mcp",
|
||||
"plugin",
|
||||
"memory",
|
||||
"context",
|
||||
"persistence",
|
||||
"hooks",
|
||||
"mcp"
|
||||
]
|
||||
"compression",
|
||||
"knowledge-graph",
|
||||
"transcript",
|
||||
"typescript",
|
||||
"nodejs"
|
||||
],
|
||||
"homepage": "https://github.com/thedotmack/claude-mem#readme"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "12.7.2",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman",
|
||||
"url": "https://github.com/thedotmack"
|
||||
},
|
||||
"homepage": "https://github.com/thedotmack/claude-mem#readme",
|
||||
"repository": "https://github.com/thedotmack/claude-mem",
|
||||
"license": "AGPL-3.0",
|
||||
"keywords": [
|
||||
"claude",
|
||||
"claude-code",
|
||||
"claude-agent-sdk",
|
||||
"mcp",
|
||||
"plugin",
|
||||
"memory",
|
||||
"compression",
|
||||
"knowledge-graph",
|
||||
"transcript",
|
||||
"typescript",
|
||||
"nodejs"
|
||||
],
|
||||
"skills": "./skills/",
|
||||
"mcpServers": "./.mcp.json",
|
||||
"hooks": "./hooks/codex-hooks.json",
|
||||
"interface": {
|
||||
"displayName": "claude-mem",
|
||||
"shortDescription": "Persistent memory and context compression across coding sessions.",
|
||||
"longDescription": "claude-mem captures coding-session activity, compresses it into reusable observations, and injects relevant context back into future Claude Code and Codex-compatible sessions.",
|
||||
"developerName": "Alex Newman",
|
||||
"category": "Productivity",
|
||||
"capabilities": [
|
||||
"Interactive",
|
||||
"Write"
|
||||
],
|
||||
"websiteURL": "https://github.com/thedotmack/claude-mem",
|
||||
"defaultPrompt": [
|
||||
"Find what I already learned about this codebase before I start a new task.",
|
||||
"Show recent observations related to the files I am editing right now.",
|
||||
"Summarize the last session and inject the most relevant context into this one."
|
||||
],
|
||||
"brandColor": "#1F6FEB"
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -2,8 +2,11 @@
|
||||
"mcpServers": {
|
||||
"mcp-search": {
|
||||
"type": "stdio",
|
||||
"command": "bun",
|
||||
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/mcp-server.cjs"]
|
||||
"command": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; exec node \"$_P/scripts/mcp-server.cjs\""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"description": "claude-mem Codex CLI hook integration",
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; CLAUDE_MEM_CODEX_HOOK=1 node \"$_P/scripts/version-check.js\"",
|
||||
"timeout": 5
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" start",
|
||||
"timeout": 60
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" hook codex context",
|
||||
"timeout": 60,
|
||||
"statusMessage": "Loading claude-mem context"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" hook codex session-init",
|
||||
"timeout": 60
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "^Bash$|^mcp__.+__(read|view|cat)(_file|_files)?$",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" hook codex file-context",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": ".*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" hook codex observation",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$PLUGIN_ROOT}\"; [ -d \"$_R/plugin/scripts\" ] && _P=\"$_R/plugin\" || _P=\"$_R\"; node \"$_P/scripts/bun-runner.js\" \"$_P/scripts/worker-service.cjs\" hook codex summarize",
|
||||
"timeout": 60
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem-plugin",
|
||||
"version": "12.5.1",
|
||||
"version": "12.7.2",
|
||||
"private": true,
|
||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||
"type": "module",
|
||||
@@ -30,7 +30,8 @@
|
||||
"@tree-sitter-grammars/tree-sitter-toml": "^0.7.0",
|
||||
"@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
|
||||
"@derekstride/tree-sitter-sql": "^0.3.11",
|
||||
"@tree-sitter-grammars/tree-sitter-markdown": "^0.3.2"
|
||||
"@tree-sitter-grammars/tree-sitter-markdown": "^0.3.2",
|
||||
"shell-quote": "^1.8.3"
|
||||
},
|
||||
"overrides": {
|
||||
"tree-sitter": "^0.25.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
import { spawnSync, spawn } from 'child_process';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { existsSync, readFileSync, mkdirSync, appendFileSync, writeFileSync } from 'fs';
|
||||
import { join, dirname, resolve } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { fileURLToPath } from 'url';
|
||||
@@ -138,8 +138,58 @@ if (IS_WINDOWS) {
|
||||
const child = spawn(spawnCmd, spawnArgs, spawnOptions);
|
||||
|
||||
if (child.stdin) {
|
||||
child.stdin.write(stdinData || '{}');
|
||||
child.stdin.end();
|
||||
if (stdinData && stdinData.length > 0) {
|
||||
child.stdin.write(stdinData);
|
||||
child.stdin.end();
|
||||
} else {
|
||||
// Issue #2188: empty/missing stdin previously masked by `|| '{}'` fallback,
|
||||
// which silently hid WSL bash failures (e.g. hooks invoked under a broken
|
||||
// shell that never piped a payload). Surface the failure mode instead.
|
||||
const dataDir = process.env.CLAUDE_MEM_DATA_DIR || join(homedir(), '.claude-mem');
|
||||
const payloadType = stdinData === null
|
||||
? 'null (no data event or stream error)'
|
||||
: stdinData === undefined
|
||||
? 'undefined'
|
||||
: Buffer.isBuffer(stdinData) && stdinData.length === 0
|
||||
? 'empty Buffer (zero bytes received)'
|
||||
: `unexpected (${typeof stdinData})`;
|
||||
const payloadByteLength = (stdinData && typeof stdinData.length === 'number')
|
||||
? stdinData.length
|
||||
: 0;
|
||||
const diagnostic = [
|
||||
`[bun-runner] empty stdin payload received — issue #2188`,
|
||||
` script: ${args[0]}`,
|
||||
` payload byte length: ${payloadByteLength}`,
|
||||
` payload type: ${payloadType}`,
|
||||
` platform: ${process.platform}`,
|
||||
` shell: ${process.env.SHELL || 'n/a'}`,
|
||||
` stdin TTY: ${process.stdin.isTTY === true ? 'true' : process.stdin.isTTY === false ? 'false' : 'undefined'}`,
|
||||
` timestamp: ${new Date().toISOString()}`,
|
||||
` CLAUDE_PLUGIN_ROOT: ${RESOLVED_PLUGIN_ROOT}`,
|
||||
].join('\n');
|
||||
|
||||
// Write to stderr so Claude Code surfaces the diagnostic.
|
||||
console.error(diagnostic);
|
||||
|
||||
// Persist diagnostic to the runner-errors log and drop a CAPTURE_BROKEN marker
|
||||
// file so the next session-start hint can surface the failure. We exit 0 to
|
||||
// honor the project's exit-code strategy (worker/hook errors exit 0 to
|
||||
// prevent Windows Terminal tab pileup) — the marker file is the durable
|
||||
// signal that something is wrong, not the exit code.
|
||||
try {
|
||||
const logsDir = join(dataDir, 'logs');
|
||||
mkdirSync(logsDir, { recursive: true });
|
||||
appendFileSync(join(logsDir, 'runner-errors.log'), diagnostic + '\n\n');
|
||||
mkdirSync(dataDir, { recursive: true });
|
||||
writeFileSync(join(dataDir, 'CAPTURE_BROKEN'), diagnostic + '\n');
|
||||
} catch (writeErr) {
|
||||
console.error(`[bun-runner] failed to persist diagnostic: ${writeErr && writeErr.message ? writeErr.message : writeErr}`);
|
||||
}
|
||||
|
||||
try { child.stdin.end(); } catch {}
|
||||
try { child.kill(); } catch {}
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
child.on('error', (err) => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -19,18 +19,31 @@ function resolveRoot() {
|
||||
const ROOT = resolveRoot();
|
||||
if (!ROOT) process.exit(0);
|
||||
|
||||
function emitUpgradeHint(message) {
|
||||
if (process.env.CLAUDE_MEM_CODEX_HOOK === '1') {
|
||||
console.log(JSON.stringify({
|
||||
hookSpecificOutput: {
|
||||
hookEventName: 'SessionStart',
|
||||
additionalContext: message,
|
||||
},
|
||||
}));
|
||||
} else {
|
||||
console.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
||||
const markerPath = join(ROOT, '.install-version');
|
||||
if (!existsSync(markerPath)) {
|
||||
console.error('claude-mem: runtime not yet set up — run: npx claude-mem repair');
|
||||
emitUpgradeHint('claude-mem: runtime not yet set up - run: npx claude-mem@latest install');
|
||||
process.exit(0);
|
||||
}
|
||||
const marker = JSON.parse(readFileSync(markerPath, 'utf-8'));
|
||||
if (marker.version !== pkg.version) {
|
||||
console.error(`claude-mem: upgraded to v${pkg.version} — run: npx claude-mem repair`);
|
||||
emitUpgradeHint(`claude-mem: upgraded to v${pkg.version} - run: npx claude-mem@latest install`);
|
||||
}
|
||||
} catch {
|
||||
console.error('claude-mem: install marker unreadable — run: npx claude-mem repair');
|
||||
emitUpgradeHint('claude-mem: install marker unreadable - run: npx claude-mem@latest install');
|
||||
}
|
||||
process.exit(0);
|
||||
|
||||
+547
-476
File diff suppressed because one or more lines are too long
@@ -0,0 +1,87 @@
|
||||
---
|
||||
name: babysit
|
||||
description: Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.
|
||||
---
|
||||
|
||||
# Babysit PR
|
||||
|
||||
Stay with the PR until it is actually clean. Do not stop after one check pass if comments or review threads are still unresolved.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Identify the PR number, branch, and base branch.
|
||||
2. Confirm the PR is not draft and inspect mergeability, checks, review decision, comments, and review threads.
|
||||
3. Watch pending checks until they finish. Poll at a practical interval, usually 30-60 seconds unless the user asks for a different cadence.
|
||||
4. Read new comments and unresolved review threads. Treat bot summaries as useful, but verify actionable findings against the code.
|
||||
5. Fix real issues in focused commits, run relevant tests/builds, push, and return to step 2.
|
||||
6. Resolve stale review threads only after verifying the code or generated artifact now addresses the comment.
|
||||
7. Stop only when checks are passing or intentionally skipped, review decision is acceptable, no actionable comments remain, and no unresolved review threads remain.
|
||||
|
||||
## GitHub CLI Checks
|
||||
|
||||
Use `gh pr view` for the coarse status:
|
||||
|
||||
```bash
|
||||
gh pr view <number> --json \
|
||||
number,state,isDraft,mergeable,mergeStateStatus,reviewDecision,headRefOid,statusCheckRollup,url
|
||||
```
|
||||
|
||||
Resolve the repository owner/name before using GraphQL:
|
||||
|
||||
```bash
|
||||
repo_json=$(gh repo view --json owner,name)
|
||||
owner=$(jq -r '.owner.login // .owner.name' <<<"$repo_json")
|
||||
repo=$(jq -r '.name' <<<"$repo_json")
|
||||
```
|
||||
|
||||
Use GraphQL for unresolved review threads. Include `pageInfo`; omit `cursor` on the first page, then pass the previous `endCursor` with `-f cursor="$cursor"` while `hasNextPage` is `true`.
|
||||
|
||||
```bash
|
||||
gh api graphql \
|
||||
-f query='query($owner:String!,$repo:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewThreads(first:100,after:$cursor){pageInfo{hasNextPage endCursor}nodes{id,isResolved,isOutdated,path,line,comments(last:1){nodes{author{login},body,createdAt,url}}}}}}}' \
|
||||
-f owner="$owner" -f repo="$repo" -F number=<number>
|
||||
```
|
||||
|
||||
Use this loop when a PR may have many review threads:
|
||||
|
||||
```bash
|
||||
thread_query='query($owner:String!,$repo:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewThreads(first:100,after:$cursor){pageInfo{hasNextPage endCursor}nodes{id,isResolved,isOutdated,path,line,comments(last:1){nodes{author{login},body,createdAt,url}}}}}}}'
|
||||
cursor_args=()
|
||||
|
||||
while :; do
|
||||
page=$(gh api graphql -f query="$thread_query" -f owner="$owner" -f repo="$repo" -F number=<number> "${cursor_args[@]}")
|
||||
printf '%s\n' "$page" | jq -r '.data.repository.pullRequest.reviewThreads.nodes[]
|
||||
| select(.isResolved==false)
|
||||
| [.id,.path,(.line//""),(.isOutdated|tostring),(.comments.nodes[-1].author.login//""),(.comments.nodes[-1].body|gsub("\n";" ")|.[0:240])]
|
||||
| @tsv'
|
||||
|
||||
jq -e '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage' >/dev/null <<<"$page" || break
|
||||
cursor=$(jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor' <<<"$page")
|
||||
cursor_args=(-f cursor="$cursor")
|
||||
done
|
||||
```
|
||||
|
||||
Filter unresolved threads with `jq`:
|
||||
|
||||
```bash
|
||||
jq -r '.data.repository.pullRequest.reviewThreads.nodes[]
|
||||
| select(.isResolved==false)
|
||||
| [.id,.path,(.line//""),(.isOutdated|tostring),(.comments.nodes[-1].author.login//""),(.comments.nodes[-1].body|gsub("\n";" ")|.[0:240])]
|
||||
| @tsv'
|
||||
```
|
||||
|
||||
Resolve a stale thread only when the fix is verified:
|
||||
|
||||
```bash
|
||||
gh api graphql \
|
||||
-f query='mutation($threadId:ID!){resolveReviewThread(input:{threadId:$threadId}){thread{id,isResolved}}}' \
|
||||
-f threadId=<thread-id>
|
||||
```
|
||||
|
||||
## Operating Rules
|
||||
|
||||
- Keep the watcher running while long checks are pending.
|
||||
- If a generated file is part of the distribution, verify the source and generated artifact agree before resolving comments.
|
||||
- If a bot reports an issue against stale code, confirm whether the thread is outdated or addressed in the latest head.
|
||||
- Before final reporting, do one fresh sweep of PR status, unresolved threads, recent comments, and local `git status`.
|
||||
- Report concrete evidence: latest commit SHA, check names and results, unresolved thread count, tests run, and any dirty local files left untouched.
|
||||
@@ -48,7 +48,11 @@ description: Automated semantic versioning and release workflow for Claude Code
|
||||
```
|
||||
(Runs `node scripts/generate-changelog.js`, which pulls releases from the GitHub API and rewrites `CHANGELOG.md`.)
|
||||
10. **Sync changelog**: Commit and push the updated `CHANGELOG.md`.
|
||||
11. **Notify**: `npm run discord:notify vX.Y.Z` if applicable.
|
||||
11. **Notify**: Run the Discord notification from `~/Scripts/claude-mem/`, where the `.env` with Discord webhook details lives:
|
||||
```bash
|
||||
cd ~/Scripts/claude-mem/ && npm run discord:notify vX.Y.Z
|
||||
```
|
||||
Do this even when the release worktree does not have a local `.env`.
|
||||
12. **Finalize**: `git status` — working tree must be clean.
|
||||
|
||||
## Checklist
|
||||
@@ -60,4 +64,5 @@ description: Automated semantic versioning and release workflow for Claude Code
|
||||
- [ ] **`npm publish` succeeded and `npm view claude-mem@X.Y.Z version` confirms it** (so `npx claude-mem@X.Y.Z` resolves)
|
||||
- [ ] GitHub release created with notes
|
||||
- [ ] `CHANGELOG.md` updated and pushed
|
||||
- [ ] Discord notification run from `~/Scripts/claude-mem/`
|
||||
- [ ] `git status` shows clean tree
|
||||
|
||||
Reference in New Issue
Block a user