You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: container/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/claude-code-headless/SKILL.md
+115-9Lines changed: 115 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ description: >-
8
8
programmatically", "set up permissions for scripts", or works with
The `result` event has top-level fields: `event.total_cost_usd`, `event.structured_output`, `event.subtype`, `event.num_turns`.
127
+
128
+
**3. `ReadableStream.getReader()` is unreliable for subprocess stdout in long-lived Bun.serve processes.** When spawning Claude as a subprocess inside a Bun HTTP server, `proc.stdout.getReader()` may silently close after reading only a few events — even though the process runs to completion and produces all output. This is a Bun runtime issue with streaming readers in server contexts.
129
+
130
+
**Fix:** Collect all stdout after the process exits instead of streaming:
This trades real-time streaming for reliability. If you need real-time progress, emit SSE events based on the process being alive rather than individual stream events.
149
+
150
+
**4. `system` events from hooks.** With `--verbose`, the stream includes `system` events for hooks (SessionStart, PreToolUse, etc.) before the first `assistant` event. Filter by `event.type === "assistant"` or `event.type === "result"` to skip them.
151
+
113
152
### jq Filtering Recipes
114
153
115
154
```bash
116
155
# Extract only text output from assistant messages
117
-
claude -p "query" --output-format stream-json \
156
+
claude -p "query" --verbose --output-format stream-json \
@@ -365,12 +404,79 @@ Check `is_error` and `subtype` to determine whether the invocation completed suc
365
404
366
405
---
367
406
407
+
## Data Quality for LLM Analyzers
408
+
409
+
When using Claude Code headless (`-p`) to build an agent that **analyzes other Claude Code sessions** (conversation logs, behavioral patterns, usage metrics), the quality of analysis depends entirely on how data is presented to the subprocess. These rules prevent the most common failure modes.
410
+
411
+
### Rule 1: Give Tools, Not Data Dumps
412
+
413
+
Instead of pre-loading all data into the prompt, provide query commands the agent can call via Bash:
414
+
415
+
```bash
416
+
# BAD — dumps everything into the prompt, wastes tokens, overwhelms the model
417
+
claude -p "Here are 500 messages: $(cat messages.json). Analyze them." \
418
+
--allowedTools "Read"
419
+
420
+
# GOOD — gives the agent tools to explore on its own
421
+
claude -p "Use these query commands to explore the session data..." \
422
+
--allowedTools "Bash(bun run scripts/query-db.ts *)""Read""Glob""Grep"
423
+
```
424
+
425
+
Benefits:
426
+
- The agent decides what's relevant, not you
427
+
- Keeps prompt tokens low
428
+
- Scales to any data size
429
+
- The agent can drill into interesting areas
430
+
431
+
### Rule 2: Explain the Data Taxonomy
432
+
433
+
When an LLM agent processes conversation data, it **MUST** understand the role taxonomy. Claude Code sessions have multiple message types that look similar but carry very different signal:
434
+
435
+
| Message type | Role | Signal value |
436
+
|-------------|------|-------------|
437
+
|`user` (string, no system tags) | Human input |**PRIMARY** — preferences, corrections, instructions |
438
+
|`user` (string, with `<system-reminder>`) | System injection |**NOISE** — hooks, workspace reminders |
439
+
|`user` (array, text blocks only) | Human input |**PRIMARY** — if no system tags in text |
**Critical distinction:** In a typical 264-message session, only **7 messages** (~3%) are actual human input. The rest is tool plumbing, system injections, and assistant actions. Without taxonomy guidance, the analyzer treats all 264 messages as equally important and produces garbage.
448
+
449
+
### Rule 3: Distinguish AI-Generated from Human-Authored Content
450
+
451
+
Plans, specs, and proposals submitted by the user were typically **AI-generated in a previous session**. The user approved them, but didn't write them:
452
+
453
+
```
454
+
# This is a user message, but the PLAN CONTENT is AI-generated:
455
+
"Implement the following plan:\n\n# Feature X\n\n## Context\n..."
456
+
```
457
+
458
+
The behavioral signal is: "user uses a plan-first workflow" — NOT the plan's content, structure, or technical decisions. Never attribute AI writing style to the user.
0 commit comments