# Stabilize JSON output schema

## Sessions

## Changes

3

- MREADME.md+7

- cmd/git-sync

- Mmain_test.go+29/-13

- internal/syncer

- Msyncer.go+103/-43

```bash
108 unmodified lines

Add `--json` to `probe`, `fetch`, `plan`, or `sync` to emit machine-readable output instead of the default text format.

The JSON interface is intentionally stable:

- keys use `snake_case`
- `probe` returns top-level keys such as `source_url`, `target_url`, `protocol`, `ref_prefixes`, `source_capabilities`, `target_capabilities`, `refs`, and `stats`
- `fetch` returns top-level keys such as `source_url`, `protocol`, `wants`, `haves`, `fetched_objects`, and `stats`
- `plan` and `sync` return top-level keys such as `plans`, `pushed`, `skipped`, `blocked`, `deleted`, `dry_run`, `protocol`, and `stats`

Probe both source and target remotes to inspect source fetch capabilities and target `receive-pack` capabilities:

```bash
```

```go

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
)

// Structs and types definitions

type BranchPlan struct {
	Branch     string
	SourceRef  plumbing.ReferenceName
	TargetRef  plumbing.ReferenceName
	SourceHash plumbing.Hash
	TargetHash plumbing.Hash
	Kind       RefKind
	Action     Action
	Reason     string
}

type Action string

type Result struct {
	Plans    []BranchPlan
	Pushed   int
	Skipped  int
	Blocked  int
	Deleted  int
	DryRun   bool
	Stats    Stats
	Protocol string
}

type Stats struct {
	Enabled bool
	Items   map[string]*ServiceStats
}

type ServiceStats struct {
	Name          string
	Requests      int
	RequestBytes  int64
	ResponseBytes int64
}

// JSON Marshalling implementations

func (p BranchPlan) MarshalJSON() ([]byte, error) {
	type branchPlanJSON struct {
		Branch     string  `json:"branch"`
		SourceRef  string  `json:"source_ref"`
		TargetRef  string  `json:"target_ref"`
		SourceHash string  `json:"source_hash"`
		TargetHash string  `json:"target_hash"`
		Kind       RefKind `json:"kind"`
		Action     Action  `json:"action"`
		Reason     string  `json:"reason"`
	}
	return json.Marshal(branchPlanJSON{
		Branch:     p.Branch,
		SourceRef:  p.SourceRef.String(),
		TargetRef:  p.TargetRef.String(),
		SourceHash: p.SourceHash.String(),
		TargetHash: p.TargetHash.String(),
		Kind:       p.Kind,
		Action:     p.Action,
		Reason:     p.Reason,
	})
}

func (r Result) Lines() []string {
   // Implementation here...
}
```
