- Status: Accepted
- Date: 2026-03-05
Claude Code CLI emits dynamic non-interactive events in print mode, observed primarily through:
claude -p --output-format jsonclaude -p --output-format stream-json --verbose
This observed CLI protocol is the source of truth for the SDK parser.
Claude Code CLI emits dynamic JSONL events (system, assistant, user, result, and similar).
Without strict parsing rules and synchronized turn execution, SDK behavior can diverge under concurrency and protocol evolution.
Project rules explicitly forbid inline string literals for protocol token matching.
- Centralize protocol tokens in
ClaudeProtocolConstants. - Parse events and items only through constant-based switches.
- Serialize execution per
ClaudeThreadinstance withSemaphoreSlim.
flowchart LR
Line["JSONL line"] --> Parse["ThreadEventParser"]
Parse --> Consts["ClaudeProtocolConstants"]
ClaudeThread["ClaudeThread.Run*Async"] --> Lock["SemaphoreSlim turn lock"]
Lock --> Exec["ClaudeExec.RunAsync"]
Exec --> Parse
- No magic literals in parser logic.
- Safer maintenance when protocol tokens change.
- Eliminates race conditions for the same thread instance.
- Additional constants maintenance when upstream adds new token names.
- Multi-thread concurrency is still allowed across different
ClaudeThreadinstances.
- Keep inline string literals: rejected by project rule and maintainability concerns.
- Lock-free per-thread execution: rejected due to shared thread state (
thread_id, event stream aggregation).