Skip to content
Open
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
3 changes: 3 additions & 0 deletions apps/claude-trace/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ claude-trace
# Include all API requests (by default, only substantial conversations are logged)
claude-trace --include-all-requests

# Skip HTML generation (JSONL only, saves ~60% disk space)
claude-trace --no-html

# Run Claude with specific arguments
claude-trace --run-with chat --model sonnet-3.5

Expand Down
8 changes: 7 additions & 1 deletion apps/claude-trace/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ${colors.yellow}OPTIONS:${colors.reset}
--run-with Pass all following arguments to Claude process
--include-all-requests Include all requests made through fetch, otherwise only requests to v1/messages with more than 2 messages in the context
--no-open Don't open generated HTML file in browser
--no-html Skip HTML generation (JSONL only)
--log Specify custom log file base name (without extension)
--claude-path Specify custom path to Claude binary
--help, -h Show this help message
Expand Down Expand Up @@ -234,6 +235,7 @@ async function runClaudeWithInterception(
openInBrowser: boolean = false,
customClaudePath?: string,
logBaseName?: string,
generateHTML: boolean = true,
): Promise<void> {
log("Claude Trace", "blue");
log("Starting Claude with traffic logging", "yellow");
Expand All @@ -257,6 +259,7 @@ async function runClaudeWithInterception(
NODE_OPTIONS: "--no-deprecation",
CLAUDE_TRACE_INCLUDE_ALL_REQUESTS: includeAllRequests ? "true" : "false",
CLAUDE_TRACE_OPEN_BROWSER: openInBrowser ? "true" : "false",
CLAUDE_TRACE_GENERATE_HTML: generateHTML ? "true" : "false",
...(logBaseName ? { CLAUDE_TRACE_LOG_NAME: logBaseName } : {}),
},
stdio: "inherit",
Expand Down Expand Up @@ -473,6 +476,9 @@ async function main(): Promise<void> {
// Check for no-open flag (inverted logic - open by default)
const openInBrowser = !claudeTraceArgs.includes("--no-open");

// Check for no-html flag (inverted logic - generate HTML by default)
const generateHTML = !claudeTraceArgs.includes("--no-html");

// Check for custom Claude path
let customClaudePath: string | undefined;
const claudePathIndex = claudeTraceArgs.indexOf("--claude-path");
Expand Down Expand Up @@ -525,7 +531,7 @@ async function main(): Promise<void> {
}

// Scenario 1: No args (or claude with args) -> launch claude with interception
await runClaudeWithInterception(claudeArgs, includeAllRequests, openInBrowser, customClaudePath, logBaseName);
await runClaudeWithInterception(claudeArgs, includeAllRequests, openInBrowser, customClaudePath, logBaseName, generateHTML);
}

main().catch((error) => {
Expand Down
9 changes: 7 additions & 2 deletions apps/claude-trace/src/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ export class ClaudeTrafficLogger {
private htmlGenerator: HTMLGenerator;

constructor(config: InterceptorConfig = {}) {
// Check environment variable for HTML generation (defaults to true)
const enableHTMLFromEnv = process.env.CLAUDE_TRACE_GENERATE_HTML !== "false";

this.config = {
logDirectory: ".claude-trace",
enableRealTimeHTML: true,
enableRealTimeHTML: enableHTMLFromEnv,
logLevel: "info",
...config,
};
Expand Down Expand Up @@ -51,7 +54,9 @@ export class ClaudeTrafficLogger {
// Output the actual filenames with absolute paths
console.log(`Logs will be written to:`);
console.log(` JSONL: ${path.resolve(this.logFile)}`);
console.log(` HTML: ${path.resolve(this.htmlFile)}`);
if (this.config.enableRealTimeHTML) {
console.log(` HTML: ${path.resolve(this.htmlFile)}`);
}
}

private isClaudeAPI(url: string | URL): boolean {
Expand Down