Skip to content

Commit 95abcf8

Browse files
committed
Fix handling of control characters in JSON output mode and when redirecting
1 parent 3cd45ec commit 95abcf8

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

cli/src/cli.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@ export class CLI {
5555
logs.info("Initializing Kilo Code CLI...", "CLI")
5656
logs.info(`Version: ${Package.version}`, "CLI")
5757

58-
// Set terminal title - use process.cwd() in parallel mode to show original directory
59-
const titleWorkspace = this.options.parallel ? process.cwd() : this.options.workspace || process.cwd()
60-
const folderName = `${basename(titleWorkspace)}${(await isGitWorktree(this.options.workspace || "")) ? " (git worktree)" : ""}`
61-
process.stdout.write(`\x1b]0;Kilo Code - ${folderName}\x07`)
58+
// Only set terminal title when stdout is a TTY (skip for JSON mode or redirected output)
59+
if (!this.options.json && process.stdout.isTTY) {
60+
// Set terminal title - use process.cwd() in parallel mode to show original directory
61+
const titleWorkspace = this.options.parallel ? process.cwd() : this.options.workspace || process.cwd()
62+
const folderName = `${basename(titleWorkspace)}${(await isGitWorktree(this.options.workspace || "")) ? " (git worktree)" : ""}`
63+
process.stdout.write(`\x1b]0;Kilo Code - ${folderName}\x07`)
64+
}
6265

6366
// Create Jotai store
6467
this.store = createStore()

cli/src/state/hooks/useTerminal.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { useAtomValue, useSetAtom } from "jotai"
22
import { refreshTerminalCounterAtom, messageResetCounterAtom } from "../atoms/ui.js"
33
import { useCallback, useEffect, useRef } from "react"
44

5-
export function useTerminal(): void {
5+
export function useTerminal(isJsonMode: boolean = false): void {
6+
// Skip all terminal operations in JSON mode to prevent control sequences in output
7+
if (isJsonMode) {
8+
return
9+
}
10+
611
const width = useRef(process.stdout.columns)
712

813
const incrementResetCounter = useSetAtom(messageResetCounterAtom)

cli/src/ui/App.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ export interface AppProps {
2828
export const App: React.FC<AppProps> = ({ store, options, onExit }) => {
2929
return (
3030
<JotaiProvider store={store}>
31-
<KeyboardProvider>
31+
{(options.json && options.ci) || !process.stdout.isTTY ? (
32+
// Skip KeyboardProvider when in JSON mode or when stdout is redirected
33+
// to prevent terminal control sequences in output
3234
<UI options={options} onExit={onExit} />
33-
</KeyboardProvider>
35+
) : (
36+
<KeyboardProvider>
37+
<UI options={options} onExit={onExit} />
38+
</KeyboardProvider>
39+
)}
3440
</JotaiProvider>
3541
)
3642
}

cli/src/ui/UI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const UI: React.FC<UIAppProps> = ({ options, onExit }) => {
8080
const { fetchTaskHistory } = useTaskHistory()
8181

8282
// This clears the terminal and forces re-render of static components
83-
useTerminal()
83+
useTerminal((options.json && options.ci) || !process.stdout.isTTY)
8484

8585
// CI mode hook for automatic exit
8686
const { shouldExit, exitReason } = useCIMode({

0 commit comments

Comments
 (0)