Skip to content

PepijnSenders/claude-pretty-printer

Repository files navigation

claude-pretty-printer

Transform raw Claude Agent SDK messages into beautiful, readable CLI output.

Screenshot 2025-10-24 at 23 46 21

npm version license

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

  • 🎨 Color Themes - Choose from multiple color themes (default, monokai, dracula, nord)
  • 📐 Layout Modes - Control output density (full, compact, minimal, header)
  • 📦 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-printer
bun add claude-pretty-printer

Usage

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 execution
  • PostToolUse - After tool execution
  • Notification - System notifications
  • UserPromptSubmit - User prompt submissions
  • SessionStart - Session initialization
  • SessionEnd - Session termination
  • Stop - Stop hook triggers
  • SubagentStop - Subagent stop triggers
  • PreCompact - 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

# Use a color theme
claude -p --output-format json "test" | npx claude-pretty-printer --theme dracula
claude -p --output-format json "test" | npx claude-pretty-printer -t monokai

# Use a layout mode
claude -p --output-format json "test" | npx claude-pretty-printer --layout compact
claude -p --output-format json "test" | npx claude-pretty-printer -l minimal

# Combine theme and layout
claude -p --output-format json "test" | npx claude-pretty-printer -t nord -l compact

# 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 --help

CLI Options:

Option Description
-h, --help Show help message
-f, --filter <types> Filter by message type(s), comma-separated
-t, --theme <name> Color theme: default, monokai, dracula, nord
-l, --layout <name> Layout mode: full, compact, minimal, header
--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 format
  • showBox?: 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));
});

Themes

Choose a color theme that matches your terminal or personal preference:

Theme Description
default Vibrant colors for maximum readability (blue, cyan, magenta, green)
monokai Warm dark theme inspired by the classic editor theme
dracula Purple-centric theme with the popular Dracula palette
nord Arctic, calm theme with muted colors
# Use the dracula theme
cat messages.json | claude-pp --theme dracula

# Short flag
cat messages.json | claude-pp -t monokai

Layouts

Control the verbosity and visual density of the output:

Layout Description
full Default - boxes, icons, full content, stats, tool parameters
compact No boxes, keeps icons and colors, condensed spacing
minimal Single line per message: ◆ ASSISTANT truncated content...
header Headers only: ◆ ASSISTANT, ◆ USER, etc. (no content)

Layout Examples

Full Layout (default):

────────────────────────────────────────────────────────────
◆ ASSISTANT
Let me read that file for you.

→ Read
  file_path: "/path/to/file.ts"
────────────────────────────────────────────────────────────

Compact Layout:

◆ ASSISTANT
Let me read that file for you.

→ Read
  file_path: "/path/to/file.ts"

Minimal Layout:

◆ ASSISTANT Let me read that file for you.

Header Layout:

◆ ASSISTANT
# Use compact layout
cat messages.json | claude-pp --layout compact

# Use minimal for quick overview
cat messages.json | claude-pp -l minimal

# Combine theme and layout
cat messages.json | claude-pp -t nord -l compact

Color Scheme (Default Theme)

  • 🔵 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: default

Notification Hook

🔔 Notification
   Build Completed

Message:
  Your build has completed successfully

   Location: /Users/ps/Documents/GitHub/claude-agent-sdk-message-format

Development

bun install     # Install dependencies
bun run build  # Build the package
bun test        # Run comprehensive test suite

Testing

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

About

Beautiful CLI formatting for Claude Agent SDK messages with colors and boxes

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors