Learning Output Style — Interactive Learning Mode

Interactive Learning Mode

Combines explanatory insights with interactive code participation. Requests meaningful code contributions from users at decision points while providing educational guidance through ★ Insight blocks.

1
Hook
2
Modes
4
Files
Shell
Language

🎓 Interactive Learning💡 Explanatory🔧 SessionStart Hook✋ User Participation

📚 What is this & why does it exist?

Learning Output Style is a dual-mode SessionStart hook that transforms Claude Code from a code-generation tool into an interactive teaching assistant. In Learning Mode, Claude identifies decision points — moments where meaningful engineering choices must be made — and pauses to let the user write that code themselves, offering guidance rather than solutions. In Explanatory Mode, it provides ★ Insight blocks just like the Explanatory Output Style plugin. The result is a workflow that teaches by doing, not just by telling.

💡 Real-world analogy

Imagine a driving instructor who handles the boring highway stretches but hands you the wheel at every intersection, roundabout, and parallel-parking spot. They don’t just say “turn left” — they explain why this turn is tricky (blind corner, yield sign, pedestrian crossing) and let you practice it. The Learning Output Style works the same way: Claude handles boilerplate and configuration, but at every meaningful decision point — error handling strategy, algorithm choice, data structure selection — it hands the keyboard back to you with context about what matters and why.

Architecture

The plugin operates through a single SessionStart hook that injects dual-mode behavior instructions. Claude dynamically switches between implementing code directly and pausing for user participation based on whether the current task involves a decision point.

flowchart TB
    subgraph Trigger["Session Start"]
        A["SessionStart event"] --> B["session-start.sh"]
        B --> C["Inject dual-mode instructions"]
    end
    subgraph Decision["Decision Router"]
        C --> D{"Is this a\ndecision point?"}
        D -->|"Yes"| E["Learning Mode"]
        D -->|"No"| F["Explanatory Mode"]
    end
    subgraph Learning["Learning Mode"]
        E --> G["Identify decision point type"]
        G --> H["Explain context & constraints"]
        H --> I[" Pause for user code"]
        I --> J["Review & guide user's solution"]
    end
    subgraph Explanatory["Explanatory Mode"]
        F --> K["Implement code directly"]
        K --> L["Add  Insight blocks"]
    end

Dual Operating Modes

🎓 Learning Mode

Activated when Claude encounters a decision point — a moment requiring genuine engineering judgment.

  • Identifies the decision type (business logic, error handling, algorithm, etc.)
  • Provides context: requirements, constraints, trade-offs
  • Pauses and asks user to write the implementation
  • Reviews user’s code with constructive feedback
  • Suggests improvements without rewriting

💡 Explanatory Mode

Activated for straightforward code that doesn’t benefit from user participation.

  • Claude implements the code directly
  • Adds ★ Insight blocks with 2–3 educational points
  • Covers implementation rationale and pattern usage
  • Same behavior as the Explanatory Output Style plugin
  • Keeps momentum on non-educational tasks

Decision Point Criteria

Claude determines whether to pause for user participation by evaluating whether the current task falls into one of five decision point categories:

Decision Point TypeDescriptionExample
Business LogicDomain rules and validation that encode business requirementsPricing calculation, eligibility checks, status transitions
Error HandlingRecovery strategies, retry policies, and failure modesWhat to do when an API call fails, timeout handling
Algorithm ChoiceSelecting between algorithms with different performance trade-offsSorting strategy for partially-sorted data, search approach
Data StructuresChoosing the right data structure for access patternsMap vs. array for lookup-heavy operations, tree vs. flat list
Design PatternsArchitectural decisions affecting extensibility and couplingStrategy vs. switch, observer vs. callback, composition vs. inheritance

Auto-Implement Criteria

Claude implements these categories directly without pausing, as they don’t provide meaningful learning opportunities:

CategoryRationale
Boilerplate & scaffoldingRepetitive code with no decisions to make
Obvious implementationsSingle correct approach with no trade-offs
Configuration filesSyntax-driven, not judgment-driven
Simple CRUD operationsWell-established patterns, low learning value
Import statements & setupMechanical, not educational

Data Flow

sequenceDiagram
    participant Dev as Developer
    participant CC as Claude Code CLI
    participant Hook as session-start.sh
    participant Claude as Claude LLM

    Dev->>CC: Start new session
    CC->>Hook: Fire SessionStart event
    Hook-->>CC: Dual-mode instruction payload
    CC->>Claude: System prompt + learning instructions

    Note over Dev,Claude: Task: Build a rate limiter

    Dev->>Claude: "Add rate limiting to the API"
    Claude->>Claude: Analyze task components

    Note over Claude: Boilerplate → Auto-implement
    Claude-->>Dev:  Express middleware skeleton +  Insight

    Note over Claude: Algorithm choice → Decision point!
    Claude-->>Dev:  "Which rate limiting algorithm?
Options: token bucket, sliding window, fixed window.
Consider: burst tolerance, memory, fairness" Dev->>Claude: "Token bucket — handles bursts well" Claude-->>Dev: Review + Insight on token bucket trade-offs Note over Claude: Error handling → Decision point! Claude-->>Dev: "Rate limit exceeded: 429 + retry-after?
Or queue and process later?" Dev->>Claude: "429 with Retry-After header" Claude-->>Dev: Complete implementation + Insight

Key Components

ComponentFileRole
session-start.shhooks-handlers/session-start.shShell hook injecting dual-mode instructions at session start
learning-prompt.mdinstructions/learning-prompt.mdInstruction template defining decision point criteria and pause behavior
plugin.json.claude-plugin/plugin.jsonPlugin manifest declaring the SessionStart hook
README.mdREADME.mdPlugin documentation with usage examples and configuration

Interactions

ModuleInterfaceData Exchanged
Claude Code CLIHook registrationSessionStart event triggers shell script
Claude LLMSystem prompt injectionDual-mode behavior rules, decision point taxonomy
DeveloperInteractive dialogueDecision point prompts → user code → feedback loop
Explanatory Output StyleShared patternUses same ★ Insight block format for Explanatory Mode

Configuration Reference

ParameterDefaultDescription
hooks.SessionStart[0].typecommandExecution type — shell command
hooks.SessionStart[0].commandhooks-handlers/session-start.shPath to the dual-mode hook handler
Decision point categories5 typesBusiness logic, error handling, algorithm, data structures, design patterns
Auto-implement categories5 typesBoilerplate, obvious code, config, CRUD, imports
Insight points per block2–3Educational points in ★ Insight blocks (both modes)
Pause behaviorAsk + waitClaude explains context, then waits for user code before continuing

Directory Map

Source tree for Learning Output Style
learning-output-style/
├── .claude-plugin/plugin.json          ← Role: Plugin manifest
├── README.md                           ← Role: Plugin documentation
├── hooks-handlers/
│   └── session-start.sh                ← Role: Dual-mode SessionStart hook
└── instructions/
    └── learning-prompt.md              ← Role: Decision point + insight rules

Usage Examples

Learning Mode in Action

✋ Decision Point — Error Handling Strategy
You need to handle the case where the external payment API returns a 503 (Service Unavailable).

Consider: Should we retry immediately? Use exponential backoff? Fail fast and notify the user? Queue for later processing?
Context: This is a checkout flow — the user is waiting. Average 503 duration for this API is 2–5 seconds.

Please write the error handling logic for this case.

Explanatory Mode in Action

// Claude auto-implements middleware setup (no decision point)
app.use(express.json({ limit: '10mb' }));
app.use(cors({ origin: config.allowedOrigins }));
app.use(helmet());
★ Insight — Middleware Ordering
• Body parsing (express.json) comes first because downstream middleware and routes need parsed request bodies.
• helmet() sets security headers — placing it early ensures all responses get protected, even error responses from later middleware.