diff --git a/README.md b/README.md index 764c5d9..409e92d 100644 --- a/README.md +++ b/README.md @@ -15,16 +15,42 @@ ep-1 production active ethereum/mainnet shared yes https://ep-1.examp ep-2 — paused solana/mainnet dedicated no https://ep-2.example — showing 1–2 of 2 -# LLM-optimized TOON format (non-TTY default) +# Piped / non-TTY output defaults to JSON $ qn endpoint list | cat -data[2]{id,name,label,status,chain,network,is_dedicated,is_flat_rate,http_url,wss_url,tags,is_multichain}: - "ep-1","ep-1","production",active,ethereum,mainnet,false,false,"https://ep-1.example",null,"prod, eu",false - "ep-2","ep-2",null,paused,solana,mainnet,true,false,"https://ep-2.example",null,"",false -pagination: - total: 2 - limit: 20 - offset: 0 -error: null +{ + "data": [ + { + "id": "ep-1", + "name": "ep-1", + "label": "production", + "status": "active", + "chain": "ethereum", + "network": "mainnet", + "is_dedicated": false, + "is_flat_rate": false, + "http_url": "https://ep-1.example", + "wss_url": null, + "tags": ["prod", "eu"], + "is_multichain": false + }, + { + "id": "ep-2", + "name": "ep-2", + "label": null, + "status": "paused", + "chain": "solana", + "network": "mainnet", + "is_dedicated": true, + "is_flat_rate": false, + "http_url": "https://ep-2.example", + "wss_url": null, + "tags": [], + "is_multichain": false + } + ], + "pagination": { "total": 2, "limit": 20, "offset": 0 }, + "error": null +} ``` ## Installation @@ -139,10 +165,10 @@ Pick a format with `--format ` (alias `-o `): | `--format` | Best for | | --- | --- | | `table` | Humans on a TTY. Pretty UTF-8 tables with optional color. Default when stdout is a terminal. | -| `json` | Scripts and pipelines (`jq`, `gron`, …). | +| `json` | Scripts and pipelines (`jq`, `gron`, …). Default when stdout is **not** a terminal (piped / agent invocations). | | `yaml` | Same shape as JSON, easier to skim by eye. | | `md` | GitHub-flavored markdown — paste into PRs, issues, docs. | -| `toon` | [Token-Oriented Object Notation](https://github.com/toon-format/toon-rust) — compact serialization optimized for LLM prompts. Default when stdout is **not** a terminal (piped / agent invocations). | +| `toon` | [Token-Oriented Object Notation](https://github.com/toon-format/toon-rust) — compact serialization optimized for LLM prompts. | Other output flags: @@ -159,7 +185,7 @@ format = "yaml" # default --format value wide = true # always show extra columns in table/md output ``` -CLI flags win over config values. Built-in defaults: `format = "table"` when stdout is a TTY, `"toon"` otherwise; `wide = false`. +CLI flags win over config values. Built-in defaults: `format = "table"` when stdout is a TTY, `"json"` otherwise; `wide = false`. `qn` follows the [Command Line Interface Guidelines](https://clig.dev/): data on stdout, diagnostics on stderr, meaningful exit codes (0 success, 2 API error, 3 network error, 4 auth/config, 5 needs confirmation), and a documented `-h`/`--help` at every subcommand level. diff --git a/src/cli.rs b/src/cli.rs index 89fac6a..6e21cee 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -50,9 +50,10 @@ pub struct Cli { #[arg(long, global = true, value_name = "PATH")] pub config_file: Option, - /// Output format. `table` is the default human view; the others are + /// Output format. `table` is the human view; the others are /// pipeline-friendly serialized forms. If unset, falls back to the - /// `[output] format = "…"` value in ~/.config/qn/config.toml, then `table`. + /// `[output] format = "…"` value in ~/.config/qn/config.toml, then the + /// TTY-aware default: `table` when stdout is a terminal, `json` otherwise. #[arg(short = 'o', long = "format", global = true, value_enum)] pub format: Option, diff --git a/src/commands/agent/context.md b/src/commands/agent/context.md index e7dc5d7..ea00f80 100644 --- a/src/commands/agent/context.md +++ b/src/commands/agent/context.md @@ -37,7 +37,7 @@ network call. ## 2. Output contract -- Default format is `table` on a TTY and **`toon`** when stdout is not a TTY (piped). +- Default format is `table` on a TTY and **`json`** when stdout is not a TTY (piped). - Data goes to **stdout**; diagnostics, prompts, and ✓ confirmations go to **stderr**. - Formats: `table`, `md`, `json`, `yaml`, `toon`. The structured forms (`json`/`yaml`/`toon`) always include every field — `--wide` is not needed and @@ -169,7 +169,7 @@ qn kv set list - Mutations are never retried; re-running a failed create can double-provision (§5). - No account-wide wipe command exists by design (§4). -- Piped output defaults to `toon`, not `json` (§2). +- Piped output defaults to `json`; pass `-o toon` for the compact LLM form (§2). - `--base-url` overrides the API host; it exists for testing. - For *this* command, `-o yaml`/`-o toon`/`-o table` print Markdown (with a note on stderr); `-o json` produces the `{version, guide}` envelope. diff --git a/src/context.rs b/src/context.rs index 1616c71..378d671 100644 --- a/src/context.rs +++ b/src/context.rs @@ -21,7 +21,7 @@ pub struct GlobalArgs { /// (`~/.config/qn/config.toml`). pub config_file: Option, /// `None` means the user didn't pass `--format`; resolve via config file - /// (then the TTY-aware default: `Table` on a TTY, `Toon` off) when we + /// (then the TTY-aware default: `Table` on a TTY, `Json` off) when we /// build the [`Ctx`]. pub format: Option, pub wide: bool, @@ -38,7 +38,7 @@ pub struct GlobalArgs { impl GlobalArgs { /// Resolve the output format: CLI flag > config file > TTY-aware default - /// (`Table` on a TTY, `Toon` off). + /// (`Table` on a TTY, `Json` off). /// Used by [`Ctx::from_global`] and `auth` (which doesn't build a Ctx). pub fn resolve_format(&self, stdout_is_tty: bool) -> Format { self.resolve_output(stdout_is_tty).0 @@ -47,7 +47,7 @@ impl GlobalArgs { /// Resolve `(format, wide)` together so we only read the config file once. /// /// For each: CLI flag > config file > built-in default. The format default - /// is TTY-aware: `Table` when stdout is a terminal, `Toon` otherwise (so + /// is TTY-aware: `Table` when stdout is a terminal, `Json` otherwise (so /// agents / piped callers get a structured format by default). `--wide` is /// purely additive — the flag sets it true; the config file can also set /// it true; otherwise it's false. @@ -85,7 +85,7 @@ fn resolve_output_inner( let format = flag_format.or(cfg_format).unwrap_or(if stdout_is_tty { Format::Table } else { - Format::Toon + Format::Json }); let wide = flag_wide || cfg_wide; (format, wide) @@ -240,8 +240,14 @@ mod tests { } #[test] - fn default_is_toon_when_stdout_is_not_a_tty() { + fn default_is_json_when_stdout_is_not_a_tty() { let (f, _) = resolve_output_inner(None, false, None, false, false); + assert_eq!(f, Format::Json); + } + + #[test] + fn config_toon_overrides_non_tty_default() { + let (f, _) = resolve_output_inner(None, false, Some(Format::Toon), false, false); assert_eq!(f, Format::Toon); } diff --git a/src/output.rs b/src/output.rs index 6715d6f..dc25071 100644 --- a/src/output.rs +++ b/src/output.rs @@ -2,7 +2,7 @@ //! //! Five formats, selected by the global `--format/-o` flag. When the flag and //! the config file both leave the format unset, the default is TTY-aware: -//! `table` when stdout is a terminal (interactive use), `toon` otherwise +//! `table` when stdout is a terminal (interactive use), `json` otherwise //! (piped / agent invocations). See [`crate::context::GlobalArgs::resolve_output`]. //! //! - `table`: comfy-table with UTF-8 borders for humans on a TTY.