diff --git a/README.md b/README.md index 232507c..b928d6e 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ cargo install arbitrum-cli # Query the latest block (JSON output, agent-ready) arbitrum-cli block latest +# Query the latest block with indented JSON for debugging +arbitrum-cli block latest --pretty + # Check an address balance arbitrum-cli balance 0xC75020d5f669F5D15Afcb81b0e5F6d21bCDa9664 @@ -72,12 +75,15 @@ All commands default to JSON output. No flags, no ceremony — pipe it into `jq` # Agent-friendly arbitrum-cli balance 0xC750... | jq .balance_eth +# Indented JSON for humans inspecting agent output +arbitrum-cli balance 0xC750... --pretty + # Generic RPC for agents — any method, any params arbitrum-cli exec eth_chainId --params '[]' arbitrum-cli exec eth_getLogs --params '[{"fromBlock":"latest","address":"0x..."}]' ``` -Use `--human` for colored terminal output when you're debugging. +Use `--pretty` for indented JSON when you're debugging agent output. Use `--human` for colored terminal output. ## Create Protocol agent-deposit diff --git a/src/main.rs b/src/main.rs index 0abcfe7..fb63ae7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod rpc; name = "arbitrum-cli", version, about = "Agent-first Arbitrum CLI — JSON in, JSON out, MCP-compatible", - long_about = "A single Rust binary to query Arbitrum, interact with contracts, monitor events, and expose an MCP server for AI agents. Default output is JSON (agent-friendly). Use --human for pretty terminal output." + long_about = "A single Rust binary to query Arbitrum, interact with contracts, monitor events, and expose an MCP server for AI agents. Default output is compact JSON (agent-friendly). Use --pretty for indented JSON or --human for colored terminal output." )] struct Cli { /// RPC URL (default: https://arb1.arbitrum.io/rpc) @@ -21,6 +21,10 @@ struct Cli { #[arg(long, global = true)] human: bool, + /// Pretty-print JSON output with indentation + #[arg(long, global = true, conflicts_with = "human")] + pretty: bool, + #[command(subcommand)] command: Commands, } @@ -126,6 +130,8 @@ async fn main() -> eyre::Result<()> { .unwrap_or_else(|| "https://arb1.arbitrum.io/rpc".to_string()); let out_mode = if cli.human { output::Mode::Human + } else if cli.pretty { + output::Mode::JsonPretty } else { output::Mode::Json }; diff --git a/src/output.rs b/src/output.rs index 2507e94..2fe1f95 100644 --- a/src/output.rs +++ b/src/output.rs @@ -4,17 +4,25 @@ use serde_json::Value; #[derive(Clone, Copy, Debug)] pub enum Mode { Json, + JsonPretty, Human, } /// Emit a result to stdout in the requested mode. /// JSON mode: raw JSON for agents (default). +/// JSON pretty mode: indented JSON for terminal debugging. /// Human mode: pretty colored output for terminals. pub fn emit(mode: Mode, label: &str, value: &Value) { match mode { Mode::Json => { println!("{}", serde_json::to_string(value).unwrap_or_default()); } + Mode::JsonPretty => { + println!( + "{}", + serde_json::to_string_pretty(value).unwrap_or_default() + ); + } Mode::Human => { println!("\n {} {}", "✓".green().bold(), label.bold()); println!(" {}", "─".repeat(50).dimmed());