name: parser-development
description: CLI stream parser development workflow. Covers the ProtocolEvent → SocketEvent pipeline, Zod schema validation, and adapter pattern. Use when creating or modifying protocol parsers, adding new event types, or debugging parse failures.
Parser Development
Architecture
CLI stdout (JSON line)
↓ ClaudeProtocol.parseLine() → ParseResult (ok | skip | unknown | error)
↓ ClaudeAdapter.transform() → AdapterOutput { events, autoResponses, controlResponses, serverActions }
↓ ProcessRunner._processLine() → emit('socket_event', SocketEvent)
↓ Socket.IO → Client
Key Types
| Type |
File |
Purpose |
ProtocolEvent |
apps/summoner/src/protocol/claude-schemas.ts |
Discriminated union of all CLI event types (21+) |
SocketEvent |
packages/shared/src/schemas/common.ts |
{ name: string; payload: Record<string, unknown> } |
ParseResult |
apps/summoner/src/protocol/provider-adapter.ts |
ok | skip | unknown | error discriminated union |
AdapterOutput |
apps/summoner/src/protocol/provider-adapter.ts |
events + autoResponses + controlResponses + serverActions |
Core Files
| File |
Purpose |
apps/summoner/src/protocol/claude-schemas.ts |
Zod schemas for all event types, getSchemaForType(), KNOWN_EVENT_TYPES |
apps/summoner/src/protocol/claude.ts |
ClaudeProtocol.parseLine() — JSON parse → Zod validate → ParseResult |
apps/summoner/src/protocol/claude-adapter.ts |
ClaudeAdapter.transform() — dispatches on event.type → SocketEvent[] |
apps/summoner/src/protocol/provider-adapter.ts |
Abstract ProviderAdapter interface |
apps/summoner/src/protocol/server-action.ts |
ServerAction union: auto_respond, read_diff, forward_to_client |
apps/summoner/src/process-runner.ts |
Orchestrates parseLine → transform → emit |
parseLine Flow
parseLine(line: string): ParseResult {
// 1. Trim + JSON.parse (skip if empty or invalid)
// 2. Check type field exists (skip if missing)
// 3. Skip keep_alive events
// 4. Check KNOWN_EVENT_TYPES (return 'unknown' if not found)
// 5. getSchemaForType(type, subtype) → Zod safeParse
// 6. Return { status: 'ok', event } or { status: 'error', error: ZodError }
}
SocketEvent Naming Convention
Events use type:subtype format:
message:assistant, message:user
stream:chunk, stream:block_start, stream:end
control:permission, control:elicitation
system:task_started, system:init
notification:show
raw:event (for unknown types)
Adding a New Event Type
- Add Zod schema in
claude-schemas.ts
- Add to
KNOWN_EVENT_TYPES set and getSchemaForType() dispatch
- Add to
ProtocolEvent union type
- Add conversion method in
claude-adapter.ts transform()
- Write tests in
apps/summoner/src/protocol/__tests__/
Test Pattern
// apps/summoner/src/protocol/__tests__/claude-adapter.test.ts
function toSocketEvent(line: string) {
const parsed = adapter.parseLine(line);
if (parsed.status !== 'ok') return null;
const r = adapter.transform(parsed.event);
return r.events.length === 1 ? r.events[0] : r.events;
}
Common Pitfalls
assistant event content is an array — may contain text + tool_use simultaneously
user events carry tool_result (CLI auto-executes tools)
result.usage is nested, not at top level
- Unknown event types →
raw:event (not errors)