@unturf/unfirehose-schema
v1.0.6
Published
unfirehose/1.0 — schema specification for machine learning agent session logging across coding harnesses
Downloads
547
Maintainers
Readme
@unturf/unfirehose-schema
The unfirehose/1.0 schema specification for machine learning agent session logging.
A standard format for logging sessions across coding agent harnesses: Claude Code, Gemini CLI, Codex, Aider, Cursor, Continue.dev, Ollama, and more. No universal standard exists for this — every harness invented its own format. This package defines the one they should converge on.
Install
npm install @unturf/unfirehose-schemaWhat's in the box
TypeScript types
import type {
Message, Session, Todo, Project, Metric,
ContentBlock, TextBlock, ReasoningBlock, ToolCallBlock, ToolResultBlock,
Usage, ToolDefinition, UnfirehoseObject
} from '@unturf/unfirehose-schema'JSON Schema files (for validation)
import messageSchema from '@unturf/unfirehose-schema/json-schema/message'
import sessionSchema from '@unturf/unfirehose-schema/json-schema/session'
import contentBlockSchema from '@unturf/unfirehose-schema/json-schema/content-block'
import usageSchema from '@unturf/unfirehose-schema/json-schema/usage'
import todoSchema from '@unturf/unfirehose-schema/json-schema/todo'
import projectSchema from '@unturf/unfirehose-schema/json-schema/project'
import metricSchema from '@unturf/unfirehose-schema/json-schema/metric'
import toolDefinitionSchema from '@unturf/unfirehose-schema/json-schema/tool-definition'Specification docs
The docs/ directory contains the full spec:
| Document | Purpose | |---|---| | Canonical Format | Full unfirehose/1.0 schema with field maps for Anthropic, OpenAI, and Google APIs | | JSONL Format | JSONL stream structure, file layout, ingestion pipeline | | Messages | Message schema with content block types | | Sessions | Session lifecycle envelope | | Projects | Repository/workspace identity | | Tool Calls | Tool invocation format and standard registry | | Thought Traces | Extended thinking / chain-of-thought | | Todos | Cross-session work items | | Metrics | Token usage, cost, timing rollups | | All Logs | How everything fits together |
Harness adapter docs
| Harness | Provider | Status | |---|---|---| | Claude Code | Anthropic | Reference implementation | | Fetch | Anthropic | Supported | | uncloseai-cli | Local (Hermes) | Supported | | Gemini CLI | Google | Documented | | OpenAI Codex | OpenAI | Documented | | Aider | Multi-provider | Documented | | Cursor | Multi-provider | Researched | | Continue.dev | Multi-provider | Researched | | Hermes Agent | Local (Hermes) | Documented | | Open Code | Multi-provider | Researched | | Ollama | Local | Researched | | Open WebUI | Multi-provider | Researched | | llama.cpp | Local | Researched | | vLLM | Local/self-hosted | Researched | | text-generation-webui | Local | Researched | | pi | Multi-provider | Extension implemented | | agnt | Multi-provider | Native target |
Quick example
A minimal unfirehose/1.0 JSONL session:
{"$schema":"unfirehose/1.0","type":"session","id":"4e0f77f7-1b16-4adc-88bd-37f46790e2ae","harness":"claude-code"}
{"$schema":"unfirehose/1.0","type":"message","role":"user","content":[{"type":"text","text":"Fix the login page"}]}
{"$schema":"unfirehose/1.0","type":"message","role":"assistant","model":"claude-opus-4-6","content":[{"type":"reasoning","text":"Let me look at the CSS..."},{"type":"tool-call","toolCallId":"tc_01","toolName":"Read","input":{"file_path":"login.css"}}],"usage":{"inputTokens":3,"outputTokens":78}}
{"$schema":"unfirehose/1.0","type":"message","role":"user","content":[{"type":"tool-result","toolCallId":"tc_01","toolName":"Read","output":".login { margin: 0 }"}]}
{"$schema":"unfirehose/1.0","type":"message","role":"assistant","content":[{"type":"text","text":"Fixed the margin."}]}Design principles
- Append-only JSONL — one line per event, never mutate written lines
- Content block array — all message content is
content: [...], never a bare string - Provider-neutral naming —
reasoningnotthinking,tool-callnottool_use - camelCase JSON — snake_case only in database (ingestion layer handles mapping)
- UUIDv7 identity — time-ordered, safe for cross-machine sync
- Idempotent ingestion — UUID dedup + byte offsets = safe re-run
- Graceful degradation — missing fields show "unknown", not errors
Implementing the standard
Three tiers of adoption, one source of truth each:
| Tier | Strategy | Example |
|------|----------|---------|
| 1 — Native | Harness writes unfirehose/1.0 as its only format | agnt, uncloseai-cli |
| 2 — Extension | Extension hooks harness lifecycle, writes unfirehose/1.0 | pi (extensions/pi-unfirehose.ts) |
| 3 — Adapter | Unfirehose reads harness native format, transforms on ingest | Claude Code, Cursor, aider |
To adopt unfirehose/1.0 in a new harness:
- Log JSONL with
$schema: "unfirehose/1.0"header - Use canonical content block types (
text,reasoning,tool-call,tool-result) - Include session envelope as first line (optional but recommended)
- Store at
~/.{harness}/projects/{slug}/{session-uuid}.jsonl
Extensions (Tier 2)
For harnesses with extension/plugin systems, this package ships ready-to-use extensions:
# pi coding agent
cp node_modules/@unturf/unfirehose-schema/extensions/pi-unfirehose.ts ~/.pi/agent/extensions/unfirehose.tsSee the harness adapter guide for the full pipeline.
Part of the unfirehose monorepo
| Package | Description | |---|---| | @unturf/unfirehose | Core data layer — ingestion, SQLite, types | | @unturf/unfirehose-router | CLI daemon — forwards JSONL to cloud | | @unturf/unfirehose-ui | Shared React components | | @unturf/unfirehose-schema | Schema specification (this package) |
License
AGPL-3.0-only
