JSON Output
All Grove CLI commands support --json flag for machine-readable output. Perfect for scripts and agent integrations.
Why Use JSON Output?
- Scriptable - Parse with
jq, Python, JavaScript, etc. - Reliable - Consistent structure, no parsing HTML/text
- Machine-friendly - Easy to integrate with automation tools
- Error handling - Structured error messages with exit codes
Command Reference
grove balance --json
Get account balance in JSON format.
Command:
grove balance --json
Output:
{
"balance": "4.99",
"token": "USDC",
"network": "base",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}
Error:
{
"error": "Unauthorized: Invalid API key"
}
grove tip --json
Send a tip and get transaction details.
Command:
grove tip olshansky.info 0.01 --json
Output:
{
"success": true,
"destination": "olshansky.info",
"amount": "0.01",
"token": "USDC",
"network": "base",
"receiver": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"tx_hash": "0xabc123...",
"tx_url": "https://basescan.org/tx/0xabc123...",
"fee": "0.001",
"new_balance": "4.98"
}
Error:
{
"error": "Insufficient balance: have 0.00 USDC, need 0.01 USDC"
}
grove check --json
Check if destination is tippable.
Command:
grove check olshansky.info --json
Output (success):
{
"tippable": true,
"destination": "olshansky.info",
"receiver": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"method": "llms.txt"
}
Output (not tippable):
{
"tippable": false,
"destination": "example.com",
"error": "No tipping address found"
}
grove history --json
Get transaction history.
Command:
grove history --json --limit 5
Output:
{
"transactions": [
{
"date": "2024-01-15T14:30:00Z",
"type": "TIP",
"destination": "olshansky.info",
"amount": "-0.01",
"token": "USDC",
"balance_after": "4.99",
"tx_hash": "0xabc123..."
},
{
"date": "2024-01-14T10:00:00Z",
"type": "FUND",
"source": "Credit Card",
"amount": "+5.00",
"token": "USDC",
"balance_after": "5.00"
}
],
"count": 2
}
grove fund --json
Fund account via x402 protocol.
Command:
grove fund 5.00 --json
Output:
{
"success": true,
"amount": "5.00",
"token": "USDC",
"network": "base",
"tx_hash": "0xdef456...",
"tx_url": "https://basescan.org/tx/0xdef456...",
"new_balance": "5.00"
}
grove contact --json
Submit support request.
Command:
echo '{
"email": "user@example.com",
"message": "How do I...?",
"category": "question"
}' | grove contact --json
Output:
{
"success": true,
"message": "Support request submitted"
}
Scripting Examples
Bash + jq
Check balance before tipping:
#!/bin/bash
set -e
BALANCE=$(grove balance --json | jq -r '.balance')
REQUIRED="0.01"
if (( $(echo "$BALANCE < $REQUIRED" | bc -l) )); then
echo "Insufficient balance: $BALANCE USDC"
exit 1
fi
RESULT=$(grove tip olshansky.info $REQUIRED --yes --json)
TX_HASH=$(echo "$RESULT" | jq -r '.tx_hash')
echo "Tip sent! Transaction: $TX_HASH"
Python
Tip multiple creators:
#!/usr/bin/env python3
import subprocess
import json
def tip(destination, amount):
result = subprocess.run(
["grove", "tip", destination, str(amount), "--yes", "--json"],
capture_output=True,
text=True
)
return json.loads(result.stdout)
creators = [
("olshansky.info", 0.01),
("@olshansky", 0.05),
("example.substack.com", 0.10)
]
for dest, amt in creators:
try:
result = tip(dest, amt)
if result.get("success"):
print(f"✓ Tipped {dest}: {amt} USDC")
else:
print(f"✗ Failed to tip {dest}: {result.get('error')}")
except Exception as e:
print(f"✗ Error tipping {dest}: {e}")
JavaScript (Node.js)
Check if destinations are tippable:
const { exec } = require('child_process');
const util = require('util');
const execPromise = util.promisify(exec);
async function checkTippable(destination) {
const { stdout } = await execPromise(
`grove check ${destination} --json`
);
return JSON.parse(stdout);
}
const destinations = [
'olshansky.info',
'@olshansky',
'example.com'
];
(async () => {
for (const dest of destinations) {
const result = await checkTippable(dest);
console.log(`${dest}: ${result.tippable ? '✓' : '✗'}`);
}
})();
Error Handling
Exit Codes
The CLI uses standard exit codes:
| Code | Meaning |
|---|---|
0 | Success |
1 | General error (API error, invalid input, etc.) |
2 | Usage error (invalid command, missing arguments) |
Example:
#!/bin/bash
set -e # Exit on error
grove tip olshansky.info 0.01 --yes --json
if [ $? -eq 0 ]; then
echo "Tip succeeded"
else
echo "Tip failed"
exit 1
fi
Error Response Format
All errors return JSON with an error field:
{
"error": "Human-readable error message",
"code": "ERROR_CODE",
"details": {}
}
Common error codes:
UNAUTHORIZED- Invalid API keyINSUFFICIENT_BALANCE- Not enough fundsINVALID_DESTINATION- Destination not tippableNETWORK_ERROR- Connection failedRATE_LIMIT- Too many requests
Parsing Tips
Using jq
Extract specific fields:
Get just the balance:
grove balance --json | jq -r '.balance'
Get multiple fields:
grove tip olshansky.info 0.01 --json | jq '{tx_hash, new_balance}'
Check for errors:
grove check example.com --json | jq -e '.tippable' || echo "Not tippable"
Conditional logic:
BALANCE=$(grove balance --json | jq -r '.balance')
if (( $(echo "$BALANCE >= 1.0" | bc -l) )); then
grove tip olshansky.info 0.01 --yes --json
fi
Using Python
import subprocess
import json
def grove_cmd(args):
"""Run Grove CLI command and return parsed JSON."""
result = subprocess.run(
["grove"] + args + ["--json"],
capture_output=True,
text=True,
check=True
)
return json.loads(result.stdout)
# Usage
balance = grove_cmd(["balance"])
print(f"Balance: {balance['balance']} {balance['token']}")
tip_result = grove_cmd(["tip", "olshansky.info", "0.01", "--yes"])
if tip_result.get("success"):
print(f"Tip sent: {tip_result['tx_url']}")