Skip to content
Closed
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
7 changes: 7 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export interface HudConfig {
showResetLabel: boolean;
usageCompact: boolean;
showTools: boolean;
toolTargetMaxLength: number;
showAgents: boolean;
showTodos: boolean;
showSessionName: boolean;
Expand Down Expand Up @@ -171,6 +172,7 @@ export const DEFAULT_CONFIG: HudConfig = {
showResetLabel: true,
usageCompact: false,
showTools: false,
toolTargetMaxLength: 0,
showAgents: false,
showTodos: false,
showSessionName: false,
Expand Down Expand Up @@ -528,6 +530,11 @@ export function mergeConfig(userConfig: Partial<HudConfig>): HudConfig {
showTools: typeof migrated.display?.showTools === 'boolean'
? migrated.display.showTools
: DEFAULT_CONFIG.display.showTools,
toolTargetMaxLength: typeof migrated.display?.toolTargetMaxLength === 'number'
&& Number.isFinite(migrated.display.toolTargetMaxLength)
&& migrated.display.toolTargetMaxLength >= 0
? Math.floor(migrated.display.toolTargetMaxLength)
: DEFAULT_CONFIG.display.toolTargetMaxLength,
showAgents: typeof migrated.display?.showAgents === 'boolean'
? migrated.display.showAgents
: DEFAULT_CONFIG.display.showAgents,
Expand Down
10 changes: 8 additions & 2 deletions src/render/tools-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { yellow, green, cyan, label } from './colors.js';
export function renderToolsLine(ctx: RenderContext): string | null {
const { tools } = ctx.transcript;
const colors = ctx.config?.colors;
const configMaxLen = ctx.config?.display?.toolTargetMaxLength;

if (tools.length === 0) {
return null;
Expand All @@ -15,7 +16,7 @@ export function renderToolsLine(ctx: RenderContext): string | null {
const completedTools = tools.filter((t) => t.status === 'completed' || t.status === 'error');

for (const tool of runningTools.slice(-2)) {
const target = tool.target ? truncatePath(tool.target) : '';
const target = tool.target ? truncatePath(tool.target, configMaxLen) : '';
parts.push(`${yellow('◐')} ${cyan(tool.name)}${target ? label(`: ${target}`, colors) : ''}`);
}

Expand All @@ -40,7 +41,12 @@ export function renderToolsLine(ctx: RenderContext): string | null {
return parts.join(' | ');
}

function truncatePath(path: string, maxLen: number = 20): string {
function truncatePath(path: string, configMaxLen?: number): string {
// 0 means auto (use terminal width), undefined/missing uses default 20
const maxLen = configMaxLen === 0
? Math.max(20, (Number.parseInt(process.env.COLUMNS ?? '', 10) || 120) - 30)
: (configMaxLen && configMaxLen > 0 ? configMaxLen : 20);

// Normalize Windows backslashes to forward slashes for consistent display
const normalizedPath = path.replace(/\\/g, '/');

Expand Down
4 changes: 3 additions & 1 deletion src/transcript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,9 @@ function extractTarget(toolName: string, input?: Record<string, unknown>): strin
: undefined;
case 'Bash':
const cmd = input.command as string;
return cmd?.slice(0, 30) + (cmd?.length > 30 ? '...' : '');
const cols = Number.parseInt(process.env.COLUMNS ?? '', 10) || 120;
const maxCmd = Math.max(30, cols - 20);
return cmd?.slice(0, maxCmd) + (cmd?.length > maxCmd ? '...' : '');
}
return undefined;
}
Expand Down
8 changes: 7 additions & 1 deletion tests/core.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,8 @@ test('parseTranscript leaves Skill target empty when input.skill is missing or i
test('parseTranscript truncates long bash commands in targets', async () => {
const dir = await mkdtemp(path.join(tmpdir(), 'claude-hud-'));
const filePath = path.join(dir, 'bash.jsonl');
const longCommand = 'echo ' + 'x'.repeat(50);
// Use a command longer than any reasonable terminal width to ensure truncation
const longCommand = 'echo ' + 'x'.repeat(200);
const lines = [
JSON.stringify({
message: {
Expand All @@ -959,11 +960,16 @@ test('parseTranscript truncates long bash commands in targets', async () => {

await writeFile(filePath, lines.join('\n'), 'utf8');

const prevColumns = process.env.COLUMNS;
process.env.COLUMNS = '60';
try {
const result = await parseTranscript(filePath);
assert.equal(result.tools.length, 1);
assert.ok(result.tools[0].target?.endsWith('...'));
assert.ok(result.tools[0].target.length <= 60 - 20 + 3); // maxCmd + '...'
} finally {
if (prevColumns === undefined) delete process.env.COLUMNS;
else process.env.COLUMNS = prevColumns;
await rm(dir, { recursive: true, force: true });
}
});
Expand Down