docs/JSON_SCHEMA.md
All bd commands that support --json output can wrap their response in
a uniform envelope by setting BD_JSON_ENVELOPE=1. This will become the
default format in v2.0.
export BD_JSON_ENVELOPE=1
Every --json command wraps output as:
{"schema_version": 1, "data": <original-payload>}
The original payload is untouched inside .data — no type corruption,
no field injection. Works identically for objects, arrays, and maps.
# Before (legacy):
bd list --json | jq '.[0].id'
bd show beads-abc --json | jq '.title'
# After (envelope):
bd list --json | jq '.data[0].id'
bd show beads-abc --json | jq '.data.title'
# Version check:
bd show beads-abc --json | jq '.schema_version'
BD_JSON_ENVELOPE=1 to opt in.
A deprecation notice is printed to stderr when --json is used without the env var.BD_JSON_ENVELOPE=0 available as
temporary escape hatch for one release cycle.Current version: 1
The schema_version field is an integer that increments when:
Additive changes (new optional fields) do NOT bump the version.
All commands emit a uniform envelope:
{
"schema_version": 1,
"data": {
"id": "beads-abc",
"title": "Example issue",
"status": "open"
}
}
Arrays are wrapped the same way:
{
"schema_version": 1,
"data": [
{"id": "beads-abc", "title": "First"},
{"id": "beads-def", "title": "Second"}
]
}
Commands that return a single issue or result emit a JSON object with
schema_version as a top-level field alongside the data:
{
"schema_version": 1,
"id": "beads-abc",
"title": "Example issue",
"status": "open",
"priority": 1,
"issue_type": "task",
"created_at": "2026-04-20T12:00:00Z"
}
Commands that return multiple items emit a raw JSON array:
[
{"id": "beads-abc", "title": "First", ...},
{"id": "beads-def", "title": "Second", ...}
]
Errors with --json active emit JSON to stderr:
{
"schema_version": 1,
"error": "issue not found: beads-xyz",
"code": "not_found"
}
Required fields per item:
id (string): Issue ID (e.g., "beads-abc")title (string): Issue titlestatus (string): open, in_progress, closed, deferredpriority (number): 0-4issue_type (string): bug, feature, task, epic, chorecreated_at (string): RFC3339 timestampOptional fields:
description, owner, updated_at, closed_atlabels (string[]): Attached labelsdependencies (object[]): Dependency recordsdependency_count, dependent_count, comment_count (number)parent (string|null): Parent issue IDSame schema as bd list --json. Items are filtered to unblocked issues only.
Each item includes dependency_count, dependent_count, comment_count,
and optional parent fields.
Returns issues that are blocked by unresolved dependencies. Each item includes all standard issue fields plus:
blocked_by_count (number): Number of blocking dependenciesblocked_by (string[]): IDs of blocking issuesReturns a single object (not wrapped in items). Same required fields as list
items, plus:
description (string)acceptance_criteria (string)dependencies (object[]): Full dependency recordscomments (object[]): Comment threadimport --jsonReturns a summary object when --json is active:
source (string): File path or "stdin"created (number): Issues createdskipped (number): Issues skipped (dedup)dedup_skipped (number): Issues skipped by --dedup title matchmemories (number): Memory records importedids (string[]): IDs of created issuesdry_run (boolean): Whether --dry-run was activeOutputs JSONL (one JSON object per line), not wrapped in an envelope.
Each line is a self-contained issue or memory record. schema_version
is included per line.
Check schema_version on object output. If the version is
higher than expected, log a warning but attempt to parse anyway
(additive changes are backward-compatible).
For list commands, parse the output as a JSON array directly.
Ignore unknown fields. New fields may be added without bumping the schema version.
Use --json flag, not --format json. The --json flag is
the stable contract; --format is for human-readable variants.