Hooks and Context Injection
ctxloom uses hooks to automatically inject context into your AI coding sessions. This guide explains how the hook system works and how to configure it.
How Context Injection Works
When you start a Claude Code session, ctxloom automatically injects your configured context (fragments, profiles) into the conversation. This happens through a SessionStart hook that runs before each session.
The Flow
- You run
ctxloom runor start Claude Code in a project with ctxloom configured - ctxloom assembles context from your default profile, bundles, and tags
- Context is written to a temporary file in
.ctxloom/context/ - The SessionStart hook injects this context into the AI session
- The context file is deleted after injection (one-time use)
Automatic Hook Setup
When you run ctxloom init or ctxloom mcp serve, ctxloom automatically configures hooks in your AI tool’s settings:
Claude Code
ctxloom adds a hook to .claude/settings.json:
{ "hooks": { "SessionStart": { "hooks": [ { "type": "command", "command": "ctxloom hook inject-context <hash>", "timeout": 60 } ] } }}Gemini
Similar configuration in .gemini/settings.json.
Manual Hook Management
Apply Hooks
Hooks are applied automatically when you run ctxloom init or start ctxloom mcp serve.
To manually reapply hooks, you can:
- Re-run init (simplest approach):
ctxloom init- Use the MCP tool (if ctxloom is running as MCP server):
Via MCP
{ "tool": "apply_hooks", "arguments": { "backend": "claude-code", "regenerate_context": true }}Context Assembly
What Gets Included
Context is assembled from:
- Default Profile - Your configured default profile
- Profile Parents - Any parent profiles inherited
- Bundles - All bundles referenced by the profile
- Tagged Fragments - Fragments matching profile tags
Assembly Order
Fragments are ordered using a “bookend” strategy to address the Lost in the Middle problem where LLMs attend poorly to middle content:
| Position | Content | Why |
|---|---|---|
| Start | Highest priority | Primacy effect - best attention |
| End | Second highest priority | Recency effect - good attention |
| Middle | Remaining (descending) | Weaker attention area |
Fragments without explicit priority default to 0. See Fragment Priority for setting priorities.
Deduplication
ctxloom automatically deduplicates content:
- Same fragment from multiple sources appears once
- Content-hash based deduplication catches identical content even from different bundles
Context Size Management
Size Warning
ctxloom warns when assembled context exceeds 16KB:
ctxloom: warning: assembled context is 24KB (recommended max: 16KB)ctxloom: warning: large context may reduce LLM effectiveness; consider using fewer/smaller fragmentsResearch shows that LLM performance degrades with larger context, particularly for middle-positioned content. See the Distillation Guide for details.
Reducing Context Size
If you see size warnings:
- Use distillation - Distill verbose fragments to compressed versions
- Be selective - Only include fragments relevant to current work
- Split profiles - Create task-specific profiles instead of one large profile
- Review bundles - Remove unused bundles from profiles
Hook Commands
inject-context
The primary hook command that injects context:
ctxloom hook inject-context <hash><hash>- Content hash identifying the context file- Reads from
.ctxloom/context/<hash>.md - Outputs context to stdout for the AI to consume
- Deletes the context file after reading
Environment Variables
The hook system uses:
| Variable | Description |
|---|---|
CTXLOOM_CONTEXT_FILE | Path to the context file to inject |
CTXLOOM_VERBOSE | Enable verbose output for debugging |
Debugging Hooks
Check Hook Configuration
# View Claude Code settingscat .claude/settings.json | jq '.hooks'
# View current context filels -la .ctxloom/context/Test Context Assembly
# Preview what would be injectedctxloom run --dry-run --print
# Assemble and show contextctxloom run --printVerbose Mode
Enable verbose output to see hook execution:
CTXLOOM_VERBOSE=1 ctxloom runCustom Hooks
While ctxloom manages its own hooks, you can add custom hooks alongside ctxloom’s:
{ "hooks": { "SessionStart": { "hooks": [ { "type": "command", "command": "ctxloom hook inject-context abc123" }, { "type": "command", "command": "my-custom-hook.sh" } ] } }}Note: ctxloom identifies its hooks by an internal marker (_ctxloom field) and only updates its own hooks, leaving your custom hooks intact.
Troubleshooting
Context Not Injected
- Check hooks are applied:
cat .claude/settings.json - Verify context file exists:
ls .ctxloom/context/ - Run with verbose:
CTXLOOM_VERBOSE=1 ctxloom run
Stale Context
If context seems outdated, re-run init to regenerate context and reapply hooks:
ctxloom initHook Timeout
If hooks timeout, increase the timeout in settings or optimize your context assembly (reduce fragments, use distillation).
Integration with Profiles
Hooks work seamlessly with profiles:
description: My default development contextbundles: - go-development - testing-patternstags: - best-practicesWhen this is your default profile, every session automatically gets these bundles and tagged fragments injected.
Best Practices
- Keep context focused - Include only what’s relevant to your current work
- Use profiles - Create different profiles for different tasks
- Monitor size - Watch for size warnings and optimize as needed
- Test changes - Use
--dry-runto preview context changes - Version control - Commit your
.ctxloom/configuration