Skip to content

feat: auto-seed project context in session-start hook #127

@wcatz

Description

@wcatz

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

  1. Parse stdin JSON (Claude Code sends {"cwd": "/path/to/project", "source": "startup", ...})
  2. Open ghost.db read-only using config.DataDir() + sql.Open("sqlite", path+"?mode=ro&...")
  3. 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)
  4. Query ghost_state.learned_context for the project summary
  5. Query top 25 memories: ORDER BY pinned DESC, importance DESC, updated_at DESC
  6. Truncate memory content at 300 chars
  7. Format and write to stdout
  8. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions