claude-pretty-printer
v1.4.1
Published
Beautiful CLI formatting for Claude Agent SDK messages with colors and boxes
Downloads
2,084
Maintainers
Readme
claude-pretty-printer
Transform raw Claude Agent SDK messages into beautiful, readable CLI output.
The Problem
The Claude Agent SDK outputs raw JSON messages that are difficult to read and debug:
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"type": "assistant",
"message": {
"id": "msg_123",
"role": "assistant",
"content": [
{"type": "text", "text": "Let me read that file for you."},
{"type": "tool_use", "id": "tool_456", "name": "Read", "input": {"file_path": "/path/to/file.txt"}}
]
}
}The Solution
claude-pretty-printer transforms these raw messages into clean, readable output:
────────────────────────────────────────────────────────────
◆ ASSISTANT
Let me read that file for you.
→ Read
file_path: "/path/to/file.txt"
────────────────────────────────────────────────────────────Features
- 🎨 Syntax Highlighting - Clear colors and formatting for different message types
- 📦 Terminal Boxes - Full-width boxes that adapt to your terminal size
- 🔍 Smart Detection - Automatically formats all message types from the SDK
- 🚀 Type-Safe - Full TypeScript support with proper types
- 💡 Developer-Focused - Built for debugging and monitoring Claude Agent interactions
Installation
npm install claude-pretty-printerbun add claude-pretty-printerUsage
Programmatic API
Perfect for debugging, monitoring, or building CLI tools that work with the Claude Agent SDK:
import { formatMessage } from 'claude-pretty-printer';
import { query } from '@anthropic-ai/claude-agent-sdk';
// Real-time message formatting during agent execution
for await (const message of query({ prompt: 'Read package.json' })) {
console.log(formatMessage(message));
}
// Batch processing of collected messages
const messages = await getAgentMessages();
messages.forEach(message => console.log(formatMessage(message)));Hook Helpers
Add beautiful formatted logging to your hooks with the withLogging() wrapper - an invisible enhancement that preserves your original hook configuration:
import { withLogging } from 'claude-pretty-printer/hooks';
import { query } from '@anthropic-ai/claude-agent-sdk';
// Simple - just add logging to empty hooks
const hooks = withLogging({
PreToolUse: [{}],
PostToolUse: [{}],
});
// Use them in your agent
for await (const message of query({
prompt: 'Read package.json',
hooks,
})) {
console.log(formatMessage(message));
}Enhancing Existing Hooks:
The power of withLogging() is that it wraps your existing hooks transparently:
import { withLogging } from 'claude-pretty-printer/hooks';
// Your original hooks with custom logic
const hooks = withLogging({
PreToolUse: [
{
matcher: '.*',
hooks: [
async (input, toolUseID, options) => {
// Your custom pre-tool logic here
console.log('About to execute:', input.name);
return {};
},
],
},
],
PostToolUse: [
{
matcher: 'Read|Write',
hooks: [
async (input, toolUseID, options) => {
// Your custom post-tool logic here
await logToDatabase(input);
return {};
},
],
},
],
});
// Now you get both: formatted logging + your custom behavior!Custom Options:
import { withLogging } from 'claude-pretty-printer/hooks';
import fs from 'fs';
// Use a custom logger (e.g., write to file)
const hooks = withLogging(
{
PreToolUse: [{}],
PostToolUse: [{}],
},
{
logger: (msg) => fs.appendFileSync('hooks.log', msg + '\n'),
}
);
// Use raw JSON output instead of formatted
const hooks = withLogging(
{
PreToolUse: [{}],
},
{
formatted: false, // Outputs JSON instead of formatted text
}
);
// Mix and match - some with logging, some without
const hooks = {
...withLogging({
PreToolUse: [{}],
PostToolUse: [{}],
}),
// These won't have automatic logging
Notification: [
{
matcher: '.*',
hooks: [async (input) => {
// Your custom notification handler
return {};
}],
},
],
};Alternative: Create Hooks from Scratch
If you prefer to create logging hooks without wrapping existing ones:
import { createLoggingHooks, createSingleLoggingHook } from 'claude-pretty-printer/hooks';
// Create formatted logging hooks for all hook types
const hooks = createLoggingHooks();
// Or create specific hook types only
const hooks = createLoggingHooks({
hookTypes: ['PreToolUse', 'PostToolUse'],
matcher: 'Read|Write', // Only match specific tools
});Available Hook Types:
PreToolUse- Before tool executionPostToolUse- After tool executionNotification- System notificationsUserPromptSubmit- User prompt submissionsSessionStart- Session initializationSessionEnd- Session terminationStop- Stop hook triggersSubagentStop- Subagent stop triggersPreCompact- Before conversation compaction
Command Line Interface
Transform JSON output directly from Claude CLI or any other source:
# Read from stdin (pipe from Claude CLI)
claude -p --output-format json "test" | npx claude-pretty-printer
# Filter specific message types
claude -p --output-format json "test" | npx claude-pretty-printer --filter result
claude -p --output-format json "test" | npx claude-pretty-printer -f result,assistant
# Hide statistics in result messages
claude -p --output-format json "test" | npx claude-pretty-printer --no-stats
# Combine filters (great for clean demos!)
claude -p --output-format json "test" | npx claude-pretty-printer --filter result --no-stats
# Read from file (multi-line JSON)
npx claude-pretty-printer messages.txt
# Inline JSON (single message)
npx claude-pretty-printer '{"type":"assistant","message":{"content":"Hello"}}'
# Show help
npx claude-pretty-printer --helpCLI Options:
| Option | Description |
|--------|-------------|
| -h, --help | Show help message |
| -f, --filter <types> | Filter by message type(s), comma-separated |
| --no-stats | Hide statistics summary in result messages |
Input Methods:
- Stdin: Pipe JSON messages line by line (default behavior)
- File: Read multi-line JSON from a file (one message per line)
- Inline: Format single JSON object as argument
CLI Input Format: Each line should be a complete JSON object representing an SDK message. The CLI automatically detects the input method based on how you call it.
What It Formats
claude-pretty-printer handles all message types from the Claude Agent SDK:
Message Types
Assistant Messages
- Blue header with
◆ ASSISTANT - Text content and tool uses
- Thinking content (dimmed and italic)
- Tool parameters in clean key-value format
User Messages
- Green header with
◆ USER - Text content and tool results
- Success/error indicators for tool execution
Result Messages
- Magenta header with
◆ RESULT - Task completion status
- Detailed statistics (duration, cost, turns)
- Token usage breakdown
- Per-model usage information
- Permission denials (if any)
System Messages
- Yellow header with
◆ SYSTEM - Session initialization details
- Conversation compaction notices
- Hook execution results
Hook Callback Messages
Specialized formatting for all Claude Agent SDK hook callbacks:
- 🔧 PreToolUse - Shows tool name and input parameters before execution
- ✅ PostToolUse - Displays tool response after execution (with truncation for long responses)
- 🔔 Notification - Shows notifications with optional titles and messages
- 📝 UserPromptSubmit - Displays user prompt submissions (with preview for long prompts)
- 🚀 SessionStart - Shows session startup with source type (startup/resume/clear/compact)
- 🛑 SessionEnd - Displays session termination with exit reason
- ⏸️/🛑 Stop - Shows stop hook triggers (active/inactive state)
- ⏸️/🛑 SubagentStop - Shows subagent stop hook triggers
- 👆/🤖 PreCompact - Shows pre-compaction events with trigger type (manual/auto) and custom instructions
Stream Events
Stream events are formatted inline without boxes for real-time output.
API
formatMessage(message, showBox?)
Formats a single SDK message for beautiful CLI output.
Parameters:
message: SDKMessage- The message to formatshowBox?: boolean- Whether to wrap in a box (default:true)
Returns: string - Formatted message ready for console output
Example - Processing multiple messages:
const messages = await getMessages();
messages.forEach(message => {
console.log(formatMessage(message));
});Color Scheme
- 🔵 Blue - Assistant messages
- 🟢 Green - User messages, success indicators
- 🟣 Magenta - Result messages
- 🟡 Yellow - System messages, costs
- 🔴 Red - Errors, permission denials
- 💙 Cyan - Tools, cache statistics, model names
- ⚫ Dim - Labels, secondary information
Examples
Tool Execution
────────────────────────────────────────────────────────────
◆ ASSISTANT
Let me read that file for you.
→ Read
file_path: "/path/to/file.ts"
────────────────────────────────────────────────────────────Result Summary
────────────────────────────────────────────────────────────
◆ RESULT
✓ Task completed successfully
Result: File successfully read and processed
Statistics:
Duration: 5.43s
API Time: 3.21s
Turns: 3
Cost: $0.0123
Token Usage:
Input: 5,000
Output: 1,200
Cache Read: 2,000
Cache Creation: 1,000
────────────────────────────────────────────────────────────Hook Callback Examples
PreToolUse Hook
🔧 Pre-Tool Use: Bash
Working directory: /Users/ps/Documents/GitHub/claude-agent-sdk-message-format
Tool input:
{
"command": "echo \"hello world\""
}PostToolUse Hook
✅ Post-Tool Use: Read
Working directory: /Users/ps/Documents/GitHub/claude-agent-sdk-message-format
Tool response:
{
"content": "File content here"
}SessionStart Hook
🚀 Session Started (startup)
Transcript: /path/to/transcript.json
Working directory: /Users/ps/Documents/GitHub/claude-agent-sdk-message-format
Permission mode: defaultNotification Hook
🔔 Notification
Build Completed
Message:
Your build has completed successfully
Location: /Users/ps/Documents/GitHub/claude-agent-sdk-message-formatDevelopment
bun install # Install dependencies
bun run build # Build the package
bun test # Run comprehensive test suiteTesting
Comprehensive test suite covering all SDK message types, edge cases, and integration scenarios. Run with bun test.
License
MIT © Pepijn Senders
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related
- @anthropic-ai/claude-agent-sdk - Official Claude Agent SDK
- picocolors - Minimal terminal colors library
