From 054064e8e008ebd269f209a46305dd1d700ea427 Mon Sep 17 00:00:00 2001
From: DTTerastar
Date: Sat, 25 Apr 2026 18:06:18 -0400
Subject: [PATCH] feat!: drop --json shortcut, default --format to "markdown"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Per quantcli shared contract §4, every CLI uses a single --format flag,
not a mix of --format and per-format boolean shortcuts. liftoff just
made the same change in PR #19; this brings crono in line.
https://github.com/quantcli/common/blob/main/CONTRACT.md#4-output-format
BREAKING:
- --json shortcut is removed. Migration: --json → --format json.
- Default --format value is "markdown" (was "md"); the help text and
prime/README now use "markdown" as the canonical name. "md" is
still accepted as a compatibility alias.
This finishes flag-name harmonization across the three CLIs:
- liftoff: --format markdown|json
- crono: --format markdown|json
- withings: --format markdown|json|csv
Co-Authored-By: Claude Opus 4.7 (1M context)
---
README.md | 6 +++---
cmd/format.go | 17 ++++++++---------
cmd/prime.go | 19 +++++++++----------
cmd/root.go | 4 ++--
4 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/README.md b/README.md
index ca905f3..087c499 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Export your personal nutrition, biometric, and food-log data from [Cronometer](h
## Features
- **Five export endpoints** — servings (per-food log with full nutrient breakdown), nutrition (daily totals), biometrics (weight, body fat, custom metrics), exercises, and notes
-- **Markdown by default, JSON on demand** — narrow fitdown-style markdown reads well in chat and terminals; pass `--json` for the full structured row to pipe through `jq`
+- **Markdown by default, JSON on demand** — narrow fitdown-style markdown reads well in chat and terminals; pass `--format json` for the full structured row to pipe through `jq`
- **Date selection** — `--since` / `--until` accepting `today`, `yesterday`, `YYYY-MM-DD`, or `Nd`/`Nw`/`Nm`/`Ny` on every subcommand
- **Single static binary** — no Python or Node runtime; drop it in `~/bin/` and go
- **Credentials via env** — `CRONOMETER_USERNAME` / `CRONOMETER_PASSWORD`, no config file needed
@@ -153,11 +153,11 @@ crono-export notes --since 30d
Default output is narrow, [Fitdown](https://github.com/datavis-tech/fitdown)-style markdown — date-grouped headings, one bullet per non-zero field, no wide tables. Markdown reads well in chat and on a terminal and is easy for an LLM to consume inline.
-For programmatic use, pass `--json` (or `--format json`) to get the full structured row as a JSON array on stdout — nothing suppressed, easy to pipe through `jq`. Errors always go to stderr, so JSON output stays clean for piping.
+For programmatic use, pass `--format json` to get the full structured row as a JSON array on stdout — nothing suppressed, easy to pipe through `jq`. Errors always go to stderr, so JSON output stays clean for piping.
```sh
crono-export servings --since today # markdown, default
-crono-export servings --since today --json | jq '[.[] | {food: .FoodName, protein: .ProteinG}]'
+crono-export servings --since today --format json | jq '[.[] | {food: .FoodName, protein: .ProteinG}]'
```
LLM agents: run `crono-export prime` for a one-screen orientation describing both formats, all subcommands, the date flags, and `jq` recipes.
diff --git a/cmd/format.go b/cmd/format.go
index c5ad521..0cfd3b6 100644
--- a/cmd/format.go
+++ b/cmd/format.go
@@ -23,24 +23,23 @@ const (
kindNotes
)
-// AddFormatFlags registers --format and --json on every export subcommand.
+// AddFormatFlags registers --format on every export subcommand, per the
+// quantcli shared contract §4.
+// https://github.com/quantcli/common/blob/main/CONTRACT.md#4-output-format
func AddFormatFlags(cmd *cobra.Command) {
- cmd.Flags().String("format", "md", "output format: md|json")
- cmd.Flags().Bool("json", false, "shortcut for --format json")
+ cmd.Flags().String("format", "markdown",
+ "Output format: markdown (default, fitdown-style) or json")
}
func chosenFormat(cmd *cobra.Command) (string, error) {
f, _ := cmd.Flags().GetString("format")
- if j, _ := cmd.Flags().GetBool("json"); j {
- f = "json"
- }
switch f {
- case "md", "markdown":
- return "md", nil
+ case "", "markdown", "md":
+ return "markdown", nil
case "json":
return "json", nil
default:
- return "", fmt.Errorf("unknown --format %q (want md or json)", f)
+ return "", fmt.Errorf("unknown --format %q (use markdown or json)", f)
}
}
diff --git a/cmd/prime.go b/cmd/prime.go
index 8441816..1ca53af 100644
--- a/cmd/prime.go
+++ b/cmd/prime.go
@@ -18,10 +18,9 @@ OUTPUT FORMATS
bullet per non-zero field, easy to skim and easy for an LLM to consume
inline. Zero-valued nutrients are suppressed in markdown.
- --json (or --format json) Pretty-printed JSON ARRAY of full rows.
- Use this when you want the complete row,
- when piping to jq, or when round-tripping
- into other tools. Nothing is suppressed.
+ --format json Pretty-printed JSON ARRAY of full rows. Use this when
+ you want the complete row, when piping to jq, or when
+ round-tripping into other tools. Nothing is suppressed.
Errors go to stderr. You do NOT need '2>&1'. Exit code is 0 on
success and non-zero on auth or network failure. An empty result is
@@ -77,20 +76,20 @@ EXAMPLES
crono-export nutrition --since today
# Today's macros, parsed (numbers via tonumber)
- crono-export nutrition --since today --json | jq '.[] | {
+ crono-export nutrition --since today --format json | jq '.[] | {
date: .Date,
kcal: (."Energy (kcal)" | tonumber),
protein: (."Protein (g)" | tonumber)
}'
# 7-day protein total (servings is typed — no tonumber needed)
- crono-export servings --since 7d --json | jq '[.[] | .ProteinG] | add'
+ crono-export servings --since 7d --format json | jq '[.[] | .ProteinG] | add'
# All foods from today's breakfast
- crono-export servings --since today --json | jq '[.[] | select(.Group == "Breakfast") | .FoodName]'
+ crono-export servings --since today --format json | jq '[.[] | select(.Group == "Breakfast") | .FoodName]'
# Latest weight reading in a 30-day window
- crono-export biometrics --since 30d --json | jq 'map(select(.Metric == "Weight")) | sort_by(.RecordedTime) | last'
+ crono-export biometrics --since 30d --format json | jq 'map(select(.Metric == "Weight")) | sort_by(.RecordedTime) | last'
GOTCHAS
- "Today" is your LOCAL calendar day, not UTC.
@@ -98,7 +97,7 @@ GOTCHAS
'jq tonumber' when doing math. 'servings', 'biometrics', 'exercises'
JSON values are already typed numbers.
- Markdown drops zero-valued nutrients to stay readable. If you need
- every column (including zeros), use --json.
+ every column (including zeros), use --format json.
- Cronometer logs by calendar day; nothing here is real-time. Two
'--since today' calls moments apart return the same data.
`
@@ -107,7 +106,7 @@ var primeCmd = &cobra.Command{
Use: "prime",
Short: "Print an LLM-targeted primer (output formats, subcommands, jq recipes)",
Long: `Print a one-screen primer aimed at LLM agents calling this CLI as a tool.
-Covers the output formats (markdown by default, --json for structured),
+Covers the output formats (markdown by default, --format json for structured),
auth env vars, the subcommands and what their rows look like, the shared
date flags, and a few jq recipes for common questions.`,
RunE: func(cmd *cobra.Command, _ []string) error {
diff --git a/cmd/root.go b/cmd/root.go
index 6c81783..9da3341 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -13,8 +13,8 @@ var rootCmd = &cobra.Command{
Short: "Export Cronometer nutrition, biometrics, and food log data",
Long: `crono-export reads your personal Cronometer data via the same export
endpoints the web app uses and prints it on stdout. Default output is
-narrow, fitdown-style markdown; pass --json (or --format json) for the
-full structured row.
+narrow, fitdown-style markdown; pass --format json for the full
+structured row.
Credentials must be supplied via environment variables:
CRONOMETER_USERNAME your Cronometer email