Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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,
}
Expand Down Expand Up @@ -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
};
Expand Down
8 changes: 8 additions & 0 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down