cmd/bd/output.go, cmd/bd/errors.go, and
cmd/bd/protocol/json_contract_test.go.
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.
Migration Guide
Opt in to the envelope format
Envelope format (BD_JSON_ENVELOPE=1, default in v2.0)
Every--json command wraps output as:
.data — no type corruption,
no field injection. Works identically for objects, arrays, and maps.
Updating consumers
Timeline
- Current release: Legacy format is default. Set
BD_JSON_ENVELOPE=1to opt in. A deprecation notice is printed to stderr when--jsonis used without the env var. - v2.0: Envelope becomes the default.
BD_JSON_ENVELOPE=0available as temporary escape hatch for one release cycle.
Schema Version
Current version: 1 Theschema_version field is an integer that increments when:
- Fields are added, renamed, or removed
- Output structure changes (e.g., nesting depth)
- Field types change (e.g., string to integer)
Output Formats
Envelope mode (BD_JSON_ENVELOPE=1)
All commands emit a uniform envelope:Legacy mode (default, until v2.0)
Object commands (show, create, close, update, etc.)
Commands that return a single issue or result emit a JSON object withschema_version as a top-level field alongside the data:
List commands (list, ready, search, stale, etc.)
Commands that return multiple items emit a raw JSON array:Error output (stderr)
Errors with--json active emit JSON to stderr:
Field Contracts by Command
bd list —json
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 timestamp
description,owner,updated_at,closed_atlabels(string[]): Attached labelsdependencies(object[]): Dependency recordsdependency_count,dependent_count,comment_count(number)parent(string|null): Parent issue ID
bd ready —json
Same schema asbd list --json. Items are filtered to unblocked issues only.
Each item includes dependency_count, dependent_count, comment_count,
and optional parent fields.
bd blocked —json
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 issues
bd show —json
Returns a single object (not wrapped initems). Same required fields as list
items, plus:
description(string)acceptance_criteria(string)dependencies(object[]): Full dependency recordscomments(object[]): Comment thread
import --json
Returns a summary object when --json is active:
source(string): File path or “stdin”created(number): Issues createdupdated(number): Existing issues updatedskipped(number): Issues skipped (stale rows + dedup)dedup_skipped(number): Issues skipped by--deduptitle matchmemories(number): Memory records importedids(string[]): IDs of created issuesupdated_issues(object[]): Per-issue summary of what an update changedtie_kept_local_ids(string[]): Equal-updated_atrows where local state wonstale_skipped_ids(string[]): Rows older than the local issue, skippedskipped_dependencies(string[]): Dependency edges whose target id was absentdry_run(boolean): Whether--dry-runwas active
bd export —json
Outputs JSONL (one JSON object per line), not wrapped in an envelope. Each line is a self-contained issue or memory record, discriminated by_type ("issue" / "memory"). Export lines do not carry
schema_version — that field belongs to the --json command envelope,
not to the interchange stream. The interchange’s own version marker is the
optional _schema header record ({"_schema":"beads-jsonl/1"}), which
readers skip.
Consumer Guidelines
-
Check
schema_versionon 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
--jsonflag, not--format json. The--jsonflag is the stable contract;--formatis for human-readable variants.