fix: Add missing process.exit(0) calls in hook entry points
All 4 hook entry point scripts were missing process.exit(0) after successful
execution, causing Node processes to hang indefinitely instead of returning
control to Claude Code with exit code 0.
Root cause: In commit 6f62a56, process.exit(0) calls were removed from the
hook functions but were never added to the entry point scripts that wrap them.
Fixed files:
- src/bin/hooks/save-hook.ts (PostToolUse)
- src/bin/hooks/new-hook.ts (UserPromptSubmit)
- src/bin/hooks/summary-hook.ts (Stop)
- src/bin/hooks/context-hook.ts (SessionStart)
This restores proper hook exit behavior and prevents Claude Code from waiting
indefinitely for hook completion.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
# Claude Code Hooks Exit Code Cheat Sheet
|
||||
|
||||
## Exit Code Behavior [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
- **Exit code 0**: Success. `stdout` is shown to the user in transcript mode, except for `UserPromptSubmit` hook where stdout is injected as context [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
- **Exit code 2**: Blocking error. `stderr` is fed back to Claude to process automatically [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
- **Other exit codes**: Non-blocking error. `stderr` is shown to the user and execution continues [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
## Per-Hook Event Behavior [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
|
||||
| Hook Event | Exit Code 2 Behavior |
|
||||
|------------|---------------------|
|
||||
| `PreToolUse` | Blocks the tool call, shows stderr to Claude [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `PostToolUse` | Shows stderr to Claude (tool already ran) [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `Notification` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `UserPromptSubmit` | Blocks prompt processing, erases prompt, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `Stop` | Blocks stoppage, shows stderr to Claude [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SubagentStop` | Blocks stoppage, shows stderr to Claude subagent [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `PreCompact` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SessionStart` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
| `SessionEnd` | N/A, shows stderr to user only [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output) |
|
||||
|
||||
## Quick Reference
|
||||
|
||||
- **Success**: `process.exit(0)` - Operation completed successfully
|
||||
- **Block & feedback**: `process.exit(2)` - Block operation and give Claude feedback via stderr
|
||||
- **Non-blocking error**: `process.exit(1)` - Show error to user but continue execution
|
||||
|
||||
**Important**: Claude Code does not see stdout if the exit code is 0, except for the `UserPromptSubmit` hook where stdout is injected as context [(1)](https://docs.claude.com/en/docs/claude-code/hooks#hook-output)
|
||||
@@ -119,4 +119,4 @@ import S from"path";import k from"better-sqlite3";import{join as m,dirname as N,
|
||||
|
||||
No previous sessions found for this project yet.`);return}let r=[];if(r.push("# Recent Session Context"),r.push(""),a.length>0){r.push(`## Recent Observations (${a.length})`),r.push("");let o={};for(let n of a)o[n.type]||(o[n.type]=[]),o[n.type].push({text:n.text,prompt_number:n.prompt_number,created_at:n.created_at});let c=["feature","bugfix","refactor","discovery","decision"];for(let n of c)if(o[n]&&o[n].length>0){r.push(`### ${n.charAt(0).toUpperCase()+n.slice(1)}s`);for(let _ of o[n]){let A=_.prompt_number?` (prompt #${_.prompt_number})`:"";r.push(`- ${_.text}${A}`)}r.push("")}}if(i.length===0){console.log(r.join(`
|
||||
`));return}r.push("## Recent Sessions"),r.push("");let u=i.length===1?"session":"sessions";r.push(`Showing last ${i.length} ${u} for **${t}**:`),r.push("");for(let o of i){r.push("---"),r.push("");let c=o.prompt_number?` (Prompt #${o.prompt_number})`:"";if(r.push(`**Summary${c}**`),r.push(""),o.request&&r.push(`**Request:** ${o.request}`),o.completed&&r.push(`**Completed:** ${o.completed}`),o.learned&&r.push(`**Learned:** ${o.learned}`),o.next_steps&&r.push(`**Next Steps:** ${o.next_steps}`),o.files_read)try{let n=JSON.parse(o.files_read);Array.isArray(n)&&n.length>0&&r.push(`**Files Read:** ${n.join(", ")}`)}catch{o.files_read.trim()&&r.push(`**Files Read:** ${o.files_read}`)}if(o.files_edited)try{let n=JSON.parse(o.files_edited);Array.isArray(n)&&n.length>0&&r.push(`**Files Edited:** ${n.join(", ")}`)}catch{o.files_edited.trim()&&r.push(`**Files Edited:** ${o.files_edited}`)}r.push(`**Date:** ${o.created_at.split("T")[0]}`),r.push("")}console.log(r.join(`
|
||||
`))}finally{s.close()}}import{stdin as g}from"process";try{if(g.isTTY)b();else{let p="";g.on("data",e=>p+=e),g.on("end",()=>{let e=p.trim()?JSON.parse(p):void 0;b(e)})}}catch(p){console.error(`[claude-mem context-hook error: ${p.message}]`),process.exit(0)}
|
||||
`))}finally{s.close()}}import{stdin as g}from"process";try{if(g.isTTY)b();else{let p="";g.on("data",e=>p+=e),g.on("end",()=>{let e=p.trim()?JSON.parse(p):void 0;b(e),process.exit(0)})}}catch(p){console.error(`[claude-mem context-hook error: ${p.message}]`),process.exit(0)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
import O from"path";import A from"better-sqlite3";import{join as c,dirname as v,basename as w}from"path";import{homedir as T}from"os";import{existsSync as U,mkdirSync as D}from"fs";var p=process.env.CLAUDE_MEM_DATA_DIR||c(T(),".claude-mem"),b=process.env.CLAUDE_CONFIG_DIR||c(T(),".claude"),H=c(p,"archives"),M=c(p,"logs"),j=c(p,"trash"),F=c(p,"backups"),W=c(p,"settings.json"),f=c(p,"claude-mem.db"),B=c(b,"settings.json"),X=c(b,"commands"),q=c(b,"CLAUDE.md");function k(r){D(r,{recursive:!0})}var l=class{db;constructor(){k(p),this.db=new A(f),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(s=>s.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(m=>m.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(m=>m.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(m=>m.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let d=this.db.pragma("index_list(session_summaries)").some(m=>m.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(s=>s.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
import O from"path";import A from"better-sqlite3";import{join as c,dirname as v,basename as w}from"path";import{homedir as T}from"os";import{existsSync as U,mkdirSync as D}from"fs";var m=process.env.CLAUDE_MEM_DATA_DIR||c(T(),".claude-mem"),b=process.env.CLAUDE_CONFIG_DIR||c(T(),".claude"),H=c(m,"archives"),M=c(m,"logs"),j=c(m,"trash"),F=c(m,"backups"),W=c(m,"settings.json"),f=c(m,"claude-mem.db"),B=c(b,"settings.json"),X=c(b,"commands"),q=c(b,"CLAUDE.md");function k(r){D(r,{recursive:!0})}var l=class{db;constructor(){k(m),this.db=new A(f),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(s=>s.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(p=>p.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(p=>p.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(p=>p.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let d=this.db.pragma("index_list(session_summaries)").some(p=>p.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(s=>s.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
CREATE TABLE session_summaries_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
@@ -115,4 +115,4 @@ import O from"path";import A from"better-sqlite3";import{join as c,dirname as v,
|
||||
UPDATE sdk_sessions
|
||||
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
|
||||
WHERE status = 'active'
|
||||
`).run(e.toISOString(),t).changes}close(){this.db.close()}};function R(r,e,t){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:t.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&t.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:t.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...t.reason&&!e?{stopReason:t.reason}:{}}}function _(r,e,t={}){let s=R(r,e,t);return JSON.stringify(s)}async function I(){let{readFileSync:r,existsSync:e}=await import("fs"),{join:t}=await import("path"),{homedir:s}=await import("os"),n=t(s(),".claude-mem","worker.port");if(!e(n))return null;try{let o=r(n,"utf8").trim();return parseInt(o,10)}catch{return null}}async function h(r){if(!r)throw new Error("newHook requires input");let{session_id:e,cwd:t,prompt:s}=r,n=O.basename(t),o=new l;try{let a=o.findActiveSDKSession(e),i,d=!1;if(a){i=a.id;let u=o.incrementPromptCounter(i);console.error(`[new-hook] Continuing session ${i}, prompt #${u}`)}else{let u=o.findAnySDKSession(e);if(u){i=u.id,o.reactivateSession(i,s);let E=o.incrementPromptCounter(i);d=!0,console.error(`[new-hook] Reactivated session ${i}, prompt #${E}`)}else{i=o.createSDKSession(e,n,s);let E=o.incrementPromptCounter(i);d=!0,console.error(`[new-hook] Created new session ${i}, prompt #${E}`)}}let m=await I();if(!m){console.error("[new-hook] Worker service not running. Start with: npm run worker:start"),console.log(_("UserPromptSubmit",!0));return}if(d){let u=await fetch(`http://127.0.0.1:${m}/sessions/${i}/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({project:n,userPrompt:s}),signal:AbortSignal.timeout(5e3)});u.ok||console.error("[new-hook] Failed to init session:",await u.text())}console.log(_("UserPromptSubmit",!0))}catch(a){console.error("[new-hook] FATAL ERROR:",a.message),console.error("[new-hook] Stack:",a.stack),console.error("[new-hook] Full error:",JSON.stringify(a,Object.getOwnPropertyNames(a))),console.log(_("UserPromptSubmit",!0))}finally{o.close()}}import{stdin as S}from"process";var g="";S.on("data",r=>g+=r);S.on("end",async()=>{try{let r=g.trim()?JSON.parse(g):void 0;await h(r)}catch(r){console.error(`[claude-mem new-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
`).run(e.toISOString(),t).changes}close(){this.db.close()}};function R(r,e,t){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:t.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&t.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:t.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...t.reason&&!e?{stopReason:t.reason}:{}}}function _(r,e,t={}){let s=R(r,e,t);return JSON.stringify(s)}async function I(){let{readFileSync:r,existsSync:e}=await import("fs"),{join:t}=await import("path"),{homedir:s}=await import("os"),n=t(s(),".claude-mem","worker.port");if(!e(n))return null;try{let o=r(n,"utf8").trim();return parseInt(o,10)}catch{return null}}async function h(r){if(!r)throw new Error("newHook requires input");let{session_id:e,cwd:t,prompt:s}=r,n=O.basename(t),o=new l;try{let a=o.findActiveSDKSession(e),i,d=!1;if(a){i=a.id;let u=o.incrementPromptCounter(i);console.error(`[new-hook] Continuing session ${i}, prompt #${u}`)}else{let u=o.findAnySDKSession(e);if(u){i=u.id,o.reactivateSession(i,s);let E=o.incrementPromptCounter(i);d=!0,console.error(`[new-hook] Reactivated session ${i}, prompt #${E}`)}else{i=o.createSDKSession(e,n,s);let E=o.incrementPromptCounter(i);d=!0,console.error(`[new-hook] Created new session ${i}, prompt #${E}`)}}let p=await I();if(!p){console.error("[new-hook] Worker service not running. Start with: npm run worker:start"),console.log(_("UserPromptSubmit",!0));return}if(d){let u=await fetch(`http://127.0.0.1:${p}/sessions/${i}/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({project:n,userPrompt:s}),signal:AbortSignal.timeout(5e3)});u.ok||console.error("[new-hook] Failed to init session:",await u.text())}console.log(_("UserPromptSubmit",!0))}catch(a){console.error("[new-hook] FATAL ERROR:",a.message),console.error("[new-hook] Stack:",a.stack),console.error("[new-hook] Full error:",JSON.stringify(a,Object.getOwnPropertyNames(a))),console.log(_("UserPromptSubmit",!0))}finally{o.close()}}import{stdin as S}from"process";var g="";S.on("data",r=>g+=r);S.on("end",async()=>{try{let r=g.trim()?JSON.parse(g):void 0;await h(r),process.exit(0)}catch(r){console.error(`[claude-mem new-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
import S from"better-sqlite3";import{join as a,dirname as I,basename as N}from"path";import{homedir as g}from"os";import{existsSync as y,mkdirSync as h}from"fs";var c=process.env.CLAUDE_MEM_DATA_DIR||a(g(),".claude-mem"),_=process.env.CLAUDE_CONFIG_DIR||a(g(),".claude"),U=a(c,"archives"),P=a(c,"logs"),w=a(c,"trash"),H=a(c,"backups"),M=a(c,"settings.json"),b=a(c,"claude-mem.db"),W=a(_,"settings.json"),B=a(_,"commands"),j=a(_,"CLAUDE.md");function T(r){h(r,{recursive:!0})}var l=class{db;constructor(){T(c),this.db=new S(b),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(t=>t.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(u=>u.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(u=>u.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(u=>u.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let m=this.db.pragma("index_list(session_summaries)").some(u=>u.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(t=>t.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
import S from"better-sqlite3";import{join as a,dirname as I,basename as N}from"path";import{homedir as g}from"os";import{existsSync as y,mkdirSync as h}from"fs";var c=process.env.CLAUDE_MEM_DATA_DIR||a(g(),".claude-mem"),_=process.env.CLAUDE_CONFIG_DIR||a(g(),".claude"),U=a(c,"archives"),P=a(c,"logs"),w=a(c,"trash"),H=a(c,"backups"),M=a(c,"settings.json"),b=a(c,"claude-mem.db"),B=a(_,"settings.json"),W=a(_,"commands"),j=a(_,"CLAUDE.md");function T(r){h(r,{recursive:!0})}var l=class{db;constructor(){T(c),this.db=new S(b),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(t=>t.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(u=>u.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(u=>u.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(u=>u.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let m=this.db.pragma("index_list(session_summaries)").some(u=>u.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(t=>t.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
CREATE TABLE session_summaries_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
@@ -115,4 +115,4 @@ import S from"better-sqlite3";import{join as a,dirname as I,basename as N}from"p
|
||||
UPDATE sdk_sessions
|
||||
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
|
||||
WHERE status = 'active'
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function D(r,e,s){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:s.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&s.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:s.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...s.reason&&!e?{stopReason:s.reason}:{}}}function d(r,e,s={}){let t=D(r,e,s);return JSON.stringify(t)}var A=new Set(["TodoWrite","ListMcpResourcesTool"]);async function f(r){if(!r)throw new Error("saveHook requires input");let{session_id:e,tool_name:s,tool_input:t,tool_output:n}=r;if(A.has(s)){console.log(d("PostToolUse",!0));return}let o=new l,i=o.findActiveSDKSession(e);if(!i){o.close(),console.log(d("PostToolUse",!0));return}if(!i.worker_port){o.close(),console.error("[save-hook] No worker port for session",i.id),console.log(d("PostToolUse",!0));return}let p=o.getPromptCounter(i.id);o.close();try{let m=await fetch(`http://127.0.0.1:${i.worker_port}/sessions/${i.id}/observations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tool_name:s,tool_input:JSON.stringify(t),tool_output:JSON.stringify(n),prompt_number:p}),signal:AbortSignal.timeout(2e3)});m.ok||console.error("[save-hook] Failed to send observation:",await m.text())}catch(m){console.error("[save-hook] Error:",m.message)}finally{console.log(d("PostToolUse",!0))}}import{stdin as k}from"process";var E="";k.on("data",r=>E+=r);k.on("end",async()=>{try{let r=E.trim()?JSON.parse(E):void 0;await f(r)}catch(r){console.error(`[claude-mem save-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function D(r,e,s){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:s.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&s.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:s.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...s.reason&&!e?{stopReason:s.reason}:{}}}function d(r,e,s={}){let t=D(r,e,s);return JSON.stringify(t)}var A=new Set(["ListMcpResourcesTool"]);async function f(r){if(!r)throw new Error("saveHook requires input");let{session_id:e,tool_name:s,tool_input:t,tool_output:n}=r;if(A.has(s)){console.log(d("PostToolUse",!0));return}let o=new l,i=o.findActiveSDKSession(e);if(!i){o.close(),console.log(d("PostToolUse",!0));return}if(!i.worker_port){o.close(),console.error("[save-hook] No worker port for session",i.id),console.log(d("PostToolUse",!0));return}let p=o.getPromptCounter(i.id);o.close();try{let m=await fetch(`http://127.0.0.1:${i.worker_port}/sessions/${i.id}/observations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tool_name:s,tool_input:JSON.stringify(t),tool_output:JSON.stringify(n),prompt_number:p}),signal:AbortSignal.timeout(2e3)});m.ok||console.error("[save-hook] Failed to send observation:",await m.text())}catch(m){console.error("[save-hook] Error:",m.message)}finally{console.log(d("PostToolUse",!0))}}import{stdin as k}from"process";var E="";k.on("data",r=>E+=r);k.on("end",async()=>{try{let r=E.trim()?JSON.parse(E):void 0;await f(r),process.exit(0)}catch(r){console.error(`[claude-mem save-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
|
||||
@@ -115,4 +115,4 @@ import h from"better-sqlite3";import{join as i,dirname as O,basename as I}from"p
|
||||
UPDATE sdk_sessions
|
||||
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
|
||||
WHERE status = 'active'
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function S(r,e,s){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:s.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&s.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:s.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...s.reason&&!e?{stopReason:s.reason}:{}}}function p(r,e,s={}){let t=S(r,e,s);return JSON.stringify(t)}async function T(r){if(!r)throw new Error("summaryHook requires input");let{session_id:e}=r,s=new m,t=s.findActiveSDKSession(e);if(!t){s.close(),console.log(p("Stop",!0));return}if(!t.worker_port){s.close(),console.error("[summary-hook] No worker port for session",t.id),console.log(p("Stop",!0));return}let o=s.getPromptCounter(t.id);s.close();try{let n=await fetch(`http://127.0.0.1:${t.worker_port}/sessions/${t.id}/summarize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt_number:o}),signal:AbortSignal.timeout(2e3)});n.ok||console.error("[summary-hook] Failed to generate summary:",await n.text())}catch(n){console.error("[summary-hook] Error:",n.message)}finally{console.log(p("Stop",!0))}}import{stdin as f}from"process";var _="";f.on("data",r=>_+=r);f.on("end",async()=>{try{let r=_.trim()?JSON.parse(_):void 0;await T(r)}catch(r){console.error(`[claude-mem summary-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function S(r,e,s){return r==="PreCompact"?e?{continue:!0,suppressOutput:!0}:{continue:!1,stopReason:s.reason||"Pre-compact operation failed",suppressOutput:!0}:r==="SessionStart"?e&&s.context?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:s.context}}:{continue:!0,suppressOutput:!0}:r==="UserPromptSubmit"||r==="PostToolUse"?{continue:!0,suppressOutput:!0}:r==="Stop"?{continue:!0,suppressOutput:!0}:{continue:e,suppressOutput:!0,...s.reason&&!e?{stopReason:s.reason}:{}}}function p(r,e,s={}){let t=S(r,e,s);return JSON.stringify(t)}async function T(r){if(!r)throw new Error("summaryHook requires input");let{session_id:e}=r,s=new m,t=s.findActiveSDKSession(e);if(!t){s.close(),console.log(p("Stop",!0));return}if(!t.worker_port){s.close(),console.error("[summary-hook] No worker port for session",t.id),console.log(p("Stop",!0));return}let o=s.getPromptCounter(t.id);s.close();try{let n=await fetch(`http://127.0.0.1:${t.worker_port}/sessions/${t.id}/summarize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt_number:o}),signal:AbortSignal.timeout(2e3)});n.ok||console.error("[summary-hook] Failed to generate summary:",await n.text())}catch(n){console.error("[summary-hook] Error:",n.message)}finally{console.log(p("Stop",!0))}}import{stdin as f}from"process";var _="";f.on("data",r=>_+=r);f.on("end",async()=>{try{let r=_.trim()?JSON.parse(_):void 0;await T(r),process.exit(0)}catch(r){console.error(`[claude-mem summary-hook error: ${r.message}]`),console.log('{"continue": true, "suppressOutput": true}'),process.exit(0)}});
|
||||
|
||||
@@ -16,6 +16,7 @@ try {
|
||||
stdin.on('end', () => {
|
||||
const parsed = input.trim() ? JSON.parse(input) : undefined;
|
||||
contextHook(parsed);
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -14,6 +14,7 @@ stdin.on('end', async () => {
|
||||
try {
|
||||
const parsed = input.trim() ? JSON.parse(input) : undefined;
|
||||
await newHook(parsed);
|
||||
process.exit(0);
|
||||
} catch (error: any) {
|
||||
console.error(`[claude-mem new-hook error: ${error.message}]`);
|
||||
console.log('{"continue": true, "suppressOutput": true}');
|
||||
|
||||
@@ -14,6 +14,7 @@ stdin.on('end', async () => {
|
||||
try {
|
||||
const parsed = input.trim() ? JSON.parse(input) : undefined;
|
||||
await saveHook(parsed);
|
||||
process.exit(0);
|
||||
} catch (error: any) {
|
||||
console.error(`[claude-mem save-hook error: ${error.message}]`);
|
||||
console.log('{"continue": true, "suppressOutput": true}');
|
||||
|
||||
@@ -14,6 +14,7 @@ stdin.on('end', async () => {
|
||||
try {
|
||||
const parsed = input.trim() ? JSON.parse(input) : undefined;
|
||||
await summaryHook(parsed);
|
||||
process.exit(0);
|
||||
} catch (error: any) {
|
||||
console.error(`[claude-mem summary-hook error: ${error.message}]`);
|
||||
console.log('{"continue": true, "suppressOutput": true}');
|
||||
|
||||
@@ -12,7 +12,6 @@ export interface PostToolUseInput {
|
||||
|
||||
// Tools to skip (low value or too frequent)
|
||||
const SKIP_TOOLS = new Set([
|
||||
'TodoWrite',
|
||||
'ListMcpResourcesTool'
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user