ompsure

Session Context Optimization

Lightweight session hooks + on-demand architecture loading reduce scaffolding overhead before any work starts.

Session Context Optimization

Scenario: Plugin scaffolding consumes too much context before any work starts Stack: Any project with Composure + companion plugins installed Plugin feature: Lightweight session hooks, on-demand architecture loading


The Problem

Claude Code has a finite context window. Every line of plugin instructions, skill listings, MCP server descriptions, and hook injections competes with the actual work — your code, your files, your conversation.

When multiple plugins are installed, session startup can inject hundreds of lines of scaffolding before you type a single character. This scaffolding includes:

  • Architecture routing tables
  • Skill registrations (each plugin lists all its skills)
  • MCP server instructions
  • Hook-injected context on every file operation

The more plugins you install, the less context remains for actual work.


What We Measured

Before Optimization

SourceLines injectedWhen
Architecture router (SKILL.md)~200Every session start, resume, compact
Skills list (with duplicates)~80 entriesEvery session lifecycle event
MCP instructions (Context7 2x)~40Every session lifecycle event
Resume agent hook60s agent spawnEvery resume

Total pre-work overhead: ~1,300+ lines of context before the user says anything.

On resume or context compaction (mid-conversation), the full 200-line architecture router would be re-injected — even though the information was already in the conversation from earlier.

Plugin Skill Duplication

Multiple plugins from the same marketplace registered identical skills:

PluginSkills registeredUnique skills
document-skills1717
example-skills170 (100% duplicate)
claude-api170 (100% duplicate)
expo-plugin-11212
expo-plugin-2120 (100% duplicate)
expo-plugin-3120 (100% duplicate)

80+ skill entries, but only ~40 unique. The duplicates consumed context for zero benefit.

An MCP server (Context7) was registered both as a plugin AND as an MCP JSON server — doubling its tool listings and instruction blocks.


The Fix

1. On-Demand Architecture Loading

Before: Full 200-line SKILL.md routing table injected at every session start After: 8-line stack note on startup, 1-line reminder on resume

# Startup (fresh session)
[composure:stack] Detected: typescript | frontend=nextjs | backend=supabase
Architecture category: fullstack (entry: fullstack/INDEX.md → nextjs/nextjs.md)

When building features:
- Non-trivial work: Run /composure:blueprint first
- Routine edits: /composure:app-architecture loads reference docs on demand

# Resume (same conversation continuing)
[composure:stack] typescript | nextjs | arch=fullstack

The full architecture docs load only when /app-architecture or /blueprint is explicitly invoked — when you're actually building something.

2. Lifecycle-Aware Hooks

SessionStart hooks now read the source field from stdin JSON to differentiate:

EventWhat firesContext injected
startupFull stack note + task/graph check~10 lines
resume1-line stack reminder + task/graph check~3 lines
compact1-line stack reminder only~1 line

The old approach treated all lifecycle events the same — 200 lines every time.

3. Stale Graph Detection

The resume hook checks if the code graph is stale and instructs Claude to rebuild before exploring:

[composure:action-required] Code graph is stale.
BEFORE any feature work, rebuild using build_or_update_graph.

This prevents the expensive fallback where Claude spawns multiple Explore agents (see Graph vs Explore case study).

4. Plugin Deduplication

Disabled redundant plugins:

ChangeImpact
Disabled example-skills-17 duplicate skill entries
Disabled claude-api plugin-17 duplicate skill entries
Disabled 2 of 3 expo plugins-24 duplicate skill entries
Disabled Context7 plugin (kept MCP JSON server)-1 duplicate MCP tool set

5. Agent Hook → Command Hook

The resume check was a type: "agent" hook that spawned a 60-second sub-agent to count tasks and check graph staleness. The docs say SessionStart only supports type: "command" hooks.

Replaced with a bash script that does the same job in <1 second:

[composure:resume] Tasks: 4 open, 0 done | Code graph is stale.

Results

MetricBeforeAfterImprovement
Session start context~200 lines~10 lines20x less
Session resume context~200 lines~3 lines67x less
Skill list entries~80~4050% reduction
Context7 tool sets21No duplication
Resume hook time~60s (agent)<1s (command)60x faster
Architecture docsAlways loadedOn-demand onlyZero waste on non-feature work

The Principle

Load what you need, when you need it.

Every line of context injected at session start is a line that can't be used for reasoning about the actual problem. Plugins should be invisible until they're needed — then load precisely the right context for the task at hand.

The ideal plugin has:

  • Zero overhead on sessions that don't need it
  • Minimal overhead on sessions that do (just enough to trigger the right loading)
  • Full context available on-demand when explicitly invoked

Docs: composure-pro.com

Composure v1.2.74 · Claude Opus 4.6

On this page