Summary
The SessionStart hook currently outputs a static reminder telling Claude to call ghost_list_projects and ghost_project_context. This relies on the agent remembering to act on it, which is unreliable.
The hook should automatically query the ghost DB and inject the full project context into the session-start output, so the agent has everything it needs from the first message without any tool calls.
Desired behavior
When Claude Code starts a session in a known project directory, the hook output should look like:
## Ghost context: dingo
**Summary:** <learned_context from ghost_state>
**Memories:**
- [convention] nerdctl command is ...
- [preference] do not use kubectl set env ...
- [fact] ...
Save new discoveries with ghost_memory_save during work.
If no matching project is found, fall back to the existing static reminder.
Implementation
File: internal/mcpinit/hook.go
Changes needed to HandleSessionStartHook
- Parse stdin JSON (Claude Code sends
{"cwd": "/path/to/project", "source": "startup", ...})
- Open ghost.db read-only using
config.DataDir() + sql.Open("sqlite", path+"?mode=ro&...")
- Find matching project:
- First try:
WHERE ? LIKE path || '%' AND LENGTH(path) > 10 (full path match for projects with absolute paths)
- Fallback:
WHERE name = filepath.Base(cwd) (name match from cwd basename)
- Query
ghost_state.learned_context for the project summary
- Query top 25 memories:
ORDER BY pinned DESC, importance DESC, updated_at DESC
- Truncate memory content at 300 chars
- Format and write to stdout
- On any error, fall back to static reminder text
Key constraints
- Must not run migrations (do not use
memory.OpenDB — open database/sql directly)
- Read-only DB access only (
?mode=ro)
- Always fall back gracefully — hook failure must not block session start
- Keep latency low (single DB open, 2 queries max)
Imports needed
import (
"database/sql"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/wcatz/ghost/internal/config"
_ "modernc.org/sqlite"
)
Test
echo '{"cwd":"/home/wayne/git/dingo","source":"startup"}' | ./ghost hook session-start
# Should output Ghost context: dingo with memories, not the static reminder
Related
- CLAUDE.md updated to: "Ghost auto-seeds project context via the session-start hook — read it before doing anything"
ghost_project_context tool call at session start is no longer needed once this is in
Summary
The
SessionStarthook currently outputs a static reminder telling Claude to callghost_list_projectsandghost_project_context. This relies on the agent remembering to act on it, which is unreliable.The hook should automatically query the ghost DB and inject the full project context into the session-start output, so the agent has everything it needs from the first message without any tool calls.
Desired behavior
When Claude Code starts a session in a known project directory, the hook output should look like:
If no matching project is found, fall back to the existing static reminder.
Implementation
File:
internal/mcpinit/hook.goChanges needed to
HandleSessionStartHook{"cwd": "/path/to/project", "source": "startup", ...})config.DataDir()+sql.Open("sqlite", path+"?mode=ro&...")WHERE ? LIKE path || '%' AND LENGTH(path) > 10(full path match for projects with absolute paths)WHERE name = filepath.Base(cwd)(name match from cwd basename)ghost_state.learned_contextfor the project summaryORDER BY pinned DESC, importance DESC, updated_at DESCKey constraints
memory.OpenDB— opendatabase/sqldirectly)?mode=ro)Imports needed
Test
Related
ghost_project_contexttool call at session start is no longer needed once this is in