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.
🎓 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 Type | Description | Example |
|---|---|---|
Business Logic | Domain rules and validation that encode business requirements | Pricing calculation, eligibility checks, status transitions |
Error Handling | Recovery strategies, retry policies, and failure modes | What to do when an API call fails, timeout handling |
Algorithm Choice | Selecting between algorithms with different performance trade-offs | Sorting strategy for partially-sorted data, search approach |
Data Structures | Choosing the right data structure for access patterns | Map vs. array for lookup-heavy operations, tree vs. flat list |
Design Patterns | Architectural decisions affecting extensibility and coupling | Strategy 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:
| Category | Rationale |
|---|---|
| Boilerplate & scaffolding | Repetitive code with no decisions to make |
| Obvious implementations | Single correct approach with no trade-offs |
| Configuration files | Syntax-driven, not judgment-driven |
| Simple CRUD operations | Well-established patterns, low learning value |
| Import statements & setup | Mechanical, 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
| Component | File | Role |
|---|---|---|
session-start.sh | hooks-handlers/session-start.sh | Shell hook injecting dual-mode instructions at session start |
learning-prompt.md | instructions/learning-prompt.md | Instruction template defining decision point criteria and pause behavior |
plugin.json | .claude-plugin/plugin.json | Plugin manifest declaring the SessionStart hook |
README.md | README.md | Plugin documentation with usage examples and configuration |
Interactions
| Module | Interface | Data Exchanged |
|---|---|---|
| Claude Code CLI | Hook registration | SessionStart event triggers shell script |
| Claude LLM | System prompt injection | Dual-mode behavior rules, decision point taxonomy |
| Developer | Interactive dialogue | Decision point prompts → user code → feedback loop |
| Explanatory Output Style | Shared pattern | Uses same ★ Insight block format for Explanatory Mode |
Configuration Reference
| Parameter | Default | Description |
|---|---|---|
hooks.SessionStart[0].type | command | Execution type — shell command |
hooks.SessionStart[0].command | hooks-handlers/session-start.sh | Path to the dual-mode hook handler |
| Decision point categories | 5 types | Business logic, error handling, algorithm, data structures, design patterns |
| Auto-implement categories | 5 types | Boilerplate, obvious code, config, CRUD, imports |
| Insight points per block | 2–3 | Educational points in ★ Insight blocks (both modes) |
| Pause behavior | Ask + wait | Claude 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.